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