mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 563938 - Refactor DST offset computation to pave the way for caching the DST offset when possible. No functionality change. r=sayrer
--HG-- extra : rebase_source : ad70045b70cc23dd7578e594490a10b4fc6fc7ef
This commit is contained in:
parent
22db0647cc
commit
e98ca56524
@ -64,6 +64,7 @@
|
||||
#include "jsarray.h"
|
||||
#include "jstask.h"
|
||||
#include "jsvector.h"
|
||||
#include "prmjtime.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
@ -1893,6 +1894,8 @@ struct JSContext
|
||||
|
||||
JSClassProtoCache classProtoCache;
|
||||
|
||||
DSTOffsetCache dstOffsetCache;
|
||||
|
||||
private:
|
||||
/*
|
||||
* To go from a live generator frame (on the stack) to its generator object
|
||||
|
@ -392,9 +392,9 @@ EquivalentYearForDST(jsint year)
|
||||
static jsdouble LocalTZA;
|
||||
|
||||
static jsdouble
|
||||
DaylightSavingTA(jsdouble t)
|
||||
DaylightSavingTA(jsdouble t, JSContext *cx)
|
||||
{
|
||||
volatile int64 PR_t;
|
||||
int64 PR_t;
|
||||
int64 ms2us;
|
||||
int64 offset;
|
||||
jsdouble result;
|
||||
@ -421,7 +421,7 @@ DaylightSavingTA(jsdouble t)
|
||||
JSLL_I2L(ms2us, PRMJ_USEC_PER_MSEC);
|
||||
JSLL_MUL(PR_t, PR_t, ms2us);
|
||||
|
||||
offset = PRMJ_DSTOffset(PR_t);
|
||||
offset = cx->dstOffsetCache.getDSTOffset(PR_t, cx);
|
||||
|
||||
JSLL_DIV(offset, offset, ms2us);
|
||||
JSLL_L2D(result, offset);
|
||||
@ -429,19 +429,23 @@ DaylightSavingTA(jsdouble t)
|
||||
}
|
||||
|
||||
static jsdouble
|
||||
AdjustTime(jsdouble date)
|
||||
AdjustTime(jsdouble date, JSContext *cx)
|
||||
{
|
||||
jsdouble t = DaylightSavingTA(date) + LocalTZA;
|
||||
jsdouble t = DaylightSavingTA(date, cx) + LocalTZA;
|
||||
t = (LocalTZA >= 0) ? fmod(t, msPerDay) : -fmod(msPerDay - t, msPerDay);
|
||||
return t;
|
||||
}
|
||||
|
||||
#define LocalTime(t) ((t) + AdjustTime(t))
|
||||
static jsdouble
|
||||
LocalTime(jsdouble t, JSContext *cx)
|
||||
{
|
||||
return t + AdjustTime(t, cx);
|
||||
}
|
||||
|
||||
static jsdouble
|
||||
UTC(jsdouble t)
|
||||
UTC(jsdouble t, JSContext *cx)
|
||||
{
|
||||
return t - AdjustTime(t - LocalTZA);
|
||||
return t - AdjustTime(t - LocalTZA, cx);
|
||||
}
|
||||
|
||||
static intN
|
||||
@ -748,7 +752,7 @@ ndigits(size_t n, size_t *result, const jschar *s, size_t* i, size_t limit)
|
||||
*/
|
||||
|
||||
static JSBool
|
||||
date_parseISOString(JSString *str, jsdouble *result)
|
||||
date_parseISOString(JSString *str, jsdouble *result, JSContext *cx)
|
||||
{
|
||||
jsdouble msec;
|
||||
|
||||
@ -856,7 +860,7 @@ date_parseISOString(JSString *str, jsdouble *result)
|
||||
frac * 1000.0);;
|
||||
|
||||
if (isLocalTime) {
|
||||
msec = UTC(msec);
|
||||
msec = UTC(msec, cx);
|
||||
} else {
|
||||
msec -= ((tzMul) * ((tzHour * msPerHour)
|
||||
+ (tzMin * msPerMinute)));
|
||||
@ -881,7 +885,7 @@ date_parseISOString(JSString *str, jsdouble *result)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
date_parseString(JSString *str, jsdouble *result)
|
||||
date_parseString(JSString *str, jsdouble *result, JSContext *cx)
|
||||
{
|
||||
jsdouble msec;
|
||||
|
||||
@ -902,7 +906,7 @@ date_parseString(JSString *str, jsdouble *result)
|
||||
int temp;
|
||||
JSBool seenmonthname = JS_FALSE;
|
||||
|
||||
if (date_parseISOString(str, result))
|
||||
if (date_parseISOString(str, result, cx))
|
||||
return JS_TRUE;
|
||||
|
||||
str->getCharsAndLength(s, limit);
|
||||
@ -1137,7 +1141,7 @@ date_parseString(JSString *str, jsdouble *result)
|
||||
msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
|
||||
|
||||
if (tzoffset == -1) { /* no time zone specified, have to use local */
|
||||
msec = UTC(msec);
|
||||
msec = UTC(msec, cx);
|
||||
} else {
|
||||
msec += tzoffset * msPerMinute;
|
||||
}
|
||||
@ -1165,7 +1169,7 @@ date_parse(JSContext *cx, uintN argc, jsval *vp)
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
vp[2] = STRING_TO_JSVAL(str);
|
||||
if (!date_parseString(str, &result)) {
|
||||
if (!date_parseString(str, &result, cx)) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
return true;
|
||||
}
|
||||
@ -1251,7 +1255,7 @@ GetAndCacheLocalTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
|
||||
|
||||
/* if result is NaN, it couldn't be finite. */
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = LocalTime(result);
|
||||
result = LocalTime(result, cx);
|
||||
|
||||
if (!js_NewDoubleInRootedValue(cx, result, slotp))
|
||||
return false;
|
||||
@ -1580,7 +1584,7 @@ date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
|
||||
}
|
||||
|
||||
if (local)
|
||||
lorutime = LocalTime(result);
|
||||
lorutime = LocalTime(result, cx);
|
||||
else
|
||||
lorutime = result;
|
||||
|
||||
@ -1612,7 +1616,7 @@ date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
|
||||
/* fprintf(stderr, "%f\n", result); */
|
||||
|
||||
if (local)
|
||||
result = UTC(result);
|
||||
result = UTC(result, cx);
|
||||
|
||||
/* fprintf(stderr, "%f\n", result); */
|
||||
|
||||
@ -1709,7 +1713,7 @@ date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
|
||||
return js_NewNumberInRootedValue(cx, result, vp);
|
||||
lorutime = +0.;
|
||||
} else {
|
||||
lorutime = local ? LocalTime(result) : result;
|
||||
lorutime = local ? LocalTime(result, cx) : result;
|
||||
}
|
||||
|
||||
argp = args;
|
||||
@ -1733,7 +1737,7 @@ date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
|
||||
result = MakeDate(day, TimeWithinDay(lorutime));
|
||||
|
||||
if (local)
|
||||
result = UTC(result);
|
||||
result = UTC(result, cx);
|
||||
|
||||
return SetUTCTime(cx, obj, TIMECLIP(result), vp);
|
||||
}
|
||||
@ -1800,10 +1804,10 @@ date_setYear(JSContext *cx, uintN argc, jsval *vp)
|
||||
if (year >= 0 && year <= 99)
|
||||
year += 1900;
|
||||
|
||||
jsdouble t = JSDOUBLE_IS_FINITE(result) ? LocalTime(result) : +0.0;
|
||||
jsdouble t = JSDOUBLE_IS_FINITE(result) ? LocalTime(result, cx) : +0.0;
|
||||
jsdouble day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
|
||||
result = MakeDate(day, TimeWithinDay(t));
|
||||
result = UTC(result);
|
||||
result = UTC(result, cx);
|
||||
|
||||
return SetUTCTime(cx, obj, TIMECLIP(result), vp);
|
||||
}
|
||||
@ -1886,7 +1890,7 @@ date_toISOString(JSContext *cx, uintN argc, jsval *vp)
|
||||
/* for Date.toLocaleString; interface to PRMJTime date struct.
|
||||
*/
|
||||
static void
|
||||
new_explode(jsdouble timeval, PRMJTime *split)
|
||||
new_explode(jsdouble timeval, PRMJTime *split, JSContext *cx)
|
||||
{
|
||||
jsint year = YearFromTime(timeval);
|
||||
|
||||
@ -1902,7 +1906,7 @@ new_explode(jsdouble timeval, PRMJTime *split)
|
||||
|
||||
/* not sure how this affects things, but it doesn't seem
|
||||
to matter. */
|
||||
split->tm_isdst = (DaylightSavingTA(timeval) != 0);
|
||||
split->tm_isdst = (DaylightSavingTA(timeval, cx) != 0);
|
||||
}
|
||||
|
||||
typedef enum formatspec {
|
||||
@ -1923,11 +1927,11 @@ date_format(JSContext *cx, jsdouble date, formatspec format, jsval *rval)
|
||||
if (!JSDOUBLE_IS_FINITE(date)) {
|
||||
JS_snprintf(buf, sizeof buf, js_NaN_date_str);
|
||||
} else {
|
||||
jsdouble local = LocalTime(date);
|
||||
jsdouble local = LocalTime(date, cx);
|
||||
|
||||
/* offset from GMT in minutes. The offset includes daylight savings,
|
||||
if it applies. */
|
||||
jsint minutes = (jsint) floor(AdjustTime(date) / msPerMinute);
|
||||
jsint minutes = (jsint) floor(AdjustTime(date, cx) / msPerMinute);
|
||||
|
||||
/* map 510 minutes to 0830 hours */
|
||||
intN offset = (minutes / 60) * 100 + minutes % 60;
|
||||
@ -1943,7 +1947,7 @@ date_format(JSContext *cx, jsdouble date, formatspec format, jsval *rval)
|
||||
|
||||
/* get a timezone string from the OS to include as a
|
||||
comment. */
|
||||
new_explode(date, &split);
|
||||
new_explode(date, &split, cx);
|
||||
if (PRMJ_FormatTime(tzbuf, sizeof tzbuf, "(%Z)", &split) != 0) {
|
||||
|
||||
/* Decide whether to use the resulting timezone string.
|
||||
@ -2040,8 +2044,8 @@ date_toLocaleHelper(JSContext *cx, const char *format, jsval *vp)
|
||||
JS_snprintf(buf, sizeof buf, js_NaN_date_str);
|
||||
} else {
|
||||
intN result_len;
|
||||
jsdouble local = LocalTime(utctime);
|
||||
new_explode(local, &split);
|
||||
jsdouble local = LocalTime(utctime, cx);
|
||||
new_explode(local, &split, cx);
|
||||
|
||||
/* let PRMJTime format it. */
|
||||
result_len = PRMJ_FormatTime(buf, sizeof buf, format, &split);
|
||||
@ -2311,7 +2315,7 @@ js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
return JS_FALSE;
|
||||
argv[0] = STRING_TO_JSVAL(str);
|
||||
|
||||
if (!date_parseString(str, &d))
|
||||
if (!date_parseString(str, &d, cx))
|
||||
d = js_NaN;
|
||||
else
|
||||
d = TIMECLIP(d);
|
||||
@ -2322,7 +2326,7 @@ js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSDOUBLE_IS_FINITE(msec_time)) {
|
||||
msec_time = UTC(msec_time);
|
||||
msec_time = UTC(msec_time, cx);
|
||||
msec_time = TIMECLIP(msec_time);
|
||||
}
|
||||
d = msec_time;
|
||||
@ -2369,7 +2373,7 @@ js_NewDateObject(JSContext* cx, int year, int mon, int mday,
|
||||
|
||||
JS_ASSERT(mon < 12);
|
||||
msec_time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
|
||||
obj = js_NewDateObjectMsec(cx, UTC(msec_time));
|
||||
obj = js_NewDateObjectMsec(cx, UTC(msec_time, cx));
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -2478,7 +2482,7 @@ js_DateSetYear(JSContext *cx, JSObject *obj, int year)
|
||||
msFromTime(local));
|
||||
|
||||
/* SetUTCTime also invalidates local time cache. */
|
||||
SetUTCTime(cx, obj, UTC(local));
|
||||
SetUTCTime(cx, obj, UTC(local, cx));
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
@ -2502,7 +2506,7 @@ js_DateSetMonth(JSContext *cx, JSObject *obj, int month)
|
||||
MinFromTime(local),
|
||||
SecFromTime(local),
|
||||
msFromTime(local));
|
||||
SetUTCTime(cx, obj, UTC(local));
|
||||
SetUTCTime(cx, obj, UTC(local, cx));
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
@ -2523,7 +2527,7 @@ js_DateSetDate(JSContext *cx, JSObject *obj, int date)
|
||||
MinFromTime(local),
|
||||
SecFromTime(local),
|
||||
msFromTime(local));
|
||||
SetUTCTime(cx, obj, UTC(local));
|
||||
SetUTCTime(cx, obj, UTC(local, cx));
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
@ -2543,7 +2547,7 @@ js_DateSetHours(JSContext *cx, JSObject *obj, int hours)
|
||||
MinFromTime(local),
|
||||
SecFromTime(local),
|
||||
msFromTime(local));
|
||||
SetUTCTime(cx, obj, UTC(local));
|
||||
SetUTCTime(cx, obj, UTC(local, cx));
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
@ -2563,7 +2567,7 @@ js_DateSetMinutes(JSContext *cx, JSObject *obj, int minutes)
|
||||
minutes,
|
||||
SecFromTime(local),
|
||||
msFromTime(local));
|
||||
SetUTCTime(cx, obj, UTC(local));
|
||||
SetUTCTime(cx, obj, UTC(local, cx));
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
@ -2583,7 +2587,7 @@ js_DateSetSeconds(JSContext *cx, JSObject *obj, int seconds)
|
||||
MinFromTime(local),
|
||||
seconds,
|
||||
msFromTime(local));
|
||||
SetUTCTime(cx, obj, UTC(local));
|
||||
SetUTCTime(cx, obj, UTC(local, cx));
|
||||
}
|
||||
|
||||
JS_FRIEND_API(jsdouble)
|
||||
|
@ -555,68 +555,6 @@ PRMJ_Now(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the DST timezone offset for the time passed in */
|
||||
JSInt64
|
||||
PRMJ_DSTOffset(JSInt64 local_time)
|
||||
{
|
||||
JSInt64 us2s;
|
||||
time_t local;
|
||||
JSInt32 diff;
|
||||
JSInt64 maxtimet;
|
||||
struct tm tm;
|
||||
PRMJTime prtm;
|
||||
#ifndef HAVE_LOCALTIME_R
|
||||
struct tm *ptm;
|
||||
#endif
|
||||
|
||||
|
||||
JSLL_UI2L(us2s, PRMJ_USEC_PER_SEC);
|
||||
JSLL_DIV(local_time, local_time, us2s);
|
||||
|
||||
/* get the maximum of time_t value */
|
||||
JSLL_UI2L(maxtimet,PRMJ_MAX_UNIX_TIMET);
|
||||
|
||||
if(JSLL_CMP(local_time,>,maxtimet)){
|
||||
JSLL_UI2L(local_time,PRMJ_MAX_UNIX_TIMET);
|
||||
} else if(!JSLL_GE_ZERO(local_time)){
|
||||
/*go ahead a day to make localtime work (does not work with 0) */
|
||||
JSLL_UI2L(local_time,PRMJ_DAY_SECONDS);
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) && !defined(WINCE)
|
||||
/* Windows does not follow POSIX. Updates to the
|
||||
* TZ environment variable are not reflected
|
||||
* immediately on that platform as they are
|
||||
* on UNIX systems without this call.
|
||||
*/
|
||||
_tzset();
|
||||
#endif
|
||||
|
||||
JSLL_L2UI(local,local_time);
|
||||
PRMJ_basetime(local_time,&prtm);
|
||||
#ifndef HAVE_LOCALTIME_R
|
||||
ptm = localtime(&local);
|
||||
if(!ptm){
|
||||
return 0;
|
||||
}
|
||||
tm = *ptm;
|
||||
#else
|
||||
localtime_r(&local,&tm); /* get dst information */
|
||||
#endif
|
||||
|
||||
diff = ((tm.tm_hour - prtm.tm_hour) * PRMJ_HOUR_SECONDS) +
|
||||
((tm.tm_min - prtm.tm_min) * 60);
|
||||
|
||||
if (diff < 0)
|
||||
diff += PRMJ_DAY_SECONDS;
|
||||
|
||||
JSLL_UI2L(local_time,diff);
|
||||
|
||||
JSLL_MUL(local_time,local_time,us2s);
|
||||
|
||||
return(local_time);
|
||||
}
|
||||
|
||||
#ifdef NS_HAVE_INVALID_PARAMETER_HANDLER
|
||||
static void
|
||||
PRMJ_InvalidParameterHandler(const wchar_t *expression,
|
||||
@ -913,3 +851,52 @@ PRMJ_basetime(JSInt64 tsecs, PRMJTime *prtm)
|
||||
prtm->tm_year = (JSInt16)year;
|
||||
prtm->tm_yday = (JSInt16)yday;
|
||||
}
|
||||
|
||||
JSInt64
|
||||
DSTOffsetCache::computeDSTOffset(int64 localTime)
|
||||
{
|
||||
localTime /= MICROSECONDS_PER_SECOND;
|
||||
|
||||
if (localTime > MAX_UNIX_TIMET) {
|
||||
localTime = MAX_UNIX_TIMET;
|
||||
} else if (localTime < 0) {
|
||||
/* Go ahead a day to make localtime work (does not work with 0). */
|
||||
localTime = SECONDS_PER_DAY;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) && !defined(WINCE)
|
||||
/* Windows does not follow POSIX. Updates to the
|
||||
* TZ environment variable are not reflected
|
||||
* immediately on that platform as they are
|
||||
* on UNIX systems without this call.
|
||||
*/
|
||||
_tzset();
|
||||
#endif
|
||||
|
||||
time_t local = static_cast<time_t>(localTime);
|
||||
PRMJTime prtm;
|
||||
struct tm tm;
|
||||
PRMJ_basetime(localTime, &prtm);
|
||||
#ifndef HAVE_LOCALTIME_R
|
||||
struct tm *ptm = localtime(&local);
|
||||
if (!ptm)
|
||||
return 0;
|
||||
tm = *ptm;
|
||||
#else
|
||||
localtime_r(&local, &tm); /* get dst information */
|
||||
#endif
|
||||
|
||||
JSInt32 diff = ((tm.tm_hour - prtm.tm_hour) * SECONDS_PER_HOUR) +
|
||||
((tm.tm_min - prtm.tm_min) * SECONDS_PER_MINUTE);
|
||||
|
||||
if (diff < 0)
|
||||
diff += SECONDS_PER_DAY;
|
||||
|
||||
return diff * MICROSECONDS_PER_SECOND;
|
||||
}
|
||||
|
||||
JSInt64
|
||||
DSTOffsetCache::getDSTOffset(JSInt64 localTime, JSContext *cx)
|
||||
{
|
||||
return computeDSTOffset(localTime);
|
||||
}
|
||||
|
@ -49,6 +49,22 @@
|
||||
#include "jscompat.h"
|
||||
#endif
|
||||
|
||||
struct JSContext;
|
||||
|
||||
class DSTOffsetCache {
|
||||
public:
|
||||
JSInt64 getDSTOffset(int64 localTime, JSContext *cx);
|
||||
|
||||
private:
|
||||
JSInt64 computeDSTOffset(int64 localTime);
|
||||
|
||||
static const JSInt64 MAX_UNIX_TIMET = 2145859200; /* time_t 12/31/2037 */
|
||||
static const JSInt64 MICROSECONDS_PER_SECOND = 1000000;
|
||||
static const JSInt64 SECONDS_PER_MINUTE = 60;
|
||||
static const JSInt64 SECONDS_PER_HOUR = 60 * SECONDS_PER_MINUTE;
|
||||
static const JSInt64 SECONDS_PER_DAY = 24 * SECONDS_PER_HOUR;
|
||||
};
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct PRMJTime PRMJTime;
|
||||
@ -93,10 +109,6 @@ PRMJ_LocalGMTDifference(void);
|
||||
extern size_t
|
||||
PRMJ_FormatTime(char *buf, int buflen, const char *fmt, PRMJTime *tm);
|
||||
|
||||
/* Get the DST offset for the local time passed in */
|
||||
extern JSInt64
|
||||
PRMJ_DSTOffset(JSInt64 local_time);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* prmjtime_h___ */
|
||||
|
Loading…
Reference in New Issue
Block a user