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