Back out changeset 6e21339a66ed (bug 1208808) for bustage in the mislabelled and deceptive arm64 simulator
CLOSED TREE
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include "DateCacheCleaner.h"
|
#include "DateCacheCleaner.h"
|
||||||
|
|
||||||
#include "js/Date.h"
|
#include "jsapi.h"
|
||||||
#include "mozilla/dom/ScriptSettings.h"
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
#include "mozilla/ClearOnShutdown.h"
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
#include "mozilla/Hal.h"
|
#include "mozilla/Hal.h"
|
||||||
@@ -33,7 +33,7 @@ public:
|
|||||||
void Notify(const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
|
void Notify(const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
|
||||||
{
|
{
|
||||||
mozilla::AutoSafeJSContext cx;
|
mozilla::AutoSafeJSContext cx;
|
||||||
JS::ResetTimeZone();
|
JS_ClearDateCaches(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
/*
|
/*
|
||||||
* InitializeDateCacheCleaner registers DateCacheCleaner to
|
* InitializeDateCacheCleaner registers DateCacheCleaner to
|
||||||
* SystemTimeChangeObserver. When time zone is changed, DateCacheCleaner calls
|
* SystemTimeChangeObserver. When time zone is changed, DateCacheCleaner calls
|
||||||
* JS::ResetTimeZone to update the time zone information.
|
* JS_ClearDateCaches to update the time zone information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|||||||
@@ -39,22 +39,6 @@ struct JSContext;
|
|||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
/**
|
|
||||||
* Re-query the system to determine the current time zone adjustment from UTC,
|
|
||||||
* including any component due to DST. If the time zone has changed, this will
|
|
||||||
* cause all Date object non-UTC methods and formatting functions to produce
|
|
||||||
* appropriately adjusted results.
|
|
||||||
*
|
|
||||||
* Left to its own devices, SpiderMonkey itself may occasionally call this
|
|
||||||
* method to attempt to keep up with system time changes. However, no
|
|
||||||
* particular frequency of checking is guaranteed. Embedders unable to accept
|
|
||||||
* occasional inaccuracies should call this method in response to system time
|
|
||||||
* changes, or immediately before operations requiring instantaneous
|
|
||||||
* correctness, to guarantee correct behavior.
|
|
||||||
*/
|
|
||||||
extern JS_PUBLIC_API(void)
|
|
||||||
ResetTimeZone();
|
|
||||||
|
|
||||||
class ClippedTime;
|
class ClippedTime;
|
||||||
inline ClippedTime TimeClip(double time);
|
inline ClippedTime TimeClip(double time);
|
||||||
|
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
/* SpiderMonkey initialization and shutdown APIs. */
|
|
||||||
|
|
||||||
#ifndef js_Initialization_h
|
|
||||||
#define js_Initialization_h
|
|
||||||
|
|
||||||
#include "jstypes.h"
|
|
||||||
|
|
||||||
namespace JS {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
enum class InitState { Uninitialized = 0, Running, ShutDown };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SpiderMonkey's initialization status is tracked here, and it controls things
|
|
||||||
* that should happen only once across all runtimes. It's an API requirement
|
|
||||||
* that JS_Init (and JS_ShutDown, if called) be called in a thread-aware
|
|
||||||
* manner, so this (internal -- embedders, don't use!) variable doesn't need to
|
|
||||||
* be atomic.
|
|
||||||
*/
|
|
||||||
extern JS_PUBLIC_DATA(InitState)
|
|
||||||
libraryInitState;
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace JS
|
|
||||||
|
|
||||||
// These are equivalent to ICU's |UMemAllocFn|, |UMemReallocFn|, and
|
|
||||||
// |UMemFreeFn| types. The first argument (called |context| in the ICU docs)
|
|
||||||
// will always be nullptr and should be ignored.
|
|
||||||
typedef void* (*JS_ICUAllocFn)(const void*, size_t size);
|
|
||||||
typedef void* (*JS_ICUReallocFn)(const void*, void* p, size_t size);
|
|
||||||
typedef void (*JS_ICUFreeFn)(const void*, void* p);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function can be used to track memory used by ICU. If it is called, it
|
|
||||||
* *must* be called before JS_Init. Don't use it unless you know what you're
|
|
||||||
* doing!
|
|
||||||
*/
|
|
||||||
extern JS_PUBLIC_API(bool)
|
|
||||||
JS_SetICUMemoryFunctions(JS_ICUAllocFn allocFn,
|
|
||||||
JS_ICUReallocFn reallocFn,
|
|
||||||
JS_ICUFreeFn freeFn);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize SpiderMonkey, returning true only if initialization succeeded.
|
|
||||||
* Once this method has succeeded, it is safe to call JS_NewRuntime and other
|
|
||||||
* JSAPI methods.
|
|
||||||
*
|
|
||||||
* This method must be called before any other JSAPI method is used on any
|
|
||||||
* thread. Once it has been used, it is safe to call any JSAPI method, and it
|
|
||||||
* remains safe to do so until JS_ShutDown is correctly called.
|
|
||||||
*
|
|
||||||
* It is currently not possible to initialize SpiderMonkey multiple times (that
|
|
||||||
* is, calling JS_Init/JSAPI methods/JS_ShutDown in that order, then doing so
|
|
||||||
* again). This restriction may eventually be lifted.
|
|
||||||
*/
|
|
||||||
extern JS_PUBLIC_API(bool)
|
|
||||||
JS_Init(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroy free-standing resources allocated by SpiderMonkey, not associated
|
|
||||||
* with any runtime, context, or other structure.
|
|
||||||
*
|
|
||||||
* This method should be called after all other JSAPI data has been properly
|
|
||||||
* cleaned up: every new runtime must have been destroyed, every new context
|
|
||||||
* must have been destroyed, and so on. Calling this method before all other
|
|
||||||
* resources have been destroyed has undefined behavior.
|
|
||||||
*
|
|
||||||
* Failure to call this method, at present, has no adverse effects other than
|
|
||||||
* leaking memory. This may not always be the case; it's recommended that all
|
|
||||||
* embedders call this method when all other JSAPI operations have completed.
|
|
||||||
*
|
|
||||||
* It is currently not possible to initialize SpiderMonkey multiple times (that
|
|
||||||
* is, calling JS_Init/JSAPI methods/JS_ShutDown in that order, then doing so
|
|
||||||
* again). This restriction may eventually be lifted.
|
|
||||||
*/
|
|
||||||
extern JS_PUBLIC_API(void)
|
|
||||||
JS_ShutDown(void);
|
|
||||||
|
|
||||||
#endif /* js_Initialization_h */
|
|
||||||
@@ -9,7 +9,6 @@
|
|||||||
#include "gdb-tests.h"
|
#include "gdb-tests.h"
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "jsfriendapi.h"
|
#include "jsfriendapi.h"
|
||||||
#include "js/Initialization.h"
|
|
||||||
|
|
||||||
using namespace JS;
|
using namespace JS;
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "js/Initialization.h"
|
|
||||||
#include "js/RootingAPI.h"
|
#include "js/RootingAPI.h"
|
||||||
|
|
||||||
JSAPITest* JSAPITest::list;
|
JSAPITest* JSAPITest::list;
|
||||||
|
|||||||
163
js/src/jsapi.cpp
163
js/src/jsapi.cpp
@@ -62,10 +62,14 @@
|
|||||||
#include "js/CharacterEncoding.h"
|
#include "js/CharacterEncoding.h"
|
||||||
#include "js/Conversions.h"
|
#include "js/Conversions.h"
|
||||||
#include "js/Date.h"
|
#include "js/Date.h"
|
||||||
#include "js/Initialization.h"
|
|
||||||
#include "js/Proxy.h"
|
#include "js/Proxy.h"
|
||||||
#include "js/SliceBudget.h"
|
#include "js/SliceBudget.h"
|
||||||
#include "js/StructuredClone.h"
|
#include "js/StructuredClone.h"
|
||||||
|
#if ENABLE_INTL_API
|
||||||
|
#include "unicode/timezone.h"
|
||||||
|
#include "unicode/uclean.h"
|
||||||
|
#include "unicode/utypes.h"
|
||||||
|
#endif // ENABLE_INTL_API
|
||||||
#include "vm/DateObject.h"
|
#include "vm/DateObject.h"
|
||||||
#include "vm/Debugger.h"
|
#include "vm/Debugger.h"
|
||||||
#include "vm/ErrorObject.h"
|
#include "vm/ErrorObject.h"
|
||||||
@@ -441,6 +445,129 @@ JS_IsBuiltinFunctionConstructor(JSFunction* fun)
|
|||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SpiderMonkey's initialization status is tracked here, and it controls things
|
||||||
|
* that should happen only once across all runtimes. It's an API requirement
|
||||||
|
* that JS_Init (and JS_ShutDown, if called) be called in a thread-aware
|
||||||
|
* manner, so this variable doesn't need to be atomic.
|
||||||
|
*
|
||||||
|
* The only reason at present for the restriction that you can't call
|
||||||
|
* JS_Init/stuff/JS_ShutDown multiple times is the Windows PRMJ NowInit
|
||||||
|
* initialization code, which uses PR_CallOnce to initialize the PRMJ_Now
|
||||||
|
* subsystem. (For reinitialization to be permitted, we'd need to "reset" the
|
||||||
|
* called-once status -- doable, but more trouble than it's worth now.)
|
||||||
|
* Initializing that subsystem from JS_Init eliminates the problem, but
|
||||||
|
* initialization can take a comparatively long time (15ms or so), so we
|
||||||
|
* really don't want to do it in JS_Init, and we really do want to do it only
|
||||||
|
* when PRMJ_Now is eventually called.
|
||||||
|
*/
|
||||||
|
enum InitState { Uninitialized, Running, ShutDown };
|
||||||
|
static InitState jsInitState = Uninitialized;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static unsigned
|
||||||
|
MessageParameterCount(const char* format)
|
||||||
|
{
|
||||||
|
unsigned numfmtspecs = 0;
|
||||||
|
for (const char* fmt = format; *fmt != '\0'; fmt++) {
|
||||||
|
if (*fmt == '{' && isdigit(fmt[1]))
|
||||||
|
++numfmtspecs;
|
||||||
|
}
|
||||||
|
return numfmtspecs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
CheckMessageParameterCounts()
|
||||||
|
{
|
||||||
|
// Assert that each message format has the correct number of braced
|
||||||
|
// parameters.
|
||||||
|
# define MSG_DEF(name, count, exception, format) \
|
||||||
|
MOZ_ASSERT(MessageParameterCount(format) == count);
|
||||||
|
# include "js.msg"
|
||||||
|
# undef MSG_DEF
|
||||||
|
}
|
||||||
|
#endif /* DEBUG */
|
||||||
|
|
||||||
|
JS_PUBLIC_API(bool)
|
||||||
|
JS_Init(void)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(jsInitState == Uninitialized,
|
||||||
|
"must call JS_Init once before any JSAPI operation except "
|
||||||
|
"JS_SetICUMemoryFunctions");
|
||||||
|
MOZ_ASSERT(!JSRuntime::hasLiveRuntimes(),
|
||||||
|
"how do we have live runtimes before JS_Init?");
|
||||||
|
|
||||||
|
PRMJ_NowInit();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
CheckMessageParameterCounts();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using js::TlsPerThreadData;
|
||||||
|
if (!TlsPerThreadData.initialized() && !TlsPerThreadData.init())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
|
||||||
|
if (!js::oom::InitThreadType())
|
||||||
|
return false;
|
||||||
|
js::oom::SetThreadType(js::oom::THREAD_TYPE_MAIN);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
jit::ExecutableAllocator::initStatic();
|
||||||
|
|
||||||
|
if (!jit::InitializeIon())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#if EXPOSE_INTL_API
|
||||||
|
UErrorCode err = U_ZERO_ERROR;
|
||||||
|
u_init(&err);
|
||||||
|
if (U_FAILURE(err))
|
||||||
|
return false;
|
||||||
|
#endif // EXPOSE_INTL_API
|
||||||
|
|
||||||
|
if (!CreateHelperThreadsState())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!FutexRuntime::initialize())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
jsInitState = Running;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(void)
|
||||||
|
JS_ShutDown(void)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(jsInitState == Running,
|
||||||
|
"JS_ShutDown must only be called after JS_Init and can't race with it");
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (JSRuntime::hasLiveRuntimes()) {
|
||||||
|
// Gecko is too buggy to assert this just yet.
|
||||||
|
fprintf(stderr,
|
||||||
|
"WARNING: YOU ARE LEAKING THE WORLD (at least one JSRuntime "
|
||||||
|
"and everything alive inside it, that is) AT JS_ShutDown "
|
||||||
|
"TIME. FIX THIS!\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FutexRuntime::destroy();
|
||||||
|
|
||||||
|
DestroyHelperThreadsState();
|
||||||
|
|
||||||
|
#ifdef JS_TRACE_LOGGING
|
||||||
|
DestroyTraceLoggerThreadState();
|
||||||
|
DestroyTraceLoggerGraphState();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PRMJ_NowShutdown();
|
||||||
|
|
||||||
|
#if EXPOSE_INTL_API
|
||||||
|
u_cleanup();
|
||||||
|
#endif // EXPOSE_INTL_API
|
||||||
|
|
||||||
|
jsInitState = ShutDown;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
JS_FRIEND_API(bool)
|
JS_FRIEND_API(bool)
|
||||||
JS::isGCEnabled()
|
JS::isGCEnabled()
|
||||||
@@ -454,7 +581,7 @@ JS_FRIEND_API(bool) JS::isGCEnabled() { return true; }
|
|||||||
JS_PUBLIC_API(JSRuntime*)
|
JS_PUBLIC_API(JSRuntime*)
|
||||||
JS_NewRuntime(uint32_t maxbytes, uint32_t maxNurseryBytes, JSRuntime* parentRuntime)
|
JS_NewRuntime(uint32_t maxbytes, uint32_t maxNurseryBytes, JSRuntime* parentRuntime)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(JS::detail::libraryInitState == JS::detail::InitState::Running,
|
MOZ_ASSERT(jsInitState == Running,
|
||||||
"must call JS_Init prior to creating any JSRuntimes");
|
"must call JS_Init prior to creating any JSRuntimes");
|
||||||
|
|
||||||
// Make sure that all parent runtimes are the topmost parent.
|
// Make sure that all parent runtimes are the topmost parent.
|
||||||
@@ -479,6 +606,22 @@ JS_DestroyRuntime(JSRuntime* rt)
|
|||||||
js_delete(rt);
|
js_delete(rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(bool)
|
||||||
|
JS_SetICUMemoryFunctions(JS_ICUAllocFn allocFn, JS_ICUReallocFn reallocFn, JS_ICUFreeFn freeFn)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(jsInitState == Uninitialized,
|
||||||
|
"must call JS_SetICUMemoryFunctions before any other JSAPI "
|
||||||
|
"operation (including JS_Init)");
|
||||||
|
|
||||||
|
#if EXPOSE_INTL_API
|
||||||
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
|
u_setMemoryFunctions(/* context = */ nullptr, allocFn, reallocFn, freeFn, &status);
|
||||||
|
return U_SUCCESS(status);
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static JS_CurrentEmbedderTimeFunction currentEmbedderTimeFunction;
|
static JS_CurrentEmbedderTimeFunction currentEmbedderTimeFunction;
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
JS_PUBLIC_API(void)
|
||||||
@@ -5430,6 +5573,14 @@ JS_ObjectIsDate(JSContext* cx, HandleObject obj, bool* isDate)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(void)
|
||||||
|
JS_ClearDateCaches(JSContext* cx)
|
||||||
|
{
|
||||||
|
AssertHeapIsIdle(cx);
|
||||||
|
CHECK_REQUEST(cx);
|
||||||
|
cx->runtime()->dateTimeInfo.updateTimeZoneAdjustment();
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -6202,3 +6353,11 @@ JS::GetObjectZone(JSObject* obj)
|
|||||||
{
|
{
|
||||||
return obj->zone();
|
return obj->zone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(void)
|
||||||
|
JS::ResetTimeZone()
|
||||||
|
{
|
||||||
|
#if ENABLE_INTL_API && defined(ICU_TZ_HAS_RECREATE_DEFAULT)
|
||||||
|
icu::TimeZone::recreateDefault();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,6 +40,9 @@
|
|||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
|
extern JS_PUBLIC_API(void)
|
||||||
|
ResetTimeZone();
|
||||||
|
|
||||||
class TwoByteChars;
|
class TwoByteChars;
|
||||||
|
|
||||||
#ifdef JS_DEBUG
|
#ifdef JS_DEBUG
|
||||||
@@ -950,14 +953,49 @@ JS_IsBuiltinFunctionConstructor(JSFunction* fun);
|
|||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Locking, contexts, and memory allocation.
|
* Initialization, locking, contexts, and memory allocation.
|
||||||
*
|
*
|
||||||
* It is important that SpiderMonkey be initialized, and the first runtime and
|
* It is important that the first runtime and first context be created in a
|
||||||
* first context be created, in a single-threaded fashion. Otherwise the
|
* single-threaded fashion, otherwise the behavior of the library is undefined.
|
||||||
* behavior of the library is undefined.
|
|
||||||
* See: http://developer.mozilla.org/en/docs/Category:JSAPI_Reference
|
* See: http://developer.mozilla.org/en/docs/Category:JSAPI_Reference
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize SpiderMonkey, returning true only if initialization succeeded.
|
||||||
|
* Once this method has succeeded, it is safe to call JS_NewRuntime and other
|
||||||
|
* JSAPI methods.
|
||||||
|
*
|
||||||
|
* This method must be called before any other JSAPI method is used on any
|
||||||
|
* thread. Once it has been used, it is safe to call any JSAPI method, and it
|
||||||
|
* remains safe to do so until JS_ShutDown is correctly called.
|
||||||
|
*
|
||||||
|
* It is currently not possible to initialize SpiderMonkey multiple times (that
|
||||||
|
* is, calling JS_Init/JSAPI methods/JS_ShutDown in that order, then doing so
|
||||||
|
* again). This restriction may eventually be lifted.
|
||||||
|
*/
|
||||||
|
extern JS_PUBLIC_API(bool)
|
||||||
|
JS_Init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy free-standing resources allocated by SpiderMonkey, not associated
|
||||||
|
* with any runtime, context, or other structure.
|
||||||
|
*
|
||||||
|
* This method should be called after all other JSAPI data has been properly
|
||||||
|
* cleaned up: every new runtime must have been destroyed, every new context
|
||||||
|
* must have been destroyed, and so on. Calling this method before all other
|
||||||
|
* resources have been destroyed has undefined behavior.
|
||||||
|
*
|
||||||
|
* Failure to call this method, at present, has no adverse effects other than
|
||||||
|
* leaking memory. This may not always be the case; it's recommended that all
|
||||||
|
* embedders call this method when all other JSAPI operations have completed.
|
||||||
|
*
|
||||||
|
* It is currently not possible to initialize SpiderMonkey multiple times (that
|
||||||
|
* is, calling JS_Init/JSAPI methods/JS_ShutDown in that order, then doing so
|
||||||
|
* again). This restriction may eventually be lifted.
|
||||||
|
*/
|
||||||
|
extern JS_PUBLIC_API(void)
|
||||||
|
JS_ShutDown(void);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSRuntime*)
|
extern JS_PUBLIC_API(JSRuntime*)
|
||||||
JS_NewRuntime(uint32_t maxbytes,
|
JS_NewRuntime(uint32_t maxbytes,
|
||||||
uint32_t maxNurseryBytes = JS::DefaultNurseryBytes,
|
uint32_t maxNurseryBytes = JS::DefaultNurseryBytes,
|
||||||
@@ -966,6 +1004,20 @@ JS_NewRuntime(uint32_t maxbytes,
|
|||||||
extern JS_PUBLIC_API(void)
|
extern JS_PUBLIC_API(void)
|
||||||
JS_DestroyRuntime(JSRuntime* rt);
|
JS_DestroyRuntime(JSRuntime* rt);
|
||||||
|
|
||||||
|
// These are equivalent to ICU's |UMemAllocFn|, |UMemReallocFn|, and
|
||||||
|
// |UMemFreeFn| types. The first argument (called |context| in the ICU docs)
|
||||||
|
// will always be nullptr, and should be ignored.
|
||||||
|
typedef void* (*JS_ICUAllocFn)(const void*, size_t size);
|
||||||
|
typedef void* (*JS_ICUReallocFn)(const void*, void* p, size_t size);
|
||||||
|
typedef void (*JS_ICUFreeFn)(const void*, void* p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function can be used to track memory used by ICU.
|
||||||
|
* Do not use it unless you know what you are doing!
|
||||||
|
*/
|
||||||
|
extern JS_PUBLIC_API(bool)
|
||||||
|
JS_SetICUMemoryFunctions(JS_ICUAllocFn allocFn, JS_ICUReallocFn reallocFn, JS_ICUFreeFn freeFn);
|
||||||
|
|
||||||
typedef double (*JS_CurrentEmbedderTimeFunction)();
|
typedef double (*JS_CurrentEmbedderTimeFunction)();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4940,6 +4992,13 @@ JS_NewDateObject(JSContext* cx, int year, int mon, int mday, int hour, int min,
|
|||||||
extern JS_PUBLIC_API(bool)
|
extern JS_PUBLIC_API(bool)
|
||||||
JS_ObjectIsDate(JSContext* cx, JS::HandleObject obj, bool* isDate);
|
JS_ObjectIsDate(JSContext* cx, JS::HandleObject obj, bool* isDate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the cache of calculated local time from each Date object.
|
||||||
|
* Call to propagate a system timezone change.
|
||||||
|
*/
|
||||||
|
extern JS_PUBLIC_API(void)
|
||||||
|
JS_ClearDateCaches(JSContext* cx);
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
#include "gc/Marking.h"
|
#include "gc/Marking.h"
|
||||||
#include "jit/JitCompartment.h"
|
#include "jit/JitCompartment.h"
|
||||||
#include "js/Date.h"
|
|
||||||
#include "js/Proxy.h"
|
#include "js/Proxy.h"
|
||||||
#include "js/RootingAPI.h"
|
#include "js/RootingAPI.h"
|
||||||
#include "proxy/DeadObjectProxy.h"
|
#include "proxy/DeadObjectProxy.h"
|
||||||
@@ -121,10 +120,11 @@ JSCompartment::init(JSContext* maybecx)
|
|||||||
*
|
*
|
||||||
* As a hack, we clear our timezone cache every time we create a new
|
* As a hack, we clear our timezone cache every time we create a new
|
||||||
* compartment. This ensures that the cache is always relatively fresh, but
|
* compartment. This ensures that the cache is always relatively fresh, but
|
||||||
* shouldn't interfere with benchmarks that create tons of date objects
|
* shouldn't interfere with benchmarks which create tons of date objects
|
||||||
* (unless they also create tons of iframes, which seems unlikely).
|
* (unless they also create tons of iframes, which seems unlikely).
|
||||||
*/
|
*/
|
||||||
JS::ResetTimeZone();
|
if (maybecx)
|
||||||
|
maybecx->runtime()->dateTimeInfo.updateTimeZoneAdjustment();
|
||||||
|
|
||||||
if (!crossCompartmentWrappers.init(0)) {
|
if (!crossCompartmentWrappers.init(0)) {
|
||||||
if (maybecx)
|
if (maybecx)
|
||||||
|
|||||||
@@ -407,7 +407,7 @@ EquivalentYearForDST(int year)
|
|||||||
|
|
||||||
/* ES5 15.9.1.8. */
|
/* ES5 15.9.1.8. */
|
||||||
static double
|
static double
|
||||||
DaylightSavingTA(double t)
|
DaylightSavingTA(double t, DateTimeInfo* dtInfo)
|
||||||
{
|
{
|
||||||
if (!IsFinite(t))
|
if (!IsFinite(t))
|
||||||
return GenericNaN();
|
return GenericNaN();
|
||||||
@@ -423,30 +423,29 @@ DaylightSavingTA(double t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int64_t utcMilliseconds = static_cast<int64_t>(t);
|
int64_t utcMilliseconds = static_cast<int64_t>(t);
|
||||||
int64_t offsetMilliseconds = DateTimeInfo::getDSTOffsetMilliseconds(utcMilliseconds);
|
int64_t offsetMilliseconds = dtInfo->getDSTOffsetMilliseconds(utcMilliseconds);
|
||||||
return static_cast<double>(offsetMilliseconds);
|
return static_cast<double>(offsetMilliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
AdjustTime(double date)
|
AdjustTime(double date, DateTimeInfo* dtInfo)
|
||||||
{
|
{
|
||||||
double localTZA = DateTimeInfo::localTZA();
|
double t = DaylightSavingTA(date, dtInfo) + dtInfo->localTZA();
|
||||||
double t = DaylightSavingTA(date) + localTZA;
|
t = (dtInfo->localTZA() >= 0) ? fmod(t, msPerDay) : -fmod(msPerDay - t, msPerDay);
|
||||||
t = (localTZA >= 0) ? fmod(t, msPerDay) : -fmod(msPerDay - t, msPerDay);
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ES5 15.9.1.9. */
|
/* ES5 15.9.1.9. */
|
||||||
static double
|
static double
|
||||||
LocalTime(double t)
|
LocalTime(double t, DateTimeInfo* dtInfo)
|
||||||
{
|
{
|
||||||
return t + AdjustTime(t);
|
return t + AdjustTime(t, dtInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
UTC(double t)
|
UTC(double t, DateTimeInfo* dtInfo)
|
||||||
{
|
{
|
||||||
return t - AdjustTime(t - DateTimeInfo::localTZA());
|
return t - AdjustTime(t - dtInfo->localTZA(), dtInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ES5 15.9.1.10. */
|
/* ES5 15.9.1.10. */
|
||||||
@@ -765,7 +764,7 @@ DaysInMonth(int year, int month)
|
|||||||
*/
|
*/
|
||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
static bool
|
static bool
|
||||||
ParseISODate(const CharT* s, size_t length, ClippedTime* result)
|
ParseISODate(const CharT* s, size_t length, ClippedTime* result, DateTimeInfo* dtInfo)
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
int tzMul = 1;
|
int tzMul = 1;
|
||||||
@@ -865,7 +864,7 @@ ParseISODate(const CharT* s, size_t length, ClippedTime* result)
|
|||||||
MakeTime(hour, min, sec, frac * 1000.0));
|
MakeTime(hour, min, sec, frac * 1000.0));
|
||||||
|
|
||||||
if (isLocalTime)
|
if (isLocalTime)
|
||||||
msec = UTC(msec);
|
msec = UTC(msec, dtInfo);
|
||||||
else
|
else
|
||||||
msec -= tzMul * (tzHour * msPerHour + tzMin * msPerMinute);
|
msec -= tzMul * (tzHour * msPerHour + tzMin * msPerMinute);
|
||||||
|
|
||||||
@@ -880,9 +879,9 @@ ParseISODate(const CharT* s, size_t length, ClippedTime* result)
|
|||||||
|
|
||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
static bool
|
static bool
|
||||||
ParseDate(const CharT* s, size_t length, ClippedTime* result)
|
ParseDate(const CharT* s, size_t length, ClippedTime* result, DateTimeInfo* dtInfo)
|
||||||
{
|
{
|
||||||
if (ParseISODate(s, length, result))
|
if (ParseISODate(s, length, result, dtInfo))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
@@ -1145,7 +1144,7 @@ ParseDate(const CharT* s, size_t length, ClippedTime* result)
|
|||||||
double msec = MakeDate(MakeDay(year, mon, mday), MakeTime(hour, min, sec, 0));
|
double msec = MakeDate(MakeDay(year, mon, mday), MakeTime(hour, min, sec, 0));
|
||||||
|
|
||||||
if (tzOffset == -1) /* no time zone specified, have to use local */
|
if (tzOffset == -1) /* no time zone specified, have to use local */
|
||||||
msec = UTC(msec);
|
msec = UTC(msec, dtInfo);
|
||||||
else
|
else
|
||||||
msec += tzOffset * msPerMinute;
|
msec += tzOffset * msPerMinute;
|
||||||
|
|
||||||
@@ -1154,12 +1153,12 @@ ParseDate(const CharT* s, size_t length, ClippedTime* result)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ParseDate(JSLinearString* s, ClippedTime* result)
|
ParseDate(JSLinearString* s, ClippedTime* result, DateTimeInfo* dtInfo)
|
||||||
{
|
{
|
||||||
AutoCheckCannotGC nogc;
|
AutoCheckCannotGC nogc;
|
||||||
return s->hasLatin1Chars()
|
return s->hasLatin1Chars()
|
||||||
? ParseDate(s->latin1Chars(nogc), s->length(), result)
|
? ParseDate(s->latin1Chars(nogc), s->length(), result, dtInfo)
|
||||||
: ParseDate(s->twoByteChars(nogc), s->length(), result);
|
: ParseDate(s->twoByteChars(nogc), s->length(), result, dtInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@@ -1180,7 +1179,7 @@ date_parse(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
ClippedTime result;
|
ClippedTime result;
|
||||||
if (!ParseDate(linearStr, &result)) {
|
if (!ParseDate(linearStr, &result, &cx->runtime()->dateTimeInfo)) {
|
||||||
args.rval().setNaN();
|
args.rval().setNaN();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1220,17 +1219,17 @@ DateObject::setUTCTime(ClippedTime t, MutableHandleValue vp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DateObject::fillLocalTimeSlots()
|
DateObject::fillLocalTimeSlots(DateTimeInfo* dtInfo)
|
||||||
{
|
{
|
||||||
/* Check if the cache is already populated. */
|
/* Check if the cache is already populated. */
|
||||||
if (!getReservedSlot(LOCAL_TIME_SLOT).isUndefined() &&
|
if (!getReservedSlot(LOCAL_TIME_SLOT).isUndefined() &&
|
||||||
getReservedSlot(TZA_SLOT).toDouble() == DateTimeInfo::localTZA())
|
getReservedSlot(TZA_SLOT).toDouble() == dtInfo->localTZA())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remember timezone used to generate the local cache. */
|
/* Remember timezone used to generate the local cache. */
|
||||||
setReservedSlot(TZA_SLOT, DoubleValue(DateTimeInfo::localTZA()));
|
setReservedSlot(TZA_SLOT, DoubleValue(dtInfo->localTZA()));
|
||||||
|
|
||||||
double utcTime = UTCTime().toNumber();
|
double utcTime = UTCTime().toNumber();
|
||||||
|
|
||||||
@@ -1240,7 +1239,7 @@ DateObject::fillLocalTimeSlots()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
double localTime = LocalTime(utcTime);
|
double localTime = LocalTime(utcTime, dtInfo);
|
||||||
|
|
||||||
setReservedSlot(LOCAL_TIME_SLOT, DoubleValue(localTime));
|
setReservedSlot(LOCAL_TIME_SLOT, DoubleValue(localTime));
|
||||||
|
|
||||||
@@ -1350,9 +1349,9 @@ DateObject::fillLocalTimeSlots()
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline double
|
inline double
|
||||||
DateObject::cachedLocalTime()
|
DateObject::cachedLocalTime(DateTimeInfo* dtInfo)
|
||||||
{
|
{
|
||||||
fillLocalTimeSlots();
|
fillLocalTimeSlots(dtInfo);
|
||||||
return getReservedSlot(LOCAL_TIME_SLOT).toDouble();
|
return getReservedSlot(LOCAL_TIME_SLOT).toDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1383,7 +1382,7 @@ date_getTime(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
DateObject::getYear_impl(JSContext* cx, const CallArgs& args)
|
DateObject::getYear_impl(JSContext* cx, const CallArgs& args)
|
||||||
{
|
{
|
||||||
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
||||||
dateObj->fillLocalTimeSlots();
|
dateObj->fillLocalTimeSlots(&cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
Value yearVal = dateObj->getReservedSlot(LOCAL_YEAR_SLOT);
|
Value yearVal = dateObj->getReservedSlot(LOCAL_YEAR_SLOT);
|
||||||
if (yearVal.isInt32()) {
|
if (yearVal.isInt32()) {
|
||||||
@@ -1408,7 +1407,7 @@ date_getYear(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
DateObject::getFullYear_impl(JSContext* cx, const CallArgs& args)
|
DateObject::getFullYear_impl(JSContext* cx, const CallArgs& args)
|
||||||
{
|
{
|
||||||
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
||||||
dateObj->fillLocalTimeSlots();
|
dateObj->fillLocalTimeSlots(&cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
args.rval().set(dateObj->getReservedSlot(LOCAL_YEAR_SLOT));
|
args.rval().set(dateObj->getReservedSlot(LOCAL_YEAR_SLOT));
|
||||||
return true;
|
return true;
|
||||||
@@ -1443,7 +1442,7 @@ date_getUTCFullYear(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
DateObject::getMonth_impl(JSContext* cx, const CallArgs& args)
|
DateObject::getMonth_impl(JSContext* cx, const CallArgs& args)
|
||||||
{
|
{
|
||||||
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
||||||
dateObj->fillLocalTimeSlots();
|
dateObj->fillLocalTimeSlots(&cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
args.rval().set(dateObj->getReservedSlot(LOCAL_MONTH_SLOT));
|
args.rval().set(dateObj->getReservedSlot(LOCAL_MONTH_SLOT));
|
||||||
return true;
|
return true;
|
||||||
@@ -1475,7 +1474,7 @@ date_getUTCMonth(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
DateObject::getDate_impl(JSContext* cx, const CallArgs& args)
|
DateObject::getDate_impl(JSContext* cx, const CallArgs& args)
|
||||||
{
|
{
|
||||||
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
||||||
dateObj->fillLocalTimeSlots();
|
dateObj->fillLocalTimeSlots(&cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
args.rval().set(dateObj->getReservedSlot(LOCAL_DATE_SLOT));
|
args.rval().set(dateObj->getReservedSlot(LOCAL_DATE_SLOT));
|
||||||
return true;
|
return true;
|
||||||
@@ -1510,7 +1509,7 @@ date_getUTCDate(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
DateObject::getDay_impl(JSContext* cx, const CallArgs& args)
|
DateObject::getDay_impl(JSContext* cx, const CallArgs& args)
|
||||||
{
|
{
|
||||||
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
||||||
dateObj->fillLocalTimeSlots();
|
dateObj->fillLocalTimeSlots(&cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
args.rval().set(dateObj->getReservedSlot(LOCAL_DAY_SLOT));
|
args.rval().set(dateObj->getReservedSlot(LOCAL_DAY_SLOT));
|
||||||
return true;
|
return true;
|
||||||
@@ -1545,7 +1544,7 @@ date_getUTCDay(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
DateObject::getHours_impl(JSContext* cx, const CallArgs& args)
|
DateObject::getHours_impl(JSContext* cx, const CallArgs& args)
|
||||||
{
|
{
|
||||||
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
||||||
dateObj->fillLocalTimeSlots();
|
dateObj->fillLocalTimeSlots(&cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
args.rval().set(dateObj->getReservedSlot(LOCAL_HOURS_SLOT));
|
args.rval().set(dateObj->getReservedSlot(LOCAL_HOURS_SLOT));
|
||||||
return true;
|
return true;
|
||||||
@@ -1580,7 +1579,7 @@ date_getUTCHours(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
DateObject::getMinutes_impl(JSContext* cx, const CallArgs& args)
|
DateObject::getMinutes_impl(JSContext* cx, const CallArgs& args)
|
||||||
{
|
{
|
||||||
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
||||||
dateObj->fillLocalTimeSlots();
|
dateObj->fillLocalTimeSlots(&cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
args.rval().set(dateObj->getReservedSlot(LOCAL_MINUTES_SLOT));
|
args.rval().set(dateObj->getReservedSlot(LOCAL_MINUTES_SLOT));
|
||||||
return true;
|
return true;
|
||||||
@@ -1617,7 +1616,7 @@ date_getUTCMinutes(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
DateObject::getUTCSeconds_impl(JSContext* cx, const CallArgs& args)
|
DateObject::getUTCSeconds_impl(JSContext* cx, const CallArgs& args)
|
||||||
{
|
{
|
||||||
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
||||||
dateObj->fillLocalTimeSlots();
|
dateObj->fillLocalTimeSlots(&cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
args.rval().set(dateObj->getReservedSlot(LOCAL_SECONDS_SLOT));
|
args.rval().set(dateObj->getReservedSlot(LOCAL_SECONDS_SLOT));
|
||||||
return true;
|
return true;
|
||||||
@@ -1655,7 +1654,7 @@ DateObject::getTimezoneOffset_impl(JSContext* cx, const CallArgs& args)
|
|||||||
{
|
{
|
||||||
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
DateObject* dateObj = &args.thisv().toObject().as<DateObject>();
|
||||||
double utctime = dateObj->UTCTime().toNumber();
|
double utctime = dateObj->UTCTime().toNumber();
|
||||||
double localtime = dateObj->cachedLocalTime();
|
double localtime = dateObj->cachedLocalTime(&cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the time zone offset in minutes for the current locale that is
|
* Return the time zone offset in minutes for the current locale that is
|
||||||
@@ -1728,27 +1727,25 @@ GetMinsOrDefault(JSContext* cx, const CallArgs& args, unsigned i, double t, doub
|
|||||||
return ToNumber(cx, args[i], mins);
|
return ToNumber(cx, args[i], mins);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ES6 20.3.4.23. */
|
/* ES5 15.9.5.28. */
|
||||||
MOZ_ALWAYS_INLINE bool
|
MOZ_ALWAYS_INLINE bool
|
||||||
date_setMilliseconds_impl(JSContext* cx, const CallArgs& args)
|
date_setMilliseconds_impl(JSContext* cx, const CallArgs& args)
|
||||||
{
|
{
|
||||||
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
||||||
|
|
||||||
// Steps 1-2.
|
/* Step 1. */
|
||||||
double t = LocalTime(dateObj->UTCTime().toNumber());
|
double t = LocalTime(dateObj->UTCTime().toNumber(), &cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
// Steps 3-4.
|
/* Step 2. */
|
||||||
double ms;
|
double milli;
|
||||||
if (!ToNumber(cx, args.get(0), &ms))
|
if (!ToNumber(cx, args.get(0), &milli))
|
||||||
return false;
|
return false;
|
||||||
|
double time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), milli);
|
||||||
|
|
||||||
// Step 5.
|
/* Step 3. */
|
||||||
double time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms);
|
ClippedTime u = TimeClip(UTC(MakeDate(Day(t), time), &cx->runtime()->dateTimeInfo));
|
||||||
|
|
||||||
// Step 6.
|
/* Steps 4-5. */
|
||||||
ClippedTime u = TimeClip(UTC(MakeDate(Day(t), time)));
|
|
||||||
|
|
||||||
// Steps 7-8.
|
|
||||||
dateObj->setUTCTime(u, args.rval());
|
dateObj->setUTCTime(u, args.rval());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1796,31 +1793,31 @@ date_setSeconds_impl(JSContext* cx, const CallArgs& args)
|
|||||||
{
|
{
|
||||||
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
||||||
|
|
||||||
// Steps 1-2.
|
/* Step 1. */
|
||||||
double t = LocalTime(dateObj->UTCTime().toNumber());
|
double t = LocalTime(dateObj->UTCTime().toNumber(), &cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
// Steps 3-4.
|
/* Step 2. */
|
||||||
double s;
|
double s;
|
||||||
if (!ToNumber(cx, args.get(0), &s))
|
if (!ToNumber(cx, args.get(0), &s))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Steps 5-6.
|
/* Step 3. */
|
||||||
double milli;
|
double milli;
|
||||||
if (!GetMsecsOrDefault(cx, args, 1, t, &milli))
|
if (!GetMsecsOrDefault(cx, args, 1, t, &milli))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Step 7.
|
/* Step 4. */
|
||||||
double date = MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli));
|
double date = MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli));
|
||||||
|
|
||||||
// Step 8.
|
/* Step 5. */
|
||||||
ClippedTime u = TimeClip(UTC(date));
|
ClippedTime u = TimeClip(UTC(date, &cx->runtime()->dateTimeInfo));
|
||||||
|
|
||||||
// Step 9.
|
/* Steps 6-7. */
|
||||||
dateObj->setUTCTime(u, args.rval());
|
dateObj->setUTCTime(u, args.rval());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ES6 20.3.4.26. */
|
/* ES5 15.9.5.31. */
|
||||||
static bool
|
static bool
|
||||||
date_setSeconds(JSContext* cx, unsigned argc, Value* vp)
|
date_setSeconds(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
@@ -1870,40 +1867,39 @@ date_setMinutes_impl(JSContext* cx, const CallArgs& args)
|
|||||||
{
|
{
|
||||||
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
||||||
|
|
||||||
// Steps 1-2.
|
/* Step 1. */
|
||||||
double t = LocalTime(dateObj->UTCTime().toNumber());
|
double t = LocalTime(dateObj->UTCTime().toNumber(), &cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
// Steps 3-4.
|
/* Step 2. */
|
||||||
double m;
|
double m;
|
||||||
if (!ToNumber(cx, args.get(0), &m))
|
if (!ToNumber(cx, args.get(0), &m))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Steps 5-6.
|
/* Step 3. */
|
||||||
double s;
|
double s;
|
||||||
if (!GetSecsOrDefault(cx, args, 1, t, &s))
|
if (!GetSecsOrDefault(cx, args, 1, t, &s))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Steps 7-8.
|
/* Step 4. */
|
||||||
double milli;
|
double milli;
|
||||||
if (!GetMsecsOrDefault(cx, args, 2, t, &milli))
|
if (!GetMsecsOrDefault(cx, args, 2, t, &milli))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Step 9.
|
/* Step 5. */
|
||||||
double date = MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli));
|
double date = MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli));
|
||||||
|
|
||||||
// Step 10.
|
/* Step 6. */
|
||||||
ClippedTime u = TimeClip(UTC(date));
|
ClippedTime u = TimeClip(UTC(date, &cx->runtime()->dateTimeInfo));
|
||||||
|
|
||||||
// Steps 11-12.
|
/* Steps 7-8. */
|
||||||
dateObj->setUTCTime(u, args.rval());
|
dateObj->setUTCTime(u, args.rval());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ES6 20.3.4.24. */
|
/* ES5 15.9.5.33. */
|
||||||
static bool
|
static bool
|
||||||
date_setMinutes(JSContext* cx, unsigned argc, Value* vp)
|
date_setMinutes(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
// Steps 1-2 (the effectful parts).
|
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
return CallNonGenericMethod<IsDate, date_setMinutes_impl>(cx, args);
|
return CallNonGenericMethod<IsDate, date_setMinutes_impl>(cx, args);
|
||||||
}
|
}
|
||||||
@@ -1955,36 +1951,36 @@ date_setHours_impl(JSContext* cx, const CallArgs& args)
|
|||||||
{
|
{
|
||||||
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
||||||
|
|
||||||
// Steps 1-2.
|
/* Step 1. */
|
||||||
double t = LocalTime(dateObj->UTCTime().toNumber());
|
double t = LocalTime(dateObj->UTCTime().toNumber(), &cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
// Steps 3-4.
|
/* Step 2. */
|
||||||
double h;
|
double h;
|
||||||
if (!ToNumber(cx, args.get(0), &h))
|
if (!ToNumber(cx, args.get(0), &h))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Steps 5-6.
|
/* Step 3. */
|
||||||
double m;
|
double m;
|
||||||
if (!GetMinsOrDefault(cx, args, 1, t, &m))
|
if (!GetMinsOrDefault(cx, args, 1, t, &m))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Steps 7-8.
|
/* Step 4. */
|
||||||
double s;
|
double s;
|
||||||
if (!GetSecsOrDefault(cx, args, 2, t, &s))
|
if (!GetSecsOrDefault(cx, args, 2, t, &s))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Steps 9-10.
|
/* Step 5. */
|
||||||
double milli;
|
double milli;
|
||||||
if (!GetMsecsOrDefault(cx, args, 3, t, &milli))
|
if (!GetMsecsOrDefault(cx, args, 3, t, &milli))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Step 11.
|
/* Step 6. */
|
||||||
double date = MakeDate(Day(t), MakeTime(h, m, s, milli));
|
double date = MakeDate(Day(t), MakeTime(h, m, s, milli));
|
||||||
|
|
||||||
// Step 12.
|
/* Step 6. */
|
||||||
ClippedTime u = TimeClip(UTC(date));
|
ClippedTime u = TimeClip(UTC(date, &cx->runtime()->dateTimeInfo));
|
||||||
|
|
||||||
// Steps 13-14.
|
/* Steps 7-8. */
|
||||||
dateObj->setUTCTime(u, args.rval());
|
dateObj->setUTCTime(u, args.rval());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2050,7 +2046,7 @@ date_setDate_impl(JSContext* cx, const CallArgs& args)
|
|||||||
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
||||||
|
|
||||||
/* Step 1. */
|
/* Step 1. */
|
||||||
double t = LocalTime(dateObj->UTCTime().toNumber());
|
double t = LocalTime(dateObj->UTCTime().toNumber(), &cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
/* Step 2. */
|
/* Step 2. */
|
||||||
double date;
|
double date;
|
||||||
@@ -2061,7 +2057,7 @@ date_setDate_impl(JSContext* cx, const CallArgs& args)
|
|||||||
double newDate = MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t));
|
double newDate = MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t));
|
||||||
|
|
||||||
/* Step 4. */
|
/* Step 4. */
|
||||||
ClippedTime u = TimeClip(UTC(newDate));
|
ClippedTime u = TimeClip(UTC(newDate, &cx->runtime()->dateTimeInfo));
|
||||||
|
|
||||||
/* Steps 5-6. */
|
/* Steps 5-6. */
|
||||||
dateObj->setUTCTime(u, args.rval());
|
dateObj->setUTCTime(u, args.rval());
|
||||||
@@ -2134,7 +2130,7 @@ date_setMonth_impl(JSContext* cx, const CallArgs& args)
|
|||||||
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
||||||
|
|
||||||
/* Step 1. */
|
/* Step 1. */
|
||||||
double t = LocalTime(dateObj->UTCTime().toNumber());
|
double t = LocalTime(dateObj->UTCTime().toNumber(), &cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
/* Step 2. */
|
/* Step 2. */
|
||||||
double m;
|
double m;
|
||||||
@@ -2150,7 +2146,7 @@ date_setMonth_impl(JSContext* cx, const CallArgs& args)
|
|||||||
double newDate = MakeDate(MakeDay(YearFromTime(t), m, date), TimeWithinDay(t));
|
double newDate = MakeDate(MakeDay(YearFromTime(t), m, date), TimeWithinDay(t));
|
||||||
|
|
||||||
/* Step 5. */
|
/* Step 5. */
|
||||||
ClippedTime u = TimeClip(UTC(newDate));
|
ClippedTime u = TimeClip(UTC(newDate, &cx->runtime()->dateTimeInfo));
|
||||||
|
|
||||||
/* Steps 6-7. */
|
/* Steps 6-7. */
|
||||||
dateObj->setUTCTime(u, args.rval());
|
dateObj->setUTCTime(u, args.rval());
|
||||||
@@ -2202,12 +2198,12 @@ date_setUTCMonth(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
ThisLocalTimeOrZero(Handle<DateObject*> dateObj)
|
ThisLocalTimeOrZero(Handle<DateObject*> dateObj, DateTimeInfo* dtInfo)
|
||||||
{
|
{
|
||||||
double t = dateObj->UTCTime().toNumber();
|
double t = dateObj->UTCTime().toNumber();
|
||||||
if (IsNaN(t))
|
if (IsNaN(t))
|
||||||
return +0;
|
return +0;
|
||||||
return LocalTime(t);
|
return LocalTime(t, dtInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
@@ -2224,7 +2220,7 @@ date_setFullYear_impl(JSContext* cx, const CallArgs& args)
|
|||||||
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
||||||
|
|
||||||
/* Step 1. */
|
/* Step 1. */
|
||||||
double t = ThisLocalTimeOrZero(dateObj);
|
double t = ThisLocalTimeOrZero(dateObj, &cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
/* Step 2. */
|
/* Step 2. */
|
||||||
double y;
|
double y;
|
||||||
@@ -2245,7 +2241,7 @@ date_setFullYear_impl(JSContext* cx, const CallArgs& args)
|
|||||||
double newDate = MakeDate(MakeDay(y, m, date), TimeWithinDay(t));
|
double newDate = MakeDate(MakeDay(y, m, date), TimeWithinDay(t));
|
||||||
|
|
||||||
/* Step 6. */
|
/* Step 6. */
|
||||||
ClippedTime u = TimeClip(UTC(newDate));
|
ClippedTime u = TimeClip(UTC(newDate, &cx->runtime()->dateTimeInfo));
|
||||||
|
|
||||||
/* Steps 7-8. */
|
/* Steps 7-8. */
|
||||||
dateObj->setUTCTime(u, args.rval());
|
dateObj->setUTCTime(u, args.rval());
|
||||||
@@ -2308,7 +2304,7 @@ date_setYear_impl(JSContext* cx, const CallArgs& args)
|
|||||||
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
||||||
|
|
||||||
/* Step 1. */
|
/* Step 1. */
|
||||||
double t = ThisLocalTimeOrZero(dateObj);
|
double t = ThisLocalTimeOrZero(dateObj, &cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
/* Step 2. */
|
/* Step 2. */
|
||||||
double y;
|
double y;
|
||||||
@@ -2330,7 +2326,7 @@ date_setYear_impl(JSContext* cx, const CallArgs& args)
|
|||||||
double day = MakeDay(yint, MonthFromTime(t), DateFromTime(t));
|
double day = MakeDay(yint, MonthFromTime(t), DateFromTime(t));
|
||||||
|
|
||||||
/* Step 6. */
|
/* Step 6. */
|
||||||
double u = UTC(MakeDate(day, TimeWithinDay(t)));
|
double u = UTC(MakeDate(day, TimeWithinDay(t)), &cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
/* Steps 7-8. */
|
/* Steps 7-8. */
|
||||||
dateObj->setUTCTime(TimeClip(u), args.rval());
|
dateObj->setUTCTime(TimeClip(u), args.rval());
|
||||||
@@ -2509,7 +2505,7 @@ date_toJSON(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
/* for Date.toLocaleFormat; interface to PRMJTime date struct.
|
/* for Date.toLocaleFormat; interface to PRMJTime date struct.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
new_explode(double timeval, PRMJTime* split)
|
new_explode(double timeval, PRMJTime* split, DateTimeInfo* dtInfo)
|
||||||
{
|
{
|
||||||
double year = YearFromTime(timeval);
|
double year = YearFromTime(timeval);
|
||||||
|
|
||||||
@@ -2525,7 +2521,7 @@ new_explode(double timeval, PRMJTime* split)
|
|||||||
|
|
||||||
/* not sure how this affects things, but it doesn't seem
|
/* not sure how this affects things, but it doesn't seem
|
||||||
to matter. */
|
to matter. */
|
||||||
split->tm_isdst = (DaylightSavingTA(timeval) != 0);
|
split->tm_isdst = (DaylightSavingTA(timeval, dtInfo) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum formatspec {
|
typedef enum formatspec {
|
||||||
@@ -2547,11 +2543,11 @@ date_format(JSContext* cx, double date, formatspec format, MutableHandleValue rv
|
|||||||
} else {
|
} else {
|
||||||
MOZ_ASSERT(NumbersAreIdentical(TimeClip(date).toDouble(), date));
|
MOZ_ASSERT(NumbersAreIdentical(TimeClip(date).toDouble(), date));
|
||||||
|
|
||||||
double local = LocalTime(date);
|
double local = LocalTime(date, &cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
/* offset from GMT in minutes. The offset includes daylight savings,
|
/* offset from GMT in minutes. The offset includes daylight savings,
|
||||||
if it applies. */
|
if it applies. */
|
||||||
int minutes = (int) floor(AdjustTime(date) / msPerMinute);
|
int minutes = (int) floor(AdjustTime(date, &cx->runtime()->dateTimeInfo) / msPerMinute);
|
||||||
|
|
||||||
/* map 510 minutes to 0830 hours */
|
/* map 510 minutes to 0830 hours */
|
||||||
int offset = (minutes / 60) * 100 + minutes % 60;
|
int offset = (minutes / 60) * 100 + minutes % 60;
|
||||||
@@ -2567,7 +2563,7 @@ date_format(JSContext* cx, double date, formatspec format, MutableHandleValue rv
|
|||||||
|
|
||||||
/* get a timezone string from the OS to include as a
|
/* get a timezone string from the OS to include as a
|
||||||
comment. */
|
comment. */
|
||||||
new_explode(date, &split);
|
new_explode(date, &split, &cx->runtime()->dateTimeInfo);
|
||||||
if (PRMJ_FormatTime(tzbuf, sizeof tzbuf, "(%Z)", &split) != 0) {
|
if (PRMJ_FormatTime(tzbuf, sizeof tzbuf, "(%Z)", &split) != 0) {
|
||||||
|
|
||||||
/* Decide whether to use the resulting timezone string.
|
/* Decide whether to use the resulting timezone string.
|
||||||
@@ -2657,9 +2653,9 @@ ToLocaleFormatHelper(JSContext* cx, HandleObject obj, const char* format, Mutabl
|
|||||||
JS_snprintf(buf, sizeof buf, js_NaN_date_str);
|
JS_snprintf(buf, sizeof buf, js_NaN_date_str);
|
||||||
} else {
|
} else {
|
||||||
int result_len;
|
int result_len;
|
||||||
double local = LocalTime(utctime);
|
double local = LocalTime(utctime, &cx->runtime()->dateTimeInfo);
|
||||||
PRMJTime split;
|
PRMJTime split;
|
||||||
new_explode(local, &split);
|
new_explode(local, &split, &cx->runtime()->dateTimeInfo);
|
||||||
|
|
||||||
/* Let PRMJTime format it. */
|
/* Let PRMJTime format it. */
|
||||||
result_len = PRMJ_FormatTime(buf, sizeof buf, format, &split);
|
result_len = PRMJ_FormatTime(buf, sizeof buf, format, &split);
|
||||||
@@ -2677,7 +2673,7 @@ ToLocaleFormatHelper(JSContext* cx, HandleObject obj, const char* format, Mutabl
|
|||||||
/* ...but not if starts with 4-digit year, like 2022/3/11. */
|
/* ...but not if starts with 4-digit year, like 2022/3/11. */
|
||||||
!(isdigit(buf[0]) && isdigit(buf[1]) &&
|
!(isdigit(buf[0]) && isdigit(buf[1]) &&
|
||||||
isdigit(buf[2]) && isdigit(buf[3]))) {
|
isdigit(buf[2]) && isdigit(buf[3]))) {
|
||||||
double localtime = obj->as<DateObject>().cachedLocalTime();
|
double localtime = obj->as<DateObject>().cachedLocalTime(&cx->runtime()->dateTimeInfo);
|
||||||
int year = IsNaN(localtime) ? 0 : (int) YearFromTime(localtime);
|
int year = IsNaN(localtime) ? 0 : (int) YearFromTime(localtime);
|
||||||
JS_snprintf(buf + (result_len - 2), (sizeof buf) - (result_len - 2),
|
JS_snprintf(buf + (result_len - 2), (sizeof buf) - (result_len - 2),
|
||||||
"%d", year);
|
"%d", year);
|
||||||
@@ -3074,7 +3070,7 @@ DateOneArgument(JSContext* cx, const CallArgs& args)
|
|||||||
if (!linearStr)
|
if (!linearStr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!ParseDate(linearStr, &t))
|
if (!ParseDate(linearStr, &t, &cx->runtime()->dateTimeInfo))
|
||||||
t = ClippedTime::invalid();
|
t = ClippedTime::invalid();
|
||||||
} else {
|
} else {
|
||||||
double d;
|
double d;
|
||||||
@@ -3163,7 +3159,7 @@ DateMultipleArguments(JSContext* cx, const CallArgs& args)
|
|||||||
double finalDate = MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli));
|
double finalDate = MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli));
|
||||||
|
|
||||||
// Steps 3q-t.
|
// Steps 3q-t.
|
||||||
return NewDateObject(cx, args, TimeClip(UTC(finalDate)));
|
return NewDateObject(cx, args, TimeClip(UTC(finalDate, &cx->runtime()->dateTimeInfo)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToDateString(cx, args, NowAsMillis());
|
return ToDateString(cx, args, NowAsMillis());
|
||||||
@@ -3275,7 +3271,7 @@ js::NewDateObject(JSContext* cx, int year, int mon, int mday,
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mon < 12);
|
MOZ_ASSERT(mon < 12);
|
||||||
double msec_time = MakeDate(MakeDay(year, mon, mday), MakeTime(hour, min, sec, 0.0));
|
double msec_time = MakeDate(MakeDay(year, mon, mday), MakeTime(hour, min, sec, 0.0));
|
||||||
return NewDateObjectMsec(cx, TimeClip(UTC(msec_time)));
|
return NewDateObjectMsec(cx, TimeClip(UTC(msec_time, &cx->runtime()->dateTimeInfo)));
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_FRIEND_API(bool)
|
JS_FRIEND_API(bool)
|
||||||
|
|||||||
@@ -114,7 +114,6 @@ EXPORTS.js += [
|
|||||||
'../public/HashTable.h',
|
'../public/HashTable.h',
|
||||||
'../public/HeapAPI.h',
|
'../public/HeapAPI.h',
|
||||||
'../public/Id.h',
|
'../public/Id.h',
|
||||||
'../public/Initialization.h',
|
|
||||||
'../public/LegacyIntTypes.h',
|
'../public/LegacyIntTypes.h',
|
||||||
'../public/MemoryMetrics.h',
|
'../public/MemoryMetrics.h',
|
||||||
'../public/Principals.h',
|
'../public/Principals.h',
|
||||||
@@ -363,7 +362,6 @@ SOURCES += [
|
|||||||
'jsatom.cpp',
|
'jsatom.cpp',
|
||||||
'jsmath.cpp',
|
'jsmath.cpp',
|
||||||
'jsutil.cpp',
|
'jsutil.cpp',
|
||||||
'vm/Initialization.cpp',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['JS_POSIX_NSPR']:
|
if CONFIG['JS_POSIX_NSPR']:
|
||||||
|
|||||||
@@ -67,7 +67,6 @@
|
|||||||
#include "jit/OptimizationTracking.h"
|
#include "jit/OptimizationTracking.h"
|
||||||
#include "js/Debug.h"
|
#include "js/Debug.h"
|
||||||
#include "js/GCAPI.h"
|
#include "js/GCAPI.h"
|
||||||
#include "js/Initialization.h"
|
|
||||||
#include "js/StructuredClone.h"
|
#include "js/StructuredClone.h"
|
||||||
#include "js/TrackedOptimizationInfo.h"
|
#include "js/TrackedOptimizationInfo.h"
|
||||||
#include "perf/jsperf.h"
|
#include "perf/jsperf.h"
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
class DateTimeInfo;
|
||||||
|
|
||||||
class DateObject : public NativeObject
|
class DateObject : public NativeObject
|
||||||
{
|
{
|
||||||
static const uint32_t UTC_TIME_SLOT = 0;
|
static const uint32_t UTC_TIME_SLOT = 0;
|
||||||
@@ -56,12 +58,12 @@ class DateObject : public NativeObject
|
|||||||
void setUTCTime(JS::ClippedTime t);
|
void setUTCTime(JS::ClippedTime t);
|
||||||
void setUTCTime(JS::ClippedTime t, MutableHandleValue vp);
|
void setUTCTime(JS::ClippedTime t, MutableHandleValue vp);
|
||||||
|
|
||||||
inline double cachedLocalTime();
|
inline double cachedLocalTime(DateTimeInfo* dtInfo);
|
||||||
|
|
||||||
// Cache the local time, year, month, and so forth of the object.
|
// Cache the local time, year, month, and so forth of the object.
|
||||||
// If UTC time is not finite (e.g., NaN), the local time
|
// If UTC time is not finite (e.g., NaN), the local time
|
||||||
// slots will be set to the UTC time without conversion.
|
// slots will be set to the UTC time without conversion.
|
||||||
void fillLocalTimeSlots();
|
void fillLocalTimeSlots(DateTimeInfo* dtInfo);
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE bool getTime_impl(JSContext* cx, const CallArgs& args);
|
static MOZ_ALWAYS_INLINE bool getTime_impl(JSContext* cx, const CallArgs& args);
|
||||||
static MOZ_ALWAYS_INLINE bool getYear_impl(JSContext* cx, const CallArgs& args);
|
static MOZ_ALWAYS_INLINE bool getYear_impl(JSContext* cx, const CallArgs& args);
|
||||||
|
|||||||
@@ -10,19 +10,8 @@
|
|||||||
|
|
||||||
#include "jsutil.h"
|
#include "jsutil.h"
|
||||||
|
|
||||||
#include "js/Date.h"
|
|
||||||
#if ENABLE_INTL_API
|
|
||||||
#include "unicode/timezone.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using mozilla::UnspecifiedNaN;
|
using mozilla::UnspecifiedNaN;
|
||||||
|
|
||||||
/* static */ js::DateTimeInfo
|
|
||||||
js::DateTimeInfo::instance;
|
|
||||||
|
|
||||||
/* static */ mozilla::Atomic<bool, mozilla::ReleaseAcquire>
|
|
||||||
js::DateTimeInfo::AcquireLock::spinLock;
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ComputeLocalTime(time_t local, struct tm* ptm)
|
ComputeLocalTime(time_t local, struct tm* ptm)
|
||||||
{
|
{
|
||||||
@@ -142,7 +131,7 @@ UTCToLocalStandardOffsetSeconds()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
js::DateTimeInfo::internalUpdateTimeZoneAdjustment()
|
js::DateTimeInfo::updateTimeZoneAdjustment()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The difference between local standard time and UTC will never change for
|
* The difference between local standard time and UTC will never change for
|
||||||
@@ -175,19 +164,12 @@ js::DateTimeInfo::internalUpdateTimeZoneAdjustment()
|
|||||||
* negative numbers to ensure the first computation is always a cache miss and
|
* negative numbers to ensure the first computation is always a cache miss and
|
||||||
* doesn't return a bogus offset.
|
* doesn't return a bogus offset.
|
||||||
*/
|
*/
|
||||||
/* static */ void
|
js::DateTimeInfo::DateTimeInfo()
|
||||||
js::DateTimeInfo::init()
|
|
||||||
{
|
{
|
||||||
DateTimeInfo* dtInfo = &DateTimeInfo::instance;
|
|
||||||
|
|
||||||
MOZ_ASSERT(dtInfo->localTZA_ == 0,
|
|
||||||
"we should be initializing only once, and the static instance "
|
|
||||||
"should have started out zeroed");
|
|
||||||
|
|
||||||
// Set to a totally impossible TZA so that the comparison above will fail
|
// Set to a totally impossible TZA so that the comparison above will fail
|
||||||
// and all fields will be properly initialized.
|
// and all fields will be properly initialized.
|
||||||
dtInfo->localTZA_ = UnspecifiedNaN<double>();
|
localTZA_ = UnspecifiedNaN<double>();
|
||||||
dtInfo->internalUpdateTimeZoneAdjustment();
|
updateTimeZoneAdjustment();
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
@@ -219,7 +201,7 @@ js::DateTimeInfo::computeDSTOffsetMilliseconds(int64_t utcSeconds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
js::DateTimeInfo::internalGetDSTOffsetMilliseconds(int64_t utcMilliseconds)
|
js::DateTimeInfo::getDSTOffsetMilliseconds(int64_t utcMilliseconds)
|
||||||
{
|
{
|
||||||
sanityCheck();
|
sanityCheck();
|
||||||
|
|
||||||
@@ -306,13 +288,3 @@ js::DateTimeInfo::sanityCheck()
|
|||||||
MOZ_ASSERT_IF(rangeStartSeconds != INT64_MIN,
|
MOZ_ASSERT_IF(rangeStartSeconds != INT64_MIN,
|
||||||
rangeStartSeconds <= MaxUnixTimeT && rangeEndSeconds <= MaxUnixTimeT);
|
rangeStartSeconds <= MaxUnixTimeT && rangeEndSeconds <= MaxUnixTimeT);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
|
||||||
JS::ResetTimeZone()
|
|
||||||
{
|
|
||||||
DateTimeInfo::updateTimeZoneAdjustment();
|
|
||||||
|
|
||||||
#if ENABLE_INTL_API && defined(ICU_TZ_HAS_RECREATE_DEFAULT)
|
|
||||||
icu::TimeZone::recreateDefault();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,17 +7,12 @@
|
|||||||
#ifndef vm_DateTime_h
|
#ifndef vm_DateTime_h
|
||||||
#define vm_DateTime_h
|
#define vm_DateTime_h
|
||||||
|
|
||||||
#include "mozilla/Assertions.h"
|
|
||||||
#include "mozilla/Atomics.h"
|
|
||||||
#include "mozilla/Attributes.h"
|
|
||||||
#include "mozilla/FloatingPoint.h"
|
#include "mozilla/FloatingPoint.h"
|
||||||
#include "mozilla/MathAlgorithms.h"
|
#include "mozilla/MathAlgorithms.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "js/Conversions.h"
|
#include "js/Conversions.h"
|
||||||
#include "js/Date.h"
|
|
||||||
#include "js/Initialization.h"
|
|
||||||
#include "js/Value.h"
|
#include "js/Value.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
@@ -93,71 +88,23 @@ const double EndOfTime = 8.64e15;
|
|||||||
*/
|
*/
|
||||||
class DateTimeInfo
|
class DateTimeInfo
|
||||||
{
|
{
|
||||||
static DateTimeInfo instance;
|
|
||||||
|
|
||||||
// Date/time info is shared across all threads in DateTimeInfo::instance,
|
|
||||||
// for consistency with ICU's handling of its default time zone. Thus we
|
|
||||||
// need something to protect concurrent accesses.
|
|
||||||
//
|
|
||||||
// The spec implicitly assumes DST and time zone adjustment information
|
|
||||||
// never change in the course of a function -- sometimes even across
|
|
||||||
// reentrancy. So make critical sections as narrow as possible, and use a
|
|
||||||
// bog-standard spinlock with busy-waiting in case of contention for
|
|
||||||
// simplicity.
|
|
||||||
class MOZ_RAII AcquireLock
|
|
||||||
{
|
|
||||||
static mozilla::Atomic<bool, mozilla::ReleaseAcquire> spinLock;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AcquireLock() {
|
DateTimeInfo();
|
||||||
while (!spinLock.compareExchange(false, true))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
~AcquireLock() {
|
|
||||||
MOZ_ASSERT(spinLock, "spinlock should have been acquired");
|
|
||||||
spinLock = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
friend bool ::JS_Init();
|
|
||||||
|
|
||||||
// Initialize global date/time tracking state. This operation occurs
|
|
||||||
// during, and is restricted to, SpiderMonkey initialization.
|
|
||||||
static void init();
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*
|
/*
|
||||||
* Get the DST offset in milliseconds at a UTC time. This is usually
|
* Get the DST offset in milliseconds at a UTC time. This is usually
|
||||||
* either 0 or |msPerSecond * SecondsPerHour|, but at least one exotic time
|
* either 0 or |msPerSecond * SecondsPerHour|, but at least one exotic time
|
||||||
* zone (Lord Howe Island, Australia) has a fractional-hour offset, just to
|
* zone (Lord Howe Island, Australia) has a fractional-hour offset, just to
|
||||||
* keep things interesting.
|
* keep things interesting.
|
||||||
*/
|
*/
|
||||||
static int64_t getDSTOffsetMilliseconds(int64_t utcMilliseconds) {
|
int64_t getDSTOffsetMilliseconds(int64_t utcMilliseconds);
|
||||||
AcquireLock lock;
|
|
||||||
|
|
||||||
return DateTimeInfo::instance.internalGetDSTOffsetMilliseconds(utcMilliseconds);
|
void updateTimeZoneAdjustment();
|
||||||
}
|
|
||||||
|
|
||||||
/* ES5 15.9.1.7. */
|
/* ES5 15.9.1.7. */
|
||||||
static double localTZA() {
|
double localTZA() { return localTZA_; }
|
||||||
AcquireLock lock;
|
|
||||||
|
|
||||||
return DateTimeInfo::instance.localTZA_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// We don't want anyone accidentally calling *only*
|
|
||||||
// DateTimeInfo::updateTimeZoneAdjustment() to respond to a system time
|
|
||||||
// zone change (missing the necessary poking of ICU as well), so ensure
|
|
||||||
// only JS::ResetTimeZone() can call this via access restrictions.
|
|
||||||
friend void JS::ResetTimeZone();
|
|
||||||
|
|
||||||
static void updateTimeZoneAdjustment() {
|
|
||||||
AcquireLock lock;
|
|
||||||
|
|
||||||
DateTimeInfo::instance.internalUpdateTimeZoneAdjustment();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The current local time zone adjustment, cached because retrieving this
|
* The current local time zone adjustment, cached because retrieving this
|
||||||
* dynamically is Slow, and a certain venerable benchmark which shall not
|
* dynamically is Slow, and a certain venerable benchmark which shall not
|
||||||
@@ -166,7 +113,7 @@ class DateTimeInfo
|
|||||||
* SpiderMonkey occasionally and arbitrarily updates this value from the
|
* SpiderMonkey occasionally and arbitrarily updates this value from the
|
||||||
* system time zone to attempt to keep this reasonably up-to-date. If
|
* system time zone to attempt to keep this reasonably up-to-date. If
|
||||||
* temporary inaccuracy can't be tolerated, JSAPI clients may call
|
* temporary inaccuracy can't be tolerated, JSAPI clients may call
|
||||||
* JS::ResetTimeZone to forcibly sync this with the system time zone.
|
* JS_ClearDateCaches to forcibly sync this with the system time zone.
|
||||||
*/
|
*/
|
||||||
double localTZA_;
|
double localTZA_;
|
||||||
|
|
||||||
@@ -194,9 +141,6 @@ class DateTimeInfo
|
|||||||
|
|
||||||
static const int64_t RangeExpansionAmount = 30 * SecondsPerDay;
|
static const int64_t RangeExpansionAmount = 30 * SecondsPerDay;
|
||||||
|
|
||||||
int64_t internalGetDSTOffsetMilliseconds(int64_t utcMilliseconds);
|
|
||||||
void internalUpdateTimeZoneAdjustment();
|
|
||||||
|
|
||||||
void sanityCheck();
|
void sanityCheck();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,166 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
||||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
/* SpiderMonkey initialization and shutdown code. */
|
|
||||||
|
|
||||||
#include "js/Initialization.h"
|
|
||||||
|
|
||||||
#include "mozilla/Assertions.h"
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "jstypes.h"
|
|
||||||
|
|
||||||
#include "builtin/AtomicsObject.h"
|
|
||||||
#include "jit/ExecutableAllocator.h"
|
|
||||||
#include "jit/Ion.h"
|
|
||||||
#include "js/Utility.h"
|
|
||||||
#if ENABLE_INTL_API
|
|
||||||
#include "unicode/uclean.h"
|
|
||||||
#include "unicode/utypes.h"
|
|
||||||
#endif // ENABLE_INTL_API
|
|
||||||
#include "vm/DateTime.h"
|
|
||||||
#include "vm/HelperThreads.h"
|
|
||||||
#include "vm/Runtime.h"
|
|
||||||
#include "vm/Time.h"
|
|
||||||
#include "vm/TraceLogging.h"
|
|
||||||
|
|
||||||
using JS::detail::InitState;
|
|
||||||
using JS::detail::libraryInitState;
|
|
||||||
using js::FutexRuntime;
|
|
||||||
|
|
||||||
InitState JS::detail::libraryInitState;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
static unsigned
|
|
||||||
MessageParameterCount(const char* format)
|
|
||||||
{
|
|
||||||
unsigned numfmtspecs = 0;
|
|
||||||
for (const char* fmt = format; *fmt != '\0'; fmt++) {
|
|
||||||
if (*fmt == '{' && isdigit(fmt[1]))
|
|
||||||
++numfmtspecs;
|
|
||||||
}
|
|
||||||
return numfmtspecs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
CheckMessageParameterCounts()
|
|
||||||
{
|
|
||||||
// Assert that each message format has the correct number of braced
|
|
||||||
// parameters.
|
|
||||||
# define MSG_DEF(name, count, exception, format) \
|
|
||||||
MOZ_ASSERT(MessageParameterCount(format) == count);
|
|
||||||
# include "js.msg"
|
|
||||||
# undef MSG_DEF
|
|
||||||
}
|
|
||||||
#endif /* DEBUG */
|
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
|
||||||
JS_Init(void)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(libraryInitState == InitState::Uninitialized,
|
|
||||||
"must call JS_Init once before any JSAPI operation except "
|
|
||||||
"JS_SetICUMemoryFunctions");
|
|
||||||
MOZ_ASSERT(!JSRuntime::hasLiveRuntimes(),
|
|
||||||
"how do we have live runtimes before JS_Init?");
|
|
||||||
|
|
||||||
PRMJ_NowInit();
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
CheckMessageParameterCounts();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using js::TlsPerThreadData;
|
|
||||||
if (!TlsPerThreadData.initialized() && !TlsPerThreadData.init())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
|
|
||||||
if (!js::oom::InitThreadType())
|
|
||||||
return false;
|
|
||||||
js::oom::SetThreadType(js::oom::THREAD_TYPE_MAIN);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
js::jit::ExecutableAllocator::initStatic();
|
|
||||||
|
|
||||||
if (!js::jit::InitializeIon())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
js::DateTimeInfo::init();
|
|
||||||
|
|
||||||
#if EXPOSE_INTL_API
|
|
||||||
UErrorCode err = U_ZERO_ERROR;
|
|
||||||
u_init(&err);
|
|
||||||
if (U_FAILURE(err))
|
|
||||||
return false;
|
|
||||||
#endif // EXPOSE_INTL_API
|
|
||||||
|
|
||||||
if (!js::CreateHelperThreadsState())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!FutexRuntime::initialize())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
libraryInitState = InitState::Running;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
|
||||||
JS_ShutDown(void)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(libraryInitState == InitState::Running,
|
|
||||||
"JS_ShutDown must only be called after JS_Init and can't race with it");
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (JSRuntime::hasLiveRuntimes()) {
|
|
||||||
// Gecko is too buggy to assert this just yet.
|
|
||||||
fprintf(stderr,
|
|
||||||
"WARNING: YOU ARE LEAKING THE WORLD (at least one JSRuntime "
|
|
||||||
"and everything alive inside it, that is) AT JS_ShutDown "
|
|
||||||
"TIME. FIX THIS!\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FutexRuntime::destroy();
|
|
||||||
|
|
||||||
js::DestroyHelperThreadsState();
|
|
||||||
|
|
||||||
#ifdef JS_TRACE_LOGGING
|
|
||||||
js::DestroyTraceLoggerThreadState();
|
|
||||||
js::DestroyTraceLoggerGraphState();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The only difficult-to-address reason for the restriction that you can't
|
|
||||||
// call JS_Init/stuff/JS_ShutDown multiple times is the Windows PRMJ
|
|
||||||
// NowInit initialization code, which uses PR_CallOnce to initialize the
|
|
||||||
// PRMJ_Now subsystem. (For reinitialization to be permitted, we'd need to
|
|
||||||
// "reset" the called-once status -- doable, but more trouble than it's
|
|
||||||
// worth now.) Initializing that subsystem from JS_Init eliminates the
|
|
||||||
// problem, but initialization can take a comparatively long time (15ms or
|
|
||||||
// so), so we really don't want to do it in JS_Init, and we really do want
|
|
||||||
// to do it only when PRMJ_Now is eventually called.
|
|
||||||
PRMJ_NowShutdown();
|
|
||||||
|
|
||||||
#if EXPOSE_INTL_API
|
|
||||||
u_cleanup();
|
|
||||||
#endif // EXPOSE_INTL_API
|
|
||||||
|
|
||||||
libraryInitState = InitState::ShutDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
|
||||||
JS_SetICUMemoryFunctions(JS_ICUAllocFn allocFn, JS_ICUReallocFn reallocFn, JS_ICUFreeFn freeFn)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(libraryInitState == InitState::Uninitialized,
|
|
||||||
"must call JS_SetICUMemoryFunctions before any other JSAPI "
|
|
||||||
"operation (including JS_Init)");
|
|
||||||
|
|
||||||
#if EXPOSE_INTL_API
|
|
||||||
UErrorCode status = U_ZERO_ERROR;
|
|
||||||
u_setMemoryFunctions(/* context = */ nullptr, allocFn, reallocFn, freeFn, &status);
|
|
||||||
return U_SUCCESS(status);
|
|
||||||
#else
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@@ -45,7 +45,6 @@
|
|||||||
#include "jit/JitCompartment.h"
|
#include "jit/JitCompartment.h"
|
||||||
#include "jit/mips32/Simulator-mips32.h"
|
#include "jit/mips32/Simulator-mips32.h"
|
||||||
#include "jit/PcScriptCache.h"
|
#include "jit/PcScriptCache.h"
|
||||||
#include "js/Date.h"
|
|
||||||
#include "js/MemoryMetrics.h"
|
#include "js/MemoryMetrics.h"
|
||||||
#include "js/SliceBudget.h"
|
#include "js/SliceBudget.h"
|
||||||
#include "vm/Debugger.h"
|
#include "vm/Debugger.h"
|
||||||
@@ -334,7 +333,7 @@ JSRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
|
|||||||
if (!InitRuntimeNumberState(this))
|
if (!InitRuntimeNumberState(this))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
JS::ResetTimeZone();
|
dateTimeInfo.updateTimeZoneAdjustment();
|
||||||
|
|
||||||
#ifdef JS_SIMULATOR
|
#ifdef JS_SIMULATOR
|
||||||
simulator_ = js::jit::Simulator::Create();
|
simulator_ = js::jit::Simulator::Create();
|
||||||
|
|||||||
@@ -1205,6 +1205,7 @@ struct JSRuntime : public JS::shadow::Runtime,
|
|||||||
js::LazyScriptCache lazyScriptCache;
|
js::LazyScriptCache lazyScriptCache;
|
||||||
|
|
||||||
js::CompressedSourceSet compressedSourceSet;
|
js::CompressedSourceSet compressedSourceSet;
|
||||||
|
js::DateTimeInfo dateTimeInfo;
|
||||||
|
|
||||||
// Pool of maps used during parse/emit. This may be modified by threads
|
// Pool of maps used during parse/emit. This may be modified by threads
|
||||||
// with an ExclusiveContext and requires a lock. Active compilations
|
// with an ExclusiveContext and requires a lock. Active compilations
|
||||||
|
|||||||
@@ -1263,7 +1263,7 @@ intrinsic_LocalTZA(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
MOZ_ASSERT(args.length() == 0, "the LocalTZA intrinsic takes no arguments");
|
MOZ_ASSERT(args.length() == 0, "the LocalTZA intrinsic takes no arguments");
|
||||||
|
|
||||||
args.rval().setDouble(DateTimeInfo::localTZA());
|
args.rval().setDouble(cx->runtime()->dateTimeInfo.localTZA());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -155,7 +155,6 @@ extern nsresult nsStringInputStreamConstructor(nsISupports*, REFNSIID, void**);
|
|||||||
#include "GeckoProfiler.h"
|
#include "GeckoProfiler.h"
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "js/Initialization.h"
|
|
||||||
|
|
||||||
#include "gfxPlatform.h"
|
#include "gfxPlatform.h"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user