commit 8b743b6a79d5be966c4f3253a69eeaf6be2e5fc1
parent 8714caa9e3eb91b49a47fb3b5d383b8b0b442a8e
Author: Yoshi Cheng-Hao Huang <allstars.chh@gmail.com>
Date: Fri, 3 Oct 2025 20:53:29 +0000
Bug 1968890 - Part 7: Add Cancel method. r=jonco
Triggers FinishLoadingImportedModule in Cancel() to prevent memory leak.
Differential Revision: https://phabricator.services.mozilla.com/D264809
Diffstat:
5 files changed, 37 insertions(+), 33 deletions(-)
diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp
@@ -4033,6 +4033,10 @@ nsresult ScriptLoader::OnStreamComplete(
NS_ASSERTION(aRequest, "null request in stream complete handler");
NS_ENSURE_TRUE(aRequest, NS_ERROR_FAILURE);
+ if (aRequest->IsCanceled()) {
+ return NS_BINDING_ABORTED;
+ }
+
nsresult rv = VerifySRI(aRequest, aLoader, aSRIStatus, aSRIDataVerifier);
if (NS_SUCCEEDED(rv)) {
@@ -4481,9 +4485,6 @@ nsresult ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest,
return aStatus;
}
- if (aRequest->IsCanceled()) {
- return NS_BINDING_ABORTED;
- }
MOZ_ASSERT(aRequest->IsFetching());
CollectScriptTelemetry(aRequest);
diff --git a/js/loader/ModuleLoadRequest.cpp b/js/loader/ModuleLoadRequest.cpp
@@ -82,22 +82,6 @@ bool ModuleLoadRequest::IsErrored() const {
return mModuleScript->HasParseError() || mModuleScript->HasErrorToRethrow();
}
-void ModuleLoadRequest::Cancel() {
- if (IsCanceled()) {
- return;
- }
-
- if (IsFinished()) {
- return;
- }
-
- ScriptLoadRequest::Cancel();
-
- mModuleScript = nullptr;
- mReferrerScript = nullptr;
- mModuleRequestObj = nullptr;
-}
-
void ModuleLoadRequest::SetReady() {
MOZ_ASSERT(!IsFinished());
diff --git a/js/loader/ModuleLoadRequest.h b/js/loader/ModuleLoadRequest.h
@@ -66,7 +66,7 @@ class ModuleLoadRequest final : public ScriptLoadRequest {
nsIGlobalObject* GetGlobalObject();
void SetReady() override;
- void Cancel() override;
+ void Cancel() override { mLoader->Cancel(this); };
void SetImport(Handle<JSScript*> aReferrerScript,
Handle<JSObject*> aModuleRequestObj, Handle<Value> aPayload);
diff --git a/js/loader/ModuleLoaderBase.cpp b/js/loader/ModuleLoaderBase.cpp
@@ -890,6 +890,37 @@ void ModuleLoaderBase::OnFetchFailed(ModuleLoadRequest* aRequest) {
aRequest->ClearImport();
}
+void ModuleLoaderBase::Cancel(ModuleLoadRequest* aRequest) {
+ if (aRequest->IsFinished()) {
+ return;
+ }
+
+ aRequest->ScriptLoadRequest::Cancel();
+ aRequest->mModuleScript = nullptr;
+
+ if (aRequest->mPayload.isUndefined()) {
+ return;
+ }
+
+ AutoJSAPI jsapi;
+ if (!jsapi.Init(mGlobalObject)) {
+ return;
+ }
+ JSContext* cx = jsapi.cx();
+
+ Rooted<Value> payload(cx, aRequest->mPayload);
+ Rooted<Value> error(cx, UndefinedValue());
+
+ LOG(
+ ("ScriptLoadRequest (%p): Canceled, calling "
+ "FinishLoadingImportedModuleFailed",
+ aRequest));
+
+ FinishLoadingImportedModuleFailed(cx, payload, error);
+ aRequest->ModuleErrored();
+ aRequest->ClearImport();
+}
+
class ModuleErroredRunnable : public MicroTaskRunnable {
public:
explicit ModuleErroredRunnable(ModuleLoadRequest* aRequest)
@@ -1429,23 +1460,10 @@ ModuleLoaderBase::~ModuleLoaderBase() {
void ModuleLoaderBase::CancelFetchingModules() {
for (const auto& entry : mFetchingModules) {
RefPtr<LoadingRequest> loadingRequest = entry.GetData();
-
- // The compile task might not execute if the global is shutting down, while
- // the root module is still awaiting the result of the compiling request.
- // Therefore, we call OnFetchFailed to notify the root module of the
- // failure.
- bool isCompiling = loadingRequest->mRequest->IsCompiling();
- if (isCompiling) {
- OnFetchFailed(loadingRequest->mRequest);
- }
-
loadingRequest->mRequest->Cancel();
for (const auto& request : loadingRequest->mWaiting) {
request->Cancel();
- if (isCompiling) {
- OnFetchFailed(request);
- }
}
}
diff --git a/js/loader/ModuleLoaderBase.h b/js/loader/ModuleLoaderBase.h
@@ -574,6 +574,7 @@ class ModuleLoaderBase : public nsISupports {
void OnFetchSucceeded(ModuleLoadRequest* aRequest);
void OnFetchFailed(ModuleLoadRequest* aRequest);
+ void Cancel(ModuleLoadRequest* aRequest);
// The slot stored in ImportMetaResolve function.
enum class ImportMetaSlots : uint32_t { ModulePrivateSlot = 0, SlotCount };