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