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