Home | History | Annotate | Download | only in runtime
      1 /*
      2  *  Copyright (C) 1999-2000 Harri Porten (porten (at) kde.org)
      3  *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
      4  *  Copyright (C) 2008, 2009 Torch Mobile, Inc. All rights reserved.
      5  *  Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
      6  *
      7  *  This library is free software; you can redistribute it and/or
      8  *  modify it under the terms of the GNU Lesser General Public
      9  *  License as published by the Free Software Foundation; either
     10  *  version 2 of the License, or (at your option) any later version.
     11  *
     12  *  This library is distributed in the hope that it will be useful,
     13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  *  Lesser General Public License for more details.
     16  *
     17  *  You should have received a copy of the GNU Lesser General Public
     18  *  License along with this library; if not, write to the Free Software
     19  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
     20  *  USA
     21  *
     22  */
     23 
     24 #include "config.h"
     25 #include "DatePrototype.h"
     26 
     27 #include "DateConversion.h"
     28 #include "DateInstance.h"
     29 #include "Error.h"
     30 #include "JSString.h"
     31 #include "JSStringBuilder.h"
     32 #include "Lookup.h"
     33 #include "ObjectPrototype.h"
     34 
     35 #if !PLATFORM(MAC) && HAVE(LANGINFO_H)
     36 #include <langinfo.h>
     37 #endif
     38 
     39 #include <limits.h>
     40 #include <locale.h>
     41 #include <math.h>
     42 #include <stdlib.h>
     43 #include <time.h>
     44 #include <wtf/Assertions.h>
     45 #include <wtf/DateMath.h>
     46 #include <wtf/MathExtras.h>
     47 #include <wtf/StringExtras.h>
     48 #include <wtf/UnusedParam.h>
     49 
     50 #if HAVE(SYS_PARAM_H)
     51 #include <sys/param.h>
     52 #endif
     53 
     54 #if HAVE(SYS_TIME_H)
     55 #include <sys/time.h>
     56 #endif
     57 
     58 #if HAVE(SYS_TIMEB_H)
     59 #include <sys/timeb.h>
     60 #endif
     61 
     62 #if PLATFORM(MAC)
     63 #include <CoreFoundation/CoreFoundation.h>
     64 #endif
     65 
     66 #if OS(WINCE) && !PLATFORM(QT)
     67 extern "C" size_t strftime(char * const s, const size_t maxsize, const char * const format, const struct tm * const t); //provided by libce
     68 #endif
     69 
     70 using namespace WTF;
     71 
     72 namespace JSC {
     73 
     74 ASSERT_CLASS_FITS_IN_CELL(DatePrototype);
     75 
     76 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState*);
     77 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState*);
     78 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState*);
     79 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState*);
     80 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState*);
     81 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState*);
     82 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState*);
     83 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState*);
     84 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState*);
     85 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState*);
     86 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState*);
     87 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState*);
     88 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState*);
     89 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState*);
     90 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState*);
     91 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState*);
     92 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState*);
     93 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState*);
     94 static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState*);
     95 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState*);
     96 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState*);
     97 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState*);
     98 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState*);
     99 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState*);
    100 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState*);
    101 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState*);
    102 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState*);
    103 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState*);
    104 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState*);
    105 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState*);
    106 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState*);
    107 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState*);
    108 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState*);
    109 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState*);
    110 static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState*);
    111 static EncodedJSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState*);
    112 static EncodedJSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState*);
    113 static EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState*);
    114 static EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState*);
    115 static EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState*);
    116 static EncodedJSValue JSC_HOST_CALL dateProtoFuncToString(ExecState*);
    117 static EncodedJSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState*);
    118 static EncodedJSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState*);
    119 static EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState*);
    120 static EncodedJSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState*);
    121 
    122 }
    123 
    124 #include "DatePrototype.lut.h"
    125 
    126 namespace JSC {
    127 
    128 enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
    129 
    130 #if PLATFORM(MAC)
    131 
    132 // FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)?
    133 // Instead we should consider using this whenever USE(CF) is true.
    134 
    135 static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateFormatterStyle defaultStyle)
    136 {
    137     if (string == "short")
    138         return kCFDateFormatterShortStyle;
    139     if (string == "medium")
    140         return kCFDateFormatterMediumStyle;
    141     if (string == "long")
    142         return kCFDateFormatterLongStyle;
    143     if (string == "full")
    144         return kCFDateFormatterFullStyle;
    145     return defaultStyle;
    146 }
    147 
    148 static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMilliseconds, LocaleDateTimeFormat format)
    149 {
    150     CFDateFormatterStyle dateStyle = (format != LocaleTime ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
    151     CFDateFormatterStyle timeStyle = (format != LocaleDate ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
    152 
    153     bool useCustomFormat = false;
    154     UString customFormatString;
    155 
    156     UString arg0String = exec->argument(0).toString(exec);
    157     if (arg0String == "custom" && !exec->argument(1).isUndefined()) {
    158         useCustomFormat = true;
    159         customFormatString = exec->argument(1).toString(exec);
    160     } else if (format == LocaleDateAndTime && !exec->argument(1).isUndefined()) {
    161         dateStyle = styleFromArgString(arg0String, dateStyle);
    162         timeStyle = styleFromArgString(exec->argument(1).toString(exec), timeStyle);
    163     } else if (format != LocaleTime && !exec->argument(0).isUndefined())
    164         dateStyle = styleFromArgString(arg0String, dateStyle);
    165     else if (format != LocaleDate && !exec->argument(0).isUndefined())
    166         timeStyle = styleFromArgString(arg0String, timeStyle);
    167 
    168     CFLocaleRef locale = CFLocaleCopyCurrent();
    169     CFDateFormatterRef formatter = CFDateFormatterCreate(0, locale, dateStyle, timeStyle);
    170     CFRelease(locale);
    171 
    172     if (useCustomFormat) {
    173         CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, customFormatString.characters(), customFormatString.length());
    174         CFDateFormatterSetFormat(formatter, customFormatCFString);
    175         CFRelease(customFormatCFString);
    176     }
    177 
    178     CFStringRef string = CFDateFormatterCreateStringWithAbsoluteTime(0, formatter, floor(timeInMilliseconds / msPerSecond) - kCFAbsoluteTimeIntervalSince1970);
    179 
    180     CFRelease(formatter);
    181 
    182     // We truncate the string returned from CFDateFormatter if it's absurdly long (> 200 characters).
    183     // That's not great error handling, but it just won't happen so it doesn't matter.
    184     UChar buffer[200];
    185     const size_t bufferLength = WTF_ARRAY_LENGTH(buffer);
    186     size_t length = CFStringGetLength(string);
    187     ASSERT(length <= bufferLength);
    188     if (length > bufferLength)
    189         length = bufferLength;
    190     CFStringGetCharacters(string, CFRangeMake(0, length), buffer);
    191 
    192     CFRelease(string);
    193 
    194     return jsNontrivialString(exec, UString(buffer, length));
    195 }
    196 
    197 #else // !PLATFORM(MAC)
    198 
    199 static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, LocaleDateTimeFormat format)
    200 {
    201 #if HAVE(LANGINFO_H)
    202     static const nl_item formats[] = { D_T_FMT, D_FMT, T_FMT };
    203 #elif (OS(WINCE) && !PLATFORM(QT)) || OS(SYMBIAN)
    204      // strftime() does not support '#' on WinCE or Symbian
    205     static const char* const formatStrings[] = { "%c", "%x", "%X" };
    206 #else
    207     static const char* const formatStrings[] = { "%#c", "%#x", "%X" };
    208 #endif
    209 
    210     // Offset year if needed
    211     struct tm localTM = gdt;
    212     int year = gdt.year + 1900;
    213     bool yearNeedsOffset = year < 1900 || year > 2038;
    214     if (yearNeedsOffset)
    215         localTM.tm_year = equivalentYearForDST(year) - 1900;
    216 
    217 #if HAVE(LANGINFO_H)
    218     // We do not allow strftime to generate dates with 2-digits years,
    219     // both to avoid ambiguity, and a crash in strncpy, for years that
    220     // need offset.
    221     char* formatString = strdup(nl_langinfo(formats[format]));
    222     char* yPos = strchr(formatString, 'y');
    223     if (yPos)
    224         *yPos = 'Y';
    225 #endif
    226 
    227     // Do the formatting
    228     const int bufsize = 128;
    229     char timebuffer[bufsize];
    230 
    231 #if HAVE(LANGINFO_H)
    232     size_t ret = strftime(timebuffer, bufsize, formatString, &localTM);
    233     free(formatString);
    234 #else
    235     size_t ret = strftime(timebuffer, bufsize, formatStrings[format], &localTM);
    236 #endif
    237 
    238     if (ret == 0)
    239         return jsEmptyString(exec);
    240 
    241     // Copy original into the buffer
    242     if (yearNeedsOffset && format != LocaleTime) {
    243         static const int yearLen = 5;   // FIXME will be a problem in the year 10,000
    244         char yearString[yearLen];
    245 
    246         snprintf(yearString, yearLen, "%d", localTM.tm_year + 1900);
    247         char* yearLocation = strstr(timebuffer, yearString);
    248         snprintf(yearString, yearLen, "%d", year);
    249 
    250         strncpy(yearLocation, yearString, yearLen - 1);
    251     }
    252 
    253     // Convert multi-byte result to UNICODE.
    254     // If __STDC_ISO_10646__ is defined, wide character represents
    255     // UTF-16 (or UTF-32) code point. In most modern Unix like system
    256     // (e.g. Linux with glibc 2.2 and above) the macro is defined,
    257     // and wide character represents UTF-32 code point.
    258     // Here we static_cast potential UTF-32 to UTF-16, it should be
    259     // safe because date and (or) time related characters in different languages
    260     // should be in UNICODE BMP. If mbstowcs fails, we just fall
    261     // back on using multi-byte result as-is.
    262 #ifdef __STDC_ISO_10646__
    263     UChar buffer[bufsize];
    264     wchar_t tempbuffer[bufsize];
    265     size_t length = mbstowcs(tempbuffer, timebuffer, bufsize - 1);
    266     if (length != static_cast<size_t>(-1)) {
    267         for (size_t i = 0; i < length; ++i)
    268             buffer[i] = static_cast<UChar>(tempbuffer[i]);
    269         return jsNontrivialString(exec, UString(buffer, length));
    270     }
    271 #endif
    272 
    273     return jsNontrivialString(exec, timebuffer);
    274 }
    275 
    276 static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, double, LocaleDateTimeFormat format)
    277 {
    278     const GregorianDateTime* gregorianDateTime = dateObject->gregorianDateTime(exec);
    279     if (!gregorianDateTime)
    280         return jsNontrivialString(exec, "Invalid Date");
    281     return formatLocaleDate(exec, *gregorianDateTime, format);
    282 }
    283 
    284 #endif // !PLATFORM(MAC)
    285 
    286 // Converts a list of arguments sent to a Date member function into milliseconds, updating
    287 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
    288 //
    289 // Format of member function: f([hour,] [min,] [sec,] [ms])
    290 static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms, GregorianDateTime* t)
    291 {
    292     double milliseconds = 0;
    293     bool ok = true;
    294     int idx = 0;
    295     int numArgs = exec->argumentCount();
    296 
    297     // JS allows extra trailing arguments -- ignore them
    298     if (numArgs > maxArgs)
    299         numArgs = maxArgs;
    300 
    301     // hours
    302     if (maxArgs >= 4 && idx < numArgs) {
    303         t->hour = 0;
    304         double hours = exec->argument(idx++).toIntegerPreserveNaN(exec);
    305         ok = isfinite(hours);
    306         milliseconds += hours * msPerHour;
    307     }
    308 
    309     // minutes
    310     if (maxArgs >= 3 && idx < numArgs && ok) {
    311         t->minute = 0;
    312         double minutes = exec->argument(idx++).toIntegerPreserveNaN(exec);
    313         ok = isfinite(minutes);
    314         milliseconds += minutes * msPerMinute;
    315     }
    316 
    317     // seconds
    318     if (maxArgs >= 2 && idx < numArgs && ok) {
    319         t->second = 0;
    320         double seconds = exec->argument(idx++).toIntegerPreserveNaN(exec);
    321         ok = isfinite(seconds);
    322         milliseconds += seconds * msPerSecond;
    323     }
    324 
    325     if (!ok)
    326         return false;
    327 
    328     // milliseconds
    329     if (idx < numArgs) {
    330         double millis = exec->argument(idx).toIntegerPreserveNaN(exec);
    331         ok = isfinite(millis);
    332         milliseconds += millis;
    333     } else
    334         milliseconds += *ms;
    335 
    336     *ms = milliseconds;
    337     return ok;
    338 }
    339 
    340 // Converts a list of arguments sent to a Date member function into years, months, and milliseconds, updating
    341 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
    342 //
    343 // Format of member function: f([years,] [months,] [days])
    344 static bool fillStructuresUsingDateArgs(ExecState *exec, int maxArgs, double *ms, GregorianDateTime *t)
    345 {
    346     int idx = 0;
    347     bool ok = true;
    348     int numArgs = exec->argumentCount();
    349 
    350     // JS allows extra trailing arguments -- ignore them
    351     if (numArgs > maxArgs)
    352         numArgs = maxArgs;
    353 
    354     // years
    355     if (maxArgs >= 3 && idx < numArgs) {
    356         double years = exec->argument(idx++).toIntegerPreserveNaN(exec);
    357         ok = isfinite(years);
    358         t->year = toInt32(years - 1900);
    359     }
    360     // months
    361     if (maxArgs >= 2 && idx < numArgs && ok) {
    362         double months = exec->argument(idx++).toIntegerPreserveNaN(exec);
    363         ok = isfinite(months);
    364         t->month = toInt32(months);
    365     }
    366     // days
    367     if (idx < numArgs && ok) {
    368         double days = exec->argument(idx++).toIntegerPreserveNaN(exec);
    369         ok = isfinite(days);
    370         t->monthDay = 0;
    371         *ms += days * msPerDay;
    372     }
    373 
    374     return ok;
    375 }
    376 
    377 const ClassInfo DatePrototype::s_info = {"Date", &DateInstance::s_info, 0, ExecState::dateTable};
    378 
    379 /* Source for DatePrototype.lut.h
    380 @begin dateTable
    381   toString              dateProtoFuncToString                DontEnum|Function       0
    382   toISOString           dateProtoFuncToISOString             DontEnum|Function       0
    383   toUTCString           dateProtoFuncToUTCString             DontEnum|Function       0
    384   toDateString          dateProtoFuncToDateString            DontEnum|Function       0
    385   toTimeString          dateProtoFuncToTimeString            DontEnum|Function       0
    386   toLocaleString        dateProtoFuncToLocaleString          DontEnum|Function       0
    387   toLocaleDateString    dateProtoFuncToLocaleDateString      DontEnum|Function       0
    388   toLocaleTimeString    dateProtoFuncToLocaleTimeString      DontEnum|Function       0
    389   valueOf               dateProtoFuncGetTime                 DontEnum|Function       0
    390   getTime               dateProtoFuncGetTime                 DontEnum|Function       0
    391   getFullYear           dateProtoFuncGetFullYear             DontEnum|Function       0
    392   getUTCFullYear        dateProtoFuncGetUTCFullYear          DontEnum|Function       0
    393   toGMTString           dateProtoFuncToGMTString             DontEnum|Function       0
    394   getMonth              dateProtoFuncGetMonth                DontEnum|Function       0
    395   getUTCMonth           dateProtoFuncGetUTCMonth             DontEnum|Function       0
    396   getDate               dateProtoFuncGetDate                 DontEnum|Function       0
    397   getUTCDate            dateProtoFuncGetUTCDate              DontEnum|Function       0
    398   getDay                dateProtoFuncGetDay                  DontEnum|Function       0
    399   getUTCDay             dateProtoFuncGetUTCDay               DontEnum|Function       0
    400   getHours              dateProtoFuncGetHours                DontEnum|Function       0
    401   getUTCHours           dateProtoFuncGetUTCHours             DontEnum|Function       0
    402   getMinutes            dateProtoFuncGetMinutes              DontEnum|Function       0
    403   getUTCMinutes         dateProtoFuncGetUTCMinutes           DontEnum|Function       0
    404   getSeconds            dateProtoFuncGetSeconds              DontEnum|Function       0
    405   getUTCSeconds         dateProtoFuncGetUTCSeconds           DontEnum|Function       0
    406   getMilliseconds       dateProtoFuncGetMilliSeconds         DontEnum|Function       0
    407   getUTCMilliseconds    dateProtoFuncGetUTCMilliseconds      DontEnum|Function       0
    408   getTimezoneOffset     dateProtoFuncGetTimezoneOffset       DontEnum|Function       0
    409   setTime               dateProtoFuncSetTime                 DontEnum|Function       1
    410   setMilliseconds       dateProtoFuncSetMilliSeconds         DontEnum|Function       1
    411   setUTCMilliseconds    dateProtoFuncSetUTCMilliseconds      DontEnum|Function       1
    412   setSeconds            dateProtoFuncSetSeconds              DontEnum|Function       2
    413   setUTCSeconds         dateProtoFuncSetUTCSeconds           DontEnum|Function       2
    414   setMinutes            dateProtoFuncSetMinutes              DontEnum|Function       3
    415   setUTCMinutes         dateProtoFuncSetUTCMinutes           DontEnum|Function       3
    416   setHours              dateProtoFuncSetHours                DontEnum|Function       4
    417   setUTCHours           dateProtoFuncSetUTCHours             DontEnum|Function       4
    418   setDate               dateProtoFuncSetDate                 DontEnum|Function       1
    419   setUTCDate            dateProtoFuncSetUTCDate              DontEnum|Function       1
    420   setMonth              dateProtoFuncSetMonth                DontEnum|Function       2
    421   setUTCMonth           dateProtoFuncSetUTCMonth             DontEnum|Function       2
    422   setFullYear           dateProtoFuncSetFullYear             DontEnum|Function       3
    423   setUTCFullYear        dateProtoFuncSetUTCFullYear          DontEnum|Function       3
    424   setYear               dateProtoFuncSetYear                 DontEnum|Function       1
    425   getYear               dateProtoFuncGetYear                 DontEnum|Function       0
    426   toJSON                dateProtoFuncToJSON                  DontEnum|Function       1
    427 @end
    428 */
    429 
    430 // ECMA 15.9.4
    431 
    432 DatePrototype::DatePrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
    433     : DateInstance(exec, structure)
    434 {
    435     ASSERT(inherits(&s_info));
    436 
    437     // The constructor will be added later, after DateConstructor has been built.
    438     putAnonymousValue(exec->globalData(), 0, globalObject);
    439 }
    440 
    441 bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
    442 {
    443     return getStaticFunctionSlot<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, slot);
    444 }
    445 
    446 
    447 bool DatePrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
    448 {
    449     return getStaticFunctionDescriptor<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, descriptor);
    450 }
    451 
    452 // Functions
    453 
    454 EncodedJSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec)
    455 {
    456     JSValue thisValue = exec->hostThisValue();
    457     if (!thisValue.inherits(&DateInstance::s_info))
    458         return throwVMTypeError(exec);
    459 
    460     DateInstance* thisDateObj = asDateInstance(thisValue);
    461 
    462     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
    463     if (!gregorianDateTime)
    464         return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
    465     DateConversionBuffer date;
    466     DateConversionBuffer time;
    467     formatDate(*gregorianDateTime, date);
    468     formatTime(*gregorianDateTime, time);
    469     return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time));
    470 }
    471 
    472 EncodedJSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec)
    473 {
    474     JSValue thisValue = exec->hostThisValue();
    475     if (!thisValue.inherits(&DateInstance::s_info))
    476         return throwVMTypeError(exec);
    477 
    478     DateInstance* thisDateObj = asDateInstance(thisValue);
    479 
    480     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
    481     if (!gregorianDateTime)
    482         return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
    483     DateConversionBuffer date;
    484     DateConversionBuffer time;
    485     formatDateUTCVariant(*gregorianDateTime, date);
    486     formatTimeUTC(*gregorianDateTime, time);
    487     return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time));
    488 }
    489 
    490 EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec)
    491 {
    492     JSValue thisValue = exec->hostThisValue();
    493     if (!thisValue.inherits(&DateInstance::s_info))
    494         return throwVMTypeError(exec);
    495 
    496     DateInstance* thisDateObj = asDateInstance(thisValue);
    497 
    498     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
    499     if (!gregorianDateTime)
    500         return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
    501     // Maximum amount of space we need in buffer: 6 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds)
    502     // 6 for formatting and one for null termination = 27.  We add one extra character to allow us to force null termination.
    503     char buffer[28];
    504     snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + gregorianDateTime->year, gregorianDateTime->month + 1, gregorianDateTime->monthDay, gregorianDateTime->hour, gregorianDateTime->minute, gregorianDateTime->second, static_cast<int>(fmod(thisDateObj->internalNumber(), 1000)));
    505     buffer[sizeof(buffer) - 1] = 0;
    506     return JSValue::encode(jsNontrivialString(exec, buffer));
    507 }
    508 
    509 EncodedJSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec)
    510 {
    511     JSValue thisValue = exec->hostThisValue();
    512     if (!thisValue.inherits(&DateInstance::s_info))
    513         return throwVMTypeError(exec);
    514 
    515     DateInstance* thisDateObj = asDateInstance(thisValue);
    516 
    517     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
    518     if (!gregorianDateTime)
    519         return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
    520     DateConversionBuffer date;
    521     formatDate(*gregorianDateTime, date);
    522     return JSValue::encode(jsNontrivialString(exec, date));
    523 }
    524 
    525 EncodedJSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec)
    526 {
    527     JSValue thisValue = exec->hostThisValue();
    528     if (!thisValue.inherits(&DateInstance::s_info))
    529         return throwVMTypeError(exec);
    530 
    531     DateInstance* thisDateObj = asDateInstance(thisValue);
    532 
    533     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
    534     if (!gregorianDateTime)
    535         return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
    536     DateConversionBuffer time;
    537     formatTime(*gregorianDateTime, time);
    538     return JSValue::encode(jsNontrivialString(exec, time));
    539 }
    540 
    541 EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec)
    542 {
    543     JSValue thisValue = exec->hostThisValue();
    544     if (!thisValue.inherits(&DateInstance::s_info))
    545         return throwVMTypeError(exec);
    546 
    547     DateInstance* thisDateObj = asDateInstance(thisValue);
    548     return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDateAndTime));
    549 }
    550 
    551 EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec)
    552 {
    553     JSValue thisValue = exec->hostThisValue();
    554     if (!thisValue.inherits(&DateInstance::s_info))
    555         return throwVMTypeError(exec);
    556 
    557     DateInstance* thisDateObj = asDateInstance(thisValue);
    558     return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDate));
    559 }
    560 
    561 EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec)
    562 {
    563     JSValue thisValue = exec->hostThisValue();
    564     if (!thisValue.inherits(&DateInstance::s_info))
    565         return throwVMTypeError(exec);
    566 
    567     DateInstance* thisDateObj = asDateInstance(thisValue);
    568     return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleTime));
    569 }
    570 
    571 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec)
    572 {
    573     JSValue thisValue = exec->hostThisValue();
    574     if (!thisValue.inherits(&DateInstance::s_info))
    575         return throwVMTypeError(exec);
    576 
    577     return JSValue::encode(asDateInstance(thisValue)->internalValue());
    578 }
    579 
    580 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec)
    581 {
    582     JSValue thisValue = exec->hostThisValue();
    583     if (!thisValue.inherits(&DateInstance::s_info))
    584         return throwVMTypeError(exec);
    585 
    586     DateInstance* thisDateObj = asDateInstance(thisValue);
    587 
    588     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
    589     if (!gregorianDateTime)
    590         return JSValue::encode(jsNaN());
    591     return JSValue::encode(jsNumber(1900 + gregorianDateTime->year));
    592 }
    593 
    594 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec)
    595 {
    596     JSValue thisValue = exec->hostThisValue();
    597     if (!thisValue.inherits(&DateInstance::s_info))
    598         return throwVMTypeError(exec);
    599 
    600     DateInstance* thisDateObj = asDateInstance(thisValue);
    601 
    602     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
    603     if (!gregorianDateTime)
    604         return JSValue::encode(jsNaN());
    605     return JSValue::encode(jsNumber(1900 + gregorianDateTime->year));
    606 }
    607 
    608 EncodedJSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec)
    609 {
    610     JSValue thisValue = exec->hostThisValue();
    611     if (!thisValue.inherits(&DateInstance::s_info))
    612         return throwVMTypeError(exec);
    613 
    614     DateInstance* thisDateObj = asDateInstance(thisValue);
    615 
    616     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
    617     if (!gregorianDateTime)
    618         return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
    619     DateConversionBuffer date;
    620     DateConversionBuffer time;
    621     formatDateUTCVariant(*gregorianDateTime, date);
    622     formatTimeUTC(*gregorianDateTime, time);
    623     return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time));
    624 }
    625 
    626 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec)
    627 {
    628     JSValue thisValue = exec->hostThisValue();
    629     if (!thisValue.inherits(&DateInstance::s_info))
    630         return throwVMTypeError(exec);
    631 
    632     DateInstance* thisDateObj = asDateInstance(thisValue);
    633 
    634     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
    635     if (!gregorianDateTime)
    636         return JSValue::encode(jsNaN());
    637     return JSValue::encode(jsNumber(gregorianDateTime->month));
    638 }
    639 
    640 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec)
    641 {
    642     JSValue thisValue = exec->hostThisValue();
    643     if (!thisValue.inherits(&DateInstance::s_info))
    644         return throwVMTypeError(exec);
    645 
    646     DateInstance* thisDateObj = asDateInstance(thisValue);
    647 
    648     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
    649     if (!gregorianDateTime)
    650         return JSValue::encode(jsNaN());
    651     return JSValue::encode(jsNumber(gregorianDateTime->month));
    652 }
    653 
    654 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec)
    655 {
    656     JSValue thisValue = exec->hostThisValue();
    657     if (!thisValue.inherits(&DateInstance::s_info))
    658         return throwVMTypeError(exec);
    659 
    660     DateInstance* thisDateObj = asDateInstance(thisValue);
    661 
    662     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
    663     if (!gregorianDateTime)
    664         return JSValue::encode(jsNaN());
    665     return JSValue::encode(jsNumber(gregorianDateTime->monthDay));
    666 }
    667 
    668 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec)
    669 {
    670     JSValue thisValue = exec->hostThisValue();
    671     if (!thisValue.inherits(&DateInstance::s_info))
    672         return throwVMTypeError(exec);
    673 
    674     DateInstance* thisDateObj = asDateInstance(thisValue);
    675 
    676     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
    677     if (!gregorianDateTime)
    678         return JSValue::encode(jsNaN());
    679     return JSValue::encode(jsNumber(gregorianDateTime->monthDay));
    680 }
    681 
    682 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec)
    683 {
    684     JSValue thisValue = exec->hostThisValue();
    685     if (!thisValue.inherits(&DateInstance::s_info))
    686         return throwVMTypeError(exec);
    687 
    688     DateInstance* thisDateObj = asDateInstance(thisValue);
    689 
    690     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
    691     if (!gregorianDateTime)
    692         return JSValue::encode(jsNaN());
    693     return JSValue::encode(jsNumber(gregorianDateTime->weekDay));
    694 }
    695 
    696 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec)
    697 {
    698     JSValue thisValue = exec->hostThisValue();
    699     if (!thisValue.inherits(&DateInstance::s_info))
    700         return throwVMTypeError(exec);
    701 
    702     DateInstance* thisDateObj = asDateInstance(thisValue);
    703 
    704     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
    705     if (!gregorianDateTime)
    706         return JSValue::encode(jsNaN());
    707     return JSValue::encode(jsNumber(gregorianDateTime->weekDay));
    708 }
    709 
    710 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec)
    711 {
    712     JSValue thisValue = exec->hostThisValue();
    713     if (!thisValue.inherits(&DateInstance::s_info))
    714         return throwVMTypeError(exec);
    715 
    716     DateInstance* thisDateObj = asDateInstance(thisValue);
    717 
    718     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
    719     if (!gregorianDateTime)
    720         return JSValue::encode(jsNaN());
    721     return JSValue::encode(jsNumber(gregorianDateTime->hour));
    722 }
    723 
    724 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec)
    725 {
    726     JSValue thisValue = exec->hostThisValue();
    727     if (!thisValue.inherits(&DateInstance::s_info))
    728         return throwVMTypeError(exec);
    729 
    730     DateInstance* thisDateObj = asDateInstance(thisValue);
    731 
    732     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
    733     if (!gregorianDateTime)
    734         return JSValue::encode(jsNaN());
    735     return JSValue::encode(jsNumber(gregorianDateTime->hour));
    736 }
    737 
    738 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec)
    739 {
    740     JSValue thisValue = exec->hostThisValue();
    741     if (!thisValue.inherits(&DateInstance::s_info))
    742         return throwVMTypeError(exec);
    743 
    744     DateInstance* thisDateObj = asDateInstance(thisValue);
    745 
    746     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
    747     if (!gregorianDateTime)
    748         return JSValue::encode(jsNaN());
    749     return JSValue::encode(jsNumber(gregorianDateTime->minute));
    750 }
    751 
    752 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec)
    753 {
    754     JSValue thisValue = exec->hostThisValue();
    755     if (!thisValue.inherits(&DateInstance::s_info))
    756         return throwVMTypeError(exec);
    757 
    758     DateInstance* thisDateObj = asDateInstance(thisValue);
    759 
    760     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
    761     if (!gregorianDateTime)
    762         return JSValue::encode(jsNaN());
    763     return JSValue::encode(jsNumber(gregorianDateTime->minute));
    764 }
    765 
    766 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec)
    767 {
    768     JSValue thisValue = exec->hostThisValue();
    769     if (!thisValue.inherits(&DateInstance::s_info))
    770         return throwVMTypeError(exec);
    771 
    772     DateInstance* thisDateObj = asDateInstance(thisValue);
    773 
    774     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
    775     if (!gregorianDateTime)
    776         return JSValue::encode(jsNaN());
    777     return JSValue::encode(jsNumber(gregorianDateTime->second));
    778 }
    779 
    780 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec)
    781 {
    782     JSValue thisValue = exec->hostThisValue();
    783     if (!thisValue.inherits(&DateInstance::s_info))
    784         return throwVMTypeError(exec);
    785 
    786     DateInstance* thisDateObj = asDateInstance(thisValue);
    787 
    788     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
    789     if (!gregorianDateTime)
    790         return JSValue::encode(jsNaN());
    791     return JSValue::encode(jsNumber(gregorianDateTime->second));
    792 }
    793 
    794 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec)
    795 {
    796     JSValue thisValue = exec->hostThisValue();
    797     if (!thisValue.inherits(&DateInstance::s_info))
    798         return throwVMTypeError(exec);
    799 
    800     DateInstance* thisDateObj = asDateInstance(thisValue);
    801     double milli = thisDateObj->internalNumber();
    802     if (isnan(milli))
    803         return JSValue::encode(jsNaN());
    804 
    805     double secs = floor(milli / msPerSecond);
    806     double ms = milli - secs * msPerSecond;
    807     return JSValue::encode(jsNumber(ms));
    808 }
    809 
    810 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec)
    811 {
    812     JSValue thisValue = exec->hostThisValue();
    813     if (!thisValue.inherits(&DateInstance::s_info))
    814         return throwVMTypeError(exec);
    815 
    816     DateInstance* thisDateObj = asDateInstance(thisValue);
    817     double milli = thisDateObj->internalNumber();
    818     if (isnan(milli))
    819         return JSValue::encode(jsNaN());
    820 
    821     double secs = floor(milli / msPerSecond);
    822     double ms = milli - secs * msPerSecond;
    823     return JSValue::encode(jsNumber(ms));
    824 }
    825 
    826 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec)
    827 {
    828     JSValue thisValue = exec->hostThisValue();
    829     if (!thisValue.inherits(&DateInstance::s_info))
    830         return throwVMTypeError(exec);
    831 
    832     DateInstance* thisDateObj = asDateInstance(thisValue);
    833 
    834     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
    835     if (!gregorianDateTime)
    836         return JSValue::encode(jsNaN());
    837     return JSValue::encode(jsNumber(-gregorianDateTime->utcOffset / minutesPerHour));
    838 }
    839 
    840 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec)
    841 {
    842     JSValue thisValue = exec->hostThisValue();
    843     if (!thisValue.inherits(&DateInstance::s_info))
    844         return throwVMTypeError(exec);
    845 
    846     DateInstance* thisDateObj = asDateInstance(thisValue);
    847 
    848     double milli = timeClip(exec->argument(0).toNumber(exec));
    849     JSValue result = jsNumber(milli);
    850     thisDateObj->setInternalValue(exec->globalData(), result);
    851     return JSValue::encode(result);
    852 }
    853 
    854 static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse, bool inputIsUTC)
    855 {
    856     JSValue thisValue = exec->hostThisValue();
    857     if (!thisValue.inherits(&DateInstance::s_info))
    858         return throwVMTypeError(exec);
    859 
    860     DateInstance* thisDateObj = asDateInstance(thisValue);
    861     double milli = thisDateObj->internalNumber();
    862 
    863     if (!exec->argumentCount() || isnan(milli)) {
    864         JSValue result = jsNaN();
    865         thisDateObj->setInternalValue(exec->globalData(), result);
    866         return JSValue::encode(result);
    867     }
    868 
    869     double secs = floor(milli / msPerSecond);
    870     double ms = milli - secs * msPerSecond;
    871 
    872     const GregorianDateTime* other = inputIsUTC
    873         ? thisDateObj->gregorianDateTimeUTC(exec)
    874         : thisDateObj->gregorianDateTime(exec);
    875     if (!other)
    876         return JSValue::encode(jsNaN());
    877 
    878     GregorianDateTime gregorianDateTime;
    879     gregorianDateTime.copyFrom(*other);
    880     if (!fillStructuresUsingTimeArgs(exec, numArgsToUse, &ms, &gregorianDateTime)) {
    881         JSValue result = jsNaN();
    882         thisDateObj->setInternalValue(exec->globalData(), result);
    883         return JSValue::encode(result);
    884     }
    885 
    886     JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC));
    887     thisDateObj->setInternalValue(exec->globalData(), result);
    888     return JSValue::encode(result);
    889 }
    890 
    891 static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse, bool inputIsUTC)
    892 {
    893     JSValue thisValue = exec->hostThisValue();
    894     if (!thisValue.inherits(&DateInstance::s_info))
    895         return throwVMTypeError(exec);
    896 
    897     DateInstance* thisDateObj = asDateInstance(thisValue);
    898     if (!exec->argumentCount()) {
    899         JSValue result = jsNaN();
    900         thisDateObj->setInternalValue(exec->globalData(), result);
    901         return JSValue::encode(result);
    902     }
    903 
    904     double milli = thisDateObj->internalNumber();
    905     double ms = 0;
    906 
    907     GregorianDateTime gregorianDateTime;
    908     if (numArgsToUse == 3 && isnan(milli))
    909         msToGregorianDateTime(exec, 0, true, gregorianDateTime);
    910     else {
    911         ms = milli - floor(milli / msPerSecond) * msPerSecond;
    912         const GregorianDateTime* other = inputIsUTC
    913             ? thisDateObj->gregorianDateTimeUTC(exec)
    914             : thisDateObj->gregorianDateTime(exec);
    915         if (!other)
    916             return JSValue::encode(jsNaN());
    917         gregorianDateTime.copyFrom(*other);
    918     }
    919 
    920     if (!fillStructuresUsingDateArgs(exec, numArgsToUse, &ms, &gregorianDateTime)) {
    921         JSValue result = jsNaN();
    922         thisDateObj->setInternalValue(exec->globalData(), result);
    923         return JSValue::encode(result);
    924     }
    925 
    926     JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC));
    927     thisDateObj->setInternalValue(exec->globalData(), result);
    928     return JSValue::encode(result);
    929 }
    930 
    931 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState* exec)
    932 {
    933     const bool inputIsUTC = false;
    934     return setNewValueFromTimeArgs(exec, 1, inputIsUTC);
    935 }
    936 
    937 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState* exec)
    938 {
    939     const bool inputIsUTC = true;
    940     return setNewValueFromTimeArgs(exec, 1, inputIsUTC);
    941 }
    942 
    943 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState* exec)
    944 {
    945     const bool inputIsUTC = false;
    946     return setNewValueFromTimeArgs(exec, 2, inputIsUTC);
    947 }
    948 
    949 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState* exec)
    950 {
    951     const bool inputIsUTC = true;
    952     return setNewValueFromTimeArgs(exec, 2, inputIsUTC);
    953 }
    954 
    955 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState* exec)
    956 {
    957     const bool inputIsUTC = false;
    958     return setNewValueFromTimeArgs(exec, 3, inputIsUTC);
    959 }
    960 
    961 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState* exec)
    962 {
    963     const bool inputIsUTC = true;
    964     return setNewValueFromTimeArgs(exec, 3, inputIsUTC);
    965 }
    966 
    967 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState* exec)
    968 {
    969     const bool inputIsUTC = false;
    970     return setNewValueFromTimeArgs(exec, 4, inputIsUTC);
    971 }
    972 
    973 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState* exec)
    974 {
    975     const bool inputIsUTC = true;
    976     return setNewValueFromTimeArgs(exec, 4, inputIsUTC);
    977 }
    978 
    979 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState* exec)
    980 {
    981     const bool inputIsUTC = false;
    982     return setNewValueFromDateArgs(exec, 1, inputIsUTC);
    983 }
    984 
    985 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState* exec)
    986 {
    987     const bool inputIsUTC = true;
    988     return setNewValueFromDateArgs(exec, 1, inputIsUTC);
    989 }
    990 
    991 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState* exec)
    992 {
    993     const bool inputIsUTC = false;
    994     return setNewValueFromDateArgs(exec, 2, inputIsUTC);
    995 }
    996 
    997 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState* exec)
    998 {
    999     const bool inputIsUTC = true;
   1000     return setNewValueFromDateArgs(exec, 2, inputIsUTC);
   1001 }
   1002 
   1003 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState* exec)
   1004 {
   1005     const bool inputIsUTC = false;
   1006     return setNewValueFromDateArgs(exec, 3, inputIsUTC);
   1007 }
   1008 
   1009 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState* exec)
   1010 {
   1011     const bool inputIsUTC = true;
   1012     return setNewValueFromDateArgs(exec, 3, inputIsUTC);
   1013 }
   1014 
   1015 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
   1016 {
   1017     JSValue thisValue = exec->hostThisValue();
   1018     if (!thisValue.inherits(&DateInstance::s_info))
   1019         return throwVMTypeError(exec);
   1020 
   1021     DateInstance* thisDateObj = asDateInstance(thisValue);
   1022     if (!exec->argumentCount()) {
   1023         JSValue result = jsNaN();
   1024         thisDateObj->setInternalValue(exec->globalData(), result);
   1025         return JSValue::encode(result);
   1026     }
   1027 
   1028     double milli = thisDateObj->internalNumber();
   1029     double ms = 0;
   1030 
   1031     GregorianDateTime gregorianDateTime;
   1032     if (isnan(milli))
   1033         // Based on ECMA 262 B.2.5 (setYear)
   1034         // the time must be reset to +0 if it is NaN.
   1035         msToGregorianDateTime(exec, 0, true, gregorianDateTime);
   1036     else {
   1037         double secs = floor(milli / msPerSecond);
   1038         ms = milli - secs * msPerSecond;
   1039         if (const GregorianDateTime* other = thisDateObj->gregorianDateTime(exec))
   1040             gregorianDateTime.copyFrom(*other);
   1041     }
   1042 
   1043     double year = exec->argument(0).toIntegerPreserveNaN(exec);
   1044     if (!isfinite(year)) {
   1045         JSValue result = jsNaN();
   1046         thisDateObj->setInternalValue(exec->globalData(), result);
   1047         return JSValue::encode(result);
   1048     }
   1049 
   1050     gregorianDateTime.year = toInt32((year > 99 || year < 0) ? year - 1900 : year);
   1051     JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, false));
   1052     thisDateObj->setInternalValue(exec->globalData(), result);
   1053     return JSValue::encode(result);
   1054 }
   1055 
   1056 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec)
   1057 {
   1058     JSValue thisValue = exec->hostThisValue();
   1059     if (!thisValue.inherits(&DateInstance::s_info))
   1060         return throwVMTypeError(exec);
   1061 
   1062     DateInstance* thisDateObj = asDateInstance(thisValue);
   1063 
   1064     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
   1065     if (!gregorianDateTime)
   1066         return JSValue::encode(jsNaN());
   1067 
   1068     // NOTE: IE returns the full year even in getYear.
   1069     return JSValue::encode(jsNumber(gregorianDateTime->year));
   1070 }
   1071 
   1072 EncodedJSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec)
   1073 {
   1074     JSValue thisValue = exec->hostThisValue();
   1075     JSObject* object = thisValue.toThisObject(exec);
   1076     if (exec->hadException())
   1077         return JSValue::encode(jsNull());
   1078 
   1079     JSValue toISOValue = object->get(exec, exec->globalData().propertyNames->toISOString);
   1080     if (exec->hadException())
   1081         return JSValue::encode(jsNull());
   1082 
   1083     CallData callData;
   1084     CallType callType = getCallData(toISOValue, callData);
   1085     if (callType == CallTypeNone)
   1086         return throwVMError(exec, createTypeError(exec, "toISOString is not a function"));
   1087 
   1088     JSValue result = call(exec, asObject(toISOValue), callType, callData, object, exec->emptyList());
   1089     if (exec->hadException())
   1090         return JSValue::encode(jsNull());
   1091     if (result.isObject())
   1092         return throwVMError(exec, createTypeError(exec, "toISOString did not return a primitive value"));
   1093     return JSValue::encode(result);
   1094 }
   1095 
   1096 } // namespace JSC
   1097