ShadowRealmGlobalScope.cpp (4261B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/dom/ShadowRealmGlobalScope.h" 8 9 #include "js/TypeDecls.h" 10 #include "js/loader/ModuleLoaderBase.h" 11 #include "mozilla/dom/BindingDeclarations.h" 12 #include "mozilla/dom/Document.h" 13 #include "mozilla/dom/ModuleLoader.h" 14 #include "mozilla/dom/ScriptLoader.h" 15 #include "mozilla/dom/ShadowRealmGlobalScopeBinding.h" 16 #include "nsGlobalWindowInner.h" 17 #include "nsIGlobalObject.h" 18 #include "xpcpublic.h" 19 20 using namespace JS::loader; 21 22 namespace mozilla::dom { 23 24 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ShadowRealmGlobalScope, mModuleLoader, 25 mCreatingGlobal) 26 27 NS_IMPL_CYCLE_COLLECTING_ADDREF(ShadowRealmGlobalScope) 28 NS_IMPL_CYCLE_COLLECTING_RELEASE(ShadowRealmGlobalScope) 29 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ShadowRealmGlobalScope) 30 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 31 NS_INTERFACE_MAP_ENTRY(nsISupports) 32 NS_INTERFACE_MAP_ENTRY(nsIGlobalObject) 33 NS_INTERFACE_MAP_ENTRY(ShadowRealmGlobalScope) 34 NS_INTERFACE_MAP_END 35 36 JSObject* NewShadowRealmGlobal(JSContext* aCx, JS::RealmOptions& aOptions, 37 JSPrincipals* aPrincipals, 38 JS::Handle<JSObject*> aGlobalObj) { 39 JS::Rooted<JSObject*> reflector(aCx); 40 { 41 RefPtr<ShadowRealmGlobalScope> scope; 42 GlobalObject global(aCx, aGlobalObj); 43 44 nsCOMPtr<nsIGlobalObject> nsGlobal = 45 do_QueryInterface(global.GetAsSupports()); 46 47 MOZ_ASSERT(nsGlobal); 48 49 scope = new ShadowRealmGlobalScope(nsGlobal); 50 ShadowRealmGlobalScope_Binding::Wrap(aCx, scope, scope, aOptions, 51 aPrincipals, &reflector); 52 } 53 54 return reflector; 55 } 56 57 static nsIGlobalObject* FindEnclosingNonShadowRealmGlobal( 58 ShadowRealmGlobalScope* scope) { 59 nsCOMPtr<nsIGlobalObject> global = scope->GetCreatingGlobal(); 60 61 do { 62 nsCOMPtr<ShadowRealmGlobalScope> shadowRealmGlobalScope = 63 do_QueryInterface(global); 64 if (!shadowRealmGlobalScope) { 65 break; 66 } 67 68 // Our global was a ShadowRealmGlobal; that's a problem, as we can't find a 69 // window or worker global associated with a ShadowRealmGlobal... so we 70 // continue following the chain. 71 // 72 // This will happen if you have nested ShadowRealms. 73 global = shadowRealmGlobalScope->GetCreatingGlobal(); 74 } while (true); 75 76 return global; 77 } 78 79 ModuleLoaderBase* ShadowRealmGlobalScope::GetModuleLoader(JSContext* aCx) { 80 if (mModuleLoader) { 81 return mModuleLoader; 82 } 83 84 // Note: if this fails, we don't need to report an exception, as one will be 85 // reported by ModuleLoaderBase::GetCurrentModuleLoader. 86 87 // Don't bother asking the ShadowRealmGlobal itself for a host object to get a 88 // module loader from, instead, delegate to the enclosing global of the shadow 89 // realm 90 nsCOMPtr<nsIGlobalObject> global = FindEnclosingNonShadowRealmGlobal(this); 91 MOZ_RELEASE_ASSERT(global); 92 93 JSObject* object = global->GetGlobalJSObject(); 94 MOZ_ASSERT(object); 95 96 // Currently Workers will never get here, because dynamic import is disabled 97 // in Worker context, and so importValue will throw before we get here. 98 // 99 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1247687 and 100 // https://bugzilla.mozilla.org/show_bug.cgi?id=1772162 101 nsGlobalWindowInner* window = xpc::WindowGlobalOrNull(object); 102 if (!window) { 103 return nullptr; 104 } 105 106 RefPtr<Document> doc = window->GetExtantDoc(); 107 if (!doc) { 108 return nullptr; 109 } 110 111 ScriptLoader* scriptLoader = doc->GetScriptLoader(); 112 if (!scriptLoader) { 113 return nullptr; 114 } 115 116 mModuleLoader = new ModuleLoader(scriptLoader, this, ModuleLoader::Normal); 117 118 // Register the shadow realm module loader for tracing and ownership. 119 scriptLoader->RegisterShadowRealmModuleLoader( 120 static_cast<ModuleLoader*>(mModuleLoader.get())); 121 122 return mModuleLoader; 123 } 124 125 bool IsShadowRealmGlobal(JSObject* aObject) { 126 return IS_INSTANCE_OF(ShadowRealmGlobalScope, aObject); 127 } 128 129 } // namespace mozilla::dom