Bug 1342416 - Preload module scripts r=baku
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 15 Feb 2018 13:18:59 +0000
changeset 403979 2da5a026626897d745c2b7b512ba1c2d1e239c8b
parent 403978 77f86d6cf76f9257edb72e9b366a1546cffe90e7
child 403980 93227b85dd4425e59eee6958c0db9669dfb01414
push id33447
push usernerli@mozilla.com
push dateThu, 15 Feb 2018 19:29:41 +0000
treeherdermozilla-central@ee717948a600 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1342416
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1342416 - Preload module scripts r=baku
dom/base/nsJSUtils.cpp
dom/base/nsJSUtils.h
dom/script/ModuleLoadRequest.h
dom/script/ModuleScript.cpp
dom/script/ModuleScript.h
dom/script/ScriptLoadRequest.h
dom/script/ScriptLoader.cpp
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/instantiation-error-8.html.ini
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -397,16 +397,39 @@ nsJSUtils::CompileModule(JSContext* aCx,
   if (!JS::CompileModule(aCx, aCompileOptions, aSrcBuf, aModule)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult
+nsJSUtils::InitModuleSourceElement(JSContext* aCx,
+                                   JS::Handle<JSObject*> aModule,
+                                   nsIScriptElement* aElement)
+{
+  JS::Rooted<JS::Value> value(aCx);
+  nsresult rv = nsContentUtils::WrapNative(aCx, aElement, &value,
+                                           /* aAllowWrapping = */ true);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  MOZ_ASSERT(value.isObject());
+  JS::Rooted<JSObject*> object(aCx, &value.toObject());
+
+  JS::Rooted<JSScript*> script(aCx, JS::GetModuleScript(aModule));
+  if (!JS::InitScriptSourceElement(aCx, script, object, nullptr)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+nsresult
 nsJSUtils::ModuleInstantiate(JSContext* aCx, JS::Handle<JSObject*> aModule)
 {
   AUTO_PROFILER_LABEL("nsJSUtils::ModuleInstantiate", JS);
 
   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(CycleCollectedJSContext::Get() &&
              CycleCollectedJSContext::Get()->MicroTaskLevel());
--- a/dom/base/nsJSUtils.h
+++ b/dom/base/nsJSUtils.h
@@ -18,16 +18,17 @@
 
 #include "GeckoProfiler.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "js/Conversions.h"
 #include "nsString.h"
 
 class nsIScriptContext;
+class nsIScriptElement;
 class nsIScriptGlobalObject;
 
 namespace mozilla {
 namespace dom {
 class AutoJSAPI;
 class Element;
 } // namespace dom
 } // namespace mozilla
@@ -180,16 +181,20 @@ public:
   };
 
   static nsresult CompileModule(JSContext* aCx,
                                 JS::SourceBufferHolder& aSrcBuf,
                                 JS::Handle<JSObject*> aEvaluationGlobal,
                                 JS::CompileOptions &aCompileOptions,
                                 JS::MutableHandle<JSObject*> aModule);
 
+  static nsresult InitModuleSourceElement(JSContext* aCx,
+                                          JS::Handle<JSObject*> aModule,
+                                          nsIScriptElement* aElement);
+
   static nsresult ModuleInstantiate(JSContext* aCx,
                                     JS::Handle<JSObject*> aModule);
 
   static nsresult ModuleEvaluate(JSContext* aCx,
                                  JS::Handle<JSObject*> aModule);
 
   // Returns false if an exception got thrown on aCx.  Passing a null
   // aElement is allowed; that wil produce an empty aScopeChain.
--- a/dom/script/ModuleLoadRequest.h
+++ b/dom/script/ModuleLoadRequest.h
@@ -50,17 +50,17 @@ public:
                     nsIURI* aReferrer,
                     mozilla::net::ReferrerPolicy,
                     ScriptLoader* aLoader);
 
   // Create a module load request for an imported module.
   ModuleLoadRequest(nsIURI* aURI,
                     ModuleLoadRequest* aParent);
 
-  bool IsTopLevel() const
+  bool IsTopLevel() const override
   {
     return mIsTopLevel;
   }
 
   void SetReady() override;
   void Cancel() override;
 
   void ModuleLoaded();
--- a/dom/script/ModuleScript.cpp
+++ b/dom/script/ModuleScript.cpp
@@ -36,17 +36,18 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Mod
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mErrorToRethrow)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(ModuleScript)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(ModuleScript)
 
 ModuleScript::ModuleScript(ScriptLoader* aLoader, nsIURI* aBaseURL)
  : mLoader(aLoader),
-   mBaseURL(aBaseURL)
+   mBaseURL(aBaseURL),
+   mSourceElementAssociated(false)
 {
   MOZ_ASSERT(mLoader);
   MOZ_ASSERT(mBaseURL);
   MOZ_ASSERT(!mModuleRecord);
   MOZ_ASSERT(!HasParseError());
   MOZ_ASSERT(!HasErrorToRethrow());
 }
 
@@ -104,10 +105,19 @@ ModuleScript::SetErrorToRethrow(const JS
 
   // This is only called after SetModuleRecord() or SetParseError() so we don't
   // need to call HoldJSObjects() here.
   MOZ_ASSERT(mModuleRecord || HasParseError());
 
   mErrorToRethrow = aError;
 }
 
+void
+ModuleScript::SetSourceElementAssociated()
+{
+  MOZ_ASSERT(mModuleRecord);
+  MOZ_ASSERT(!mSourceElementAssociated);
+
+  mSourceElementAssociated = true;
+}
+
 } // dom namespace
 } // mozilla namespace
