Bug 1788532 - Block dynamic module load processing during sync XHR r=smaug

The problem is that synchronous XMLHttpRequest requests can spin the event loop
and cause us to process dynamic module loads (by calling
JS::FinishDynamicModuleImport) when we are already inside JS::ModuleEvaluate.
The module algorithms assume that they are not reentrant.

The patch changes dyammic module load processing to happen in the same way as
async script loads (of both classic scripts and modules), which are blocked
during sync XHR by Document::SuppressEventHandling calling
ScriptLoader::AddExecuteBlocker.

Differential Revision: https://phabricator.services.mozilla.com/D157218
This commit is contained in:
Jon Coppeard 2022-09-15 09:14:11 +00:00
Родитель 2b578705b7
Коммит bccb7ef6f3
3 изменённых файлов: 17 добавлений и 13 удалений

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

@ -130,10 +130,9 @@ void ModuleLoader::OnModuleLoadComplete(ModuleLoadRequest* aRequest) {
MOZ_ASSERT(aRequest->IsReadyToRun());
if (aRequest->IsTopLevel()) {
if (aRequest->IsDynamicImport() ||
(aRequest->GetScriptLoadContext()->mIsInline &&
aRequest->GetScriptLoadContext()->GetParserCreated() ==
NOT_FROM_PARSER)) {
if (aRequest->GetScriptLoadContext()->mIsInline &&
aRequest->GetScriptLoadContext()->GetParserCreated() ==
NOT_FROM_PARSER) {
GetScriptLoader()->RunScriptWhenSafe(aRequest);
} else {
GetScriptLoader()->MaybeMoveToLoadedList(aRequest);

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

@ -495,15 +495,7 @@ class ScriptRequestProcessor : public Runnable {
: Runnable("dom::ScriptRequestProcessor"),
mLoader(aLoader),
mRequest(aRequest) {}
NS_IMETHOD Run() override {
if (mRequest->IsModuleRequest() &&
mRequest->AsModuleRequest()->IsDynamicImport()) {
mRequest->AsModuleRequest()->ProcessDynamicImport();
return NS_OK;
}
return mLoader->ProcessRequest(mRequest);
}
NS_IMETHOD Run() override { return mLoader->ProcessRequest(mRequest); }
};
void ScriptLoader::RunScriptWhenSafe(ScriptLoadRequest* aRequest) {
@ -1792,6 +1784,11 @@ nsresult ScriptLoader::ProcessRequest(ScriptLoadRequest* aRequest) {
if (aRequest->IsModuleRequest()) {
ModuleLoadRequest* request = aRequest->AsModuleRequest();
if (request->IsDynamicImport()) {
request->ProcessDynamicImport();
return NS_OK;
}
if (request->mModuleScript) {
if (!request->InstantiateModuleGraph()) {
request->mModuleScript = nullptr;
@ -3629,6 +3626,7 @@ void ScriptLoader::AddAsyncRequest(ScriptLoadRequest* aRequest) {
void ScriptLoader::MaybeMoveToLoadedList(ScriptLoadRequest* aRequest) {
MOZ_ASSERT(aRequest->IsReadyToRun());
MOZ_ASSERT(aRequest->IsTopLevel());
// If it's async, move it to the loaded list.
// aRequest->GetScriptLoadContext()->mInAsyncList really _should_ be in a
@ -3640,6 +3638,11 @@ void ScriptLoader::MaybeMoveToLoadedList(ScriptLoadRequest* aRequest) {
RefPtr<ScriptLoadRequest> req = mLoadingAsyncRequests.Steal(aRequest);
mLoadedAsyncRequests.AppendElement(req);
}
} else if (aRequest->IsModuleRequest() &&
aRequest->AsModuleRequest()->IsDynamicImport()) {
// Process dynamic imports with async scripts.
MOZ_ASSERT(!aRequest->isInList());
mLoadedAsyncRequests.AppendElement(aRequest);
}
}

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

@ -682,6 +682,8 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface {
// mLoadingAsyncRequests holds async requests while they're loading; when they
// have been loaded they are moved to mLoadedAsyncRequests.
ScriptLoadRequestList mLoadingAsyncRequests;
// mLoadedAsyncRequests holds async script requests and dynamic module import
// requests, which are processed in the same way.
ScriptLoadRequestList mLoadedAsyncRequests;
ScriptLoadRequestList mDeferRequests;
ScriptLoadRequestList mXSLTRequests;