Bug 1747059 - Gecko support for ShadowRealms r=peterv,smaug

This connects [Exposed=*] in WebIDL to ShadowRealms

Differential Revision: https://phabricator.services.mozilla.com/D146349
This commit is contained in:
Matthew Gaudet 2022-06-28 22:04:18 +00:00
Родитель d390a7f144
Коммит 580a35d01e
19 изменённых файлов: 497 добавлений и 5 удалений

Просмотреть файл

@ -2809,7 +2809,8 @@ bool IsNonExposedGlobal(JSContext* aCx, JSObject* aGlobal,
GlobalNames::WorkerDebuggerGlobalScope |
GlobalNames::WorkletGlobalScope |
GlobalNames::AudioWorkletGlobalScope |
GlobalNames::PaintWorkletGlobalScope)) == 0,
GlobalNames::PaintWorkletGlobalScope |
GlobalNames::ShadowRealmGlobalScope)) == 0,
"Unknown non-exposed global type");
const char* name = JS::GetClass(aGlobal)->name;
@ -2854,6 +2855,11 @@ bool IsNonExposedGlobal(JSContext* aCx, JSObject* aGlobal,
return true;
}
if ((aNonExposedGlobals & GlobalNames::ShadowRealmGlobalScope) &&
!strcmp(name, "ShadowRealmGlobalScope")) {
return true;
}
return false;
}

Просмотреть файл

@ -17754,6 +17754,38 @@ class CGRegisterWorkletBindings(CGAbstractMethod):
return CGList(lines, "\n").define()
class CGRegisterShadowRealmBindings(CGAbstractMethod):
def __init__(self, config):
CGAbstractMethod.__init__(
self,
None,
"RegisterShadowRealmBindings",
"bool",
[Argument("JSContext*", "aCx"), Argument("JS::Handle<JSObject*>", "aObj")],
)
self.config = config
def definition_body(self):
descriptors = self.config.getDescriptors(
hasInterfaceObject=True, isExposedInShadowRealms=True, register=True
)
conditions = []
for desc in descriptors:
bindingNS = toBindingNamespace(desc.name)
condition = "!%s::GetConstructorObject(aCx)" % bindingNS
if desc.isExposedConditionally():
condition = (
"%s::ConstructorEnabled(aCx, aObj) && " % bindingNS + condition
)
conditions.append(condition)
lines = [
CGIfWrapper(CGGeneric("return false;\n"), condition)
for condition in conditions
]
lines.append(CGGeneric("return true;\n"))
return CGList(lines, "\n").define()
def BindingNamesOffsetEnum(name):
return CppKeywords.checkMethodName(name.replace(" ", "_"))
@ -23086,6 +23118,33 @@ class GlobalGenRoots:
# Done.
return curr
@staticmethod
def RegisterShadowRealmBindings(config):
curr = CGRegisterShadowRealmBindings(config)
# Wrap all of that in our namespaces.
curr = CGNamespace.build(["mozilla", "dom"], CGWrapper(curr, post="\n"))
curr = CGWrapper(curr, post="\n")
# Add the includes
defineIncludes = [
CGHeaders.getDeclarationFilename(desc.interface)
for desc in config.getDescriptors(
hasInterfaceObject=True, register=True, isExposedInShadowRealms=True
)
]
curr = CGHeaders(
[], [], [], [], [], defineIncludes, "RegisterShadowRealmBindings", curr
)
# Add include guards.
curr = CGIncludeGuard("RegisterShadowRealmBindings", curr)
# Done.
return curr
@staticmethod
def UnionTypes(config):
unionTypes = UnionsForFile(config, None)

Просмотреть файл

@ -296,6 +296,8 @@ class Configuration(DescriptorProvider):
getter = lambda x: x.interface.isExposedInAnyWorklet()
elif key == "isExposedInWindow":
getter = lambda x: x.interface.isExposedInWindow()
elif key == "isExposedInShadowRealms":
getter = lambda x: x.interface.isExposedInShadowRealms()
elif key == "isSerializable":
getter = lambda x: x.interface.isSerializable()
else:

