Foo::s_info should be Foo::info(), so that you can change how the s_info is actually...
[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->argument(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->argument(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->argument(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->argument(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->argument(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->argument(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->argument(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(ExecState* exec, Structure* structure)
505     : DateInstance(exec, structure)
506 {
507 }
508
509 void DatePrototype::finishCreation(ExecState* exec, JSGlobalObject*)
510 {
511     Base::finishCreation(exec->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 bool DatePrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)
523 {
524     return getStaticFunctionDescriptor<JSObject>(exec, ExecState::dateTable(exec), jsCast<DatePrototype*>(object), propertyName, descriptor);
525 }
526
527 // Functions
528
529 EncodedJSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec)
530 {
531     const bool asUTCVariant = false;
532     return formateDateInstance(exec, DateTimeFormatDateAndTime, asUTCVariant);
533 }
534
535 EncodedJSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec)
536 {
537     const bool asUTCVariant = true;
538     return formateDateInstance(exec, DateTimeFormatDateAndTime, asUTCVariant);
539 }
540
541 EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec)
542 {
543     JSValue thisValue = exec->hostThisValue();
544     if (!thisValue.inherits(DateInstance::info()))
545         return throwVMTypeError(exec);
546     
547     DateInstance* thisDateObj = asDateInstance(thisValue); 
548     if (!std::isfinite(thisDateObj->internalNumber()))
549         return throwVMError(exec, createRangeError(exec, ASCIILiteral("Invalid Date")));
550
551     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
552     if (!gregorianDateTime)
553         return JSValue::encode(jsNontrivialString(exec, String(ASCIILiteral("Invalid Date"))));
554     // 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)
555     // 6 for formatting and one for null termination = 28. We add one extra character to allow us to force null termination.
556     char buffer[28];
557     // 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).
558     int ms = static_cast<int>(fmod(thisDateObj->internalNumber(), msPerSecond));
559     if (ms < 0)
560         ms += msPerSecond;
561
562     int charactersWritten;
563     if (gregorianDateTime->year() > 9999 || gregorianDateTime->year() < 0)
564         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);
565     else
566         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);
567
568     ASSERT(charactersWritten > 0 && static_cast<unsigned>(charactersWritten) < sizeof(buffer));
569     if (static_cast<unsigned>(charactersWritten) >= sizeof(buffer))
570         return JSValue::encode(jsEmptyString(exec));
571
572     return JSValue::encode(jsNontrivialString(exec, String(buffer, charactersWritten)));
573 }
574
575 EncodedJSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec)
576 {
577     const bool asUTCVariant = false;
578     return formateDateInstance(exec, DateTimeFormatDate, asUTCVariant);
579 }
580
581 EncodedJSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec)
582 {
583     const bool asUTCVariant = false;
584     return formateDateInstance(exec, DateTimeFormatTime, asUTCVariant);
585 }
586
587 EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec)
588 {
589     JSValue thisValue = exec->hostThisValue();
590     if (!thisValue.inherits(DateInstance::info()))
591         return throwVMTypeError(exec);
592
593     DateInstance* thisDateObj = asDateInstance(thisValue); 
594     return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDateAndTime));
595 }
596
597 EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec)
598 {
599     JSValue thisValue = exec->hostThisValue();
600     if (!thisValue.inherits(DateInstance::info()))
601         return throwVMTypeError(exec);
602
603     DateInstance* thisDateObj = asDateInstance(thisValue); 
604     return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDate));
605 }
606
607 EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec)
608 {
609     JSValue thisValue = exec->hostThisValue();
610     if (!thisValue.inherits(DateInstance::info()))
611         return throwVMTypeError(exec);
612
613     DateInstance* thisDateObj = asDateInstance(thisValue); 
614     return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleTime));
615 }
616
617 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec)
618 {
619     JSValue thisValue = exec->hostThisValue();
620     if (!thisValue.inherits(DateInstance::info()))
621         return throwVMTypeError(exec);
622
623     return JSValue::encode(asDateInstance(thisValue)->internalValue());
624 }
625
626 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec)
627 {
628     JSValue thisValue = exec->hostThisValue();
629     if (!thisValue.inherits(DateInstance::info()))
630         return throwVMTypeError(exec);
631
632     DateInstance* thisDateObj = asDateInstance(thisValue); 
633
634     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
635     if (!gregorianDateTime)
636         return JSValue::encode(jsNaN());
637     return JSValue::encode(jsNumber(gregorianDateTime->year()));
638 }
639
640 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec)
641 {
642     JSValue thisValue = exec->hostThisValue();
643     if (!thisValue.inherits(DateInstance::info()))
644         return throwVMTypeError(exec);
645
646     DateInstance* thisDateObj = asDateInstance(thisValue); 
647
648     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
649     if (!gregorianDateTime)
650         return JSValue::encode(jsNaN());
651     return JSValue::encode(jsNumber(gregorianDateTime->year()));
652 }
653
654 EncodedJSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec)
655 {
656     const bool asUTCVariant = true;
657     return formateDateInstance(exec, DateTimeFormatDateAndTime, asUTCVariant);
658 }
659
660 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec)
661 {
662     JSValue thisValue = exec->hostThisValue();
663     if (!thisValue.inherits(DateInstance::info()))
664         return throwVMTypeError(exec);
665
666     DateInstance* thisDateObj = asDateInstance(thisValue); 
667
668     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
669     if (!gregorianDateTime)
670         return JSValue::encode(jsNaN());
671     return JSValue::encode(jsNumber(gregorianDateTime->month()));
672 }
673
674 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec)
675 {
676     JSValue thisValue = exec->hostThisValue();
677     if (!thisValue.inherits(DateInstance::info()))
678         return throwVMTypeError(exec);
679
680     DateInstance* thisDateObj = asDateInstance(thisValue); 
681
682     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
683     if (!gregorianDateTime)
684         return JSValue::encode(jsNaN());
685     return JSValue::encode(jsNumber(gregorianDateTime->month()));
686 }
687
688 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec)
689 {
690     JSValue thisValue = exec->hostThisValue();
691     if (!thisValue.inherits(DateInstance::info()))
692         return throwVMTypeError(exec);
693
694     DateInstance* thisDateObj = asDateInstance(thisValue); 
695
696     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
697     if (!gregorianDateTime)
698         return JSValue::encode(jsNaN());
699     return JSValue::encode(jsNumber(gregorianDateTime->monthDay()));
700 }
701
702 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec)
703 {
704     JSValue thisValue = exec->hostThisValue();
705     if (!thisValue.inherits(DateInstance::info()))
706         return throwVMTypeError(exec);
707
708     DateInstance* thisDateObj = asDateInstance(thisValue); 
709
710     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
711     if (!gregorianDateTime)
712         return JSValue::encode(jsNaN());
713     return JSValue::encode(jsNumber(gregorianDateTime->monthDay()));
714 }
715
716 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec)
717 {
718     JSValue thisValue = exec->hostThisValue();
719     if (!thisValue.inherits(DateInstance::info()))
720         return throwVMTypeError(exec);
721
722     DateInstance* thisDateObj = asDateInstance(thisValue); 
723
724     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
725     if (!gregorianDateTime)
726         return JSValue::encode(jsNaN());
727     return JSValue::encode(jsNumber(gregorianDateTime->weekDay()));
728 }
729
730 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec)
731 {
732     JSValue thisValue = exec->hostThisValue();
733     if (!thisValue.inherits(DateInstance::info()))
734         return throwVMTypeError(exec);
735
736     DateInstance* thisDateObj = asDateInstance(thisValue); 
737
738     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
739     if (!gregorianDateTime)
740         return JSValue::encode(jsNaN());
741     return JSValue::encode(jsNumber(gregorianDateTime->weekDay()));
742 }
743
744 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec)
745 {
746     JSValue thisValue = exec->hostThisValue();
747     if (!thisValue.inherits(DateInstance::info()))
748         return throwVMTypeError(exec);
749
750     DateInstance* thisDateObj = asDateInstance(thisValue); 
751
752     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
753     if (!gregorianDateTime)
754         return JSValue::encode(jsNaN());
755     return JSValue::encode(jsNumber(gregorianDateTime->hour()));
756 }
757
758 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec)
759 {
760     JSValue thisValue = exec->hostThisValue();
761     if (!thisValue.inherits(DateInstance::info()))
762         return throwVMTypeError(exec);
763
764     DateInstance* thisDateObj = asDateInstance(thisValue); 
765
766     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
767     if (!gregorianDateTime)
768         return JSValue::encode(jsNaN());
769     return JSValue::encode(jsNumber(gregorianDateTime->hour()));
770 }
771
772 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec)
773 {
774     JSValue thisValue = exec->hostThisValue();
775     if (!thisValue.inherits(DateInstance::info()))
776         return throwVMTypeError(exec);
777
778     DateInstance* thisDateObj = asDateInstance(thisValue); 
779
780     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
781     if (!gregorianDateTime)
782         return JSValue::encode(jsNaN());
783     return JSValue::encode(jsNumber(gregorianDateTime->minute()));
784 }
785
786 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec)
787 {
788     JSValue thisValue = exec->hostThisValue();
789     if (!thisValue.inherits(DateInstance::info()))
790         return throwVMTypeError(exec);
791
792     DateInstance* thisDateObj = asDateInstance(thisValue); 
793
794     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
795     if (!gregorianDateTime)
796         return JSValue::encode(jsNaN());
797     return JSValue::encode(jsNumber(gregorianDateTime->minute()));
798 }
799
800 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec)
801 {
802     JSValue thisValue = exec->hostThisValue();
803     if (!thisValue.inherits(DateInstance::info()))
804         return throwVMTypeError(exec);
805
806     DateInstance* thisDateObj = asDateInstance(thisValue); 
807
808     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
809     if (!gregorianDateTime)
810         return JSValue::encode(jsNaN());
811     return JSValue::encode(jsNumber(gregorianDateTime->second()));
812 }
813
814 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec)
815 {
816     JSValue thisValue = exec->hostThisValue();
817     if (!thisValue.inherits(DateInstance::info()))
818         return throwVMTypeError(exec);
819
820     DateInstance* thisDateObj = asDateInstance(thisValue); 
821
822     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
823     if (!gregorianDateTime)
824         return JSValue::encode(jsNaN());
825     return JSValue::encode(jsNumber(gregorianDateTime->second()));
826 }
827
828 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec)
829 {
830     JSValue thisValue = exec->hostThisValue();
831     if (!thisValue.inherits(DateInstance::info()))
832         return throwVMTypeError(exec);
833
834     DateInstance* thisDateObj = asDateInstance(thisValue); 
835     double milli = thisDateObj->internalNumber();
836     if (std::isnan(milli))
837         return JSValue::encode(jsNaN());
838
839     double secs = floor(milli / msPerSecond);
840     double ms = milli - secs * msPerSecond;
841     return JSValue::encode(jsNumber(ms));
842 }
843
844 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec)
845 {
846     JSValue thisValue = exec->hostThisValue();
847     if (!thisValue.inherits(DateInstance::info()))
848         return throwVMTypeError(exec);
849
850     DateInstance* thisDateObj = asDateInstance(thisValue); 
851     double milli = thisDateObj->internalNumber();
852     if (std::isnan(milli))
853         return JSValue::encode(jsNaN());
854
855     double secs = floor(milli / msPerSecond);
856     double ms = milli - secs * msPerSecond;
857     return JSValue::encode(jsNumber(ms));
858 }
859
860 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec)
861 {
862     JSValue thisValue = exec->hostThisValue();
863     if (!thisValue.inherits(DateInstance::info()))
864         return throwVMTypeError(exec);
865
866     DateInstance* thisDateObj = asDateInstance(thisValue); 
867
868     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
869     if (!gregorianDateTime)
870         return JSValue::encode(jsNaN());
871     return JSValue::encode(jsNumber(-gregorianDateTime->utcOffset() / minutesPerHour));
872 }
873
874 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec)
875 {
876     JSValue thisValue = exec->hostThisValue();
877     if (!thisValue.inherits(DateInstance::info()))
878         return throwVMTypeError(exec);
879
880     DateInstance* thisDateObj = asDateInstance(thisValue); 
881
882     double milli = timeClip(exec->argument(0).toNumber(exec));
883     JSValue result = jsNumber(milli);
884     thisDateObj->setInternalValue(exec->vm(), result);
885     return JSValue::encode(result);
886 }
887
888 static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse, bool inputIsUTC)
889 {
890     JSValue thisValue = exec->hostThisValue();
891     if (!thisValue.inherits(DateInstance::info()))
892         return throwVMTypeError(exec);
893
894     DateInstance* thisDateObj = asDateInstance(thisValue);
895     double milli = thisDateObj->internalNumber();
896     
897     if (!exec->argumentCount() || std::isnan(milli)) {
898         JSValue result = jsNaN();
899         thisDateObj->setInternalValue(exec->vm(), result);
900         return JSValue::encode(result);
901     }
902      
903     double secs = floor(milli / msPerSecond);
904     double ms = milli - secs * msPerSecond;
905
906     const GregorianDateTime* other = inputIsUTC 
907         ? thisDateObj->gregorianDateTimeUTC(exec)
908         : thisDateObj->gregorianDateTime(exec);
909     if (!other)
910         return JSValue::encode(jsNaN());
911
912     GregorianDateTime gregorianDateTime;
913     gregorianDateTime.copyFrom(*other);
914     if (!fillStructuresUsingTimeArgs(exec, numArgsToUse, &ms, &gregorianDateTime)) {
915         JSValue result = jsNaN();
916         thisDateObj->setInternalValue(exec->vm(), result);
917         return JSValue::encode(result);
918     } 
919     
920     JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC));
921     thisDateObj->setInternalValue(exec->vm(), result);
922     return JSValue::encode(result);
923 }
924
925 static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse, bool inputIsUTC)
926 {
927     JSValue thisValue = exec->hostThisValue();
928     if (!thisValue.inherits(DateInstance::info()))
929         return throwVMTypeError(exec);
930
931     DateInstance* thisDateObj = asDateInstance(thisValue);
932     if (!exec->argumentCount()) {
933         JSValue result = jsNaN();
934         thisDateObj->setInternalValue(exec->vm(), result);
935         return JSValue::encode(result);
936     }      
937     
938     double milli = thisDateObj->internalNumber();
939     double ms = 0; 
940
941     GregorianDateTime gregorianDateTime; 
942     if (numArgsToUse == 3 && std::isnan(milli)) 
943         msToGregorianDateTime(exec, 0, true, gregorianDateTime); 
944     else { 
945         ms = milli - floor(milli / msPerSecond) * msPerSecond; 
946         const GregorianDateTime* other = inputIsUTC 
947             ? thisDateObj->gregorianDateTimeUTC(exec)
948             : thisDateObj->gregorianDateTime(exec);
949         if (!other)
950             return JSValue::encode(jsNaN());
951         gregorianDateTime.copyFrom(*other);
952     }
953     
954     if (!fillStructuresUsingDateArgs(exec, numArgsToUse, &ms, &gregorianDateTime)) {
955         JSValue result = jsNaN();
956         thisDateObj->setInternalValue(exec->vm(), result);
957         return JSValue::encode(result);
958     } 
959            
960     JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC));
961     thisDateObj->setInternalValue(exec->vm(), result);
962     return JSValue::encode(result);
963 }
964
965 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState* exec)
966 {
967     const bool inputIsUTC = false;
968     return setNewValueFromTimeArgs(exec, 1, inputIsUTC);
969 }
970
971 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState* exec)
972 {
973     const bool inputIsUTC = true;
974     return setNewValueFromTimeArgs(exec, 1, inputIsUTC);
975 }
976
977 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState* exec)
978 {
979     const bool inputIsUTC = false;
980     return setNewValueFromTimeArgs(exec, 2, inputIsUTC);
981 }
982
983 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState* exec)
984 {
985     const bool inputIsUTC = true;
986     return setNewValueFromTimeArgs(exec, 2, inputIsUTC);
987 }
988
989 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState* exec)
990 {
991     const bool inputIsUTC = false;
992     return setNewValueFromTimeArgs(exec, 3, inputIsUTC);
993 }
994
995 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState* exec)
996 {
997     const bool inputIsUTC = true;
998     return setNewValueFromTimeArgs(exec, 3, inputIsUTC);
999 }
1000
1001 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState* exec)
1002 {
1003     const bool inputIsUTC = false;
1004     return setNewValueFromTimeArgs(exec, 4, inputIsUTC);
1005 }
1006
1007 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState* exec)
1008 {
1009     const bool inputIsUTC = true;
1010     return setNewValueFromTimeArgs(exec, 4, inputIsUTC);
1011 }
1012
1013 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState* exec)
1014 {
1015     const bool inputIsUTC = false;
1016     return setNewValueFromDateArgs(exec, 1, inputIsUTC);
1017 }
1018
1019 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState* exec)
1020 {
1021     const bool inputIsUTC = true;
1022     return setNewValueFromDateArgs(exec, 1, inputIsUTC);
1023 }
1024
1025 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState* exec)
1026 {
1027     const bool inputIsUTC = false;
1028     return setNewValueFromDateArgs(exec, 2, inputIsUTC);
1029 }
1030
1031 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState* exec)
1032 {
1033     const bool inputIsUTC = true;
1034     return setNewValueFromDateArgs(exec, 2, inputIsUTC);
1035 }
1036
1037 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState* exec)
1038 {
1039     const bool inputIsUTC = false;
1040     return setNewValueFromDateArgs(exec, 3, inputIsUTC);
1041 }
1042
1043 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState* exec)
1044 {
1045     const bool inputIsUTC = true;
1046     return setNewValueFromDateArgs(exec, 3, inputIsUTC);
1047 }
1048
1049 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
1050 {
1051     JSValue thisValue = exec->hostThisValue();
1052     if (!thisValue.inherits(DateInstance::info()))
1053         return throwVMTypeError(exec);
1054
1055     DateInstance* thisDateObj = asDateInstance(thisValue);
1056     if (!exec->argumentCount()) { 
1057         JSValue result = jsNaN();
1058         thisDateObj->setInternalValue(exec->vm(), result);
1059         return JSValue::encode(result);
1060     }
1061
1062     double milli = thisDateObj->internalNumber();
1063     double ms = 0;
1064
1065     GregorianDateTime gregorianDateTime;
1066     if (std::isnan(milli))
1067         // Based on ECMA 262 B.2.5 (setYear)
1068         // the time must be reset to +0 if it is NaN.
1069         msToGregorianDateTime(exec, 0, true, gregorianDateTime);
1070     else {
1071         double secs = floor(milli / msPerSecond);
1072         ms = milli - secs * msPerSecond;
1073         if (const GregorianDateTime* other = thisDateObj->gregorianDateTime(exec))
1074             gregorianDateTime.copyFrom(*other);
1075     }
1076
1077     double year = exec->argument(0).toIntegerPreserveNaN(exec);
1078     if (!std::isfinite(year)) {
1079         JSValue result = jsNaN();
1080         thisDateObj->setInternalValue(exec->vm(), result);
1081         return JSValue::encode(result);
1082     }
1083
1084     gregorianDateTime.setYear(toInt32((year >= 0 && year <= 99) ? (year + 1900) : year));
1085     JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, false));
1086     thisDateObj->setInternalValue(exec->vm(), result);
1087     return JSValue::encode(result);
1088 }
1089
1090 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec)
1091 {
1092     JSValue thisValue = exec->hostThisValue();
1093     if (!thisValue.inherits(DateInstance::info()))
1094         return throwVMTypeError(exec);
1095
1096     DateInstance* thisDateObj = asDateInstance(thisValue); 
1097
1098     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
1099     if (!gregorianDateTime)
1100         return JSValue::encode(jsNaN());
1101
1102     // NOTE: IE returns the full year even in getYear.
1103     return JSValue::encode(jsNumber(gregorianDateTime->year() - 1900));
1104 }
1105
1106 EncodedJSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec)
1107 {
1108     JSValue thisValue = exec->hostThisValue();
1109     JSObject* object = jsCast<JSObject*>(thisValue.toThis(exec, NotStrictMode));
1110     if (exec->hadException())
1111         return JSValue::encode(jsNull());
1112     
1113     JSValue toISOValue = object->get(exec, exec->vm().propertyNames->toISOString);
1114     if (exec->hadException())
1115         return JSValue::encode(jsNull());
1116
1117     CallData callData;
1118     CallType callType = getCallData(toISOValue, callData);
1119     if (callType == CallTypeNone)
1120         return throwVMError(exec, createTypeError(exec, ASCIILiteral("toISOString is not a function")));
1121
1122     JSValue result = call(exec, asObject(toISOValue), callType, callData, object, exec->emptyList());
1123     if (exec->hadException())
1124         return JSValue::encode(jsNull());
1125     if (result.isObject())
1126         return throwVMError(exec, createTypeError(exec, ASCIILiteral("toISOString did not return a primitive value")));
1127     return JSValue::encode(result);
1128 }
1129
1130 } // namespace JSC