Bug 487070 - a pref for enabling the lastest version of JS in Web Workers, r=baku, r=bent

This commit is contained in:
Andrea Marchesini 2013-12-10 11:43:16 +00:00
parent fdbe4cde3f
commit 58736053af
10 changed files with 179 additions and 67 deletions

View File

@ -132,6 +132,14 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1,
#define PREF_JIT_HARDENING "jit_hardening"
#define PREF_GCZEAL "gcZeal"
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
#define DUMP_CONTROLLED_BY_PREF 1
#define PREF_DOM_WINDOW_DUMP_ENABLED "browser.dom.window.dump.enabled"
#endif
#define PREF_PROMISE_ENABLED "dom.promise.enabled"
#define PREF_WORKERS_LATEST_JS_VERSION "dom.workers.latestJSVersion"
namespace {
const uint32_t kNoIndex = uint32_t(-1);
@ -175,13 +183,6 @@ const char* gStringChars[] = {
static_assert(NS_ARRAY_LENGTH(gStringChars) == ID_COUNT,
"gStringChars should have the right length.");
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
#define DUMP_CONTROLLED_BY_PREF 1
#define PREF_DOM_WINDOW_DUMP_ENABLED "browser.dom.window.dump.enabled"
#endif
#define PREF_PROMISE_ENABLED "dom.promise.enabled"
class LiteralRebindingCString : public nsDependentCString
{
public:
@ -875,9 +876,9 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate, JSRuntime* aRuntime)
js::SetCTypesActivityCallback(aRuntime, CTypesActivityCallback);
JS::ContextOptionsRef(workerCx) = aWorkerPrivate->IsChromeWorker()
? settings.chrome.options
: settings.content.options;
JS::ContextOptionsRef(workerCx) =
aWorkerPrivate->IsChromeWorker() ? settings.chrome.contextOptions
: settings.content.contextOptions;
JS_SetJitHardening(aRuntime, settings.jitHardening);
@ -1593,9 +1594,10 @@ RuntimeService::Init()
// Initialize JSSettings.
if (!sDefaultJSSettings.gcSettings[0].IsSet()) {
sDefaultJSSettings.chrome.options = kRequiredJSContextOptions;
sDefaultJSSettings.chrome.contextOptions = kRequiredJSContextOptions;
sDefaultJSSettings.chrome.maxScriptRuntime = -1;
sDefaultJSSettings.content.options = kRequiredJSContextOptions;
sDefaultJSSettings.chrome.compartmentOptions.setVersion(JSVERSION_LATEST);
sDefaultJSSettings.content.contextOptions = kRequiredJSContextOptions;
sDefaultJSSettings.content.maxScriptRuntime = MAX_SCRIPT_RUN_TIME_SEC;
#ifdef JS_GC_ZEAL
sDefaultJSSettings.gcZealFrequency = JS_DEFAULT_ZEAL_FREQ;
@ -1670,21 +1672,25 @@ RuntimeService::Init()
#endif
#if DUMP_CONTROLLED_BY_PREF
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_DOM_WINDOW_DUMP_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DUMP))) ||
WorkerPrefChanged,
PREF_DOM_WINDOW_DUMP_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DUMP))) ||
#endif
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_PROMISE_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PROMISE))) ||
WorkerPrefChanged,
PREF_PROMISE_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PROMISE))) ||
NS_FAILED(Preferences::RegisterCallback(LoadJSContextOptions,
PREF_JS_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
LoadJSContextOptions,
PREF_WORKERS_OPTIONS_PREFIX,
nullptr))) {
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
JSVersionChanged,
PREF_WORKERS_LATEST_JS_VERSION,
nullptr))) {
NS_WARNING("Failed to register pref callbacks!");
}
@ -1834,19 +1840,24 @@ RuntimeService::Cleanup()
NS_ASSERTION(!mWindowMap.Count(), "All windows should have been released!");
if (mObserved) {
if (NS_FAILED(Preferences::UnregisterCallback(LoadJSContextOptions,
if (NS_FAILED(Preferences::UnregisterCallback(JSVersionChanged,
PREF_WORKERS_LATEST_JS_VERSION,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(LoadJSContextOptions,
PREF_JS_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(LoadJSContextOptions,
PREF_WORKERS_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(WorkerPrefChanged,
PREF_PROMISE_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PROMISE))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_PROMISE_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PROMISE))) ||
#if DUMP_CONTROLLED_BY_PREF
NS_FAILED(Preferences::UnregisterCallback(WorkerPrefChanged,
PREF_DOM_WINDOW_DUMP_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DUMP))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_DOM_WINDOW_DUMP_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DUMP))) ||
#endif
#ifdef JS_GC_ZEAL
NS_FAILED(Preferences::UnregisterCallback(
@ -2224,8 +2235,8 @@ void
RuntimeService::UpdateAllWorkerJSContextOptions()
{
BROADCAST_ALL_WORKERS(UpdateJSContextOptions,
sDefaultJSSettings.content.options,
sDefaultJSSettings.chrome.options);
sDefaultJSSettings.content.contextOptions,
sDefaultJSSettings.chrome.contextOptions);
}
void
@ -2333,3 +2344,15 @@ RuntimeService::WorkerPrefChanged(const char* aPrefName, void* aClosure)
rts->UpdateAllWorkerPreference(key, sDefaultPreferences[key]);
}
}
int
RuntimeService::JSVersionChanged(const char* /* aPrefName */, void* /* aClosure */)
{
AssertIsOnMainThread();
bool useLatest = Preferences::GetBool(PREF_WORKERS_LATEST_JS_VERSION, false);
JS::CompartmentOptions& options = sDefaultJSSettings.content.compartmentOptions;
options.setVersion(useLatest ? JSVERSION_LATEST : JSVERSION_DEFAULT);
return 0;
}

View File

@ -194,8 +194,8 @@ public:
const JS::ContextOptions& aChromeOptions)
{
AssertIsOnMainThread();
sDefaultJSSettings.content.options = aContentOptions;
sDefaultJSSettings.chrome.options = aChromeOptions;
sDefaultJSSettings.content.contextOptions = aContentOptions;
sDefaultJSSettings.chrome.contextOptions = aChromeOptions;
}
void
@ -295,6 +295,9 @@ private:
static void
WorkerPrefChanged(const char* aPrefName, void* aClosure);
static int
JSVersionChanged(const char* aPrefName, void* aClosure);
};
END_WORKERS_NAMESPACE