Просмотреть файл

@ -112,8 +112,9 @@ static const uint32_t WorkerDebuggerGlobalScope = 1u << 4;
static const uint32_t WorkletGlobalScope = 1u << 5;
static const uint32_t AudioWorkletGlobalScope = 1u << 6;
static const uint32_t PaintWorkletGlobalScope = 1u << 7;
static const uint32_t ShadowRealmGlobalScope = 1u << 8;
static constexpr uint32_t kCount = 8;
static constexpr uint32_t kCount = 9;
} // namespace GlobalNames
struct PrefableDisablers {

Просмотреть файл

@ -156,6 +156,7 @@ class WebIDLCodegenManager(LoggingMixin):
"GeneratedEventList.h",
"PrototypeList.h",
"RegisterBindings.h",
"RegisterShadowRealmBindings.h",
"RegisterWorkerBindings.h",
"RegisterWorkerDebuggerBindings.h",
"RegisterWorkletBindings.h",
@ -169,6 +170,7 @@ class WebIDLCodegenManager(LoggingMixin):
GLOBAL_DEFINE_FILES = {
"BindingNames.cpp",
"RegisterBindings.cpp",
"RegisterShadowRealmBindings.cpp",
"RegisterWorkerBindings.cpp",
"RegisterWorkerDebuggerBindings.cpp",
"RegisterWorkletBindings.cpp",

Просмотреть файл

@ -492,7 +492,7 @@ class IDLExposureMixins:
# and add global interfaces and [Exposed] annotations to all those
# tests.
if len(scope.globalNames) != 0:
if len(self._exposureGlobalNames) == 0:
if len(self._exposureGlobalNames) == 0 and not self.isPseudoInterface():
raise WebIDLError(
(
"'%s' is not exposed anywhere even though we have "
@ -528,6 +528,9 @@ class IDLExposureMixins:
workerScopes = self.parentScope.globalNameMapping["Worker"]
return len(workerScopes.difference(self.exposureSet)) > 0
def isExposedInShadowRealms(self):
return "ShadowRealmGlobalScope" in self.exposureSet
def getWorkerExposureSet(self):
workerScopes = self._globalScope.globalNameMapping["Worker"]
return workerScopes.intersection(self.exposureSet)
@ -959,6 +962,9 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
self.interfacesBasedOnSelf = set([self])
self._hasChildInterfaces = False
self._isOnGlobalProtoChain = False
# Pseudo interfaces aren't exposed anywhere, and so shouldn't issue warnings
self._isPseudo = False
# Tracking of the number of reserved slots we need for our
# members and those of ancestor interfaces.
self.totalMembersInSlots = 0
@ -1713,13 +1719,14 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
def hasInterfaceObject(self):
if self.isCallback():
return self.hasConstants()
return not hasattr(self, "_noInterfaceObject")
return not hasattr(self, "_noInterfaceObject") and not self.isPseudoInterface()
def hasInterfacePrototypeObject(self):
return (
not self.isCallback()
and not self.isNamespace()
and self.getUserData("hasConcreteDescendant", False)
and not self.isPseudoInterface()
)
def addIncludedMixin(self, includedMixin):
@ -1783,6 +1790,9 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
def isOnGlobalProtoChain(self):
return self._isOnGlobalProtoChain
def isPseudoInterface(self):
return self._isPseudo
def _getDependentObjects(self):
deps = set(self.members)
deps.update(self.includedMixins)

Просмотреть файл

@ -0,0 +1,122 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#include "nsGlobalWindowInner.h"
#include "nsIGlobalObject.h"
#include "xpcpublic.h"
#include "js/TypeDecls.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/ModuleLoader.h"
#include "mozilla/dom/ShadowRealmGlobalScope.h"
#include "mozilla/dom/ShadowRealmGlobalScopeBinding.h"
#include "js/loader/ModuleLoaderBase.h"
using namespace JS::loader;
namespace mozilla::dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ShadowRealmGlobalScope, mModuleLoader,
mCreatingGlobal)
NS_IMPL_CYCLE_COLLECTING_ADDREF(ShadowRealmGlobalScope)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ShadowRealmGlobalScope)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ShadowRealmGlobalScope)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
NS_INTERFACE_MAP_ENTRY(ShadowRealmGlobalScope)
NS_INTERFACE_MAP_END
JSObject* NewShadowRealmGlobal(JSContext* aCx, JS::RealmOptions& aOptions,
JSPrincipals* aPrincipals,
JS::Handle<JSObject*> aGlobalObj) {
JS::Rooted<JSObject*> reflector(aCx);
{
RefPtr<ShadowRealmGlobalScope> scope;
GlobalObject global(aCx, aGlobalObj);
nsCOMPtr<nsIGlobalObject> nsGlobal =
do_QueryInterface(global.GetAsSupports());
MOZ_ASSERT(nsGlobal);
scope = new ShadowRealmGlobalScope(nsGlobal);
ShadowRealmGlobalScope_Binding::Wrap(aCx, scope, scope, aOptions,
aPrincipals, true, &reflector);
}
return reflector;
}
static nsIGlobalObject* FindEnclosingNonShadowRealmGlobal(
ShadowRealmGlobalScope* scope) {
nsCOMPtr<nsIGlobalObject> global = scope->GetCreatingGlobal();
do {
nsCOMPtr<ShadowRealmGlobalScope> shadowRealmGlobalScope =
do_QueryInterface(global);
if (!shadowRealmGlobalScope) {
break;
}
// Our global was a ShadowRealmGlobal; that's a problem, as we can't find a
// window or worker global associated with a ShadowRealmGlobal... so we
// continue following the chain.
//
// This will happen if you have nested ShadowRealms.
global = shadowRealmGlobalScope->GetCreatingGlobal();
} while (true);
return global;
}
ModuleLoaderBase* ShadowRealmGlobalScope::GetModuleLoader(JSContext* aCx) {
if (mModuleLoader) {
return mModuleLoader;
}
// Note: if this fails, we don't need to report an exception, as one will be
// reported by ModuleLoaderBase::GetCurrentModuleLoader.
// Don't bother asking the ShadowRealmGlobal itself for a host object to get a
// module loader from, instead, delegate to the enclosing global of the shadow
// realm
nsCOMPtr<nsIGlobalObject> global = FindEnclosingNonShadowRealmGlobal(this);
MOZ_RELEASE_ASSERT(global);
JSObject* object = global->GetGlobalJSObject();
MOZ_ASSERT(object);
// Currently Workers will never get here, because dynamic import is disabled
// in Worker context, and so importValue will throw before we get here.
//
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1247687 and
// https://bugzilla.mozilla.org/show_bug.cgi?id=1772162
nsGlobalWindowInner* window = xpc::WindowGlobalOrNull(object);
if (!window) {
return nullptr;
}
RefPtr<Document> doc = window->GetExtantDoc();
if (!doc) {
return nullptr;
}
ScriptLoader* scriptLoader = doc->ScriptLoader();
mModuleLoader = new ModuleLoader(scriptLoader, this, ModuleLoader::Normal);
// Register the shadow realm module loader for tracing and ownership.
scriptLoader->RegisterShadowRealmModuleLoader(
static_cast<ModuleLoader*>(mModuleLoader.get()));
return mModuleLoader;
}
} // namespace mozilla::dom

