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) |
63 | extern "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 | |
66 | using namespace WTF; |
67 | |
68 | namespace JSC { |
69 | |
70 | ASSERT_CLASS_FITS_IN_CELL(DatePrototype); |
71 | |
72 | static JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState*, JSObject*, JSValue, const ArgList&); |
73 | static JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState*, JSObject*, JSValue, const ArgList&); |
74 | static JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState*, JSObject*, JSValue, const ArgList&); |
75 | static JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState*, JSObject*, JSValue, const ArgList&); |
76 | static JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState*, JSObject*, JSValue, const ArgList&); |
77 | static JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState*, JSObject*, JSValue, const ArgList&); |
78 | static JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState*, JSObject*, JSValue, const ArgList&); |
79 | static JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState*, JSObject*, JSValue, const ArgList&); |
80 | static JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState*, JSObject*, JSValue, const ArgList&); |
81 | static JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState*, JSObject*, JSValue, const ArgList&); |
82 | static JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState*, JSObject*, JSValue, const ArgList&); |
83 | static JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState*, JSObject*, JSValue, const ArgList&); |
84 | static JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState*, JSObject*, JSValue, const ArgList&); |
85 | static JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState*, JSObject*, JSValue, const ArgList&); |
86 | static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState*, JSObject*, JSValue, const ArgList&); |
87 | static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState*, JSObject*, JSValue, const ArgList&); |
88 | static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState*, JSObject*, JSValue, const ArgList&); |
89 | static JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState*, JSObject*, JSValue, const ArgList&); |
90 | static JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState*, JSObject*, JSValue, const ArgList&); |
91 | static JSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState*, JSObject*, JSValue, const ArgList&); |
92 | static JSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState*, JSObject*, JSValue, const ArgList&); |
93 | static JSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState*, JSObject*, JSValue, const ArgList&); |
94 | static JSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState*, JSObject*, JSValue, const ArgList&); |
95 | static JSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState*, JSObject*, JSValue, const ArgList&); |
96 | static JSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState*, JSObject*, JSValue, const ArgList&); |
97 | static JSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState*, JSObject*, JSValue, const ArgList&); |
98 | static JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState*, JSObject*, JSValue, const ArgList&); |
99 | static JSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState*, JSObject*, JSValue, const ArgList&); |
100 | static JSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState*, JSObject*, JSValue, const ArgList&); |
101 | static JSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState*, JSObject*, JSValue, const ArgList&); |
102 | static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState*, JSObject*, JSValue, const ArgList&); |
103 | static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState*, JSObject*, JSValue, const ArgList&); |
104 | static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState*, JSObject*, JSValue, const ArgList&); |
105 | static JSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState*, JSObject*, JSValue, const ArgList&); |
106 | static JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState*, JSObject*, JSValue, const ArgList&); |
107 | static JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState*, JSObject*, JSValue, const ArgList&); |
108 | static JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState*, JSObject*, JSValue, const ArgList&); |
109 | static JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState*, JSObject*, JSValue, const ArgList&); |
110 | static JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&); |
111 | static JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState*, JSObject*, JSValue, const ArgList&); |
112 | static JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&); |
113 | static JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState*, JSObject*, JSValue, const ArgList&); |
114 | static JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState*, JSObject*, JSValue, const ArgList&); |
115 | static JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState*, JSObject*, JSValue, const ArgList&); |
116 | |
117 | static JSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState*, JSObject*, JSValue, const ArgList&); |
118 | |
119 | } |
120 | |
121 | #include "DatePrototype.lut.h" |
122 | |
123 | namespace JSC { |
124 | |
125 | enum 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 | |
132 | static 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 | |
145 | static 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 | |
196 | static 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 | |
253 | static 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]) |
267 | static 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]) |
315 | static 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 | |
342 | const 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 | |
397 | DatePrototype::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 | |
403 | bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) |
404 | { |
405 | return getStaticFunctionSlot<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, slot); |
406 | } |
407 | |
408 | |
409 | bool 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 | |
416 | JSValue 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 | |
433 | JSValue 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 | |
450 | JSValue 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 | |
468 | JSValue 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 | |
483 | JSValue 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 | |
498 | JSValue 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 | |
507 | JSValue 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 | |
516 | JSValue 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 | |
525 | JSValue 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 | |
533 | JSValue 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 | |
546 | JSValue 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 | |
559 | JSValue 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 | |
576 | JSValue 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 | |
589 | JSValue 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 | |
602 | JSValue 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 | |
615 | JSValue 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 | |
628 | JSValue 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 | |
641 | JSValue 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 | |
654 | JSValue 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 | |
667 | JSValue 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 | |
680 | JSValue 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 | |
693 | JSValue 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 | |
706 | JSValue 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 | |
719 | JSValue 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 | |
732 | JSValue 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 | |
747 | JSValue 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 | |
762 | JSValue 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 | |
775 | JSValue 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 | |
788 | static 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 | |
824 | static 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 | |
863 | JSValue 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 | |
869 | JSValue 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 | |
875 | JSValue 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 | |
881 | JSValue 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 | |
887 | JSValue 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 | |
893 | JSValue 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 | |
899 | JSValue 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 | |
905 | JSValue 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 | |
911 | JSValue 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 | |
917 | JSValue 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 | |
923 | JSValue 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 | |
929 | JSValue 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 | |
935 | JSValue 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 | |
941 | JSValue 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 | |
947 | JSValue 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 | |
988 | JSValue 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 | |
1003 | JSValue 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 | |