--- a/dom/script/ModuleScript.h
+++ b/dom/script/ModuleScript.h
@@ -20,37 +20,40 @@ class ScriptLoader;
 
 class ModuleScript final : public nsISupports
 {
   RefPtr<ScriptLoader> mLoader;
   nsCOMPtr<nsIURI> mBaseURL;
   JS::Heap<JSObject*> mModuleRecord;
   JS::Heap<JS::Value> mParseError;
   JS::Heap<JS::Value> mErrorToRethrow;
+  bool mSourceElementAssociated;
 
   ~ModuleScript();
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ModuleScript)
 
   ModuleScript(ScriptLoader* aLoader,
                nsIURI* aBaseURL);
 
   void SetModuleRecord(JS::Handle<JSObject*> aModuleRecord);
   void SetParseError(const JS::Value& aError);
   void SetErrorToRethrow(const JS::Value& aError);
+  void SetSourceElementAssociated();
 
   ScriptLoader* Loader() const { return mLoader; }
   JSObject* ModuleRecord() const { return mModuleRecord; }
   nsIURI* BaseURL() const { return mBaseURL; }
   JS::Value ParseError() const { return mParseError; }
   JS::Value ErrorToRethrow() const { return mErrorToRethrow; }
   bool HasParseError() const { return !mParseError.isUndefined(); }
   bool HasErrorToRethrow() const { return !mErrorToRethrow.isUndefined(); }
+  bool SourceElementAssociated() const { return mSourceElementAssociated; }
 
   void UnlinkModuleRecord();
 };
 
 } // dom namespace
 } // mozilla namespace
 
 #endif // mozilla_dom_ModuleScript_h
--- a/dom/script/ScriptLoadRequest.h
+++ b/dom/script/ScriptLoadRequest.h
@@ -169,16 +169,23 @@ public:
     return mScriptMode == ScriptMode::eDeferred;
   }
 
   bool IsAsyncScript() const
   {
     return mScriptMode == ScriptMode::eAsync;
   }
 
+  virtual bool IsTopLevel() const
+  {
+    // Classic scripts are always top level.
+    return true;
+  }
+
+
   void MaybeCancelOffThreadScript();
   void DropBytecodeCacheReferences();
 
   using super::getNext;
   using super::isInList;
 
   const ScriptKind mKind;
   nsCOMPtr<nsIScriptElement> mElement;
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -506,16 +506,17 @@ ScriptLoader::CreateModuleScript(ModuleL
       if (NS_SUCCEEDED(rv)) {
         nsAutoString inlineData;
         SourceBufferHolder srcBuf = GetScriptSource(aRequest, inlineData);
         rv = nsJSUtils::CompileModule(cx, srcBuf, global, options, &module);
       }
     }
 
     MOZ_ASSERT(NS_SUCCEEDED(rv) == (module != nullptr));
