Backed out 4 changesets (bug 1842798) for causing wpt failures in /html/webappapis/dynamic-markup-insertion/document-write/module-dynamic-import.html CLOSED TREE

Backed out changeset b153ebf104ef (bug 1842798)
Backed out changeset 05bcaff61b68 (bug 1842798)
Backed out changeset 0864a23409e6 (bug 1842798)
Backed out changeset 98a1aa86513d (bug 1842798)
This commit is contained in:
Sandor Molnar 2023-08-02 14:58:13 +03:00
Родитель 13c7e4a350
Коммит 9de1620f3b
8 изменённых файлов: 108 добавлений и 202 удалений

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

@ -1221,13 +1221,6 @@ bool WorkerScriptLoader::EvaluateScript(JSContext* aCx,
}
void WorkerScriptLoader::TryShutdown() {
{
MutexAutoLock lock(CleanUpLock());
if (CleanedUp()) {
return;
}
}
if (AllScriptsExecuted() && AllModuleRequestsLoaded()) {
ShutdownScriptLoader(!mExecutionAborted, mMutedErrorFlag);
}

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

@ -27,15 +27,14 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(ModuleLoadRequest)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ModuleLoadRequest,
ScriptLoadRequest)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader, mRootModule, mModuleScript, mImports,
mWaitingParentRequest)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader, mModuleScript, mImports, mRootModule)
tmp->ClearDynamicImport();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ModuleLoadRequest,
ScriptLoadRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader, mRootModule, mModuleScript,
mImports, mWaitingParentRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader, mModuleScript, mImports,
mRootModule)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(ModuleLoadRequest,
@ -82,34 +81,25 @@ void ModuleLoadRequest::Cancel() {
return;
}
if (IsReadyToRun()) {
return;
}
ScriptLoadRequest::Cancel();
mModuleScript = nullptr;
CancelImports();
if (mWaitingParentRequest) {
ChildLoadComplete(false);
}
mReady.RejectIfExists(NS_ERROR_DOM_ABORT_ERR, __func__);
}
void ModuleLoadRequest::SetReady() {
MOZ_ASSERT(!IsReadyToRun());
// Mark a module as ready to execute. This means that this module and all it
// dependencies have had their source loaded, parsed as a module and the
// modules instantiated.
//
// The mReady promise is used to ensure that when all dependencies of a module
// have become ready, DependenciesLoaded is called on that module
// request. This is set up in StartFetchingModuleDependencies.
AssertAllImportsReady();
ScriptLoadRequest::SetReady();
if (mWaitingParentRequest) {
ChildLoadComplete(true);
}
mReady.ResolveIfExists(true, __func__);
}
void ModuleLoadRequest::ModuleLoaded() {
@ -167,11 +157,6 @@ void ModuleLoadRequest::ModuleErrored() {
MOZ_ASSERT(IsErrored());
CancelImports();
if (IsReadyToRun()) {
// Cancelling an outstanding import will error this request.
return;
}
SetReady();
LoadFinished();
}

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

@ -11,6 +11,7 @@
#include "ScriptLoadRequest.h"
#include "ModuleLoaderBase.h"
#include "mozilla/Assertions.h"
#include "mozilla/MozPromise.h"
#include "js/RootingAPI.h"
#include "js/Value.h"
#include "nsURIHashKey.h"
@ -35,10 +36,7 @@ class VisitedURLSet : public nsTHashtable<nsURIHashKey> {
// multiple imports of the same module.
class ModuleLoadRequest final : public ScriptLoadRequest {
~ModuleLoadRequest() {
MOZ_ASSERT(!mWaitingParentRequest);
MOZ_ASSERT(mAwaitingImports == 0);
}
~ModuleLoadRequest() = default;
ModuleLoadRequest(const ModuleLoadRequest& aOther) = delete;
ModuleLoadRequest(ModuleLoadRequest&& aOther) = delete;
@ -49,6 +47,10 @@ class ModuleLoadRequest final : public ScriptLoadRequest {
ScriptLoadRequest)
using SRIMetadata = mozilla::dom::SRIMetadata;
template <typename T>
using MozPromiseHolder = mozilla::MozPromiseHolder<T>;
using GenericPromise = mozilla::GenericPromise;
ModuleLoadRequest(nsIURI* aURI, ScriptFetchOptions* aFetchOptions,
const SRIMetadata& aIntegrity, nsIURI* aReferrer,
LoadContextBase* aContext, bool aIsTopLevel,
@ -112,8 +114,6 @@ class ModuleLoadRequest final : public ScriptLoadRequest {
void StartDynamicImport() { mLoader->StartDynamicImport(this); }
void ProcessDynamicImport() { mLoader->ProcessDynamicImport(this); }
void ChildLoadComplete(bool aSuccess);
private:
void LoadFinished();
void CancelImports();
@ -146,17 +146,14 @@ class ModuleLoadRequest final : public ScriptLoadRequest {
// failure.
RefPtr<ModuleScript> mModuleScript;
// A promise that is completed on successful load of this module and all of
// its dependencies, indicating that the module is ready for instantiation and
// evaluation.
MozPromiseHolder<GenericPromise> mReady;
// Array of imported modules.
nsTArray<RefPtr<ModuleLoadRequest>> mImports;
// Parent module (i.e. importer of this module) that is waiting for this
// module and its dependencies to load, or null.
RefPtr<ModuleLoadRequest> mWaitingParentRequest;
// Number of child modules (i.e. imported modules) that this module is waiting
// for.
size_t mAwaitingImports = 0;
// Set of module URLs visited while fetching the module graph this request is
// part of.
RefPtr<VisitedURLSet> mVisitedSet;

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

@ -30,7 +30,6 @@
#include "nsNetUtil.h" // NS_NewURI
#include "xpcpublic.h"
using mozilla::CycleCollectedJSContext;
using mozilla::Err;
using mozilla::Preferences;
using mozilla::UniquePtr;
@ -51,19 +50,6 @@ 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
//////////////////////////////////////////////////////////////
@ -72,7 +58,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleLoaderBase)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION(ModuleLoaderBase, mFetchingModules, mFetchedModules,
NS_IMPL_CYCLE_COLLECTION(ModuleLoaderBase, mFetchedModules,
mDynamicImportRequests, mGlobalObject, mEventTarget,
mLoader)
@ -422,7 +408,10 @@ nsresult ModuleLoaderBase::StartOrRestartModuleLoad(ModuleLoadRequest* aRequest,
if (aRestart == RestartRequest::No && ModuleMapContainsURL(request->mURI)) {
LOG(("ScriptLoadRequest (%p): Waiting for module fetch", aRequest));
WaitForModuleFetch(request);
WaitForModuleFetch(request->mURI)
->Then(mEventTarget, __func__, request,
&ModuleLoadRequest::ModuleLoaded,
&ModuleLoadRequest::LoadFailed);
return NS_OK;
}
@ -482,15 +471,17 @@ void ModuleLoaderBase::SetModuleFetchStarted(ModuleLoadRequest* aRequest) {
MOZ_ASSERT(aRequest->IsFetching());
MOZ_ASSERT(!ModuleMapContainsURL(aRequest->mURI));
mFetchingModules.InsertOrUpdate(aRequest->mURI, nullptr);
mFetchingModules.InsertOrUpdate(
aRequest->mURI, RefPtr<mozilla::GenericNonExclusivePromise::Private>{});
}
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, call
// ModuleLoaded or LoadFailed to resume or fail them as appropriate.
// 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.
MOZ_ASSERT(aRequest->mLoader == this);
@ -499,9 +490,8 @@ void ModuleLoaderBase::SetModuleFetchFinishedAndResumeWaitingRequests(
"%u)",
aRequest, aRequest->mModuleScript.get(), unsigned(aResult)));
RefPtr<WaitingRequests> waitingRequests;
if (!mFetchingModules.Remove(aRequest->mURI,
getter_AddRefs(waitingRequests))) {
RefPtr<mozilla::GenericNonExclusivePromise::Private> promise;
if (!mFetchingModules.Remove(aRequest->mURI, getter_AddRefs(promise))) {
LOG(
("ScriptLoadRequest (%p): Key not found in mFetchingModules, "
"assuming we have an inline module or have finished fetching already",
@ -514,47 +504,37 @@ void ModuleLoaderBase::SetModuleFetchFinishedAndResumeWaitingRequests(
mFetchedModules.InsertOrUpdate(aRequest->mURI, RefPtr{moduleScript});
if (waitingRequests) {
LOG(("ScriptLoadRequest (%p): Resuming waiting requests", aRequest));
ResumeWaitingRequests(waitingRequests, bool(moduleScript));
}
}
void ModuleLoaderBase::ResumeWaitingRequests(WaitingRequests* aWaitingRequests,
bool aSuccess) {
for (ModuleLoadRequest* request : aWaitingRequests->mWaiting) {
ResumeWaitingRequest(request, aSuccess);
}
}
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);
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__);
}
}
}
waitingRequests->mWaiting.AppendElement(aRequest);
return;
RefPtr<mozilla::GenericNonExclusivePromise>
ModuleLoaderBase::WaitForModuleFetch(nsIURI* aURL) {
MOZ_ASSERT(ModuleMapContainsURL(aURL));
nsURIHashKey key(aURL);
if (auto entry = mFetchingModules.Lookup(aURL)) {
if (!entry.Data()) {
entry.Data() = new mozilla::GenericNonExclusivePromise::Private(__func__);
}
return entry.Data();
}
RefPtr<ModuleScript> ms;
MOZ_ALWAYS_TRUE(mFetchedModules.Get(uri, getter_AddRefs(ms)));
MOZ_ALWAYS_TRUE(mFetchedModules.Get(aURL, getter_AddRefs(ms)));
if (!ms) {
return mozilla::GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_FAILURE, __func__);
}
ResumeWaitingRequest(aRequest, bool(ms));
return mozilla::GenericNonExclusivePromise::CreateAndResolve(true, __func__);
}
ModuleScript* ModuleLoaderBase::GetFetchedModule(nsIURI* aURL) const {
@ -852,7 +832,7 @@ void ModuleLoaderBase::StartFetchingModuleDependencies(
MOZ_ASSERT(aRequest->mModuleScript);
MOZ_ASSERT(!aRequest->mModuleScript->HasParseError());
MOZ_ASSERT(aRequest->IsFetching() || aRequest->IsCompiling());
MOZ_ASSERT(!aRequest->IsReadyToRun());
auto visitedSet = aRequest->mVisitedSet;
MOZ_ASSERT(visitedSet->Contains(aRequest->mURI));
@ -886,18 +866,26 @@ void ModuleLoaderBase::StartFetchingModuleDependencies(
return;
}
MOZ_ASSERT(aRequest->mAwaitingImports == 0);
aRequest->mAwaitingImports = urls.Count();
// For each url in urls, fetch a module script graph given url, module
// script's CORS setting, and module script's settings object.
nsTArray<RefPtr<mozilla::GenericPromise>> importsReady;
for (auto* url : urls) {
StartFetchingModuleAndDependencies(aRequest, url);
RefPtr<mozilla::GenericPromise> childReady =
StartFetchingModuleAndDependencies(aRequest, url);
importsReady.AppendElement(childReady);
}
// Wait for all imports to become ready.
RefPtr<mozilla::GenericPromise::AllPromiseType> allReady =
mozilla::GenericPromise::All(mEventTarget, importsReady);
allReady->Then(mEventTarget, __func__, aRequest,
&ModuleLoadRequest::DependenciesLoaded,
&ModuleLoadRequest::ModuleErrored);
}
void ModuleLoaderBase::StartFetchingModuleAndDependencies(
ModuleLoadRequest* aParent, nsIURI* aURI) {
RefPtr<mozilla::GenericPromise>
ModuleLoaderBase::StartFetchingModuleAndDependencies(ModuleLoadRequest* aParent,
nsIURI* aURI) {
MOZ_ASSERT(aURI);
RefPtr<ModuleLoadRequest> childRequest = CreateStaticImport(aURI, aParent);
@ -917,38 +905,20 @@ void ModuleLoaderBase::StartFetchingModuleAndDependencies(
url2.get()));
}
MOZ_ASSERT(!childRequest->mWaitingParentRequest);
childRequest->mWaitingParentRequest = aParent;
RefPtr<mozilla::GenericPromise> ready = childRequest->mReady.Ensure(__func__);
nsresult rv = StartModuleLoad(childRequest);
if (NS_FAILED(rv)) {
MOZ_ASSERT(!childRequest->mModuleScript);
LOG(("ScriptLoadRequest (%p): rejecting %p", aParent,
childRequest.get()));
&childRequest->mReady));
mLoader->ReportErrorToConsole(childRequest, rv);
childRequest->LoadFailed();
}
}
void ModuleLoadRequest::ChildLoadComplete(bool aSuccess) {
RefPtr<ModuleLoadRequest> parent = mWaitingParentRequest;
MOZ_ASSERT(parent);
MOZ_ASSERT(parent->mAwaitingImports != 0);
mWaitingParentRequest = nullptr;
parent->mAwaitingImports--;
if (parent->IsReadyToRun()) {
MOZ_ASSERT_IF(!aSuccess, parent->IsErrored());
return;
childRequest->mReady.Reject(rv, __func__);
return ready;
}
if (!aSuccess) {
parent->ModuleErrored();
} else if (parent->mAwaitingImports == 0) {
parent->DependenciesLoaded();
}
return ready;
}
void ModuleLoaderBase::StartDynamicImport(ModuleLoadRequest* aRequest) {
@ -1047,9 +1017,8 @@ void ModuleLoaderBase::Shutdown() {
CancelAndClearDynamicImports();
for (const auto& entry : mFetchingModules) {
RefPtr<WaitingRequests> waitingRequests(entry.GetData());
if (waitingRequests) {
ResumeWaitingRequests(waitingRequests, false);
if (entry.GetData()) {
entry.GetData()->Reject(NS_ERROR_FAILURE, __func__);
}
}
@ -1196,50 +1165,12 @@ nsresult ModuleLoaderBase::InitDebuggerDataForModuleGraph(
}
void ModuleLoaderBase::ProcessDynamicImport(ModuleLoadRequest* aRequest) {
// Instantiate and evaluate the imported module.
// See: https://tc39.es/ecma262/#sec-ContinueDynamicImport
//
// Since this is specced as happening on promise resolution (step 8) this must
// at least run as part of a microtask. We don't create the unobservable
// promise.
class DynamicImportMicroTask : public mozilla::MicroTaskRunnable {
public:
explicit DynamicImportMicroTask(ModuleLoadRequest* aRequest)
: MicroTaskRunnable(), mRequest(aRequest) {}
virtual void Run(mozilla::AutoSlowOperation& aAso) override {
mRequest->mLoader->InstantiateAndEvaluateDynamicImport(mRequest);
mRequest = nullptr;
}
virtual bool Suppressed() override {
return mRequest->mLoader->mGlobalObject->IsInSyncOperation();
}
private:
RefPtr<ModuleLoadRequest> mRequest;
};
MOZ_ASSERT(aRequest->mLoader == this);
if (!aRequest->mModuleScript) {
FinishDynamicImportAndReject(aRequest, NS_ERROR_FAILURE);
return;
}
CycleCollectedJSContext* context = CycleCollectedJSContext::Get();
RefPtr<DynamicImportMicroTask> runnable =
new DynamicImportMicroTask(aRequest);
context->DispatchToMicroTask(do_AddRef(runnable));
}
void ModuleLoaderBase::InstantiateAndEvaluateDynamicImport(
ModuleLoadRequest* aRequest) {
MOZ_ASSERT(aRequest->mModuleScript);
if (!InstantiateModuleGraph(aRequest)) {
aRequest->mModuleScript = nullptr;
if (aRequest->mModuleScript) {
if (!InstantiateModuleGraph(aRequest)) {
aRequest->mModuleScript = nullptr;
}
}
nsresult rv = NS_ERROR_FAILURE;

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

@ -23,6 +23,7 @@
#include "mozilla/CORSMode.h"
#include "mozilla/dom/JSExecutionContext.h"
#include "mozilla/MaybeOneOf.h"
#include "mozilla/MozPromise.h"
#include "mozilla/UniquePtr.h"
#include "ResolveResult.h"
@ -123,9 +124,9 @@ class ScriptLoaderInterface : public nsISupports {
* module map.
*
* The module map is made up of two parts. A module that has been requested but
* has not finished fetching is represented by an entry in the mFetchingModules
* map. A module which has been fetched and compiled is represented by a
* ModuleScript in the mFetchedModules map.
* has not yet loaded is represented by a promise in the mFetchingModules map. A
* module which has been loaded is represented by a ModuleScript in the
* mFetchedModules map.
*
* Module loading typically works as follows:
*
@ -162,21 +163,13 @@ class ScriptLoaderInterface : public nsISupports {
* 10. The client calls EvaluateModule() to execute the top-level module.
*/
class ModuleLoaderBase : public nsISupports {
/*
* The set of requests that are waiting for an ongoing fetch to complete.
*/
class WaitingRequests final : public nsISupports {
virtual ~WaitingRequests() = default;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(WaitingRequests)
nsTArray<RefPtr<ModuleLoadRequest>> mWaiting;
};
private:
using GenericNonExclusivePromise = mozilla::GenericNonExclusivePromise;
using GenericPromise = mozilla::GenericPromise;
// Module map
nsRefPtrHashtable<nsURIHashKey, WaitingRequests> mFetchingModules;
nsRefPtrHashtable<nsURIHashKey, GenericNonExclusivePromise::Private>
mFetchingModules;
nsRefPtrHashtable<nsURIHashKey, ModuleScript> mFetchedModules;
// List of dynamic imports that are currently being loaded.
@ -190,8 +183,8 @@ class ModuleLoaderBase : public nsISupports {
bool mImportMapsAllowed = true;
protected:
// Event handler used to dispatch runnables, used internally to wait for
// fetches to finish and for imports to become avilable.
// Event handler used to process MozPromise actions, used internally to wait
// for fetches to finish and for imports to become avilable.
nsCOMPtr<nsISerialEventTarget> mEventTarget;
RefPtr<ScriptLoaderInterface> mLoader;
@ -367,7 +360,7 @@ class ModuleLoaderBase : public nsISupports {
bool ModuleMapContainsURL(nsIURI* aURL) const;
bool IsModuleFetching(nsIURI* aURL) const;
void WaitForModuleFetch(ModuleLoadRequest* aRequest);
RefPtr<GenericNonExclusivePromise> WaitForModuleFetch(nsIURI* aURL);
void SetModuleFetchStarted(ModuleLoadRequest* aRequest);
ModuleScript* GetFetchedModule(nsIURI* aURL) const;
@ -380,15 +373,11 @@ class ModuleLoaderBase : public nsISupports {
void SetModuleFetchFinishedAndResumeWaitingRequests(
ModuleLoadRequest* aRequest, nsresult aResult);
void ResumeWaitingRequests(WaitingRequests* aWaitingRequests, bool aSuccess);
void ResumeWaitingRequest(ModuleLoadRequest* aRequest, bool aSuccess);
void StartFetchingModuleDependencies(ModuleLoadRequest* aRequest);
void StartFetchingModuleAndDependencies(ModuleLoadRequest* aParent,
nsIURI* aURI);
void InstantiateAndEvaluateDynamicImport(ModuleLoadRequest* aRequest);
RefPtr<GenericPromise> StartFetchingModuleAndDependencies(
ModuleLoadRequest* aParent, nsIURI* aURI);
/**
* Shorthand Wrapper for JSAPI FinishDynamicImport function for the reject

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

@ -1,5 +1,6 @@
[basic.any.html]
expected:
if (os == "mac") and not debug: [OK, TIMEOUT]
[TIMEOUT, OK]
[import() should not drain the microtask queue when loading an already loaded module]
expected: FAIL
@ -10,8 +11,14 @@
[import() should drain the microtask queue when fetching a new module]
expected: TIMEOUT
[import() should not drain the microtask queue when loading an already loaded module]
expected: FAIL
[basic.any.worker.html]
expected: [TIMEOUT, OK]
[import() should not drain the microtask queue when loading an already loaded module]
expected: FAIL
[import() should drain the microtask queue when fetching a new module]
expected: TIMEOUT

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

@ -1,3 +1,5 @@
[module-dynamic-import.html]
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[document.write in an imported module]
expected: FAIL

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

@ -2,3 +2,5 @@
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1678052
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[document.write in an imported module]
expected: FAIL