/src/3rdparty/webkit/Source/JavaScriptCore/runtime/DatePrototype.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 1096 lines · 792 code · 187 blank · 117 comment · 141 complexity · bd36c3d4db9d4c48fe1d9a817dcb59cd MD5 · raw file

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