From: Carlos Garcia Campos Date: Fri, 6 Mar 2015 07:33:11 +0000 (+0000) Subject: String(new Date(Mar 30 2014 01:00:00)) is wrong in CET X-Git-Tag: archive/raspbian/2.14.3-1+rpi1~1^2^2^2~1 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=d1cc1ab35c80000c3517e21a08e0c32d04ad5991;p=webkit2gtk.git String(new Date(Mar 30 2014 01:00:00)) is wrong in CET =================================================================== Gbp-Pq: Name fix-date.patch --- diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp index 49a1c36955..a310d47181 100644 --- a/Source/JavaScriptCore/runtime/DateConstructor.cpp +++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp @@ -166,7 +166,7 @@ JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const Arg t.setSecond(JSC::toInt32(doubleArguments[5])); t.setIsDST(-1); double ms = (numArgs >= 7) ? doubleArguments[6] : 0; - value = gregorianDateTimeToMS(vm, t, ms, false); + value = gregorianDateTimeToMS(vm, t, ms, WTF::LocalTime); } } @@ -190,7 +190,7 @@ static EncodedJSValue JSC_HOST_CALL callDate(ExecState* exec) { VM& vm = exec->vm(); GregorianDateTime ts; - msToGregorianDateTime(vm, currentTimeMS(), false, ts); + msToGregorianDateTime(vm, currentTimeMS(), WTF::LocalTime, ts); return JSValue::encode(jsNontrivialString(&vm, formatDateTime(ts, DateTimeFormatDateAndTime, false))); } @@ -244,7 +244,7 @@ EncodedJSValue JSC_HOST_CALL dateUTC(ExecState* exec) t.setMinute(JSC::toInt32(doubleArguments[4])); t.setSecond(JSC::toInt32(doubleArguments[5])); double ms = (n >= 7) ? doubleArguments[6] : 0; - return JSValue::encode(jsNumber(timeClip(gregorianDateTimeToMS(exec->vm(), t, ms, true)))); + return JSValue::encode(jsNumber(timeClip(gregorianDateTimeToMS(exec->vm(), t, ms, WTF::UTCTime)))); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/DateInstance.cpp b/Source/JavaScriptCore/runtime/DateInstance.cpp index c1749f6fbd..e095f882c8 100644 --- a/Source/JavaScriptCore/runtime/DateInstance.cpp +++ b/Source/JavaScriptCore/runtime/DateInstance.cpp @@ -69,7 +69,7 @@ const GregorianDateTime* DateInstance::calculateGregorianDateTime(ExecState* exe m_data = vm.dateInstanceCache.add(milli); if (m_data->m_gregorianDateTimeCachedForMS != milli) { - msToGregorianDateTime(vm, milli, false, m_data->m_cachedGregorianDateTime); + msToGregorianDateTime(vm, milli, WTF::LocalTime, m_data->m_cachedGregorianDateTime); m_data->m_gregorianDateTimeCachedForMS = milli; } return &m_data->m_cachedGregorianDateTime; @@ -86,7 +86,7 @@ const GregorianDateTime* DateInstance::calculateGregorianDateTimeUTC(ExecState* m_data = vm.dateInstanceCache.add(milli); if (m_data->m_gregorianDateTimeUTCCachedForMS != milli) { - msToGregorianDateTime(vm, milli, true, m_data->m_cachedGregorianDateTimeUTC); + msToGregorianDateTime(vm, milli, WTF::UTCTime, m_data->m_cachedGregorianDateTimeUTC); m_data->m_gregorianDateTimeUTCCachedForMS = milli; } return &m_data->m_cachedGregorianDateTimeUTC; diff --git a/Source/JavaScriptCore/runtime/DatePrototype.cpp b/Source/JavaScriptCore/runtime/DatePrototype.cpp index 5eaf86af65..b9d8262f63 100644 --- a/Source/JavaScriptCore/runtime/DatePrototype.cpp +++ b/Source/JavaScriptCore/runtime/DatePrototype.cpp @@ -859,7 +859,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec) return JSValue::encode(result); } -static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse, bool inputIsUTC) +static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse, WTF::TimeType inputTimeType) { JSValue thisValue = exec->thisValue(); if (!thisValue.inherits(DateInstance::info())) @@ -878,7 +878,7 @@ static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse, double secs = floor(milli / msPerSecond); double ms = milli - secs * msPerSecond; - const GregorianDateTime* other = inputIsUTC + const GregorianDateTime* other = inputTimeType == WTF::UTCTime ? thisDateObj->gregorianDateTimeUTC(exec) : thisDateObj->gregorianDateTime(exec); if (!other) @@ -892,12 +892,12 @@ static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse, return JSValue::encode(result); } - JSValue result = jsNumber(gregorianDateTimeToMS(vm, gregorianDateTime, ms, inputIsUTC)); + JSValue result = jsNumber(gregorianDateTimeToMS(vm, gregorianDateTime, ms, inputTimeType)); thisDateObj->setInternalValue(vm, result); return JSValue::encode(result); } -static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse, bool inputIsUTC) +static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse, WTF::TimeType inputTimeType) { JSValue thisValue = exec->thisValue(); if (!thisValue.inherits(DateInstance::info())) @@ -916,10 +916,10 @@ static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse, GregorianDateTime gregorianDateTime; if (numArgsToUse == 3 && std::isnan(milli)) - msToGregorianDateTime(vm, 0, true, gregorianDateTime); + msToGregorianDateTime(vm, 0, WTF::UTCTime, gregorianDateTime); else { ms = milli - floor(milli / msPerSecond) * msPerSecond; - const GregorianDateTime* other = inputIsUTC + const GregorianDateTime* other = inputTimeType == WTF::UTCTime ? thisDateObj->gregorianDateTimeUTC(exec) : thisDateObj->gregorianDateTime(exec); if (!other) @@ -933,93 +933,93 @@ static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse, return JSValue::encode(result); } - JSValue result = jsNumber(gregorianDateTimeToMS(vm, gregorianDateTime, ms, inputIsUTC)); + JSValue result = jsNumber(gregorianDateTimeToMS(vm, gregorianDateTime, ms, inputTimeType)); thisDateObj->setInternalValue(vm, result); return JSValue::encode(result); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState* exec) { - const bool inputIsUTC = false; - return setNewValueFromTimeArgs(exec, 1, inputIsUTC); + const WTF::TimeType inputTimeType = WTF::LocalTime; + return setNewValueFromTimeArgs(exec, 1, inputTimeType); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState* exec) { - const bool inputIsUTC = true; - return setNewValueFromTimeArgs(exec, 1, inputIsUTC); + const WTF::TimeType inputTimeType = WTF::UTCTime; + return setNewValueFromTimeArgs(exec, 1, inputTimeType); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState* exec) { - const bool inputIsUTC = false; - return setNewValueFromTimeArgs(exec, 2, inputIsUTC); + const WTF::TimeType inputTimeType = WTF::LocalTime; + return setNewValueFromTimeArgs(exec, 2, inputTimeType); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState* exec) { - const bool inputIsUTC = true; - return setNewValueFromTimeArgs(exec, 2, inputIsUTC); + const WTF::TimeType inputTimeType = WTF::UTCTime; + return setNewValueFromTimeArgs(exec, 2, inputTimeType); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState* exec) { - const bool inputIsUTC = false; - return setNewValueFromTimeArgs(exec, 3, inputIsUTC); + const WTF::TimeType inputTimeType = WTF::LocalTime; + return setNewValueFromTimeArgs(exec, 3, inputTimeType); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState* exec) { - const bool inputIsUTC = true; - return setNewValueFromTimeArgs(exec, 3, inputIsUTC); + const WTF::TimeType inputTimeType = WTF::UTCTime; + return setNewValueFromTimeArgs(exec, 3, inputTimeType); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState* exec) { - const bool inputIsUTC = false; - return setNewValueFromTimeArgs(exec, 4, inputIsUTC); + const WTF::TimeType inputTimeType = WTF::LocalTime; + return setNewValueFromTimeArgs(exec, 4, inputTimeType); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState* exec) { - const bool inputIsUTC = true; - return setNewValueFromTimeArgs(exec, 4, inputIsUTC); + const WTF::TimeType inputTimeType = WTF::UTCTime; + return setNewValueFromTimeArgs(exec, 4, inputTimeType); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState* exec) { - const bool inputIsUTC = false; - return setNewValueFromDateArgs(exec, 1, inputIsUTC); + const WTF::TimeType inputTimeType = WTF::LocalTime; + return setNewValueFromDateArgs(exec, 1, inputTimeType); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState* exec) { - const bool inputIsUTC = true; - return setNewValueFromDateArgs(exec, 1, inputIsUTC); + const WTF::TimeType inputTimeType = WTF::UTCTime; + return setNewValueFromDateArgs(exec, 1, inputTimeType); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState* exec) { - const bool inputIsUTC = false; - return setNewValueFromDateArgs(exec, 2, inputIsUTC); + const WTF::TimeType inputTimeType = WTF::LocalTime; + return setNewValueFromDateArgs(exec, 2, inputTimeType); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState* exec) { - const bool inputIsUTC = true; - return setNewValueFromDateArgs(exec, 2, inputIsUTC); + const WTF::TimeType inputTimeType = WTF::UTCTime; + return setNewValueFromDateArgs(exec, 2, inputTimeType); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState* exec) { - const bool inputIsUTC = false; - return setNewValueFromDateArgs(exec, 3, inputIsUTC); + const WTF::TimeType inputTimeType = WTF::LocalTime; + return setNewValueFromDateArgs(exec, 3, inputTimeType); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState* exec) { - const bool inputIsUTC = true; - return setNewValueFromDateArgs(exec, 3, inputIsUTC); + const WTF::TimeType inputTimeType = WTF::UTCTime; + return setNewValueFromDateArgs(exec, 3, inputTimeType); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec) @@ -1043,7 +1043,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec) if (std::isnan(milli)) // Based on ECMA 262 B.2.5 (setYear) // the time must be reset to +0 if it is NaN. - msToGregorianDateTime(vm, 0, true, gregorianDateTime); + msToGregorianDateTime(vm, 0, WTF::UTCTime, gregorianDateTime); else { double secs = floor(milli / msPerSecond); ms = milli - secs * msPerSecond; @@ -1059,7 +1059,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec) } gregorianDateTime.setYear(toInt32((year >= 0 && year <= 99) ? (year + 1900) : year)); - JSValue result = jsNumber(gregorianDateTimeToMS(vm, gregorianDateTime, ms, false)); + JSValue result = jsNumber(gregorianDateTimeToMS(vm, gregorianDateTime, ms, WTF::LocalTime)); thisDateObj->setInternalValue(vm, result); return JSValue::encode(result); } diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp index c8a2acc7e8..1482e312f3 100644 --- a/Source/JavaScriptCore/runtime/JSDateMath.cpp +++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp @@ -132,13 +132,14 @@ static inline int msToWeekDay(double ms) // NOTE: The implementation relies on the fact that no time zones have // more than one daylight savings offset change per month. // If this function is called with NaN it returns NaN. -static LocalTimeOffset localTimeOffset(VM& vm, double ms) +static LocalTimeOffset localTimeOffset(VM& vm, double ms, WTF::TimeType inputTimeType = WTF::UTCTime) { LocalTimeOffsetCache& cache = vm.localTimeOffsetCache; double start = cache.start; double end = cache.end; + WTF::TimeType cachedTimeType = cache.timeType; - if (start <= ms) { + if (cachedTimeType == inputTimeType && start <= ms) { // If the time fits in the cached interval, return the cached offset. if (ms <= end) return cache.offset; @@ -146,7 +147,7 @@ static LocalTimeOffset localTimeOffset(VM& vm, double ms) double newEnd = end + cache.increment; if (ms <= newEnd) { - LocalTimeOffset endOffset = calculateLocalTimeOffset(newEnd); + LocalTimeOffset endOffset = calculateLocalTimeOffset(newEnd, inputTimeType); if (cache.offset == endOffset) { // If the offset at the end of the new interval still matches // the offset in the cache, we grow the cached time interval @@ -155,7 +156,7 @@ static LocalTimeOffset localTimeOffset(VM& vm, double ms) cache.increment = msPerMonth; return endOffset; } - LocalTimeOffset offset = calculateLocalTimeOffset(ms); + LocalTimeOffset offset = calculateLocalTimeOffset(ms, inputTimeType); if (offset == endOffset) { // The offset at the given time is equal to the offset at the // new end of the interval, so that means that we've just skipped @@ -180,31 +181,31 @@ static LocalTimeOffset localTimeOffset(VM& vm, double ms) // Compute the DST offset for the time and shrink the cache interval // to only contain the time. This allows fast repeated DST offset // computations for the same time. - LocalTimeOffset offset = calculateLocalTimeOffset(ms); + LocalTimeOffset offset = calculateLocalTimeOffset(ms, inputTimeType); cache.offset = offset; cache.start = ms; cache.end = ms; cache.increment = msPerMonth; + cache.timeType = inputTimeType; return offset; } -double gregorianDateTimeToMS(VM& vm, const GregorianDateTime& t, double milliSeconds, bool inputIsUTC) +double gregorianDateTimeToMS(VM& vm, const GregorianDateTime& t, double milliSeconds, WTF::TimeType inputTimeType) { double day = dateToDaysFrom1970(t.year(), t.month(), t.monthDay()); double ms = timeToMS(t.hour(), t.minute(), t.second(), milliSeconds); - double result = (day * WTF::msPerDay) + ms; + double localTimeResult = (day * WTF::msPerDay) + ms; + double localToUTCTimeOffset = inputTimeType == LocalTime + ? localTimeOffset(vm, localTimeResult, inputTimeType).offset : 0; - if (!inputIsUTC) - result -= localTimeOffset(vm, result).offset; - - return result; + return localTimeResult - localToUTCTimeOffset; } // input is UTC -void msToGregorianDateTime(VM& vm, double ms, bool outputIsUTC, GregorianDateTime& tm) +void msToGregorianDateTime(VM& vm, double ms, WTF::TimeType outputTimeType, GregorianDateTime& tm) { LocalTimeOffset localTime; - if (!outputIsUTC) { + if (outputTimeType == WTF::LocalTime) { localTime = localTimeOffset(vm, ms); ms += localTime.offset; } @@ -226,15 +227,15 @@ double parseDateFromNullTerminatedCharacters(VM& vm, const char* dateString) { bool haveTZ; int offset; - double ms = WTF::parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset); - if (std::isnan(ms)) + double localTimeMS = WTF::parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset); + if (std::isnan(localTimeMS)) return std::numeric_limits::quiet_NaN(); - // fall back to local timezone + // fall back to local timezone. if (!haveTZ) - offset = localTimeOffset(vm, ms).offset / WTF::msPerMinute; + offset = localTimeOffset(vm, localTimeMS, WTF::LocalTime).offset / WTF::msPerMinute; - return ms - (offset * WTF::msPerMinute); + return localTimeMS - (offset * WTF::msPerMinute); } double parseDate(VM& vm, const String& date) diff --git a/Source/JavaScriptCore/runtime/JSDateMath.h b/Source/JavaScriptCore/runtime/JSDateMath.h index 9a1ae30835..4e4d16ff56 100644 --- a/Source/JavaScriptCore/runtime/JSDateMath.h +++ b/Source/JavaScriptCore/runtime/JSDateMath.h @@ -50,8 +50,8 @@ namespace JSC { class VM; -JS_EXPORT_PRIVATE void msToGregorianDateTime(VM&, double, bool outputIsUTC, GregorianDateTime&); -JS_EXPORT_PRIVATE double gregorianDateTimeToMS(VM&, const GregorianDateTime&, double, bool inputIsUTC); +JS_EXPORT_PRIVATE void msToGregorianDateTime(VM&, double, WTF::TimeType outputTimeType, GregorianDateTime&); +JS_EXPORT_PRIVATE double gregorianDateTimeToMS(VM&, const GregorianDateTime&, double, WTF::TimeType inputTimeType); JS_EXPORT_PRIVATE double getUTCOffset(VM&); JS_EXPORT_PRIVATE double parseDateFromNullTerminatedCharacters(VM&, const char* dateString); JS_EXPORT_PRIVATE double parseDate(VM&, const WTF::String&); diff --git a/Source/JavaScriptCore/runtime/VM.h b/Source/JavaScriptCore/runtime/VM.h index 37ac9b16f3..c088b4269e 100644 --- a/Source/JavaScriptCore/runtime/VM.h +++ b/Source/JavaScriptCore/runtime/VM.h @@ -133,6 +133,7 @@ struct LocalTimeOffsetCache { : start(0.0) , end(-1.0) , increment(0.0) + , timeType(WTF::UTCTime) { } @@ -142,12 +143,14 @@ struct LocalTimeOffsetCache { start = 0.0; end = -1.0; increment = 0.0; + timeType = WTF::UTCTime; } LocalTimeOffset offset; double start; double end; double increment; + WTF::TimeType timeType; }; class ConservativeRoots; diff --git a/Source/WTF/wtf/DateMath.cpp b/Source/WTF/wtf/DateMath.cpp index 6ee36d3c5f..29824a31a3 100644 --- a/Source/WTF/wtf/DateMath.cpp +++ b/Source/WTF/wtf/DateMath.cpp @@ -363,8 +363,6 @@ int equivalentYearForDST(int year) return year; } -#if !HAVE(TM_GMTOFF) - static int32_t calculateUTCOffset() { #if OS(WINDOWS) @@ -406,6 +404,8 @@ static int32_t calculateUTCOffset() #endif } +#if !HAVE(TM_GMTOFF) + #if OS(WINDOWS) // Code taken from http://support.microsoft.com/kb/167296 static void UnixTimeToFileTime(time_t t, LPFILETIME pft) @@ -467,8 +467,16 @@ static double calculateDSTOffset(time_t localTime, double utcOffset) #endif // Returns combined offset in millisecond (UTC + DST). -LocalTimeOffset calculateLocalTimeOffset(double ms) +LocalTimeOffset calculateLocalTimeOffset(double ms, TimeType inputTimeType) { +#if HAVE(TM_GMTOFF) + double localToUTCTimeOffset = inputTimeType == LocalTime ? calculateUTCOffset() : 0; +#else + double localToUTCTimeOffset = calculateUTCOffset(); +#endif + if (inputTimeType == LocalTime) + ms -= localToUTCTimeOffset; + // On Mac OS X, the call to localtime (see calculateDSTOffset) will return historically accurate // DST information (e.g. New Zealand did not have DST from 1946 to 1974) however the JavaScript // standard explicitly dictates that historical information should not be considered when @@ -498,9 +506,8 @@ LocalTimeOffset calculateLocalTimeOffset(double ms) getLocalTime(&localTime, &localTM); return LocalTimeOffset(localTM.tm_isdst, localTM.tm_gmtoff * msPerSecond); #else - double utcOffset = calculateUTCOffset(); - double dstOffset = calculateDSTOffset(localTime, utcOffset); - return LocalTimeOffset(dstOffset, utcOffset + dstOffset); + double dstOffset = calculateDSTOffset(localTime, localToUTCTimeOffset); + return LocalTimeOffset(dstOffset, localToUTCTimeOffset + dstOffset); #endif } @@ -1091,7 +1098,7 @@ double parseDateFromNullTerminatedCharacters(const char* dateString) // fall back to local timezone if (!haveTZ) - offset = calculateLocalTimeOffset(ms).offset / msPerMinute; + offset = calculateLocalTimeOffset(ms, LocalTime).offset / msPerMinute; // ms value is in local time milliseconds. return ms - (offset * msPerMinute); } diff --git a/Source/WTF/wtf/DateMath.h b/Source/WTF/wtf/DateMath.h index c8ae0d912f..73889a5682 100644 --- a/Source/WTF/wtf/DateMath.h +++ b/Source/WTF/wtf/DateMath.h @@ -53,6 +53,11 @@ namespace WTF { +enum TimeType { + UTCTime = 0, + LocalTime +}; + struct LocalTimeOffset { LocalTimeOffset() : isDST(false) @@ -126,7 +131,7 @@ WTF_EXPORT_PRIVATE int monthFromDayInYear(int dayInYear, bool leapYear); WTF_EXPORT_PRIVATE int dayInMonthFromDayInYear(int dayInYear, bool leapYear); // Returns combined offset in millisecond (UTC + DST). -WTF_EXPORT_PRIVATE LocalTimeOffset calculateLocalTimeOffset(double utcInMilliseconds); +WTF_EXPORT_PRIVATE LocalTimeOffset calculateLocalTimeOffset(double utcInMilliseconds, TimeType = UTCTime); } // namespace WTF