Bug 1342012 - Allow dynamic import in cases where there's no referencing script or module r=smaug
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 06 Dec 2018 16:52:18 -0500
changeset 509508 be8cd28e487c1971f21b691befd0e268ce6d5855
parent 509507 248ed24187a21a78acf2243ee8a1b4d247e46c36
child 509509 c89629ed81defdd8968b1dd3cfd50c1bcd7eea24
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1342012
milestone66.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 1342012 - Allow dynamic import in cases where there's no referencing script or module r=smaug
dom/script/LoadedScript.cpp
dom/script/LoadedScript.h
dom/script/ModuleLoadRequest.cpp
dom/script/ModuleLoadRequest.h
dom/script/ScriptLoader.cpp
dom/script/ScriptLoader.h
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/inline-event-handler.html.ini
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html.ini
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html.ini
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-classic.html.ini
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-module.html.ini
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-of-promise-result.html.ini
--- a/dom/script/LoadedScript.cpp
+++ b/dom/script/LoadedScript.cpp
@@ -19,39 +19,35 @@ namespace dom {
 //////////////////////////////////////////////////////////////
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(LoadedScript)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(LoadedScript)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(LoadedScript)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFetchOptions)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(LoadedScript)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFetchOptions)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(LoadedScript)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(LoadedScript)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(LoadedScript)
 
-LoadedScript::LoadedScript(ScriptKind aKind, ScriptLoader* aLoader,
-                           ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL)
+LoadedScript::LoadedScript(ScriptKind aKind, ScriptFetchOptions* aFetchOptions,
+                           nsIURI* aBaseURL)
     : mKind(aKind),
-      mLoader(aLoader),
       mFetchOptions(aFetchOptions),
       mBaseURL(aBaseURL) {
-  MOZ_ASSERT(mLoader);
   MOZ_ASSERT(mFetchOptions);
   MOZ_ASSERT(mBaseURL);
 }
 
 LoadedScript::~LoadedScript() { DropJSObjects(this); }
 
 void LoadedScript::AssociateWithScript(JSScript* aScript) {
   // Set a JSScript's private value to point to this object and
@@ -79,20 +75,19 @@ void HostFinalizeTopLevelScript(JSFreeOp
 
   script->Release();
 }
 
 //////////////////////////////////////////////////////////////
 // ClassicScript
 //////////////////////////////////////////////////////////////
 
-ClassicScript::ClassicScript(ScriptLoader* aLoader,
-                             ScriptFetchOptions* aFetchOptions,
+ClassicScript::ClassicScript(ScriptFetchOptions* aFetchOptions,
                              nsIURI* aBaseURL)
-    : LoadedScript(ScriptKind::eClassic, aLoader, aFetchOptions, aBaseURL) {}
+    : LoadedScript(ScriptKind::eClassic, aFetchOptions, aBaseURL) {}
 
 //////////////////////////////////////////////////////////////
 // ModuleScript
 //////////////////////////////////////////////////////////////
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleScript)
 NS_INTERFACE_MAP_END_INHERITING(LoadedScript)
 
@@ -111,19 +106,18 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INH
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mModuleRecord)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mParseError)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mErrorToRethrow)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_ADDREF_INHERITED(ModuleScript, LoadedScript)
 NS_IMPL_RELEASE_INHERITED(ModuleScript, LoadedScript)
 
