Bug 1842798 - Part 1: Remove use of MozPromise to wait for module fetch r=smaug

This replaces the promise with a list of module requests that are waiting for a
resource to be fetched. When the fetch completes the waiting requests are
resumed appropriately. This now happens immediately rather tha via dispatching
a runnable.

Differential Revision: https://phabricator.services.mozilla.com/D183272
This commit is contained in:
Jon Coppeard
2023-08-02 09:34:39 +00:00
parent 30b2527f91
commit 1938262e85
2 changed files with 76 additions and 44 deletions

View File

@@ -50,6 +50,19 @@ mozilla::LazyLogModule ModuleLoaderBase::gModuleLoaderBaseLog(
#define LOG_ENABLED() \
MOZ_LOG_TEST(ModuleLoaderBase::gModuleLoaderBaseLog, mozilla::LogLevel::Debug)
//////////////////////////////////////////////////////////////
// ModuleLoaderBase::WaitingRequests
//////////////////////////////////////////////////////////////
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleLoaderBase::WaitingRequests)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION(ModuleLoaderBase::WaitingRequests, mWaiting)
NS_IMPL_CYCLE_COLLECTING_ADDREF(ModuleLoaderBase::WaitingRequests)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ModuleLoaderBase::WaitingRequests)
//////////////////////////////////////////////////////////////
// ModuleLoaderBase
//////////////////////////////////////////////////////////////
@@ -58,7 +71,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleLoaderBase)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION(ModuleLoaderBase, mFetchedModules,
NS_IMPL_CYCLE_COLLECTION(ModuleLoaderBase, mFetchingModules, mFetchedModules,
mDynamicImportRequests, mGlobalObject, mEventTarget,
mLoader)
@@ -408,10 +421,7 @@ nsresult ModuleLoaderBase::StartOrRestartModuleLoad(ModuleLoadRequest* aRequest,
if (aRestart == RestartRequest::No && ModuleMapContainsURL(request->mURI)) {
LOG(("ScriptLoadRequest (%p): Waiting for module fetch", aRequest));
WaitForModuleFetch(request->mURI)
->Then(mEventTarget, __func__, request,
&ModuleLoadRequest::ModuleLoaded,
&ModuleLoadRequest::LoadFailed);
WaitForModuleFetch(request);
return NS_OK;
}
@@ -471,17 +481,15 @@ void ModuleLoaderBase::SetModuleFetchStarted(ModuleLoadRequest* aRequest) {
MOZ_ASSERT(aRequest->IsFetching());
MOZ_ASSERT(!ModuleMapContainsURL(aRequest->mURI));
mFetchingModules.InsertOrUpdate(
aRequest->mURI, RefPtr<mozilla::GenericNonExclusivePromise::Private>{});
mFetchingModules.InsertOrUpdate(aRequest->mURI, nullptr);
}
void ModuleLoaderBase::SetModuleFetchFinishedAndResumeWaitingRequests(
ModuleLoadRequest* aRequest, nsresult aResult) {
// Update module map with the result of fetching a single module script.
//
// If any requests for the same URL are waiting on this one to complete, they
// will have ModuleLoaded or LoadFailed on them when the promise is
// resolved/rejected. This is set up in StartLoad.
// If any requests for the same URL are waiting on this one to complete, call
// ModuleLoaded or LoadFailed to resume or fail them as appropriate.
MOZ_ASSERT(aRequest->mLoader == this);
@@ -490,8 +498,9 @@ void ModuleLoaderBase::SetModuleFetchFinishedAndResumeWaitingRequests(
"%u)",
aRequest, aRequest->mModuleScript.get(), unsigned(aResult)));
RefPtr<mozilla::GenericNonExclusivePromise::Private> promise;
if (!mFetchingModules.Remove(aRequest->mURI, getter_AddRefs(promise))) {
RefPtr<WaitingRequests> waitingRequests;
if (!mFetchingModules.Remove(aRequest->mURI,
getter_AddRefs(waitingRequests))) {
LOG(
("ScriptLoadRequest (%p): Key not found in mFetchingModules, "
"assuming we have an inline module or have finished fetching already",
@@ -504,37 +513,47 @@ void ModuleLoaderBase::SetModuleFetchFinishedAndResumeWaitingRequests(
mFetchedModules.InsertOrUpdate(aRequest->mURI, RefPtr{moduleScript});
if (promise) {
if (moduleScript) {
LOG(("ScriptLoadRequest (%p): resolving %p", aRequest, promise.get()));
promise->Resolve(true, __func__);
} else {
LOG(("ScriptLoadRequest (%p): rejecting %p", aRequest, promise.get()));
promise->Reject(aResult, __func__);
}
if (waitingRequests) {
LOG(("ScriptLoadRequest (%p): Resuming waiting requests", aRequest));
ResumeWaitingRequests(waitingRequests, bool(moduleScript));
}
}
RefPtr<mozilla::GenericNonExclusivePromise>
ModuleLoaderBase::WaitForModuleFetch(nsIURI* aURL) {
MOZ_ASSERT(ModuleMapContainsURL(aURL));
void ModuleLoaderBase::ResumeWaitingRequests(WaitingRequests* aWaitingRequests,
bool aSuccess) {
for (ModuleLoadRequest* request : aWaitingRequests->mWaiting) {
ResumeWaitingRequest(request, aSuccess);
}
}
nsURIHashKey key(aURL);
if (auto entry = mFetchingModules.Lookup(aURL)) {
if (!entry.Data()) {
entry.Data() = new mozilla::GenericNonExclusivePromise::Private(__func__);
void ModuleLoaderBase::ResumeWaitingRequest(ModuleLoadRequest* aRequest,
bool aSuccess) {
if (aSuccess) {
aRequest->ModuleLoaded();
} else {
aRequest->LoadFailed();
}
}
void ModuleLoaderBase::WaitForModuleFetch(ModuleLoadRequest* aRequest) {
nsIURI* uri = aRequest->mURI;
MOZ_ASSERT(ModuleMapContainsURL(uri));
if (auto entry = mFetchingModules.Lookup(uri)) {
RefPtr<WaitingRequests> waitingRequests = entry.Data();
if (!waitingRequests) {
waitingRequests = new WaitingRequests();
mFetchingModules.InsertOrUpdate(uri, waitingRequests);
}
return entry.Data();
waitingRequests->mWaiting.AppendElement(aRequest);
return;
}
RefPtr<ModuleScript> ms;
MOZ_ALWAYS_TRUE(mFetchedModules.Get(aURL, getter_AddRefs(ms)));
if (!ms) {
return mozilla::GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_FAILURE, __func__);
}
MOZ_ALWAYS_TRUE(mFetchedModules.Get(uri, getter_AddRefs(ms)));
return mozilla::GenericNonExclusivePromise::CreateAndResolve(true, __func__);
ResumeWaitingRequest(aRequest, bool(ms));
}
ModuleScript* ModuleLoaderBase::GetFetchedModule(nsIURI* aURL) const {
@@ -1017,8 +1036,9 @@ void ModuleLoaderBase::Shutdown() {
CancelAndClearDynamicImports();
for (const auto& entry : mFetchingModules) {
if (entry.GetData()) {
entry.GetData()->Reject(NS_ERROR_FAILURE, __func__);
RefPtr<WaitingRequests> waitingRequests(entry.GetData());
if (waitingRequests) {
ResumeWaitingRequests(waitingRequests, false);
}
}