Bug 1761938 - Part 4: Give module loaders a global object field r=smaug,yulia

This gives the module loader a field for the current global, since a module map
is only associated with a single global.

This adds a method to Document to tell the script loader when its global
changes. I'm not sure of when we do this exactly.

Differential Revision: https://phabricator.services.mozilla.com/D142831
This commit is contained in:
Jon Coppeard 2022-04-11 15:35:29 +00:00
Родитель 79f031217b
Коммит d4aae71cf3
8 изменённых файлов: 60 добавлений и 14 удалений

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

@ -7713,6 +7713,11 @@ void Document::SetScriptGlobalObject(
mTemplateContentsOwner->SetScriptGlobalObject(aScriptGlobalObject);
}
// Tell the script loader about the new global object.
if (mScriptLoader) {
mScriptLoader->SetGlobalObject(mScriptGlobalObject);
}
if (!mMaybeServiceWorkerControlled && mDocumentContainer &&
mScriptGlobalObject && GetChannel()) {
// If we are shift-reloaded, don't associate with a ServiceWorker.

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

@ -48,8 +48,9 @@ namespace mozilla::dom {
// DOM module loader
//////////////////////////////////////////////////////////////
ModuleLoader::ModuleLoader(ScriptLoader* aLoader, Kind aKind)
: ModuleLoaderBase(aLoader), mKind(aKind) {}
ModuleLoader::ModuleLoader(ScriptLoader* aLoader,
nsIGlobalObject* aGlobalObject, Kind aKind)
: ModuleLoaderBase(aLoader, aGlobalObject), mKind(aKind) {}
ScriptLoader* ModuleLoader::GetScriptLoader() {
return static_cast<ScriptLoader*>(mLoader.get());

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

@ -42,7 +42,8 @@ class ModuleLoader final : public JS::loader::ModuleLoaderBase {
public:
enum Kind { Normal, WebExtension };
ModuleLoader(ScriptLoader* aLoader, Kind aKind);
ModuleLoader(ScriptLoader* aLoader, nsIGlobalObject* aGlobalObject,
Kind aKind);
Kind GetKind() const { return mKind; }

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

@ -187,8 +187,7 @@ ScriptLoader::ScriptLoader(Document* aDocument)
mBlockingDOMContentLoaded(false),
mLoadEventFired(false),
mGiveUpEncoding(false),
mReporter(new ConsoleReportCollector()),
mModuleLoader(new ModuleLoader(this, ModuleLoader::Normal)) {
mReporter(new ConsoleReportCollector()) {
LOG(("ScriptLoader::ScriptLoader %p", this));
mSpeculativeOMTParsingEnabled = StaticPrefs::
@ -251,6 +250,24 @@ ScriptLoader::~ScriptLoader() {
mModuleLoader = nullptr;
}
void ScriptLoader::SetGlobalObject(nsIGlobalObject* aGlobalObject) {
if (!aGlobalObject) {
// The document is being detached.
return;
}
MOZ_ASSERT(!HasPendingRequests());
if (mModuleLoader) {
MOZ_ASSERT(mModuleLoader->GetGlobalObject() == aGlobalObject);
return;
}
// The module loader is associated with a global object, so don't create it
// until we have a global set.
mModuleLoader = new ModuleLoader(this, aGlobalObject, ModuleLoader::Normal);
}
void ScriptLoader::RegisterContentScriptModuleLoader(ModuleLoader* aLoader) {
MOZ_ASSERT(aLoader);
MOZ_ASSERT(aLoader->GetScriptLoader() == this);
@ -2543,7 +2560,7 @@ void ScriptLoader::GiveUpBytecodeEncoding() {
}
}
bool ScriptLoader::HasPendingRequests() {
bool ScriptLoader::HasPendingRequests() const {
return mParserBlockingRequest || !mXSLTRequests.isEmpty() ||
!mLoadedAsyncRequests.isEmpty() ||
!mNonAsyncExternalScriptInsertedRequests.isEmpty() ||
@ -2553,7 +2570,7 @@ bool ScriptLoader::HasPendingRequests() {
}
bool ScriptLoader::HasPendingDynamicImports() const {
if (mModuleLoader->HasPendingDynamicImports()) {
if (mModuleLoader && mModuleLoader->HasPendingDynamicImports()) {
return true;
}
@ -3354,7 +3371,9 @@ void ScriptLoader::ParsingComplete(bool aTerminated) {
mNonAsyncExternalScriptInsertedRequests.CancelRequestsAndClear();
mXSLTRequests.CancelRequestsAndClear();
mModuleLoader->CancelAndClearDynamicImports();
if (mModuleLoader) {
mModuleLoader->CancelAndClearDynamicImports();
}
for (ModuleLoader* loader : mWebExtModuleLoaders) {
loader->CancelAndClearDynamicImports();

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

@ -132,6 +132,12 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface {
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(ScriptLoader)
/**
* Called when the document that owns this script loader changes global. The
* argument is null when the document is detached from a window.
*/
void SetGlobalObject(nsIGlobalObject* aGlobalObject);
/**
* The loader maintains a weak reference to the document with
* which it is initialized. This call forces the reference to
@ -322,7 +328,7 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface {
/**
* Returns wether any request is queued, and not executed yet.
*/
bool HasPendingRequests();
bool HasPendingRequests() const;
/**
* Returns wether there are any dynamic module import requests pending.

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

@ -52,7 +52,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleLoaderBase)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION(ModuleLoaderBase, mFetchedModules,
mDynamicImportRequests, mLoader)
mDynamicImportRequests, mGlobalObject, mLoader)
NS_IMPL_CYCLE_COLLECTING_ADDREF(ModuleLoaderBase)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ModuleLoaderBase)
@ -255,6 +255,8 @@ ModuleLoaderBase* ModuleLoaderBase::GetCurrentModuleLoader(JSContext* aCx) {
return nullptr;
}
MOZ_ASSERT(loader->mGlobalObject == global);
reportError.release();
return loader;
}
@ -461,6 +463,8 @@ nsresult ModuleLoaderBase::CreateModuleScript(ModuleLoadRequest* aRequest) {
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(globalObject == mGlobalObject);
AutoJSAPI jsapi;
if (!jsapi.Init(globalObject)) {
return NS_ERROR_FAILURE;
@ -832,8 +836,12 @@ void ModuleLoaderBase::FinishDynamicImport(
aRequest->ClearDynamicImport();
}
ModuleLoaderBase::ModuleLoaderBase(ScriptLoaderInterface* aLoader)
: mLoader(aLoader) {
ModuleLoaderBase::ModuleLoaderBase(ScriptLoaderInterface* aLoader,
nsIGlobalObject* aGlobalObject)
: mGlobalObject(aGlobalObject), mLoader(aLoader) {
MOZ_ASSERT(mGlobalObject);
MOZ_ASSERT(mLoader);
EnsureModuleHooksInitialized();
}
@ -992,6 +1000,7 @@ void ModuleLoaderBase::ProcessDynamicImport(ModuleLoadRequest* aRequest) {
nsresult ModuleLoaderBase::EvaluateModule(nsIGlobalObject* aGlobalObject,
ModuleLoadRequest* aRequest) {
MOZ_ASSERT(aRequest->mLoader == this);
MOZ_ASSERT(aGlobalObject == mGlobalObject);
AUTO_PROFILER_LABEL("ModuleLoaderBase::EvaluateModule", JS);

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

@ -92,6 +92,8 @@ class ModuleLoaderBase : public nsISupports {
// List of dynamic imports that are currently being loaded.
ScriptLoadRequestList mDynamicImportRequests;
nsCOMPtr<nsIGlobalObject> mGlobalObject;
protected:
RefPtr<ScriptLoaderInterface> mLoader;
@ -100,7 +102,8 @@ class ModuleLoaderBase : public nsISupports {
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(ModuleLoaderBase)
explicit ModuleLoaderBase(ScriptLoaderInterface* aLoader);
explicit ModuleLoaderBase(ScriptLoaderInterface* aLoader,
nsIGlobalObject* aGlobalObject);
using LoadedScript = JS::loader::LoadedScript;
using ScriptFetchOptions = JS::loader::ScriptFetchOptions;
@ -143,6 +146,8 @@ class ModuleLoaderBase : public nsISupports {
public:
ScriptLoaderInterface* GetScriptLoaderInterface() const { return mLoader; }
nsIGlobalObject* GetGlobalObject() const { return mGlobalObject; }
bool HasPendingDynamicImports() const;
void CancelDynamicImport(ModuleLoadRequest* aRequest, nsresult aResult);
#ifdef DEBUG

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

@ -2230,7 +2230,7 @@ ModuleLoaderBase* SandboxPrivate::GetModuleLoader(JSContext* aCx) {
ScriptLoader* scriptLoader = mainModuleLoader->GetScriptLoader();
ModuleLoader* moduleLoader =
new ModuleLoader(scriptLoader, ModuleLoader::WebExtension);
new ModuleLoader(scriptLoader, this, ModuleLoader::WebExtension);
scriptLoader->RegisterContentScriptModuleLoader(moduleLoader);
mModuleLoader = moduleLoader;