-ModuleScript::ModuleScript(ScriptLoader* aLoader,
-                           ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL)
-    : LoadedScript(ScriptKind::eModule, aLoader, aFetchOptions, aBaseURL),
+ModuleScript::ModuleScript(ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL)
+    : LoadedScript(ScriptKind::eModule, aFetchOptions, aBaseURL),
       mSourceElementAssociated(false) {
   MOZ_ASSERT(!ModuleRecord());
   MOZ_ASSERT(!HasParseError());
   MOZ_ASSERT(!HasErrorToRethrow());
 }
 
 void ModuleScript::UnlinkModuleRecord() {
   // Remove the module record's pointer to this object if present and
--- a/dom/script/LoadedScript.h
+++ b/dom/script/LoadedScript.h
@@ -21,48 +21,45 @@ class ScriptLoader;
 
 void HostFinalizeTopLevelScript(JSFreeOp* aFop, const JS::Value& aPrivate);
 
 class ClassicScript;
 class ModuleScript;
 
 class LoadedScript : public nsISupports {
   ScriptKind mKind;
-  RefPtr<ScriptLoader> mLoader;
   RefPtr<ScriptFetchOptions> mFetchOptions;
   nsCOMPtr<nsIURI> mBaseURL;
 
  protected:
-  LoadedScript(ScriptKind aKind, ScriptLoader* aLoader,
-               ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL);
+  LoadedScript(ScriptKind aKind, ScriptFetchOptions* aFetchOptions,
+               nsIURI* aBaseURL);
 
   virtual ~LoadedScript();
 
  public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(LoadedScript)
 
   bool IsModuleScript() const { return mKind == ScriptKind::eModule; }
 
   inline ClassicScript* AsClassicScript();
   inline ModuleScript* AsModuleScript();
 
-  ScriptLoader* Loader() const { return mLoader; }
   ScriptFetchOptions* FetchOptions() const { return mFetchOptions; }
   nsIURI* BaseURL() const { return mBaseURL; }
 
   void AssociateWithScript(JSScript* aScript);
 };
 
 class ClassicScript final : public LoadedScript {
   ~ClassicScript() = default;
 
  public:
-  ClassicScript(ScriptLoader* aLoader, ScriptFetchOptions* aFetchOptions,
-                nsIURI* aBaseURL);
+  ClassicScript(ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL);
 };
 
 // A single module script. May be used to satisfy multiple load requests.
 
 class ModuleScript final : public LoadedScript {
   JS::Heap<JSObject*> mModuleRecord;
   JS::Heap<JS::Value> mParseError;
   JS::Heap<JS::Value> mErrorToRethrow;
@@ -70,18 +67,17 @@ class ModuleScript final : public Loaded
 
   ~ModuleScript();
 
  public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ModuleScript,
                                                          LoadedScript)
 
-  ModuleScript(ScriptLoader* aLoader, ScriptFetchOptions* aFetchOptions,
-               nsIURI* aBaseURL);
+  ModuleScript(ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL);
 
   void SetModuleRecord(JS::Handle<JSObject*> aModuleRecord);
   void SetParseError(const JS::Value& aError);
   void SetErrorToRethrow(const JS::Value& aError);
   void SetSourceElementAssociated();
 
   JSObject* ModuleRecord() const { return mModuleRecord; }
 
--- a/dom/script/ModuleLoadRequest.cpp
+++ b/dom/script/ModuleLoadRequest.cpp
@@ -69,27 +69,26 @@ static VisitedURLSet* NewVisitedSetForTo
 
   request->mIsInline = false;
   request->mScriptMode = aParent->mScriptMode;
 
   return request;
 }
 
 /* static */ ModuleLoadRequest* ModuleLoadRequest::CreateDynamicImport(
-    nsIURI* aURI, LoadedScript* aScript,
-    JS::Handle<JS::Value> aReferencingPrivate, JS::Handle<JSString*> aSpecifier,
-    JS::Handle<JSObject*> aPromise) {
+    nsIURI* aURI, ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL,
+    ScriptLoader* aLoader, JS::Handle<JS::Value> aReferencingPrivate,
+    JS::Handle<JSString*> aSpecifier, JS::Handle<JSObject*> aPromise) {
   MOZ_ASSERT(aSpecifier);
   MOZ_ASSERT(aPromise);
 
   auto request = new ModuleLoadRequest(
-      aURI, aScript->FetchOptions(), SRIMetadata(), aScript->BaseURL(),
-      true, /* is top level */
+      aURI, aFetchOptions, SRIMetadata(), aBaseURL, true, /* is top level */
       true, /* is dynamic import */
-      aScript->Loader(), NewVisitedSetForTopLevelImport(aURI));
+      aLoader, NewVisitedSetForTopLevelImport(aURI));
 
   request->mIsInline = false;
   request->mScriptMode = ScriptMode::eAsync;
   request->mDynamicReferencingPrivate = aReferencingPrivate;
   request->mDynamicSpecifier = aSpecifier;
   request->mDynamicPromise = aPromise;
 
   HoldJSObjects(request);
