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