@@ -720,6 +720,8 @@ void ModuleLoaderBase::ResumeWaitingRequest(ModuleLoadRequest* aRequest,
720720
721721 if (!aRequest->IsErrored ()) {
722722 OnFetchSucceeded (aRequest);
723+ } else {
724+ OnFetchFailed (aRequest);
723725 }
724726}
725727
@@ -789,6 +791,8 @@ nsresult ModuleLoaderBase::OnFetchComplete(ModuleLoadRequest* aRequest,
789791
790792 if (!aRequest->IsErrored ()) {
791793 OnFetchSucceeded (aRequest);
794+ } else {
795+ OnFetchFailed (aRequest);
792796 }
793797
794798 if (!waitingRequests) {
@@ -816,6 +820,71 @@ void ModuleLoaderBase::OnFetchSucceeded(ModuleLoadRequest* aRequest) {
816820 }
817821}
818822
823+ void ModuleLoaderBase::OnFetchFailed (ModuleLoadRequest* aRequest) {
824+ MOZ_ASSERT (aRequest->IsErrored ());
825+ // For dynamic import, the error handling is done in ProcessDynamicImport
826+ if (aRequest->IsDynamicImport ()) {
827+ return ;
828+ }
829+
830+ if (aRequest->IsTopLevel ()) {
831+ // https://html.spec.whatwg.org/#fetch-the-descendants-of-and-link-a-module-script
832+ // Step 2. If record is null, then:
833+ // Step 2.1. Set moduleScript's error to rethrow to moduleScript's parse
834+ // error.
835+ if (aRequest->mModuleScript && !aRequest->mModuleScript ->ModuleRecord ()) {
836+ MOZ_ASSERT (aRequest->mModuleScript ->HasParseError ());
837+ JS::Value parseError = aRequest->mModuleScript ->ParseError ();
838+ LOG ((" ScriptLoadRequest (%p): found parse error" , aRequest));
839+ aRequest->mModuleScript ->SetErrorToRethrow (parseError);
840+ }
841+ } else {
842+ // The remaining case is static import.
843+ AutoJSAPI jsapi;
844+ if (!jsapi.Init (mGlobalObject )) {
845+ return ;
846+ }
847+ JSContext* cx = jsapi.cx ();
848+
849+ MOZ_ASSERT (!aRequest->mStatePrivate .isUndefined ());
850+ JS::Rooted<JS::Value> statePrivate (cx, aRequest->mStatePrivate );
851+ JS::Rooted<JS::Value> error (cx);
852+
853+ // https://html.spec.whatwg.org/#hostloadimportedmodule
854+ //
855+ // Step 14.2. If moduleScript is null, then set completion to Completion
856+ // Record { [[Type]]: throw, [[Value]]: a new TypeError,
857+ // [[Target]]: empty }.
858+ //
859+ // Impl note:
860+ // When moduleScript is null, the ScriptLoader will call onerror handler.
861+ // So we don't actually create a TypeError for this.
862+ if (!aRequest->mModuleScript ) {
863+ error = UndefinedValue ();
864+ } else {
865+ // Step 14.3. Otherwise, if moduleScript's parse error is not null, then:
866+ // 1. Let parseError be moduleScript's parse error.
867+ // 2. Set completion to Completion Record { [[Type]]: throw,
868+ // [[Value]]: parseError, [[Target]]: empty }.
869+ // 3. If loadState is not undefined and loadState.[[ErrorToRethrow]]
870+ // is null, set loadState.[[ErrorToRethrow]] to parseError.
871+ MOZ_ASSERT (aRequest->mModuleScript ->HasParseError ());
872+ error = aRequest->mModuleScript ->ParseError ();
873+ }
874+
875+ LOG ((" ScriptLoadRequest (%p): FinishLoadingImportedModuleFailed" ,
876+ aRequest));
877+ // Step 14.5. Perform FinishLoadingImportedModule(referrer, moduleRequest,
878+ // payload, completion).
879+ JS::FinishLoadingImportedModuleFailed (cx, statePrivate, nullptr , error);
880+
881+ aRequest->mReferrerObj = nullptr ;
882+ aRequest->mReferencingPrivate .setUndefined ();
883+ aRequest->mModuleRequestObj = nullptr ;
884+ aRequest->mStatePrivate .setUndefined ();
885+ }
886+ }
887+
819888nsresult ModuleLoaderBase::CreateModuleScript (ModuleLoadRequest* aRequest) {
820889 MOZ_ASSERT (!aRequest->mModuleScript );
821890 MOZ_ASSERT (aRequest->mBaseURL );
@@ -1081,6 +1150,22 @@ static bool OnLoadRequestedModulesResolvedImpl(ModuleLoadRequest* aRequest) {
10811150static bool OnLoadRequestedModulesRejectedImpl (ModuleLoadRequest* aRequest,
10821151 Handle<JS::Value> error) {
10831152 LOG ((" ScriptLoadRequest (%p): LoadRequestedModules rejected" , aRequest));
1153+ ModuleScript* moduleScript = aRequest->mModuleScript ;
1154+ // https://html.spec.whatwg.org/#fetch-the-descendants-of-and-link-a-module-script
1155+ // Step 7. Upon rejection of loadingPromise, run the following
1156+ // steps:
1157+ // Step 7.1. If state.[[ErrorToRethrow]] is not null, set moduleScript's
1158+ // error to rethrow to state.[[ErrorToRethrow]] and run
1159+ // onComplete given moduleScript.
1160+ if (moduleScript && !error.isUndefined ()) {
1161+ moduleScript->SetErrorToRethrow (error);
1162+ } else {
1163+ // Step 7.2. Otherwise, run onComplete given null.
1164+ aRequest->mModuleScript = nullptr ;
1165+ }
1166+
1167+ aRequest->ModuleErrored ();
1168+
10841169 // Decrease the reference 'AddRef'ed when converting the hostDefined.
10851170 aRequest->Release ();
10861171 return true ;
@@ -1275,6 +1360,7 @@ void ModuleLoaderBase::StartFetchingModuleAndDependencies(
12751360 MOZ_ASSERT (!childRequest->mModuleScript );
12761361 mLoader ->ReportErrorToConsole (childRequest, rv);
12771362 childRequest->LoadFailed ();
1363+ OnFetchFailed (childRequest);
12781364 }
12791365}
12801366
@@ -1440,6 +1526,7 @@ bool ModuleLoaderBase::HasPendingDynamicImports() const {
14401526 return !mDynamicImportRequests .isEmpty ();
14411527}
14421528
1529+ // TODO: Bug 1968890 : Update error handling for dynamic import
14431530void ModuleLoaderBase::CancelDynamicImport (ModuleLoadRequest* aRequest,
14441531 nsresult aResult) {
14451532 // aRequest may have already been unlinked by CC.
0 commit comments