+
     RefPtr<ModuleScript> moduleScript = new ModuleScript(this, aRequest->mBaseURL);
     aRequest->mModuleScript = moduleScript;
 
     if (!module) {
       LOG(("ScriptLoadRequest (%p):   compilation failed (%d)",
            aRequest, unsigned(rv)));
 
       MOZ_ASSERT(aes.HasException());
@@ -994,30 +995,26 @@ ScriptLoader::StartLoad(ScriptLoadReques
   if (LOG_ENABLED()) {
     nsAutoCString url;
     aRequest->mURI->GetAsciiSpec(url);
     LOG(("ScriptLoadRequest (%p): Start Load (url = %s)", aRequest, url.get()));
   }
 
   if (aRequest->IsModuleRequest()) {
     // Check whether the module has been fetched or is currently being fetched,
-    // and if so wait for it.
+    // and if so wait for it rather than starting a new fetch.
     ModuleLoadRequest* request = aRequest->AsModuleRequest();
     if (ModuleMapContainsURL(request->mURI)) {
       LOG(("ScriptLoadRequest (%p): Waiting for module fetch", aRequest));
       WaitForModuleFetch(request->mURI)
         ->Then(GetMainThreadSerialEventTarget(), __func__, request,
                &ModuleLoadRequest::ModuleLoaded,
                &ModuleLoadRequest::LoadFailed);
       return NS_OK;
     }
-
-    // Otherwise put the URL in the module map and mark it as fetching.
-    SetModuleFetchStarted(request);
-    LOG(("ScriptLoadRequest (%p): Start fetching module", aRequest));
   }
 
   nsContentPolicyType contentPolicyType = aRequest->IsPreload()
                                           ? nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD
                                           : nsIContentPolicy::TYPE_INTERNAL_SCRIPT;
   nsCOMPtr<nsINode> context;
   if (aRequest->mElement) {
     context = do_QueryInterface(aRequest->mElement);
@@ -1170,17 +1167,27 @@ ScriptLoader::StartLoad(ScriptLoadReques
 
   RefPtr<ScriptLoadHandler> handler =
       new ScriptLoadHandler(this, aRequest, sriDataVerifier.forget());
 
   nsCOMPtr<nsIIncrementalStreamLoader> loader;
   rv = NS_NewIncrementalStreamLoader(getter_AddRefs(loader), handler);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return channel->AsyncOpen2(loader);
+  rv = channel->AsyncOpen2(loader);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (aRequest->IsModuleRequest()) {
+    // We successfully started fetching a module so put its URL in the module
+    // map and mark it as fetching.
+    SetModuleFetchStarted(aRequest->AsModuleRequest());
+    LOG(("ScriptLoadRequest (%p): Start fetching module", aRequest));
+  }
+
+  return NS_OK;
 }
 
 bool
 ScriptLoader::PreloadURIComparator::Equals(const PreloadInfo& aPi,
                                            nsIURI* const& aURI) const
 {
   bool same;
   return NS_SUCCEEDED(aPi.mRequest->mURI->Equals(aURI, &same)) &&
@@ -1221,22 +1228,18 @@ ScriptLoader::CreateLoadRequest(ScriptKi
                                 nsIScriptElement* aElement,
                                 CORSMode aCORSMode,
                                 const SRIMetadata& aIntegrity,
                                 mozilla::net::ReferrerPolicy aReferrerPolicy)
 {
   nsIURI* referrer = mDocument->GetDocumentURI();
 
   if (aKind == ScriptKind::eClassic) {
-    ScriptLoadRequest* slr = new ScriptLoadRequest(aKind, aURI, aElement,
-                                                   aCORSMode, aIntegrity,
-                                                   referrer, aReferrerPolicy);
-
-    LOG(("ScriptLoader %p creates ScriptLoadRequest %p", this, slr));
-    return slr;
+    return new ScriptLoadRequest(aKind, aURI, aElement, aCORSMode, aIntegrity,
+                                 referrer, aReferrerPolicy);
   }
 
   MOZ_ASSERT(aKind == ScriptKind::eModule);
   return new ModuleLoadRequest(aURI, aElement, aCORSMode, aIntegrity, referrer,
                                aReferrerPolicy, this);
 }
 
 bool
@@ -1308,40 +1311,47 @@ ScriptLoader::ProcessScriptElement(nsISc
 }
 
 bool
 ScriptLoader::ProcessExternalScript(nsIScriptElement* aElement,
                                     ScriptKind aScriptKind,
                                     nsAutoString aTypeAttr,
                                     nsIContent* aScriptContent)
 {
+  LOG(("ScriptLoader (%p): Process external script for element %p",
+       this, aElement));
+
   nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI();
   if (!scriptURI) {
     // Asynchronously report the failure to create a URI object
     NS_DispatchToCurrentThread(
       NewRunnableMethod("nsIScriptElement::FireErrorEvent",
                         aElement,
                         &nsIScriptElement::FireErrorEvent));
     return false;
   }
 
   RefPtr<ScriptLoadRequest> request = LookupPreloadRequest(aElement, aScriptKind);
 
   if (request && NS_FAILED(CheckContentPolicy(mDocument, aElement, request->mURI,
                                               aTypeAttr, false))) {
+    LOG(("ScriptLoader (%p): content policy check failed for preload", this));
+
     // Probably plans have changed; even though the preload was allowed seems
     // like the actual load is not; let's cancel the preload request.
     request->Cancel();
     AccumulateCategorical(LABELS_DOM_SCRIPT_PRELOAD_RESULT::RejectedByPolicy);
     return false;
   }
 
   if (request) {
     // Use the preload request.
 
+    LOG(("ScriptLoadRequest (%p): Using preload request", request.get()));
+
     // It's possible these attributes changed since we started the preload so
     // update them here.
     request->SetScriptMode(aElement->GetScriptDeferred(),
                            aElement->GetScriptAsync());
 
     AccumulateCategorical(LABELS_DOM_SCRIPT_PRELOAD_RESULT::Used);
   } else {
     // No usable preload found.
@@ -1366,16 +1376,19 @@ ScriptLoader::ProcessExternalScript(nsIS
                                 ourCORSMode, sriMetadata, ourRefPolicy);
     request->mTriggeringPrincipal = Move(principal);
     request->mIsInline = false;
     request->SetScriptMode(aElement->GetScriptDeferred(),
                            aElement->GetScriptAsync());
     // keep request->mScriptFromHead to false so we don't treat non preloaded
     // scripts as blockers for full page load. See bug 792438.
 
+    LOG(("ScriptLoadRequest (%p): Created request for external script",
+         request.get()));
+
     nsresult rv = StartLoad(request);
     if (NS_FAILED(rv)) {
       ReportErrorToConsole(request, rv);
 
       // Asynchronously report the load failure
       nsCOMPtr<nsIRunnable> runnable =
         NewRunnableMethod("nsIScriptElement::FireErrorEvent",
                           aElement,
@@ -1384,18 +1397,19 @@ ScriptLoader::ProcessExternalScript(nsIS
         mDocument->Dispatch(TaskCategory::Other, runnable.forget());
       } else {
         NS_DispatchToCurrentThread(runnable);
       }
       return false;
     }
   }
 
-  // Should still be in loading stage of script.
-  NS_ASSERTION(!request->InCompilingStage(),
+  // We should still be in loading stage of script unless we're loading a
+  // module.
+  NS_ASSERTION(!request->InCompilingStage() || request->IsModuleRequest(),
                "Request should not yet be in compiling stage.");
 
   if (request->IsAsyncScript()) {
     AddAsyncRequest(request);
     if (request->IsReadyToRun()) {
       // The script is available already. Run it ASAP when the event
       // loop gets a chance to spin.
 
@@ -1576,16 +1590,18 @@ ScriptLoader::ProcessInlineScript(nsIScr
       "Not safe to run a parser-inserted script?");
   return ProcessRequest(request) == NS_ERROR_HTMLPARSER_BLOCK;
 }
 
 ScriptLoadRequest*
 ScriptLoader::LookupPreloadRequest(nsIScriptElement* aElement,
                                    ScriptKind aScriptKind)
 {
+  MOZ_ASSERT(aElement);
+
   nsTArray<PreloadInfo>::index_type i =
     mPreloads.IndexOf(aElement->GetScriptURI(), 0, PreloadURIComparator());
   if (i == nsTArray<PreloadInfo>::NoIndex) {
     return nullptr;
   }
 
   // Found preloaded request. Note that a script-inserted script can steal a
   // preload!
@@ -2053,24 +2069,26 @@ ScriptLoader::FillCompileOptionsForReque
     aOptions->setSourceMapURL(aRequest->mSourceMapURL.get());
   }
   if (aRequest->mOriginPrincipal) {
     nsIPrincipal* scriptPrin = nsContentUtils::ObjectPrincipal(aScopeChain);
     bool subsumes = scriptPrin->Subsumes(aRequest->mOriginPrincipal);
     aOptions->setMutedErrors(!subsumes);
   }
 
-  JSContext* cx = jsapi.cx();
-  JS::Rooted<JS::Value> elementVal(cx);
-  MOZ_ASSERT(aRequest->mElement);
-  if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, aRequest->mElement,
-                                              &elementVal,
-                                              /* aAllowWrapping = */ true))) {
-    MOZ_ASSERT(elementVal.isObject());
-    aOptions->setElement(&elementVal.toObject());
+  if (!aRequest->IsModuleRequest()) {
+    JSContext* cx = jsapi.cx();
+    JS::Rooted<JS::Value> elementVal(cx);
+    MOZ_ASSERT(aRequest->mElement);
+    if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, aRequest->mElement,
+                                                &elementVal,
+                                                /* aAllowWrapping = */ true))) {
+      MOZ_ASSERT(elementVal.isObject());
+      aOptions->setElement(&elementVal.toObject());
+    }
   }
 
   return NS_OK;
 }
 
 /* static */ bool
 ScriptLoader::ShouldCacheBytecode(ScriptLoadRequest* aRequest)
 {
@@ -2218,16 +2236,22 @@ ScriptLoader::EvaluateScript(ScriptLoadR
         JS::Rooted<JS::Value> error(cx, moduleScript->ErrorToRethrow());
         JS_SetPendingException(cx, error);
         return NS_OK; // An error is reported by AutoEntryScript.
       }
 
       JS::Rooted<JSObject*> module(cx, moduleScript->ModuleRecord());
       MOZ_ASSERT(module);
 
+      if (!moduleScript->SourceElementAssociated()) {
+        rv = nsJSUtils::InitModuleSourceElement(cx, module, aRequest->mElement);
+        NS_ENSURE_SUCCESS(rv, rv);
+        moduleScript->SetSourceElementAssociated();
+      }
+
       rv = nsJSUtils::ModuleEvaluate(cx, module);
       MOZ_ASSERT(NS_FAILED(rv) == aes.HasException());
       if (NS_FAILED(rv)) {
         LOG(("ScriptLoadRequest (%p):   evaluation failed", aRequest));
         rv = NS_OK; // An error is reported by AutoEntryScript.
       }
 
       aRequest->mCacheInfo = nullptr;
@@ -2953,17 +2977,17 @@ ScriptLoader::HandleLoadError(ScriptLoad
         mNonAsyncExternalScriptInsertedRequests.Steal(aRequest);
       FireScriptAvailable(aResult, req);
     }
   } else if (aRequest->mIsXSLT) {
     if (aRequest->isInList()) {
       RefPtr<ScriptLoadRequest> req = mXSLTRequests.Steal(aRequest);
       FireScriptAvailable(aResult, req);
     }
-  } else if (aRequest->IsModuleRequest()) {
+  } else if (aRequest->IsModuleRequest() && !aRequest->IsPreload()) {
     ModuleLoadRequest* modReq = aRequest->AsModuleRequest();
     MOZ_ASSERT(!modReq->IsTopLevel());
     MOZ_ASSERT(!modReq->isInList());
     modReq->Cancel();
     // A single error is fired for the top level module.
   } else if (mParserBlockingRequest == aRequest) {
     MOZ_ASSERT(!aRequest->isInList());
     mParserBlockingRequest = nullptr;
@@ -2973,19 +2997,29 @@ ScriptLoader::HandleLoadError(ScriptLoad
     // script while firing onerror on it.
     MOZ_ASSERT(aRequest->mElement->GetParserCreated());
     nsCOMPtr<nsIScriptElement> oldParserInsertedScript =
       mCurrentParserInsertedScript;
     mCurrentParserInsertedScript = aRequest->mElement;
     FireScriptAvailable(aResult, aRequest);
     ContinueParserAsync(aRequest);
     mCurrentParserInsertedScript = oldParserInsertedScript;
+  } else if (aRequest->IsPreload()) {
+    if (aRequest->IsModuleRequest()) {
+      aRequest->Cancel();
+    }
+    if (aRequest->IsTopLevel()) {
+      MOZ_ALWAYS_TRUE(mPreloads.RemoveElement(aRequest, PreloadRequestComparator()));
+    }
+    MOZ_ASSERT(!aRequest->isInList());
+    AccumulateCategorical(LABELS_DOM_SCRIPT_PRELOAD_RESULT::LoadError);
   } else {
-    mPreloads.RemoveElement(aRequest, PreloadRequestComparator());
-    AccumulateCategorical(LABELS_DOM_SCRIPT_PRELOAD_RESULT::LoadError);
+    // This happens for blocking requests cancelled by ParsingComplete().
+    MOZ_ASSERT(aRequest->IsCanceled());
+    MOZ_ASSERT(!aRequest->isInList());
   }
 }
 
 void
 ScriptLoader::UnblockParser(ScriptLoadRequest* aParserBlockingRequest)
 {
   aParserBlockingRequest->mElement->UnblockParser();
 }
@@ -3181,45 +3215,59 @@ ScriptLoader::PreloadURI(nsIURI* aURI,
                          const mozilla::net::ReferrerPolicy aReferrerPolicy)
 {
   NS_ENSURE_TRUE_VOID(mDocument);
   // Check to see if scripts has been turned off.
   if (!mEnabled || !mDocument->IsScriptEnabled()) {
     return;
   }
 
+  ScriptKind scriptKind = ScriptKind::eClassic;
+
   if (mDocument->ModuleScriptsEnabled()) {
     // Don't load nomodule scripts.
     if (aNoModule) {
       return;
     }
 
-    // TODO: Preload module scripts.
-    if (aType.LowerCaseEqualsASCII("module")) {
-      return;
+    static const char kASCIIWhitespace[] = "\t\n\f\r ";
+
+    nsAutoString type(aType);
+    type.Trim(kASCIIWhitespace);
+    if (type.LowerCaseEqualsASCII("module")) {
+      scriptKind = ScriptKind::eModule;
     }
   }
 
-  if (!aType.IsEmpty() && !nsContentUtils::IsJavascriptMIMEType(aType)) {
+  if (scriptKind == ScriptKind::eClassic &&
+      !aType.IsEmpty() && !nsContentUtils::IsJavascriptMIMEType(aType))
+  {
     // Unknown type.  Don't load it.
     return;
   }
 
   SRIMetadata sriMetadata;
   GetSRIMetadata(aIntegrity, &sriMetadata);
 
   RefPtr<ScriptLoadRequest> request =
-    CreateLoadRequest(ScriptKind::eClassic, aURI, nullptr,
+    CreateLoadRequest(scriptKind, aURI, nullptr,
                       Element::StringToCORSMode(aCrossOrigin), sriMetadata,
                       aReferrerPolicy);
   request->mTriggeringPrincipal = mDocument->NodePrincipal();
   request->mIsInline = false;
   request->mScriptFromHead = aScriptFromHead;
   request->SetScriptMode(aDefer, aAsync);
 
+  if (LOG_ENABLED()) {
+    nsAutoCString url;
+    aURI->GetAsciiSpec(url);
+    LOG(("ScriptLoadRequest (%p): Created preload request for %s",
+         request.get(), url.get()));
+  }
+
   nsresult rv = StartLoad(request);
   if (NS_FAILED(rv)) {
     return;
   }
 
   PreloadInfo* pi = mPreloads.AppendElement();
   pi->mRequest = request;
   pi->mCharset = aCharset;
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/instantiation-error-8.html.ini
@@ -0,0 +1,2 @@
+[instantiation-error-8.html]
+  disabled: unstable