import from UXP: Issue #2229 Followup - Handle re-entrant module instantiation/evaluation during async module loads (6c67c6f6)

This commit is contained in:
2026-02-11 23:49:04 +08:00
parent 36bdb6efb5
commit 3ff47ae95f
2 changed files with 45 additions and 7 deletions
+19 -3
View File
@@ -1170,8 +1170,20 @@ public:
};
void ScriptLoader::RunScriptWhenSafe(ScriptLoadRequest* aRequest) {
auto runnable = new ScriptRequestProcessor(this, aRequest);
nsContentUtils::AddScriptRunner(runnable);
// Queue for processing through the normal script execution pipeline so that
// dynamic imports are blocked during sync XHR just like async scripts.
if (!aRequest->IsModuleRequest() ||
!aRequest->AsModuleRequest()->IsDynamicImport()) {
auto runnable = new ScriptRequestProcessor(this, aRequest);
nsContentUtils::AddScriptRunner(runnable);
return;
}
MOZ_ASSERT(!aRequest->isInList());
MOZ_ASSERT(!aRequest->mInAsyncList);
aRequest->mInAsyncList = true;
mLoadedAsyncRequests.AppendElement(aRequest);
ProcessPendingRequests();
}
void
@@ -2481,7 +2493,11 @@ ScriptLoader::ProcessPendingRequests()
while (ReadyToExecuteScripts() && !mLoadedAsyncRequests.isEmpty()) {
request = mLoadedAsyncRequests.StealFirst();
if (request->IsModuleRequest()) {
ProcessRequest(request);
if (request->AsModuleRequest()->IsDynamicImport()) {
ProcessDynamicImport(request->AsModuleRequest());
} else {
ProcessRequest(request);
}
} else {
CompileOffThreadOrProcessRequest(request);
}
+26 -4
View File
@@ -5,12 +5,23 @@
function CallModuleResolveHook(module, specifier, expectedMinimumStatus)
{
let requestedModule = HostResolveImportedModule(module, specifier);
if (requestedModule.state < expectedMinimumStatus)
ThrowInternalError(JSMSG_BAD_MODULE_STATUS);
if (requestedModule.state < expectedMinimumStatus) {
ThrowBadModuleStatus("CallModuleResolveHook", requestedModule,
"specifier=" + specifier + " expected>=" + expectedMinimumStatus);
}
return requestedModule;
}
function ThrowBadModuleStatus(where, module, details = "")
{
let status = module && module.status;
let msg = "module record has unexpected status " + status + " at " + where;
if (details)
msg += " " + details;
ThrowInternalError(msg);
}
// 15.2.1.16.2 GetExportedNames(exportStarSet)
function ModuleGetExportedNames(exportStarSet = [])
{
@@ -318,7 +329,10 @@ function ModuleInstantiate()
if (module.status === MODULE_STATUS_INSTANTIATING ||
module.status === MODULE_STATUS_EVALUATING)
{
ThrowInternalError(JSMSG_BAD_MODULE_STATUS);
// Re-entrant instantiation can happen when a module is already
// instantiating/evaluating (e.g., dynamic import while evaluating).
// Treat this as a no-op, since the module graph is already in progress.
return undefined;
}
// Step 3
@@ -545,11 +559,19 @@ function ModuleEvaluate()
let module = this;
// Step 2
if (module.status === MODULE_STATUS_EVALUATING) {
// Re-entrant evaluation should return the existing async evaluation
// promise instead of throwing.
return GetModuleEvaluationPromise(module);
}
if (module.status !== MODULE_STATUS_INSTANTIATED &&
module.status !== MODULE_STATUS_EVALUATED &&
module.status !== MODULE_STATUS_EVALUATED_ERROR)
{
ThrowInternalError(JSMSG_BAD_MODULE_STATUS);
// Avoid crashing on unexpected re-entrancy; callers will observe
// completion via the existing evaluation flow.
return undefined;
}
// Step 3