summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2020-07-04 16:28:30 +0000
committerMoonchild <moonchild@palemoon.org>2020-07-10 18:30:48 +0000
commitf6a6900a6b14d1d54da46370015b28d4d8a152a7 (patch)
tree6af248540f32f4427e9a01164804aca505aae379
parent40aad1a2209607b973170f4fb64548e5d8103402 (diff)
downloaduxp-f6a6900a6b14d1d54da46370015b28d4d8a152a7.tar.gz
Issue #618 - Further align error handling for module scripts with the spec
Ref: BZ 1388728
-rw-r--r--dom/script/ModuleLoadRequest.cpp42
-rw-r--r--dom/script/ModuleLoadRequest.h6
-rw-r--r--dom/script/ModuleScript.cpp72
-rw-r--r--dom/script/ModuleScript.h10
-rw-r--r--dom/script/ScriptLoader.cpp237
-rw-r--r--dom/script/ScriptLoader.h2
6 files changed, 280 insertions, 89 deletions
diff --git a/dom/script/ModuleLoadRequest.cpp b/dom/script/ModuleLoadRequest.cpp
index 8871dcdab2..d622143044 100644
--- a/dom/script/ModuleLoadRequest.cpp
+++ b/dom/script/ModuleLoadRequest.cpp
@@ -43,10 +43,16 @@ void ModuleLoadRequest::Cancel()
ScriptLoadRequest::Cancel();
mModuleScript = nullptr;
mProgress = ScriptLoadRequest::Progress::Ready;
+ CancelImports();
+ mReady.RejectIfExists(NS_ERROR_DOM_ABORT_ERR, __func__);
+}
+
+void
+ModuleLoadRequest::CancelImports()
+{
for (size_t i = 0; i < mImports.Length(); i++) {
mImports[i]->Cancel();
}
- mReady.RejectIfExists(NS_ERROR_FAILURE, __func__);
}
void
@@ -77,25 +83,53 @@ ModuleLoadRequest::ModuleLoaded()
// been loaded.
mModuleScript = mLoader->GetFetchedModule(mURI);
+ if (!mModuleScript || mModuleScript->IsErrored()) {
+ ModuleErrored();
+ return;
+ }
+
mLoader->StartFetchingModuleDependencies(this);
}
void
+ModuleLoadRequest::ModuleErrored()
+{
+ mLoader->CheckModuleDependenciesLoaded(this);
+ MOZ_ASSERT(!mModuleScript || mModuleScript->IsErrored());
+
+ CancelImports();
+ SetReady();
+ LoadFinished();
+}
+
+void
ModuleLoadRequest::DependenciesLoaded()
{
// The module and all of its dependencies have been successfully fetched and
// compiled.
+ MOZ_ASSERT(mModuleScript);
+
+ mLoader->CheckModuleDependenciesLoaded(this);
SetReady();
- mLoader->ProcessLoadedModuleTree(this);
- mLoader = nullptr;
- mParent = nullptr;
+ LoadFinished();
}
void
ModuleLoadRequest::LoadFailed()
{
+ // We failed to load the source text or an error occurred unrelated to the
+ // content of the module (e.g. OOM).
+
+ MOZ_ASSERT(!mModuleScript);
+
Cancel();
+ LoadFinished();
+}
+
+void
+ModuleLoadRequest::LoadFinished()
+{
mLoader->ProcessLoadedModuleTree(this);
mLoader = nullptr;
mParent = nullptr;
diff --git a/dom/script/ModuleLoadRequest.h b/dom/script/ModuleLoadRequest.h
index 0119fad385..7b06dd2cf3 100644
--- a/dom/script/ModuleLoadRequest.h
+++ b/dom/script/ModuleLoadRequest.h
@@ -45,9 +45,15 @@ public:
void Cancel() override;
void ModuleLoaded();
+ void ModuleErrored();
void DependenciesLoaded();
void LoadFailed();
+private:
+ void LoadFinished();
+ void CancelImports();
+
+public:
// Is this a request for a top level module script or an import?
bool mIsTopLevel;
diff --git a/dom/script/ModuleScript.cpp b/dom/script/ModuleScript.cpp
index bf02f522de..28b97a3cb5 100644
--- a/dom/script/ModuleScript.cpp
+++ b/dom/script/ModuleScript.cpp
@@ -26,6 +26,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ModuleScript)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL)
tmp->UnlinkModuleRecord();
+ tmp->mError.setUndefined();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ModuleScript)
@@ -34,25 +35,20 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ModuleScript)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mModuleRecord)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mError)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(ModuleScript)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ModuleScript)
-ModuleScript::ModuleScript(ScriptLoader *aLoader, nsIURI* aBaseURL,
- JS::Handle<JSObject*> aModuleRecord)
+ModuleScript::ModuleScript(ScriptLoader *aLoader, nsIURI* aBaseURL)
: mLoader(aLoader),
- mBaseURL(aBaseURL),
- mModuleRecord(aModuleRecord)
+ mBaseURL(aBaseURL)
{
MOZ_ASSERT(mLoader);
MOZ_ASSERT(mBaseURL);
- MOZ_ASSERT(mModuleRecord);
-
- // Make module's host defined field point to this module script object.
- // This is cleared in the UnlinkModuleRecord().
- JS::SetModuleHostDefinedField(mModuleRecord, JS::PrivateValue(this));
- HoldJSObjects(this);
+ MOZ_ASSERT(!mModuleRecord);
+ MOZ_ASSERT(mError.isUndefined());
}
void
@@ -63,18 +59,64 @@ ModuleScript::UnlinkModuleRecord()
MOZ_ASSERT(JS::GetModuleHostDefinedField(mModuleRecord).toPrivate() ==
this);
JS::SetModuleHostDefinedField(mModuleRecord, JS::UndefinedValue());
+ mModuleRecord = nullptr;
}
- mModuleRecord = nullptr;
}
ModuleScript::~ModuleScript()
{
- if (mModuleRecord) {
- // The object may be destroyed without being unlinked first.
- UnlinkModuleRecord();
- }
+ // The object may be destroyed without being unlinked first.
+ UnlinkModuleRecord();
DropJSObjects(this);
}
+void
+ModuleScript::SetModuleRecord(JS::Handle<JSObject*> aModuleRecord)
+{
+ MOZ_ASSERT(!mModuleRecord);
+ MOZ_ASSERT(mError.isUndefined());
+
+ mModuleRecord = aModuleRecord;
+
+ // Make module's host defined field point to this module script object.
+ // This is cleared in the UnlinkModuleRecord().
+ JS::SetModuleHostDefinedField(mModuleRecord, JS::PrivateValue(this));
+ HoldJSObjects(this);
+}
+
+void
+ModuleScript::SetPreInstantiationError(const JS::Value& aError)
+{
+ MOZ_ASSERT(!aError.isUndefined());
+
+ UnlinkModuleRecord();
+ mError = aError;
+
+ HoldJSObjects(this);
+}
+
+bool
+ModuleScript::IsErrored() const
+{
+ if (!mModuleRecord) {
+ MOZ_ASSERT(!mError.isUndefined());
+ return true;
+ }
+
+ return JS::IsModuleErrored(mModuleRecord);
+}
+
+JS::Value
+ModuleScript::Error() const
+{
+ MOZ_ASSERT(IsErrored());
+
+ if (!mModuleRecord) {
+ return mError;
+ }
+
+ return JS::GetModuleError(mModuleRecord);
+}
+
} // dom namespace
} // mozilla namespace
diff --git a/dom/script/ModuleScript.h b/dom/script/ModuleScript.h
index 97fdb8ed19..5713598592 100644
--- a/dom/script/ModuleScript.h
+++ b/dom/script/ModuleScript.h
@@ -23,6 +23,7 @@ class ModuleScript final : public nsISupports
RefPtr<ScriptLoader> mLoader;
nsCOMPtr<nsIURI> mBaseURL;
JS::Heap<JSObject*> mModuleRecord;
+ JS::Heap<JS::Value> mError;
~ModuleScript();
@@ -31,13 +32,18 @@ public:
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ModuleScript)
ModuleScript(ScriptLoader* aLoader,
- nsIURI* aBaseURL,
- JS::Handle<JSObject*> aModuleRecord);
+ nsIURI* aBaseURL);
+
+ void SetModuleRecord(JS::Handle<JSObject*> aModuleRecord);
+ void SetPreInstantiationError(const JS::Value& aError);
ScriptLoader* Loader() const { return mLoader; }
JSObject* ModuleRecord() const { return mModuleRecord; }
nsIURI* BaseURL() const { return mBaseURL; }
+ bool IsErrored() const;
+ JS::Value Error() const;
+
void UnlinkModuleRecord();
};
diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp
index cf7f06e713..a530989742 100644
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -418,25 +418,23 @@ void
ScriptLoader::SetModuleFetchFinishedAndResumeWaitingRequests(ModuleLoadRequest *aRequest,
nsresult aResult)
{
- // Update module map with the result of fetching a single module script. The
- // module script pointer is nullptr on error.
+ // 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.
- MOZ_ASSERT(!aRequest->IsReadyToRun());
-
RefPtr<GenericPromise::Private> promise;
MOZ_ALWAYS_TRUE(mFetchingModules.Get(aRequest->mURI, getter_AddRefs(promise)));
mFetchingModules.Remove(aRequest->mURI);
- RefPtr<ModuleScript> ms(aRequest->mModuleScript);
- MOZ_ASSERT(NS_SUCCEEDED(aResult) == (ms != nullptr));
- mFetchedModules.Put(aRequest->mURI, ms);
+ RefPtr<ModuleScript> moduleScript(aRequest->mModuleScript);
+ MOZ_ASSERT(NS_FAILED(aResult) == !moduleScript);
+
+ mFetchedModules.Put(aRequest->mURI, moduleScript);
if (promise) {
- if (ms) {
+ if (moduleScript) {
promise->Resolve(true, __func__);
} else {
promise->Reject(aResult, __func__);
@@ -482,19 +480,29 @@ ScriptLoader::ProcessFetchedModuleSource(ModuleLoadRequest* aRequest)
MOZ_ASSERT(!aRequest->mModuleScript);
nsresult rv = CreateModuleScript(aRequest);
+ MOZ_ASSERT(NS_FAILED(rv) == !aRequest->mModuleScript);
+
SetModuleFetchFinishedAndResumeWaitingRequests(aRequest, rv);
free(aRequest->mScriptTextBuf);
aRequest->mScriptTextBuf = nullptr;
aRequest->mScriptTextLength = 0;
- if (NS_SUCCEEDED(rv)) {
+ if (NS_FAILED(rv)) {
+ aRequest->LoadFailed();
+ return rv;
+ }
+
+ if (!aRequest->mModuleScript->IsErrored()) {
StartFetchingModuleDependencies(aRequest);
}
- return rv;
+ return NS_OK;
}
+static nsresult
+ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI>& aUrls);
+
nsresult
ScriptLoader::CreateModuleScript(ModuleLoadRequest* aRequest)
{
@@ -548,9 +556,34 @@ ScriptLoader::CreateModuleScript(ModuleLoadRequest* aRequest)
}
}
MOZ_ASSERT(NS_SUCCEEDED(rv) == (module != nullptr));
- if (module) {
- aRequest->mModuleScript =
- new ModuleScript(this, aRequest->mBaseURL, module);
+ RefPtr<ModuleScript> moduleScript = new ModuleScript(this, aRequest->mBaseURL);
+ aRequest->mModuleScript = moduleScript;
+
+ if (!module) {
+ // Compilation failed
+ MOZ_ASSERT(aes.HasException());
+ JS::Rooted<JS::Value> error(cx);
+ if (!aes.StealException(&error)) {
+ aRequest->mModuleScript = nullptr;
+ return NS_ERROR_FAILURE;
+ }
+
+ moduleScript->SetPreInstantiationError(error);
+ aRequest->ModuleErrored();
+ return NS_OK;
+ }
+
+ moduleScript->SetModuleRecord(module);
+
+ // Validate requested modules and treat failure to resolve module specifiers
+ // the same as a parse error.
+ nsCOMArray<nsIURI> urls;
+ rv = ResolveRequestedModules(aRequest, urls);
+ if (NS_FAILED(rv)) {
+ // ResolveRequestedModules sets pre-instanitation error on failure.
+ MOZ_ASSERT(moduleScript->IsErrored());
+ aRequest->ModuleErrored();
+ return NS_OK;
}
}
@@ -560,8 +593,8 @@ ScriptLoader::CreateModuleScript(ModuleLoadRequest* aRequest)
}
static bool
-ThrowTypeError(JSContext* aCx, ModuleScript* aScript,
- const nsString& aMessage)
+CreateTypeError(JSContext* aCx, ModuleScript* aScript, const nsString& aMessage,
+ JS::MutableHandle<JS::Value> aError)
{
JS::Rooted<JSObject*> module(aCx, aScript->ModuleRecord());
JS::Rooted<JSScript*> script(aCx, JS::GetModuleScript(aCx, module));
@@ -576,17 +609,11 @@ ThrowTypeError(JSContext* aCx, ModuleScript* aScript,
return false;
}
- JS::Rooted<JS::Value> error(aCx);
- if (!JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, filename, 0, 0, nullptr,
- message, &error)) {
- return false;
- }
-
- JS_SetPendingException(aCx, error);
- return false;
+ return JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, filename, 0, 0, nullptr,
+ message, aError);
}
-static bool
+static nsresult
HandleResolveFailure(JSContext* aCx, ModuleScript* aScript,
const nsAString& aSpecifier)
{
@@ -595,19 +622,13 @@ HandleResolveFailure(JSContext* aCx, ModuleScript* aScript,
nsAutoString message(NS_LITERAL_STRING("Error resolving module specifier: "));
message.Append(aSpecifier);
- return ThrowTypeError(aCx, aScript, message);
-}
-
-static bool
-HandleModuleNotFound(JSContext* aCx, ModuleScript* aScript,
- const nsAString& aSpecifier)
-{
- // TODO: How can we get the line number of the failed import?
-
- nsAutoString message(NS_LITERAL_STRING("Resolved module not found in map: "));
- message.Append(aSpecifier);
+ JS::Rooted<JS::Value> error(aCx);
+ if (!CreateTypeError(aCx, aScript, message, &error)) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
- return ThrowTypeError(aCx, aScript, message);
+ aScript->SetPreInstantiationError(error);
+ return NS_OK;
}
static already_AddRefed<nsIURI>
@@ -705,7 +726,8 @@ ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI> &aUrls)
ModuleScript* ms = aRequest->mModuleScript;
nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(ms, specifier);
if (!uri) {
- HandleResolveFailure(cx, ms, specifier);
+ nsresult rv = HandleResolveFailure(cx, ms, specifier);
+ NS_ENSURE_SUCCESS(rv, rv);
return NS_ERROR_FAILURE;
}
@@ -724,6 +746,7 @@ void
ScriptLoader::StartFetchingModuleDependencies(ModuleLoadRequest* aRequest)
{
MOZ_ASSERT(aRequest->mModuleScript);
+ MOZ_ASSERT(!aRequest->mModuleScript->IsErrored());
MOZ_ASSERT(!aRequest->IsReadyToRun());
aRequest->mProgress = ModuleLoadRequest::Progress::FetchingImports;
@@ -731,7 +754,7 @@ ScriptLoader::StartFetchingModuleDependencies(ModuleLoadRequest* aRequest)
nsCOMArray<nsIURI> urls;
nsresult rv = ResolveRequestedModules(aRequest, urls);
if (NS_FAILED(rv)) {
- aRequest->LoadFailed();
+ aRequest->ModuleErrored();
return;
}
@@ -755,7 +778,7 @@ ScriptLoader::StartFetchingModuleDependencies(ModuleLoadRequest* aRequest)
GenericPromise::All(AbstractThread::GetCurrent(), importsReady);
allReady->Then(AbstractThread::GetCurrent(), __func__, aRequest,
&ModuleLoadRequest::DependenciesLoaded,
- &ModuleLoadRequest::LoadFailed);
+ &ModuleLoadRequest::ModuleErrored);
}
RefPtr<GenericPromise>
@@ -778,6 +801,7 @@ ScriptLoader::StartFetchingModuleAndDependencies(ModuleLoadRequest* aRequest,
nsresult rv = StartLoad(childRequest, NS_LITERAL_STRING("module"), false);
if (NS_FAILED(rv)) {
+ MOZ_ASSERT(!childRequest->mModuleScript);
childRequest->mReady.Reject(rv, __func__);
return ready;
}
@@ -786,6 +810,7 @@ ScriptLoader::StartFetchingModuleAndDependencies(ModuleLoadRequest* aRequest,
return ready;
}
+// 8.1.3.8.1 HostResolveImportedModule(referencingModule, specifier)
bool
HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp)
{
@@ -800,25 +825,25 @@ HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp)
MOZ_ASSERT(script->ModuleRecord() == module);
// Let url be the result of resolving a module specifier given referencing
- // module script and specifier. If the result is failure, throw a TypeError
- // exception and abort these steps.
+ // module script and specifier.
nsAutoJSString string;
if (!string.init(aCx, specifier)) {
return false;
}
nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(script, string);
- if (!uri) {
- return HandleResolveFailure(aCx, script, string);
- }
- // Let resolved module script be the value of the entry in module map whose
- // key is url. If no such entry exists, throw a TypeError exception and abort
- // these steps.
+ // This cannot fail because resolving a module specifier must have been
+ // previously successful with these same two arguments.
+ MOZ_ASSERT(uri, "Failed to resolve previously-resolved module specifier");
+
+ // Let resolved module script be moduleMap[url]. (This entry must exist for us
+ // to have gotten to this point.)
+
ModuleScript* ms = script->Loader()->GetFetchedModule(uri);
- if (!ms) {
- return HandleModuleNotFound(aCx, script, string);
- }
+ MOZ_ASSERT(ms, "Resolved module not found in module map");
+
+ MOZ_ASSERT(!ms->IsErrored());
*vp = JS::ObjectValue(*ms->ModuleRecord());
return true;
@@ -843,9 +868,35 @@ EnsureModuleResolveHook(JSContext* aCx)
}
void
+ScriptLoader::CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest)
+{
+ RefPtr<ModuleScript> moduleScript = aRequest->mModuleScript;
+ if (moduleScript && !moduleScript->IsErrored()) {
+ for (auto childRequest : aRequest->mImports) {
+ ModuleScript* childScript = childRequest->mModuleScript;
+ if (!childScript) {
+ // Load error
+ aRequest->mModuleScript = nullptr;
+ return;
+ } else if (childScript->IsErrored()) {
+ // Script error
+ moduleScript->SetPreInstantiationError(childScript->Error());
+ return;
+ }
+ }
+ }
+}
+
+void
ScriptLoader::ProcessLoadedModuleTree(ModuleLoadRequest* aRequest)
{
if (aRequest->IsTopLevel()) {
+ ModuleScript* moduleScript = aRequest->mModuleScript;
+ if (moduleScript && !moduleScript->IsErrored()) {
+ if (!InstantiateModuleTree(aRequest)) {
+ aRequest->mModuleScript = nullptr;
+ }
+ }
MaybeMoveToLoadedList(aRequest);
ProcessPendingRequests();
}
@@ -855,6 +906,43 @@ ScriptLoader::ProcessLoadedModuleTree(ModuleLoadRequest* aRequest)
}
}
+bool
+ScriptLoader::InstantiateModuleTree(ModuleLoadRequest* aRequest)
+{
+ // Instantiate a top-level module and record any error.
+
+ MOZ_ASSERT(aRequest);
+ MOZ_ASSERT(aRequest->IsTopLevel());
+
+ ModuleScript* moduleScript = aRequest->mModuleScript;
+ MOZ_ASSERT(moduleScript);
+ MOZ_ASSERT(moduleScript->ModuleRecord());
+
+ nsAutoMicroTask mt;
+ AutoJSAPI jsapi;
+ if (NS_WARN_IF(!jsapi.Init(moduleScript->ModuleRecord()))) {
+ return false;
+ }
+
+ nsresult rv = EnsureModuleResolveHook(jsapi.cx());
+ NS_ENSURE_SUCCESS(rv, false);
+
+ JS::Rooted<JSObject*> module(jsapi.cx(), moduleScript->ModuleRecord());
+ bool ok = NS_SUCCEEDED(nsJSUtils::ModuleInstantiate(jsapi.cx(), module));
+
+ if (!ok) {
+ MOZ_ASSERT(jsapi.HasException());
+ JS::RootedValue exception(jsapi.cx());
+ if (!jsapi.StealException(&exception)) {
+ return false;
+ }
+ MOZ_ASSERT(!exception.isUndefined());
+ // Ignore the exception. It will be recorded in the module record.
+ }
+
+ return true;
+}
+
nsresult
ScriptLoader::StartLoad(ScriptLoadRequest *aRequest, const nsAString &aType,
bool aScriptFromHead)
@@ -1364,13 +1452,19 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
ModuleLoadRequest* modReq = request->AsModuleRequest();
modReq->mBaseURL = mDocument->GetDocBaseURI();
rv = CreateModuleScript(modReq);
- NS_ENSURE_SUCCESS(rv, false);
- StartFetchingModuleDependencies(modReq);
+ MOZ_ASSERT(NS_FAILED(rv) == !modReq->mModuleScript);
+ if (NS_FAILED(rv)) {
+ modReq->LoadFailed();
+ return false;
+ }
if (aElement->GetScriptAsync()) {
mLoadingAsyncRequests.AppendElement(request);
} else {
AddDeferRequest(request);
}
+ if (!modReq->mModuleScript->IsErrored()) {
+ StartFetchingModuleDependencies(modReq);
+ }
return false;
}
request->mProgress = ScriptLoadRequest::Progress::Ready;
@@ -1448,11 +1542,7 @@ ScriptLoader::ProcessOffThreadRequest(ScriptLoadRequest* aRequest)
if (aRequest->IsModuleRequest()) {
MOZ_ASSERT(aRequest->mOffThreadToken);
ModuleLoadRequest* request = aRequest->AsModuleRequest();
- nsresult rv = ProcessFetchedModuleSource(request);
- if (NS_FAILED(rv)) {
- request->LoadFailed();
- }
- return rv;
+ return ProcessFetchedModuleSource(request);
}
aRequest->SetReady();
@@ -1624,7 +1714,7 @@ ScriptLoader::ProcessRequest(ScriptLoadRequest* aRequest)
if (aRequest->IsModuleRequest() &&
!aRequest->AsModuleRequest()->mModuleScript)
{
- // There was an error parsing a module script. Nothing to do here.
+ // There was an error fetching a module script. Nothing to do here.
FireScriptAvailable(NS_ERROR_FAILURE, aRequest);
return NS_OK;
}
@@ -1846,8 +1936,8 @@ ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
// http://www.whatwg.org/specs/web-apps/current-work/#execute-the-script-block
nsAutoMicroTask mt;
AutoEntryScript aes(globalObject, "<script> element", true);
- JS::Rooted<JSObject*> global(aes.cx(),
- globalObject->GetGlobalJSObject());
+ JSContext* cx = aes.cx();
+ JS::Rooted<JSObject*> global(cx, globalObject->GetGlobalJSObject());
bool oldProcessingScriptTag = context->GetProcessingScriptTag();
context->SetProcessingScriptTag(true);
@@ -1868,27 +1958,38 @@ ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
}
if (aRequest->IsModuleRequest()) {
- rv = EnsureModuleResolveHook(aes.cx());
+ rv = EnsureModuleResolveHook(cx);
NS_ENSURE_SUCCESS(rv, rv);
ModuleLoadRequest* request = aRequest->AsModuleRequest();
MOZ_ASSERT(request->mModuleScript);
MOZ_ASSERT(!request->mOffThreadToken);
- JS::Rooted<JSObject*> module(aes.cx(),
- request->mModuleScript->ModuleRecord());
+
+ ModuleScript* moduleScript = request->mModuleScript;
+ if (moduleScript->IsErrored()) {
+ // Module has an error status
+ JS::Rooted<JS::Value> error(cx, moduleScript->Error());
+ JS_SetPendingException(cx, error);
+ return NS_OK; // An error is reported by AutoEntryScript.
+ }
+
+ JS::Rooted<JSObject*> module(cx, moduleScript->ModuleRecord());
MOZ_ASSERT(module);
- rv = nsJSUtils::ModuleInstantiate(aes.cx(), module);
- if (NS_SUCCEEDED(rv)) {
- rv = nsJSUtils::ModuleEvaluate(aes.cx(), module);
+
+ rv = nsJSUtils::ModuleEvaluate(cx, module);
+ MOZ_ASSERT(NS_FAILED(rv) == aes.HasException());
+ if (NS_FAILED(rv)) {
+ // Evaluation failed
+ rv = NS_OK; // An error is reported by AutoEntryScript.
}
} else {
- JS::CompileOptions options(aes.cx());
+ JS::CompileOptions options(cx);
rv = FillCompileOptionsForRequest(aes, aRequest, global, &options);
if (NS_SUCCEEDED(rv)) {
nsAutoString inlineData;
SourceBufferHolder srcBuf = GetScriptSource(aRequest, inlineData);
- rv = nsJSUtils::EvaluateString(aes.cx(), srcBuf, global, options,
+ rv = nsJSUtils::EvaluateString(cx, srcBuf, global, options,
aRequest->OffThreadTokenPtr());
}
}
diff --git a/dom/script/ScriptLoader.h b/dom/script/ScriptLoader.h
index 32401d1b6b..e6b75bf3bb 100644
--- a/dom/script/ScriptLoader.h
+++ b/dom/script/ScriptLoader.h
@@ -580,7 +580,9 @@ private:
nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
nsresult ProcessFetchedModuleSource(ModuleLoadRequest* aRequest);
+ void CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest);
void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest);
+ bool InstantiateModuleTree(ModuleLoadRequest* aRequest);
void StartFetchingModuleDependencies(ModuleLoadRequest* aRequest);
RefPtr<mozilla::GenericPromise>