--- a/dom/script/ModuleLoadRequest.h
+++ b/dom/script/ModuleLoadRequest.h
@@ -54,18 +54,18 @@ class ModuleLoadRequest final : public S
                                            ScriptLoader* aLoader);
 
   // Create a module load request for a static module import.
   static ModuleLoadRequest* CreateStaticImport(nsIURI* aURI,
                                                ModuleLoadRequest* aParent);
 
   // Create a module load request for dynamic module import.
   static ModuleLoadRequest* CreateDynamicImport(
-      nsIURI* aURI, LoadedScript* aScript,
-      JS::Handle<JS::Value> aReferencingPrivate,
+      nsIURI* aURI, ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL,
+      ScriptLoader* aLoader, JS::Handle<JS::Value> aReferencingPrivate,
       JS::Handle<JSString*> aSpecifier, JS::Handle<JSObject*> aPromise);
 
   bool IsTopLevel() const override { return mIsTopLevel; }
 
   bool IsDynamicImport() const { return mIsDynamicImport; }
 
   void SetReady() override;
   void Cancel() override;
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -12,28 +12,30 @@
 #include "ModuleLoadRequest.h"
 
 #include "prsystem.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "js/CompilationAndEvaluation.h"
 #include "js/MemoryFunctions.h"
 #include "js/OffThreadScriptCompilation.h"
+#include "js/Realm.h"
 #include "js/SourceText.h"
 #include "js/Utility.h"
 #include "xpcpublic.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIContent.h"
 #include "nsJSUtils.h"
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/SRILogHelper.h"
 #include "nsGkAtoms.h"
 #include "nsNetUtil.h"
+#include "nsGlobalWindowInner.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIPrincipal.h"
 #include "nsJSPrincipals.h"
 #include "nsContentPolicyUtils.h"
 #include "nsIHttpChannel.h"
 #include "nsIHttpChannelInternal.h"
@@ -470,17 +472,17 @@ nsresult ScriptLoader::CreateModuleScrip
           rv = NS_ERROR_OUT_OF_MEMORY;
         }
       }
     }
 
     MOZ_ASSERT(NS_SUCCEEDED(rv) == (module != nullptr));
 
     RefPtr<ModuleScript> moduleScript =
-        new ModuleScript(this, aRequest->mFetchOptions, aRequest->mBaseURL);
+        new ModuleScript(aRequest->mFetchOptions, aRequest->mBaseURL);
     aRequest->mModuleScript = moduleScript;
 
     if (!module) {
       LOG(("ScriptLoadRequest (%p):   compilation failed (%d)", aRequest,
            unsigned(rv)));
 
       MOZ_ASSERT(aes.HasException());
       JS::Rooted<JS::Value> error(cx);
@@ -540,17 +542,17 @@ static nsresult HandleResolveFailure(JSC
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   aScript->SetParseError(error);
   return NS_OK;
 }
 
 static already_AddRefed<nsIURI> ResolveModuleSpecifier(
-    LoadedScript* aScript, const nsAString& aSpecifier) {
+    ScriptLoader* aLoader, LoadedScript* aScript, const nsAString& aSpecifier) {
   // The following module specifiers are allowed by the spec:
   //  - a valid absolute URL
   //  - a valid relative URL that starts with "/", "./" or "../"
   //
   // Bareword module specifiers are currently disallowed as these may be given
   // special meanings in the future.
 
   nsCOMPtr<nsIURI> uri;
@@ -564,17 +566,25 @@ static already_AddRefed<nsIURI> ResolveM
   }
 
   if (!StringBeginsWith(aSpecifier, NS_LITERAL_STRING("/")) &&
       !StringBeginsWith(aSpecifier, NS_LITERAL_STRING("./")) &&
       !StringBeginsWith(aSpecifier, NS_LITERAL_STRING("../"))) {
     return nullptr;
   }
 
-  rv = NS_NewURI(getter_AddRefs(uri), aSpecifier, nullptr, aScript->BaseURL());
+  // Get the document's base URL if we don't have a referencing script here.
+  nsCOMPtr<nsIURI> baseURL;
+  if (aScript) {
+    baseURL = aScript->BaseURL();
+  } else {
+    baseURL = aLoader->GetDocument()->GetDocBaseURI();
+  }
+
+  rv = NS_NewURI(getter_AddRefs(uri), aSpecifier, nullptr, baseURL);
   if (NS_SUCCEEDED(rv)) {
     return uri.forget();
   }
 
   return nullptr;
 }
 
 static nsresult ResolveRequestedModules(ModuleLoadRequest* aRequest,
@@ -608,17 +618,18 @@ static nsresult ResolveRequestedModules(
 
     nsAutoJSString specifier;
     if (!specifier.init(cx, str)) {
       return NS_ERROR_FAILURE;
     }
 
     // Let url be the result of resolving a module specifier given module script
     // and requested.
-    nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(ms, specifier);
+    nsCOMPtr<nsIURI> uri =
+        ResolveModuleSpecifier(aRequest->mLoader, ms, specifier);
     if (!uri) {
       uint32_t lineNumber = 0;
       uint32_t columnNumber = 0;
       JS::GetRequestedModuleSourcePos(cx, element, &lineNumber, &columnNumber);
 
       nsresult rv =
           HandleResolveFailure(cx, ms, specifier, lineNumber, columnNumber);
       NS_ENSURE_SUCCESS(rv, rv);
@@ -720,56 +731,104 @@ RefPtr<GenericPromise> ScriptLoader::Sta
          &childRequest->mReady));
     childRequest->mReady.Reject(rv, __func__);
     return ready;
   }
 
   return ready;
 }
 
