diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index f63b1de981..65f778b5f9 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -301,6 +301,7 @@ LoadContextOptions(const char* aPrefName, void* /* aClosure */) .setAsyncStack(GetWorkerPref(NS_LITERAL_CSTRING("asyncstack"))) .setWerror(GetWorkerPref(NS_LITERAL_CSTRING("werror"))) .setStreams(GetWorkerPref(NS_LITERAL_CSTRING("streams"))) + .setWeakRefs(GetWorkerPref(NS_LITERAL_CSTRING("weakrefs"))) .setExtraWarnings(GetWorkerPref(NS_LITERAL_CSTRING("strict"))) .setArrayProtoValues(GetWorkerPref( NS_LITERAL_CSTRING("array_prototype_values"))); diff --git a/dom/workers/WorkerPrefs.h b/dom/workers/WorkerPrefs.h index 87806a6fbc..d870ac8e46 100644 --- a/dom/workers/WorkerPrefs.h +++ b/dom/workers/WorkerPrefs.h @@ -35,6 +35,7 @@ WORKER_SIMPLE_PREF("dom.serviceWorkers.openWindow.enabled", OpenWindowEnabled, O WORKER_SIMPLE_PREF("dom.storageManager.enabled", StorageManagerEnabled, STORAGEMANAGER_ENABLED) WORKER_SIMPLE_PREF("dom.push.enabled", PushEnabled, PUSH_ENABLED) WORKER_SIMPLE_PREF("dom.streams.enabled", StreamsEnabled, STREAMS_ENABLED) +WORKER_SIMPLE_PREF("javascript.options.weakrefs", WeakRefsEnabled, WEAKREFS_ENABLED) WORKER_SIMPLE_PREF("dom.requestcontext.enabled", RequestContextEnabled, REQUESTCONTEXT_ENABLED) WORKER_SIMPLE_PREF("gfx.offscreencanvas.enabled", OffscreenCanvasEnabled, OFFSCREENCANVAS_ENABLED) WORKER_SIMPLE_PREF("dom.webkitBlink.dirPicker.enabled", WebkitBlinkDirectoryPickerEnabled, DOM_WEBKITBLINK_DIRPICKER_WEBKITBLINK) diff --git a/js/src/builtin/WeakRefObject.cpp b/js/src/builtin/WeakRefObject.cpp index 4b02f8189f..8e8feb3f3d 100644 --- a/js/src/builtin/WeakRefObject.cpp +++ b/js/src/builtin/WeakRefObject.cpp @@ -89,7 +89,7 @@ WeakRefObject::create(JSContext* cx, HandleObject target, HandleObject proto /* if (!obj) return nullptr; - Referent* data = cx->new_(target); + Referent* data = cx->new_(target, cx->options().weakRefs()); if (!data) return nullptr; @@ -146,12 +146,16 @@ WeakRefObject::trace(JSTracer* trc, JSObject* obj) if (!target) return; - // Weak edges must be tenured; fall back to a strong trace while the - // referent is still in the nursery to avoid crashing the GC. - if (IsInsideNursery(target)) + // When pref-disabled, keep referent alive via strong trace so deref() + // stays usable as a stub without touching GC internals. + if (!data->enabled) { + TraceManuallyBarrieredEdge(trc, data->target.unsafeGet(), "WeakRef stub referent"); + } else if (IsInsideNursery(target)) { + // Weak edges must be tenured; trace strongly while referent is in the nursery. TraceManuallyBarrieredEdge(trc, data->target.unsafeGet(), "WeakRef nursery referent"); - else + } else { TraceWeakEdge(trc, &data->target, "WeakRef referent"); + } } } diff --git a/js/src/builtin/WeakRefObject.h b/js/src/builtin/WeakRefObject.h index e528f9fd37..f4d7e547e4 100644 --- a/js/src/builtin/WeakRefObject.h +++ b/js/src/builtin/WeakRefObject.h @@ -15,8 +15,10 @@ class WeakRefObject : public NativeObject { public: struct Referent { - explicit Referent(JSObject* obj) : target(obj) {} + explicit Referent(JSObject* obj, bool enabled) + : target(obj), enabled(enabled) {} WeakRef target; + bool enabled; }; static const Class class_; diff --git a/js/src/jsapi.h b/js/src/jsapi.h index cae2297ae4..7744bdd592 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -998,7 +998,9 @@ class JS_PUBLIC_API(ContextOptions) { werror_(false), strictMode_(false), extraWarnings_(false), - arrayProtoValues_(true) + arrayProtoValues_(true), + streams_(true), + weakRefs_(false) { } @@ -1138,6 +1140,16 @@ class JS_PUBLIC_API(ContextOptions) { return *this; } + bool weakRefs() const { return weakRefs_; } + ContextOptions& setWeakRefs(bool flag) { + weakRefs_ = flag; + return *this; + } + ContextOptions& toggleWeakRefs() { + weakRefs_ = !weakRefs_; + return *this; + } + private: bool baseline_ : 1; bool ion_ : 1; @@ -1155,6 +1167,7 @@ class JS_PUBLIC_API(ContextOptions) { bool extraWarnings_ : 1; bool arrayProtoValues_ : 1; bool streams_ : 1; + bool weakRefs_ : 1; }; JS_PUBLIC_API(ContextOptions&) diff --git a/js/xpconnect/src/XPCJSContext.cpp b/js/xpconnect/src/XPCJSContext.cpp index 0a5d248185..62971d380c 100644 --- a/js/xpconnect/src/XPCJSContext.cpp +++ b/js/xpconnect/src/XPCJSContext.cpp @@ -1441,6 +1441,7 @@ ReloadPrefsCallback(const char* pref, void* data) bool extraWarnings = Preferences::GetBool(JS_OPTIONS_DOT_STR "strict"); bool streams = Preferences::GetBool(JS_OPTIONS_DOT_STR "streams"); + bool weakRefs = Preferences::GetBool(JS_OPTIONS_DOT_STR "weakrefs"); bool unboxedObjects = Preferences::GetBool(JS_OPTIONS_DOT_STR "unboxed_objects"); @@ -1467,7 +1468,8 @@ ReloadPrefsCallback(const char* pref, void* data) .setWerror(werror) .setExtraWarnings(extraWarnings) .setArrayProtoValues(arrayProtoValues) - .setStreams(streams); + .setStreams(streams) + .setWeakRefs(weakRefs); JS_SetParallelParsingEnabled(cx, parallelParsing); JS_SetOffthreadIonCompilationEnabled(cx, offthreadIonCompilation); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 823749116b..83873c05ed 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1340,6 +1340,7 @@ pref("javascript.options.dynamicImport", true); // Streams API pref("javascript.options.streams", true); +pref("javascript.options.weakrefs", false); // advanced prefs pref("advanced.mailftp", false);