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