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