summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/runtime/DatePrototype.cpp
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
commit1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch)
tree4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /JavaScriptCore/runtime/DatePrototype.cpp
parent9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff)
downloadexternal_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.zip
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.gz
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'JavaScriptCore/runtime/DatePrototype.cpp')
-rw-r--r--JavaScriptCore/runtime/DatePrototype.cpp1056
1 files changed, 1056 insertions, 0 deletions
diff --git a/JavaScriptCore/runtime/DatePrototype.cpp b/JavaScriptCore/runtime/DatePrototype.cpp
new file mode 100644
index 0000000..a3e792e
--- /dev/null
+++ b/JavaScriptCore/runtime/DatePrototype.cpp
@@ -0,0 +1,1056 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "DatePrototype.h"
+
+#include "DateMath.h"
+#include "JSString.h"
+#include "ObjectPrototype.h"
+#include "DateInstance.h"
+#include <float.h>
+#include <limits.h>
+#include <locale.h>
+#include <math.h>
+#include <time.h>
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+#include <wtf/StringExtras.h>
+#include <wtf/UnusedParam.h>
+
+#if HAVE(SYS_PARAM_H)
+#include <sys/param.h>
+#endif
+
+#if HAVE(SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#if HAVE(SYS_TIMEB_H)
+#include <sys/timeb.h>
+#endif
+
+#if PLATFORM(MAC)
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+using namespace WTF;
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(DatePrototype);
+
+static JSValue* dateProtoFuncGetDate(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetDay(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetFullYear(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetHours(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetMilliSeconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetMinutes(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetMonth(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetSeconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetTime(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetTimezoneOffset(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCDate(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCDay(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCFullYear(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCHours(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCMilliseconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCMinutes(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCMonth(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCSeconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetYear(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetDate(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetFullYear(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetHours(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetMilliSeconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetMinutes(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetMonth(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetSeconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetTime(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetUTCDate(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetUTCFullYear(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetUTCHours(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetUTCMilliseconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetUTCMinutes(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetUTCMonth(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetUTCSeconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetYear(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToDateString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToGMTString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToLocaleDateString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToLocaleString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToLocaleTimeString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToTimeString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToUTCString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncValueOf(ExecState*, JSObject*, JSValue*, const ArgList&);
+
+}
+
+#include "DatePrototype.lut.h"
+
+namespace JSC {
+
+#if PLATFORM(MAC)
+
+static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateFormatterStyle defaultStyle)
+{
+ if (string == "short")
+ return kCFDateFormatterShortStyle;
+ if (string == "medium")
+ return kCFDateFormatterMediumStyle;
+ if (string == "long")
+ return kCFDateFormatterLongStyle;
+ if (string == "full")
+ return kCFDateFormatterFullStyle;
+ return defaultStyle;
+}
+
+static UString formatLocaleDate(ExecState* exec, double time, bool includeDate, bool includeTime, const ArgList& args)
+{
+ CFDateFormatterStyle dateStyle = (includeDate ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
+ CFDateFormatterStyle timeStyle = (includeTime ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
+
+ bool useCustomFormat = false;
+ UString customFormatString;
+
+ UString arg0String = args.at(exec, 0)->toString(exec);
+ if (arg0String == "custom" && !args.at(exec, 1)->isUndefined()) {
+ useCustomFormat = true;
+ customFormatString = args.at(exec, 1)->toString(exec);
+ } else if (includeDate && includeTime && !args.at(exec, 1)->isUndefined()) {
+ dateStyle = styleFromArgString(arg0String, dateStyle);
+ timeStyle = styleFromArgString(args.at(exec, 1)->toString(exec), timeStyle);
+ } else if (includeDate && !args.at(exec, 0)->isUndefined())
+ dateStyle = styleFromArgString(arg0String, dateStyle);
+ else if (includeTime && !args.at(exec, 0)->isUndefined())
+ timeStyle = styleFromArgString(arg0String, timeStyle);
+
+ CFLocaleRef locale = CFLocaleCopyCurrent();
+ CFDateFormatterRef formatter = CFDateFormatterCreate(0, locale, dateStyle, timeStyle);
+ CFRelease(locale);
+
+ if (useCustomFormat) {
+ CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, (UniChar *)customFormatString.data(), customFormatString.size());
+ CFDateFormatterSetFormat(formatter, customFormatCFString);
+ CFRelease(customFormatCFString);
+ }
+
+ CFStringRef string = CFDateFormatterCreateStringWithAbsoluteTime(0, formatter, time - kCFAbsoluteTimeIntervalSince1970);
+
+ CFRelease(formatter);
+
+ // We truncate the string returned from CFDateFormatter if it's absurdly long (> 200 characters).
+ // That's not great error handling, but it just won't happen so it doesn't matter.
+ UChar buffer[200];
+ const size_t bufferLength = sizeof(buffer) / sizeof(buffer[0]);
+ size_t length = CFStringGetLength(string);
+ ASSERT(length <= bufferLength);
+ if (length > bufferLength)
+ length = bufferLength;
+ CFStringGetCharacters(string, CFRangeMake(0, length), reinterpret_cast<UniChar *>(buffer));
+
+ CFRelease(string);
+
+ return UString(buffer, length);
+}
+
+#else
+
+enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
+
+static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, const LocaleDateTimeFormat format)
+{
+ static const char* formatStrings[] = {"%#c", "%#x", "%X"};
+
+ // Offset year if needed
+ struct tm localTM = gdt;
+ int year = gdt.year + 1900;
+ bool yearNeedsOffset = year < 1900 || year > 2038;
+ if (yearNeedsOffset)
+ localTM.tm_year = equivalentYearForDST(year) - 1900;
+
+ // Do the formatting
+ const int bufsize = 128;
+ char timebuffer[bufsize];
+ size_t ret = strftime(timebuffer, bufsize, formatStrings[format], &localTM);
+
+ if (ret == 0)
+ return jsEmptyString(exec);
+
+ // Copy original into the buffer
+ if (yearNeedsOffset && format != LocaleTime) {
+ static const int yearLen = 5; // FIXME will be a problem in the year 10,000
+ char yearString[yearLen];
+
+ snprintf(yearString, yearLen, "%d", localTM.tm_year + 1900);
+ char* yearLocation = strstr(timebuffer, yearString);
+ snprintf(yearString, yearLen, "%d", year);
+
+ strncpy(yearLocation, yearString, yearLen - 1);
+ }
+
+ return jsNontrivialString(exec, timebuffer);
+}
+
+#endif // PLATFORM(WIN_OS)
+
+// Converts a list of arguments sent to a Date member function into milliseconds, updating
+// ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
+//
+// Format of member function: f([hour,] [min,] [sec,] [ms])
+static bool fillStructuresUsingTimeArgs(ExecState* exec, const ArgList& args, int maxArgs, double* ms, GregorianDateTime* t)
+{
+ double milliseconds = 0;
+ bool ok = true;
+ int idx = 0;
+ int numArgs = args.size();
+
+ // JS allows extra trailing arguments -- ignore them
+ if (numArgs > maxArgs)
+ numArgs = maxArgs;
+
+ // hours
+ if (maxArgs >= 4 && idx < numArgs) {
+ t->hour = 0;
+ milliseconds += args.at(exec, idx++)->toInt32(exec, ok) * msPerHour;
+ }
+
+ // minutes
+ if (maxArgs >= 3 && idx < numArgs && ok) {
+ t->minute = 0;
+ milliseconds += args.at(exec, idx++)->toInt32(exec, ok) * msPerMinute;
+ }
+
+ // seconds
+ if (maxArgs >= 2 && idx < numArgs && ok) {
+ t->second = 0;
+ milliseconds += args.at(exec, idx++)->toInt32(exec, ok) * msPerSecond;
+ }
+
+ if (!ok)
+ return false;
+
+ // milliseconds
+ if (idx < numArgs) {
+ double millis = args.at(exec, idx)->toNumber(exec);
+ ok = isfinite(millis);
+ milliseconds += millis;
+ } else
+ milliseconds += *ms;
+
+ *ms = milliseconds;
+ return ok;
+}
+
+// Converts a list of arguments sent to a Date member function into years, months, and milliseconds, updating
+// ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
+//
+// Format of member function: f([years,] [months,] [days])
+static bool fillStructuresUsingDateArgs(ExecState *exec, const ArgList& args, int maxArgs, double *ms, GregorianDateTime *t)
+{
+ int idx = 0;
+ bool ok = true;
+ int numArgs = args.size();
+
+ // JS allows extra trailing arguments -- ignore them
+ if (numArgs > maxArgs)
+ numArgs = maxArgs;
+
+ // years
+ if (maxArgs >= 3 && idx < numArgs)
+ t->year = args.at(exec, idx++)->toInt32(exec, ok) - 1900;
+
+ // months
+ if (maxArgs >= 2 && idx < numArgs && ok)
+ t->month = args.at(exec, idx++)->toInt32(exec, ok);
+
+ // days
+ if (idx < numArgs && ok) {
+ t->monthDay = 0;
+ *ms += args.at(exec, idx)->toInt32(exec, ok) * msPerDay;
+ }
+
+ return ok;
+}
+
+const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState::dateTable};
+
+/* Source for DatePrototype.lut.h
+ FIXME: We could use templates to simplify the UTC variants.
+@begin dateTable
+ toString dateProtoFuncToString DontEnum|Function 0
+ toUTCString dateProtoFuncToUTCString DontEnum|Function 0
+ toDateString dateProtoFuncToDateString DontEnum|Function 0
+ toTimeString dateProtoFuncToTimeString DontEnum|Function 0
+ toLocaleString dateProtoFuncToLocaleString DontEnum|Function 0
+ toLocaleDateString dateProtoFuncToLocaleDateString DontEnum|Function 0
+ toLocaleTimeString dateProtoFuncToLocaleTimeString DontEnum|Function 0
+ valueOf dateProtoFuncValueOf DontEnum|Function 0
+ getTime dateProtoFuncGetTime DontEnum|Function 0
+ getFullYear dateProtoFuncGetFullYear DontEnum|Function 0
+ getUTCFullYear dateProtoFuncGetUTCFullYear DontEnum|Function 0
+ toGMTString dateProtoFuncToGMTString DontEnum|Function 0
+ getMonth dateProtoFuncGetMonth DontEnum|Function 0
+ getUTCMonth dateProtoFuncGetUTCMonth DontEnum|Function 0
+ getDate dateProtoFuncGetDate DontEnum|Function 0
+ getUTCDate dateProtoFuncGetUTCDate DontEnum|Function 0
+ getDay dateProtoFuncGetDay DontEnum|Function 0
+ getUTCDay dateProtoFuncGetUTCDay DontEnum|Function 0
+ getHours dateProtoFuncGetHours DontEnum|Function 0
+ getUTCHours dateProtoFuncGetUTCHours DontEnum|Function 0
+ getMinutes dateProtoFuncGetMinutes DontEnum|Function 0
+ getUTCMinutes dateProtoFuncGetUTCMinutes DontEnum|Function 0
+ getSeconds dateProtoFuncGetSeconds DontEnum|Function 0
+ getUTCSeconds dateProtoFuncGetUTCSeconds DontEnum|Function 0
+ getMilliseconds dateProtoFuncGetMilliSeconds DontEnum|Function 0
+ getUTCMilliseconds dateProtoFuncGetUTCMilliseconds DontEnum|Function 0
+ getTimezoneOffset dateProtoFuncGetTimezoneOffset DontEnum|Function 0
+ setTime dateProtoFuncSetTime DontEnum|Function 1
+ setMilliseconds dateProtoFuncSetMilliSeconds DontEnum|Function 1
+ setUTCMilliseconds dateProtoFuncSetUTCMilliseconds DontEnum|Function 1
+ setSeconds dateProtoFuncSetSeconds DontEnum|Function 2
+ setUTCSeconds dateProtoFuncSetUTCSeconds DontEnum|Function 2
+ setMinutes dateProtoFuncSetMinutes DontEnum|Function 3
+ setUTCMinutes dateProtoFuncSetUTCMinutes DontEnum|Function 3
+ setHours dateProtoFuncSetHours DontEnum|Function 4
+ setUTCHours dateProtoFuncSetUTCHours DontEnum|Function 4
+ setDate dateProtoFuncSetDate DontEnum|Function 1
+ setUTCDate dateProtoFuncSetUTCDate DontEnum|Function 1
+ setMonth dateProtoFuncSetMonth DontEnum|Function 2
+ setUTCMonth dateProtoFuncSetUTCMonth DontEnum|Function 2
+ setFullYear dateProtoFuncSetFullYear DontEnum|Function 3
+ setUTCFullYear dateProtoFuncSetUTCFullYear DontEnum|Function 3
+ setYear dateProtoFuncSetYear DontEnum|Function 1
+ getYear dateProtoFuncGetYear DontEnum|Function 0
+@end
+*/
+// ECMA 15.9.4
+
+DatePrototype::DatePrototype(ExecState* exec, PassRefPtr<StructureID> structure)
+ : DateInstance(structure)
+{
+ setInternalValue(jsNaN(exec));
+ // The constructor will be added later, after DateConstructor has been built.
+}
+
+bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return getStaticFunctionSlot<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, slot);
+}
+
+// Functions
+
+JSValue* dateProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatDate(t) + " " + formatTime(t, utc));
+}
+
+JSValue* dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
+}
+
+JSValue* dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatDate(t));
+}
+
+JSValue* dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatTime(t, utc));
+}
+
+JSValue* dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+#if PLATFORM(MAC)
+ double secs = floor(milli / msPerSecond);
+ return jsNontrivialString(exec, formatLocaleDate(exec, secs, true, true, args));
+#else
+ UNUSED_PARAM(args);
+
+ const bool utc = false;
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return formatLocaleDate(exec, t, LocaleDateAndTime);
+#endif
+}
+
+JSValue* dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+#if PLATFORM(MAC)
+ double secs = floor(milli / msPerSecond);
+ return jsNontrivialString(exec, formatLocaleDate(exec, secs, true, false, args));
+#else
+ UNUSED_PARAM(args);
+
+ const bool utc = false;
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return formatLocaleDate(exec, t, LocaleDate);
+#endif
+}
+
+JSValue* dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+#if PLATFORM(MAC)
+ double secs = floor(milli / msPerSecond);
+ return jsNontrivialString(exec, formatLocaleDate(exec, secs, false, true, args));
+#else
+ UNUSED_PARAM(args);
+
+ const bool utc = false;
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return formatLocaleDate(exec, t, LocaleTime);
+#endif
+}
+
+JSValue* dateProtoFuncValueOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ return jsNumber(exec, milli);
+}
+
+JSValue* dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ return jsNumber(exec, milli);
+}
+
+JSValue* dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, 1900 + t.year);
+}
+
+JSValue* dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, 1900 + t.year);
+}
+
+JSValue* dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
+}
+
+JSValue* dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.month);
+}
+
+JSValue* dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.month);
+}
+
+JSValue* dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.monthDay);
+}
+
+JSValue* dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.monthDay);
+}
+
+JSValue* dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.weekDay);
+}
+
+JSValue* dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.weekDay);
+}
+
+JSValue* dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.hour);
+}
+
+JSValue* dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.hour);
+}
+
+JSValue* dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.minute);
+}
+
+JSValue* dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.minute);
+}
+
+JSValue* dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.second);
+}
+
+JSValue* dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.second);
+}
+
+JSValue* dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ double secs = floor(milli / msPerSecond);
+ double ms = milli - secs * msPerSecond;
+ return jsNumber(exec, ms);
+}
+
+JSValue* dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ double secs = floor(milli / msPerSecond);
+ double ms = milli - secs * msPerSecond;
+ return jsNumber(exec, ms);
+}
+
+JSValue* dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, -gmtoffset(t) / minutesPerHour);
+}
+
+JSValue* dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+
+ double milli = timeClip(args.at(exec, 0)->toNumber(exec));
+ JSValue* result = jsNumber(exec, milli);
+ thisDateObj->setInternalValue(result);
+ return result;
+}
+
+static JSValue* setNewValueFromTimeArgs(ExecState* exec, JSValue* thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+
+ if (args.isEmpty() || isnan(milli)) {
+ JSValue* result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ double secs = floor(milli / msPerSecond);
+ double ms = milli - secs * msPerSecond;
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
+
+ if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t)) {
+ JSValue* result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ JSValue* result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
+ thisDateObj->setInternalValue(result);
+ return result;
+}
+
+static JSValue* setNewValueFromDateArgs(ExecState* exec, JSValue* thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ if (args.isEmpty()) {
+ JSValue* result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ double milli = thisDateObj->internalNumber();
+ double ms = 0;
+
+ GregorianDateTime t;
+ if (numArgsToUse == 3 && isnan(milli))
+ // Based on ECMA 262 15.9.5.40 - .41 (set[UTC]FullYear)
+ // the time must be reset to +0 if it is NaN.
+ thisDateObj->msToGregorianDateTime(0, true, t);
+ else {
+ double secs = floor(milli / msPerSecond);
+ ms = milli - secs * msPerSecond;
+ thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
+ }
+
+ if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t)) {
+ JSValue* result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ JSValue* result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
+ thisDateObj->setInternalValue(result);
+ return result;
+}
+
+JSValue* dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetUTCMilliseconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetUTCSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetMinutes(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetUTCMinutes(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetHours(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetUTCHours(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetDate(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetUTCDate(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetMonth(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetUTCMonth(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetFullYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ if (args.isEmpty()) {
+ JSValue* result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ double milli = thisDateObj->internalNumber();
+ double ms = 0;
+
+ GregorianDateTime t;
+ if (isnan(milli))
+ // Based on ECMA 262 B.2.5 (setYear)
+ // the time must be reset to +0 if it is NaN.
+ thisDateObj->msToGregorianDateTime(0, true, t);
+ else {
+ double secs = floor(milli / msPerSecond);
+ ms = milli - secs * msPerSecond;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ }
+
+ bool ok = true;
+ int32_t year = args.at(exec, 0)->toInt32(exec, ok);
+ if (!ok) {
+ JSValue* result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ t.year = (year > 99 || year < 0) ? year - 1900 : year;
+ JSValue* result = jsNumber(exec, gregorianDateTimeToMS(t, ms, utc));
+ thisDateObj->setInternalValue(result);
+ return result;
+}
+
+JSValue* dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+
+ // NOTE: IE returns the full year even in getYear.
+ return jsNumber(exec, t.year);
+}
+
+} // namespace JSC