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