View File

@ -2816,16 +2816,17 @@ WorkerPrivateParent<Derived>::GetInnerWindowId()
template <class Derived>
void
WorkerPrivateParent<Derived>::UpdateJSContextOptions(JSContext* aCx,
const JS::ContextOptions& aContentOptions,
const JS::ContextOptions& aChromeOptions)
WorkerPrivateParent<Derived>::UpdateJSContextOptions(
JSContext* aCx,
const JS::ContextOptions& aContentOptions,
const JS::ContextOptions& aChromeOptions)
{
AssertIsOnParentThread();
{
MutexAutoLock lock(mMutex);
mJSSettings.content.options = aContentOptions;
mJSSettings.chrome.options = aChromeOptions;
mJSSettings.content.contextOptions = aContentOptions;
mJSSettings.chrome.contextOptions = aChromeOptions;
}
nsRefPtr<UpdateJSContextOptionsRunnable> runnable =
@ -5449,14 +5450,7 @@ WorkerPrivate::CreateGlobalScope(JSContext* aCx)
globalScope = new DedicatedWorkerGlobalScope(this);
}
JS::CompartmentOptions options;
if (IsChromeWorker()) {
options.setVersion(JSVERSION_LATEST);
}
JS::Rooted<JSObject*> global(aCx,
globalScope->WrapGlobalObject(aCx, options,
GetWorkerPrincipal()));
JS::Rooted<JSObject*> global(aCx, globalScope->WrapGlobalObject(aCx));
NS_ENSURE_TRUE(global, nullptr);
JSAutoCompartment ac(aCx, global);

View File

@ -377,7 +377,6 @@ private:
ErrorResult& aRv);
public:
virtual JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
@ -696,6 +695,14 @@ public:
aSettings = mJSSettings;
}
void
CopyJSCompartmentOptions(JS::CompartmentOptions& aOptions)
{
mozilla::MutexAutoLock lock(mMutex);
aOptions = IsChromeWorker() ? mJSSettings.chrome.compartmentOptions
: mJSSettings.content.compartmentOptions;
}
// The ability to be a chrome worker is orthogonal to the type of
// worker [Dedicated|Shared].
bool

View File