+static ScriptLoader* GetCurrentScriptLoader(JSContext* aCx) {
+  JSObject* object = JS::CurrentGlobalOrNull(aCx);
+  if (!object) {
+    return nullptr;
+  }
+
+  nsIGlobalObject* global = xpc::NativeGlobal(object);
+  if (!global) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(global);
+  nsGlobalWindowInner* innerWindow = nsGlobalWindowInner::Cast(win);
+  if (!innerWindow) {
+    return nullptr;
+  }
+
+  nsIDocument* document = innerWindow->GetDocument();
+  if (!document) {
+    return nullptr;
+  }
+
+  ScriptLoader* loader = document->ScriptLoader();
+  if (!loader) {
+    return nullptr;
+  }
+
+  return loader;
+}
+
+static LoadedScript* GetLoadedScriptOrNull(
+    JSContext* aCx, JS::Handle<JS::Value> aReferencingPrivate) {
+  if (aReferencingPrivate.isUndefined()) {
+    return nullptr;
+  }
+
+  auto script = static_cast<LoadedScript*>(aReferencingPrivate.toPrivate());
+  MOZ_ASSERT_IF(
+      script->IsModuleScript(),
+      JS::GetModulePrivate(script->AsModuleScript()->ModuleRecord()) ==
+          aReferencingPrivate);
+
+  return script;
+}
+
 // 8.1.3.8.1 HostResolveImportedModule(referencingModule, specifier)
 JSObject* HostResolveImportedModule(JSContext* aCx,
                                     JS::Handle<JS::Value> aReferencingPrivate,
                                     JS::Handle<JSString*> aSpecifier) {
-  // Let referencing module script be referencingModule.[[HostDefined]].
-  if (aReferencingPrivate.isUndefined()) {
-    JS_ReportErrorNumberUC(aCx, js::GetErrorMessage, nullptr,
-                           JSMSG_IMPORT_SCRIPT_NOT_FOUND);
-    return nullptr;
-  }
-
-  RefPtr<LoadedScript> script =
-      static_cast<LoadedScript*>(aReferencingPrivate.toPrivate());
-  MOZ_ASSERT_IF(
-      script->IsModuleScript(),
-      JS::GetModulePrivate(script->AsModuleScript()->ModuleRecord()) ==
-          aReferencingPrivate);
+  JS::Rooted<JSObject*> module(aCx);
+  ScriptLoader::ResolveImportedModule(aCx, aReferencingPrivate, aSpecifier,
+                                      &module);
+  return module;
+}
+
+/* static */ void ScriptLoader::ResolveImportedModule(
+    JSContext* aCx, JS::Handle<JS::Value> aReferencingPrivate,
+    JS::Handle<JSString*> aSpecifier, JS::MutableHandle<JSObject*> aModuleOut) {
+  MOZ_ASSERT(!aModuleOut);
+
+  RefPtr<LoadedScript> script(GetLoadedScriptOrNull(aCx, aReferencingPrivate));
 
   // Let url be the result of resolving a module specifier given referencing
   // module script and specifier.
   nsAutoJSString string;
   if (!string.init(aCx, aSpecifier)) {
-    return nullptr;
+    return;
   }
 
-  nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(script, string);
+  RefPtr<ScriptLoader> loader = GetCurrentScriptLoader(aCx);
+  if (!loader) {
+    return;
+  }
+
+  nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(loader, script, string);
 
   // 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);
+  ModuleScript* ms = loader->GetFetchedModule(uri);
   MOZ_ASSERT(ms, "Resolved module not found in module map");
-
   MOZ_ASSERT(!ms->HasParseError());
   MOZ_ASSERT(ms->ModuleRecord());
 
-  return ms->ModuleRecord();
+  aModuleOut.set(ms->ModuleRecord());
 }
 
 bool HostPopulateImportMeta(JSContext* aCx,
                             JS::Handle<JS::Value> aReferencingPrivate,
                             JS::Handle<JSObject*> aMetaObject) {
   RefPtr<ModuleScript> script =
       static_cast<ModuleScript*>(aReferencingPrivate.toPrivate());
   MOZ_ASSERT(script->IsModuleScript());
@@ -789,46 +848,58 @@ bool HostPopulateImportMeta(JSContext* a
   return JS_DefineProperty(aCx, aMetaObject, "url", urlString,
                            JSPROP_ENUMERATE);
 }
 
 bool HostImportModuleDynamically(JSContext* aCx,
                                  JS::Handle<JS::Value> aReferencingPrivate,
                                  JS::Handle<JSString*> aSpecifier,
                                  JS::Handle<JSObject*> aPromise) {
-  if (aReferencingPrivate.isUndefined()) {
-    JS_ReportErrorNumberUC(aCx, js::GetErrorMessage, nullptr,
-                           JSMSG_IMPORT_SCRIPT_NOT_FOUND);
-    return false;
-  }
-
-  auto script = static_cast<LoadedScript*>(aReferencingPrivate.toPrivate());
-  MOZ_ASSERT_IF(
-      script->IsModuleScript(),
-      JS::GetModulePrivate(script->AsModuleScript()->ModuleRecord()) ==
-          aReferencingPrivate);
+  RefPtr<LoadedScript> script(GetLoadedScriptOrNull(aCx, aReferencingPrivate));
 
   // Attempt to resolve the module specifier.
   nsAutoJSString string;
   if (!string.init(aCx, aSpecifier)) {
     return false;
   }
 
-  nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(script, string);
+  RefPtr<ScriptLoader> loader = GetCurrentScriptLoader(aCx);
+  if (!loader) {
+    return false;
+  }
+
+  nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(loader, script, string);
   if (!uri) {
     JS_ReportErrorNumberUC(aCx, js::GetErrorMessage, nullptr,
                            JSMSG_BAD_MODULE_SPECIFIER, string.get());
     return false;
   }
 
   // Create a new top-level load request.
+  ScriptFetchOptions* options;
+  nsIURI* baseURL;
+  if (script) {
+    options = script->FetchOptions();
+    baseURL = script->BaseURL();
+  } else {
+    // We don't have a referencing script so fall back on using
+    // options from the document. This can happen when the user
+    // triggers an inline event handler, as there is no active script
+    // there.
+    nsIDocument* document = loader->GetDocument();
+    options = new ScriptFetchOptions(mozilla::CORS_NONE,
+                                     document->GetReferrerPolicy(), nullptr,
+                                     document->NodePrincipal());
+    baseURL = document->GetDocBaseURI();
+  }
+
   RefPtr<ModuleLoadRequest> request = ModuleLoadRequest::CreateDynamicImport(
-      uri, script, aReferencingPrivate, aSpecifier, aPromise);
-
-  script->Loader()->StartDynamicImport(request);
+      uri, options, baseURL, loader, aReferencingPrivate, aSpecifier, aPromise);
+
+  loader->StartDynamicImport(request);
   return true;
 }
 
 void ScriptLoader::StartDynamicImport(ModuleLoadRequest* aRequest) {
   LOG(("ScriptLoadRequest (%p): Start dynamic import", aRequest));
 
   mDynamicImportRequests.AppendElement(aRequest);
 
@@ -843,17 +914,17 @@ void ScriptLoader::FinishDynamicImport(M
   AutoJSAPI jsapi;
   MOZ_ALWAYS_TRUE(jsapi.Init(aRequest->mDynamicPromise));
   FinishDynamicImport(jsapi.cx(), aRequest, aResult);
 }
 
 void ScriptLoader::FinishDynamicImport(JSContext* aCx,
                                        ModuleLoadRequest* aRequest,
                                        nsresult aResult) {
-  LOG(("ScriptLoadRequest (%p): Finish dynamic import %d %d", aRequest,
+  LOG(("ScriptLoadRequest (%p): Finish dynamic import %x %d", aRequest,
        unsigned(aResult), JS_IsExceptionPending(aCx)));
 
   // Complete the dynamic import, report failures indicated by aResult or as a
   // pending exception on the context.
 
   if (NS_FAILED(aResult)) {
     MOZ_ASSERT(!JS_IsExceptionPending(aCx));
     JS_ReportErrorNumberUC(aCx, js::GetErrorMessage, nullptr,
@@ -2529,17 +2600,17 @@ nsresult ScriptLoader::EvaluateScript(Sc
             }
 
             if (rv == NS_OK) {
               script = exec.GetScript();
 
               // Create a ClassicScript object and associate it with the
               // JSScript.
               RefPtr<ClassicScript> classicScript = new ClassicScript(
-                  this, aRequest->mFetchOptions, aRequest->mBaseURL);
+                  aRequest->mFetchOptions, aRequest->mBaseURL);
               classicScript->AssociateWithScript(script);
 
               rv = exec.ExecScript();
             }
           }
 
           // Queue the current script load request to later save the bytecode.
           if (script && encodeBytecode) {
--- a/dom/script/ScriptLoader.h
+++ b/dom/script/ScriptLoader.h
@@ -306,27 +306,46 @@ class ScriptLoader final : public nsISup
 
   /**
    * Destroy and prevent the ScriptLoader or the ScriptLoadRequests from owning
    * any references to the JSScript or to the Request which might be used for
    * caching the encoded bytecode.
    */
   void Destroy() { GiveUpBytecodeEncoding(); }
 
+  /**
+   * Implement the HostResolveImportedModule abstract operation.
+   *
+   * Resolve a module specifier string and look this up in the module
+   * map, returning the result. This is only called for previously
+   * loaded modules and always succeeds.
+   *
+   * @param aReferencingPrivate A JS::Value which is either undefined
+   *                            or contains a LoadedScript private pointer.
+   * @param aSpecifier The module specifier.
+   * @param aModuleOut This is set to the module found.
+   */
+  static void ResolveImportedModule(JSContext* aCx,
+                                    JS::Handle<JS::Value> aReferencingPrivate,
+                                    JS::Handle<JSString*> aSpecifier,
+                                    JS::MutableHandle<JSObject*> aModuleOut);
+
   void StartDynamicImport(ModuleLoadRequest* aRequest);
   void FinishDynamicImport(ModuleLoadRequest* aRequest, nsresult aResult);
   void FinishDynamicImport(JSContext* aCx, ModuleLoadRequest* aRequest,
                            nsresult aResult);
 
   /*
    * Get the currently active script. This is used as the initiating script when
    * executing timeout handler scripts.
    */
   static LoadedScript* GetActiveScript(JSContext* aCx);
 
+  nsIDocument* GetDocument() const { return mDocument; }
+
  private:
   virtual ~ScriptLoader();
 
   void EnsureModuleHooksInitialized();
 
   ScriptLoadRequest* CreateLoadRequest(
       ScriptKind aKind, nsIURI* aURI, nsIScriptElement* aElement,
       nsIPrincipal* aTriggeringPrincipal, mozilla::CORSMode aCORSMode,
@@ -573,16 +592,17 @@ class ScriptLoader final : public nsISup
   // Module map
   nsRefPtrHashtable<nsURIHashKey, mozilla::GenericNonExclusivePromise::Private>
       mFetchingModules;
   nsRefPtrHashtable<nsURIHashKey, ModuleScript> mFetchedModules;
 
   nsCOMPtr<nsIConsoleReportCollector> mReporter;
 
   // Logging
+ public:
   static LazyLogModule gCspPRLog;
   static LazyLogModule gScriptLoaderLog;
 };
 
 class nsAutoScriptLoaderDisabler {
  public:
   explicit nsAutoScriptLoaderDisabler(nsIDocument* aDoc) {
     mLoader = aDoc->ScriptLoader();
deleted file mode 100644
--- a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/inline-event-handler.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[inline-event-handler.html]
-  expected: TIMEOUT
-  [dynamic import should work when triggered from inline event handlers]
-    expected: TIMEOUT
-
deleted file mode 100644
--- a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[string-compilation-base-url-inline-classic.html]
-  [reflected inline event handlers should successfully import]
-    expected: FAIL
-
-  [inline event handlers triggered via UA code should successfully import]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[string-compilation-base-url-inline-module.html]
-  [reflected inline event handlers should successfully import]
-    expected: FAIL
-
-  [inline event handlers triggered via UA code should successfully import]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-classic.html.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[string-compilation-classic.html]
-  [reflected inline event handlers should successfully import]
-    expected: FAIL
-
-  [inline event handlers triggered via UA code should successfully import]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-module.html.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[string-compilation-module.html]
-  [reflected inline event handlers should successfully import]
-    expected: FAIL
-
-  [inline event handlers triggered via UA code should successfully import]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-of-promise-result.html.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[string-compilation-of-promise-result.html]
-  [Evaled the script via eval, successful import]
-    expected: FAIL
-
-  [Evaled the script via Function, successful import]
-    expected: FAIL
-