Bug 1875836 - Part 2: Support dynamic import in ComponentModuleLoader. r=jonco

Differential Revision: https://phabricator.services.mozilla.com/D199279
This commit is contained in:
Tooru Fujisawa
2024-01-23 23:29:53 +00:00
parent 8d9ed15dd6
commit 412ee81bc1
4 changed files with 73 additions and 5 deletions

View File

@@ -335,7 +335,11 @@ bool ModuleLoaderBase::HostImportModuleDynamically(
return false;
}
loader->StartDynamicImport(request);
nsresult rv = loader->StartDynamicImport(request);
if (NS_SUCCEEDED(rv)) {
loader->OnDynamicImportStarted(request);
}
return true;
}
@@ -898,7 +902,7 @@ void ModuleLoadRequest::ChildLoadComplete(bool aSuccess) {
}
}
void ModuleLoaderBase::StartDynamicImport(ModuleLoadRequest* aRequest) {
nsresult ModuleLoaderBase::StartDynamicImport(ModuleLoadRequest* aRequest) {
MOZ_ASSERT(aRequest->mLoader == this);
LOG(("ScriptLoadRequest (%p): Start dynamic import", aRequest));
@@ -910,6 +914,7 @@ void ModuleLoaderBase::StartDynamicImport(ModuleLoadRequest* aRequest) {
mLoader->ReportErrorToConsole(aRequest, rv);
FinishDynamicImportAndReject(aRequest, rv);
}
return rv;
}
void ModuleLoaderBase::FinishDynamicImportAndReject(ModuleLoadRequest* aRequest,

View File

@@ -200,6 +200,12 @@ class ModuleLoaderBase : public nsISupports {
virtual ~ModuleLoaderBase();
#ifdef DEBUG
const ScriptLoadRequestList& DynamicImportRequests() const {
return mDynamicImportRequests;
}
#endif
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(ModuleLoaderBase)
@@ -234,6 +240,9 @@ class ModuleLoaderBase : public nsISupports {
JSContext* aCx, nsIURI* aURI, LoadedScript* aMaybeActiveScript,
JS::Handle<JSString*> aSpecifier, JS::Handle<JSObject*> aPromise) = 0;
// Called when dynamic import started successfully.
virtual void OnDynamicImportStarted(ModuleLoadRequest* aRequest) {}
// Check whether we can load a module. May return false with |aRvOut| set to
// NS_OK to abort load without returning an error.
virtual bool CanStartLoad(ModuleLoadRequest* aRequest, nsresult* aRvOut) = 0;
@@ -298,7 +307,7 @@ class ModuleLoaderBase : public nsISupports {
nsresult EvaluateModuleInContext(JSContext* aCx, ModuleLoadRequest* aRequest,
JS::ModuleErrorBehaviour errorBehaviour);
void StartDynamicImport(ModuleLoadRequest* aRequest);
nsresult StartDynamicImport(ModuleLoadRequest* aRequest);
void ProcessDynamicImport(ModuleLoadRequest* aRequest);
void CancelAndClearDynamicImports();

View File

@@ -76,7 +76,56 @@ already_AddRefed<ModuleLoadRequest> ComponentModuleLoader::CreateStaticImport(
already_AddRefed<ModuleLoadRequest> ComponentModuleLoader::CreateDynamicImport(
JSContext* aCx, nsIURI* aURI, LoadedScript* aMaybeActiveScript,
JS::Handle<JSString*> aSpecifier, JS::Handle<JSObject*> aPromise) {
return nullptr; // Not yet implemented.
RefPtr<ComponentLoadContext> context = new ComponentLoadContext();
RefPtr<ModuleLoadRequest> request = new ModuleLoadRequest(
aURI, aMaybeActiveScript->ReferrerPolicy(),
aMaybeActiveScript->GetFetchOptions(), dom::SRIMetadata(),
aMaybeActiveScript->BaseURL(), context,
/* aIsTopLevel = */ true, /* aIsDynamicImport = */ true, this,
ModuleLoadRequest::NewVisitedSetForTopLevelImport(aURI), nullptr);
request->SetDynamicImport(aMaybeActiveScript, aSpecifier, aPromise);
request->NoCacheEntryFound();
return request.forget();
}
void ComponentModuleLoader::OnDynamicImportStarted(
ModuleLoadRequest* aRequest) {
MOZ_ASSERT(aRequest->IsDynamicImport());
MOZ_ASSERT(!mLoadRequests.Contains(aRequest));
if (aRequest->IsFetching()) {
// This module is newly imported.
//
// DynamicImportRequests() can contain multiple requests when a dynamic
// import is performed while evaluating the top-level script of other
// dynamic imports.
//
// mLoadRequests should be empty given evaluation is performed after
// handling all fetching requests.
MOZ_ASSERT(DynamicImportRequests().Contains(aRequest));
MOZ_ASSERT(mLoadRequests.isEmpty());
nsresult rv = OnFetchComplete(aRequest, NS_OK);
if (NS_FAILED(rv)) {
mLoadRequests.CancelRequestsAndClear();
CancelDynamicImport(aRequest, rv);
return;
}
rv = ProcessRequests();
if (NS_FAILED(rv)) {
CancelDynamicImport(aRequest, rv);
return;
}
} else {
// This module had already been imported.
MOZ_ASSERT(DynamicImportRequests().isEmpty());
MOZ_ASSERT(mLoadRequests.isEmpty());
}
ProcessDynamicImport(aRequest);
}
bool ComponentModuleLoader::CanStartLoad(ModuleLoadRequest* aRequest,
@@ -150,7 +199,10 @@ nsresult ComponentModuleLoader::StartFetch(ModuleLoadRequest* aRequest) {
context->mScript = script;
}
mLoadRequests.AppendElement(aRequest);
if (!aRequest->IsDynamicImport()) {
// NOTE: Dynamic import is stored into mDynamicImportRequests.
mLoadRequests.AppendElement(aRequest);
}
return NS_OK;
}

View File

@@ -73,6 +73,8 @@ class ComponentModuleLoader : public JS::loader::ModuleLoaderBase {
JS::Handle<JSString*> aSpecifier,
JS::Handle<JSObject*> aPromise) override;
void OnDynamicImportStarted(ModuleLoadRequest* aRequest) override;
bool CanStartLoad(ModuleLoadRequest* aRequest, nsresult* aRvOut) override;
nsresult StartFetch(ModuleLoadRequest* aRequest) override;