Просмотреть файл

@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_dom_ShadowRealmGlobalScope_h
#define mozilla_dom_ShadowRealmGlobalScope_h
#include "js/TypeDecls.h"
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/OriginTrials.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "nsIGlobalObject.h"
#include "nsWrapperCache.h"
#include "js/loader/ModuleLoaderBase.h"
namespace mozilla::dom {
#define SHADOWREALMGLOBALSCOPE_IID \
{ /* 1b0a59dd-c1cb-429a-bb90-cea17994dba2 */ \
0x1b0a59dd, 0xc1cb, 0x429a, { \
0xbb, 0x90, 0xce, 0xa1, 0x79, 0x94, 0xdb, 0xa2 \
} \
}
// Required for providing the wrapper, as this is the global used inside a Gecko
// backed ShadowRealm, but also required to power module resolution.
class ShadowRealmGlobalScope : public nsIGlobalObject, public nsWrapperCache {
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ShadowRealmGlobalScope)
NS_DECLARE_STATIC_IID_ACCESSOR(SHADOWREALMGLOBALSCOPE_IID)
explicit ShadowRealmGlobalScope(nsIGlobalObject* aCreatingGlobal)
: mCreatingGlobal(aCreatingGlobal){};
nsIGlobalObject* GetCreatingGlobal() const { return mCreatingGlobal; }
OriginTrials Trials() const override { return {}; }
JSObject* GetGlobalJSObject() override { return GetWrapper(); }
JSObject* GetGlobalJSObjectPreserveColor() const override {
return GetWrapperPreserveColor();
}
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override {
MOZ_CRASH("Shouldn't be here");
return nullptr;
}
JS::loader::ModuleLoaderBase* GetModuleLoader(JSContext* aCx) override;
private:
virtual ~ShadowRealmGlobalScope() = default;
RefPtr<JS::loader::ModuleLoaderBase> mModuleLoader;
// The global which created this ShadowRealm
nsCOMPtr<nsIGlobalObject> mCreatingGlobal;
};
NS_DEFINE_STATIC_IID_ACCESSOR(ShadowRealmGlobalScope,
SHADOWREALMGLOBALSCOPE_IID)
JSObject* NewShadowRealmGlobal(JSContext* aCx, JS::RealmOptions& aOptions,
JSPrincipals* aPrincipals,
JS::Handle<JSObject*> aGlobalObj);
} // namespace mozilla::dom
#endif

