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