1 /* 2 * Copyright (C) 1999-2000 Harri Porten (porten (at) 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 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 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 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 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]) 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]) 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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