Просмотреть файл

@ -27,6 +27,7 @@ EXPORTS.mozilla.dom += [
"ScriptLoader.h",
"ScriptSettings.h",
"ScriptTrace.h",
"ShadowRealmGlobalScope.h",
]
UNIFIED_SOURCES += [
@ -39,6 +40,7 @@ UNIFIED_SOURCES += [
"ScriptLoader.cpp",
"ScriptLoadHandler.cpp",
"ScriptSettings.cpp",
"ShadowRealmGlobalScope.cpp",
]
LOCAL_INCLUDES += [

Просмотреть файл

@ -0,0 +1,11 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*/
// This interface exists purely to register a new global as part of
// code generation so that we can properly hook this into
// shadow realms.
[Global=(ShadowRealmGlobal), Exposed=ShadowRealmGlobal]
interface ShadowRealmGlobalScope { };

Просмотреть файл

@ -812,6 +812,7 @@ WEBIDL_FILES = [
"ServiceWorkerContainer.webidl",
"ServiceWorkerGlobalScope.webidl",
"ServiceWorkerRegistration.webidl",
"ShadowRealmGlobalScope.webidl",
"ShadowRoot.webidl",
"SharedWorker.webidl",
"SharedWorkerGlobalScope.webidl",

Просмотреть файл

@ -777,6 +777,7 @@ static mozilla::Atomic<bool> sWeakRefsEnabled(false);
static mozilla::Atomic<bool> sWeakRefsExposeCleanupSome(false);
static mozilla::Atomic<bool> sIteratorHelpersEnabled(false);
static mozilla::Atomic<bool> sArrayFindLastEnabled(false);
static mozilla::Atomic<bool> sShadowRealmsEnabled(false);
#ifdef NIGHTLY_BUILD
static mozilla::Atomic<bool> sArrayGroupingEnabled(true);
#endif
@ -802,6 +803,7 @@ void xpc::SetPrefableRealmOptions(JS::RealmOptions& options) {
.setPropertyErrorMessageFixEnabled(sPropertyErrorMessageFixEnabled)
.setWeakRefsEnabled(GetWeakRefsEnabled())
.setIteratorHelpersEnabled(sIteratorHelpersEnabled)
.setShadowRealmsEnabled(sShadowRealmsEnabled)
#ifdef NIGHTLY_BUILD
.setArrayGroupingEnabled(sArrayGroupingEnabled)
#endif
@ -1006,6 +1008,8 @@ static void ReloadPrefsCallback(const char* pref, void* aXpccx) {
sArrayFindLastEnabled =
Preferences::GetBool(JS_OPTIONS_DOT_STR "experimental.array_find_last");
sShadowRealmsEnabled =
Preferences::GetBool(JS_OPTIONS_DOT_STR "experimental.shadow_realms");
#ifdef NIGHTLY_BUILD
sIteratorHelpersEnabled =
Preferences::GetBool(JS_OPTIONS_DOT_STR "experimental.iterator_helpers");

Просмотреть файл

@ -40,13 +40,15 @@ support-files =
private_field_worker.js
class_static_worker.js
bug1681664_helper.js
shadow_realm_worker.js
shadow_realm_module.js
prefs =
javascript.options.weakrefs=true
javascript.options.experimental.ergonomic_brand_checks=true
javascript.options.experimental.top_level_await=true
javascript.options.experimental.enable_change_array_by_copy=false
javascript.options.experimental.enable_new_set_methods=false
javascript.options.experimental.shadow_realms=true
[test_bug384632.html]
[test_bug390488.html]
[test_bug393269.html]
@ -130,3 +132,6 @@ skip-if = (debug == false)
[test_private_field_worker.html]
[test_class_static_block_worker.html]
skip-if = !nightly_build
[test_shadowRealm.html]
[test_shadowRealm_worker.html]

Просмотреть файл

@ -0,0 +1 @@
export var x = 1;

Просмотреть файл

@ -0,0 +1,71 @@
var sr = new ShadowRealm();
self.onmessage = async function (e) {
try {
// Test evaluate
if (e.data === 'evaluate') {
sr.evaluate("var s = 'PASS set string in realm';")
var res = sr.evaluate('s');
postMessage(res);
return;
}
// If Import works in a worker, then it ought to work in a shadow realm
//
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1247687 and
// https://bugzilla.mozilla.org/show_bug.cgi?id=1772162
if (e.data == 'import') {
var import_worked = false;
var importValue_worked = false;
var importNested_worked = false;
try {
var module = await import("./shadow_realm_module.js");
if (module.x != 1) {
throw "mismatch";
}
import_worked = true;
} catch (e) { }
try {
await sr.importValue("./shadow_realm_module.js", 'x').then((x) => {
if (x == 1) { importValue_worked = true; }
});
} catch (e) { }
try {
sr.evaluate(`
var imported = false;
import("./shadow_realm_module.js").then((module) => {
if (module.x == 1) {
imported = true;
}
});
true;
`);
importNested_worked = sr.evaluate("imported");
} catch (e) {
}
if (importValue_worked == import_worked && importValue_worked == importNested_worked) {
postMessage(`PASS: importValue, import, and nested import all ${importValue_worked ? "worked" : "failed"} `);
return;
}
postMessage(`FAIL: importValue ${importValue_worked}, import ${import_worked}, importNested ${importNested_worked}`);
return;
}
// Reply back with finish
if (e.data == 'finish') {
postMessage("finish");
return;
}
} catch (e) {
postMessage("FAIL: " + e.message);
}
postMessage('Unknown message type.');
}

Просмотреть файл

@ -0,0 +1,34 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for ShadowRealms</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<iframe id="ifr"></iframe>
</head>
<body>
<p id="display"></p>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
info("running")
let realm = new ShadowRealm();
let install = (fun, internal_name) => {
let installer = realm.evaluate(`var ${internal_name}; (x) => { ${internal_name} = x}`);
installer(fun);
}
install(info, "log");
install(is, "is");
realm.evaluate(`is(true, true, 'inside realm')`);
is(realm.evaluate("10"), 10, "ten is ten");
SimpleTest.finish();
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,63 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for ShadowRealms</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<iframe id="ifr"></iframe>
</head>
<body>
<p id="display"></p>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
var promise = (async ()=> {
var module = await import("./shadow_realm_module.js");
is(module.x, 1, "import works outside worker");
var sr = new ShadowRealm();
await sr.importValue("./shadow_realm_module.js", 'x').then((x) => is(x,1, "imported x and got 1"));
})();
promise.then(() => {
var worker = new Worker("shadow_realm_worker.js");
var expected = 0;
var recieved = 0;
function test(str) {
worker.postMessage(str);
expected++;
}
worker.onmessage = function(e) {
console.log("Received Message: "+e.data);
recieved++;
if (e.data == "finish") {
is(expected, recieved, "Got the appropriate Number of messages");
SimpleTest.finish();
return;
}
if (e.data.startsWith("PASS")) {
ok(true, e.data);
return;
}
ok(false, e.data);
};
test("evaluate");
test("import");
test("finish");
});
</script>
</body>
</html>

Просмотреть файл

@ -6771,6 +6771,14 @@
value: false
mirror: always
# ShadowRealms: https://github.com/tc39/proposal-shadowrealm
- name: javascript.options.experimental.shadow_realms
# Atomic, as we assert the preference, and that assertion may happen
# in a worker.
type: RelaxedAtomicBool
value: false
mirror: always
#ifdef NIGHTLY_BUILD
# Experimental support for Iterator Helpers in JavaScript.
- name: javascript.options.experimental.iterator_helpers

Просмотреть файл

@ -59,12 +59,14 @@
#include <utility>
#include "js/Debug.h"
#include "js/RealmOptions.h"
#include "js/friend/DumpFunctions.h" // js::DumpHeap
#include "js/GCAPI.h"
#include "js/HeapAPI.h"
#include "js/Object.h" // JS::GetClass, JS::GetCompartment, JS::GetPrivate
#include "js/PropertyAndElement.h" // JS_DefineProperty
#include "js/Warnings.h" // JS::SetWarningReporter
#include "js/ShadowRealmCallbacks.h"
#include "js/SliceBudget.h"
#include "jsfriendapi.h"
#include "mozilla/ArrayUtils.h"
@ -75,6 +77,7 @@
#include "mozilla/ProfilerLabels.h"
#include "mozilla/ProfilerMarkers.h"
#include "mozilla/Sprintf.h"
#include "mozilla/StaticPrefs_javascript.h"
#include "mozilla/Telemetry.h"
#include "mozilla/TimelineConsumers.h"
#include "mozilla/TimelineMarker.h"
@ -87,6 +90,8 @@
#include "mozilla/dom/PromiseBinding.h"
#include "mozilla/dom/PromiseDebugging.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/ShadowRealmGlobalScope.h"
#include "mozilla/dom/RegisterShadowRealmBindings.h"
#include "nsContentUtils.h"
#include "nsCycleCollectionNoteRootCallback.h"
#include "nsCycleCollectionParticipant.h"
@ -656,6 +661,14 @@ size_t JSHolderMap::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
return n;
}
static bool InitializeShadowRealm(JSContext* aCx,
JS::Handle<JSObject*> aGlobal) {
MOZ_ASSERT(StaticPrefs::javascript_options_experimental_shadow_realms());
JSAutoRealm ar(aCx, aGlobal);
return dom::RegisterShadowRealmBindings(aCx, aGlobal);
}
CycleCollectedJSRuntime::CycleCollectedJSRuntime(JSContext* aCx)
: mContext(nullptr),
mGCThingCycleCollectorGlobal(sGCThingCycleCollectorGlobal),
@ -705,6 +718,8 @@ CycleCollectedJSRuntime::CycleCollectedJSRuntime(JSContext* aCx)
JS::SetWaitCallback(mJSRuntime, BeforeWaitCallback, AfterWaitCallback,
sizeof(dom::AutoYieldJSThreadExecution));
JS::SetWarningReporter(aCx, MozCrashWarningReporter);
JS::SetShadowRealmInitializeGlobalCallback(aCx, InitializeShadowRealm);
JS::SetShadowRealmGlobalCreationCallback(aCx, dom::NewShadowRealmGlobal);
js::AutoEnterOOMUnsafeRegion::setAnnotateOOMAllocationSizeCallback(
CrashReporter::AnnotateOOMAllocationSize);