@ -6,11 +6,6 @@
#include "WorkerScope.h"
#include "Location.h"
#include "Navigator.h"
#include "ScriptLoader.h"
#include "WorkerPrivate.h"
#include "jsapi.h"
#include "mozilla/dom/FunctionBinding.h"
#include "mozilla/dom/DedicatedWorkerGlobalScopeBinding.h"
@ -20,7 +15,12 @@
#include <android/log.h>
#endif
#include "RuntimeService.h" // For WorkersDumpEnabled().
#include "Location.h"
#include "Navigator.h"
#include "Principal.h"
#include "RuntimeService.h"
#include "ScriptLoader.h"
#include "WorkerPrivate.h"
#define UNWRAP_WORKER_OBJECT(Interface, obj, value) \
UnwrapObject<prototypes::id::Interface##_workers, \
@ -261,19 +261,20 @@ DedicatedWorkerGlobalScope::Visible(JSContext* aCx, JSObject* aObj)
}
JSObject*
DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
JS::CompartmentOptions& aOptions,
JSPrincipals* aPrincipal)
DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx)
{
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(!mWorkerPrivate->IsSharedWorker());
JS::CompartmentOptions options;
mWorkerPrivate->CopyJSCompartmentOptions(options);
// We're wrapping the global, so the scope is undefined.
JS::Rooted<JSObject*> scope(aCx);
return DedicatedWorkerGlobalScopeBinding_workers::Wrap(aCx, scope, this,
this, aOptions,
aPrincipal);
this, options,
GetWorkerPrincipal());
}
void
@ -301,18 +302,20 @@ SharedWorkerGlobalScope::Visible(JSContext* aCx, JSObject* aObj)
}
JSObject*
SharedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
JS::CompartmentOptions& aOptions,
JSPrincipals* aPrincipal)
SharedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx)
{
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(mWorkerPrivate->IsSharedWorker());
JS::CompartmentOptions options;
mWorkerPrivate->CopyJSCompartmentOptions(options);
// We're wrapping the global, so the scope is undefined.
JS::Rooted<JSObject*> scope(aCx);
return SharedWorkerGlobalScopeBinding_workers::Wrap(aCx, scope, this, this,
aOptions, aPrincipal);
options,
GetWorkerPrincipal());
}
bool

View File

@ -40,8 +40,7 @@ public:
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
virtual JSObject*
WrapGlobalObject(JSContext* aCx, JS::CompartmentOptions& aOptions,
JSPrincipals* aPrincipal) = 0;
WrapGlobalObject(JSContext* aCx) = 0;
virtual JSObject*
GetGlobalJSObject(void) MOZ_OVERRIDE
@ -115,8 +114,7 @@ public:
Visible(JSContext* aCx, JSObject* aObj);
virtual JSObject*
WrapGlobalObject(JSContext* aCx, JS::CompartmentOptions& aOptions,
JSPrincipals* aPrincipal) MOZ_OVERRIDE;
WrapGlobalObject(JSContext* aCx) MOZ_OVERRIDE;
void
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
@ -139,8 +137,7 @@ public:
Visible(JSContext* aCx, JSObject* aObj);
virtual JSObject*
WrapGlobalObject(JSContext* aCx, JS::CompartmentOptions& aOptions,
JSPrincipals* aPrincipal) MOZ_OVERRIDE;
WrapGlobalObject(JSContext* aCx) MOZ_OVERRIDE;
void GetName(DOMString& aName) const {
aName.AsAString() = mName;

View File

@ -95,11 +95,12 @@ struct JSSettings
// Settings that change based on chrome/content context.
struct JSContentChromeSettings
{
JS::ContextOptions options;
JS::ContextOptions contextOptions;
JS::CompartmentOptions compartmentOptions;
int32_t maxScriptRuntime;
JSContentChromeSettings()
: options(), maxScriptRuntime(0)
: contextOptions(), compartmentOptions(), maxScriptRuntime(0)
{ }
};

View File

@ -0,0 +1,14 @@
onmessage = function(evt) {
if (evt.data != 0) {
var worker = new Worker('jsversion_worker.js');
worker.onmessage = function(evt) {
postMessage(evt.data);
}
worker.postMessage(evt.data - 1);
return;
}
let foo = 'bar';
postMessage(true);
}

View File

@ -56,6 +56,7 @@ support-files =
xhr_implicit_cancel_worker.js
xhr_worker.js
url_exceptions_worker.js
jsversion_worker.js
[test_404.html]
[test_atob.html]
@ -113,3 +114,4 @@ support-files =
[test_xhr_system.html]
[test_xhr_system.js]
[test_url_exceptions.html]
[test_jsversion.html]

View File

@ -0,0 +1,68 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test for JSVersion in workers - Bug 487070</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" language="javascript">
var gExpectedError = false;
onerror = function(evt) {
ok(gExpectedError, "Error expected!");
runTest();
}
function doMagic() {
var worker = new Worker('jsversion_worker.js');
worker.onmessage = function(evt) {
ok(evt.data, 'All the tests passed');
runTest();
}
worker.postMessage(1);
}
var tests = [
// No custom version
function() {
gExpectedError = true;
SpecialPowers.pushPrefEnv({"set":[['dom.workers.latestJSVersion', false]]},
function() { doMagic(true); });
},
// Enable latest JS Version
function() {
gExpectedError = false;
SpecialPowers.pushPrefEnv({"set":[['dom.workers.latestJSVersion', true]]},
function() { doMagic(false); });
}
];
function runTest() {
if (!tests.length) {
SimpleTest.finish();
return;
}
var test = tests.shift();
test();
}
SimpleTest.waitForExplicitFinish();
runTest();
</script>
</pre>
</body>
</html>