Backed out changeset ba122021b8b5 (bug 1481196)
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 04 Oct 2018 11:50:55 +0100
changeset 487905 c704d1a108c221863b72e41d7641a21d17557b11
parent 487904 92181c289ffa370c103d333f6cc3b0c620a897b4
child 487906 1b1d6fa744e7a7ceaf6e680ca450441a160fc00f
push id246
push userfmarier@mozilla.com
push dateSat, 13 Oct 2018 00:15:40 +0000
bugs1481196
milestone64.0a1
backs outba122021b8b576cf33a17c148a2e6c73d1d32862
Backed out changeset ba122021b8b5 (bug 1481196)
dom/base/nsJSUtils.cpp
dom/base/nsJSUtils.h
dom/script/ModuleScript.cpp
dom/script/ModuleScript.h
dom/script/ScriptLoader.cpp
dom/script/ScriptLoader.h
js/public/OffThreadScriptCompilation.h
js/public/Realm.h
js/src/builtin/ModuleObject.cpp
js/src/builtin/ModuleObject.h
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/BytecodeCompiler.h
js/src/jit/BaselineCompiler.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/shell/js.cpp
js/src/vm/HelperThreads.cpp
js/src/vm/HelperThreads.h
js/src/vm/Interpreter.cpp
js/src/vm/OffThreadScriptCompilation.cpp
js/src/vm/Realm.cpp
js/src/vm/SelfHosting.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/src/xpcpublic.h
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -471,91 +471,92 @@ nsJSUtils::ExecutionContext::ExtractRetu
   return NS_OK;
 }
 
 nsresult
 nsJSUtils::CompileModule(JSContext* aCx,
                        JS::SourceBufferHolder& aSrcBuf,
                        JS::Handle<JSObject*> aEvaluationGlobal,
                        JS::CompileOptions &aCompileOptions,
-                       JS::MutableHandle<JSScript*> aScript)
+                       JS::MutableHandle<JSObject*> aModule)
 {
   AUTO_PROFILER_LABEL("nsJSUtils::CompileModule", JS);
 
   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
   MOZ_ASSERT(aSrcBuf.get());
   MOZ_ASSERT(JS_IsGlobalObject(aEvaluationGlobal));
   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx) == aEvaluationGlobal);
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(CycleCollectedJSContext::Get() &&
              CycleCollectedJSContext::Get()->MicroTaskLevel());
 
   NS_ENSURE_TRUE(xpc::Scriptability::Get(aEvaluationGlobal).Allowed(), NS_OK);
 
-  if (!JS::CompileModule(aCx, aCompileOptions, aSrcBuf, aScript)) {
+  if (!JS::CompileModule(aCx, aCompileOptions, aSrcBuf, aModule)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult
 nsJSUtils::InitModuleSourceElement(JSContext* aCx,
-                                   JS::Handle<JSScript*> aScript,
+                                   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());
 
-  if (!JS::InitScriptSourceElement(aCx, aScript, object, nullptr)) {
+  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<JSScript*> aScript)
+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());
 
-  NS_ENSURE_TRUE(xpc::Scriptability::Get(aScript).Allowed(), NS_OK);
+  NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
 
-  if (!JS::ModuleInstantiate(aCx, aScript)) {
+  if (!JS::ModuleInstantiate(aCx, aModule)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult
-nsJSUtils::ModuleEvaluate(JSContext* aCx, JS::Handle<JSScript*> aScript)
+nsJSUtils::ModuleEvaluate(JSContext* aCx, JS::Handle<JSObject*> aModule)
 {
   AUTO_PROFILER_LABEL("nsJSUtils::ModuleEvaluate", JS);
 
   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(CycleCollectedJSContext::Get() &&
              CycleCollectedJSContext::Get()->MicroTaskLevel());
 
-  NS_ENSURE_TRUE(xpc::Scriptability::Get(aScript).Allowed(), NS_OK);
+  NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
 
-  if (!JS::ModuleEvaluate(aCx, aScript)) {
+  if (!JS::ModuleEvaluate(aCx, aModule)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 static bool
 AddScopeChainItem(JSContext* aCx,
--- a/dom/base/nsJSUtils.h
+++ b/dom/base/nsJSUtils.h
@@ -184,27 +184,27 @@ public:
                                  const uint8_t* aBuf, size_t aLength,
                                  JS::MutableHandle<JSScript*> aScript);
   };
 
   static nsresult CompileModule(JSContext* aCx,
                                 JS::SourceBufferHolder& aSrcBuf,
                                 JS::Handle<JSObject*> aEvaluationGlobal,
                                 JS::CompileOptions &aCompileOptions,
-                                JS::MutableHandle<JSScript*> aScript);
+                                JS::MutableHandle<JSObject*> aModule);
 
   static nsresult InitModuleSourceElement(JSContext* aCx,
-                                          JS::Handle<JSScript*> aScript,
+                                          JS::Handle<JSObject*> aModule,
                                           nsIScriptElement* aElement);
 
   static nsresult ModuleInstantiate(JSContext* aCx,
-                                    JS::Handle<JSScript*> aScript);
+                                    JS::Handle<JSObject*> aModule);
 
   static nsresult ModuleEvaluate(JSContext* aCx,
-                                 JS::Handle<JSScript*> aScript);
+                                 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.
   static bool GetScopeChainForElement(JSContext* aCx,
                                       mozilla::dom::Element* aElement,
                                       JS::AutoObjectVector& aScopeChain);
 
   // Returns a scope chain suitable for XBL execution.
--- a/dom/script/ModuleScript.cpp
+++ b/dom/script/ModuleScript.cpp
@@ -16,108 +16,108 @@ namespace dom {
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleScript)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(ModuleScript)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ModuleScript)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL)
-  tmp->UnlinkScript();
+  tmp->UnlinkModuleRecord();
   tmp->mParseError.setUndefined();
   tmp->mErrorToRethrow.setUndefined();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ModuleScript)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ModuleScript)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScript)
+  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_CYCLE_COLLECTING_ADDREF(ModuleScript)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(ModuleScript)
 
 ModuleScript::ModuleScript(ScriptLoader* aLoader, nsIURI* aBaseURL)
  : mLoader(aLoader),
    mBaseURL(aBaseURL),
    mSourceElementAssociated(false)
 {
   MOZ_ASSERT(mLoader);
   MOZ_ASSERT(mBaseURL);
-  MOZ_ASSERT(!mScript);
+  MOZ_ASSERT(!mModuleRecord);
   MOZ_ASSERT(!HasParseError());
   MOZ_ASSERT(!HasErrorToRethrow());
 }
 
 void
-ModuleScript::UnlinkScript()
+ModuleScript::UnlinkModuleRecord()
 {
   // Remove module's back reference to this object request if present.
-  if (mScript) {
-    MOZ_ASSERT(JS::GetModuleHostDefinedField(mScript).toPrivate() ==
+  if (mModuleRecord) {
+    MOZ_ASSERT(JS::GetModuleHostDefinedField(mModuleRecord).toPrivate() ==
                this);
-    JS::SetModuleHostDefinedField(mScript, JS::UndefinedValue());
-    mScript = nullptr;
+    JS::SetModuleHostDefinedField(mModuleRecord, JS::UndefinedValue());
+    mModuleRecord = nullptr;
   }
 }
 
 ModuleScript::~ModuleScript()
 {
   // The object may be destroyed without being unlinked first.
-  UnlinkScript();
+  UnlinkModuleRecord();
   DropJSObjects(this);
 }
 
 void
-ModuleScript::SetScript(JS::Handle<JSScript*> aScript)
+ModuleScript::SetModuleRecord(JS::Handle<JSObject*> aModuleRecord)
 {
-  MOZ_ASSERT(!mScript);
+  MOZ_ASSERT(!mModuleRecord);
   MOZ_ASSERT(!HasParseError());
   MOZ_ASSERT(!HasErrorToRethrow());
 
-  mScript = aScript;
+  mModuleRecord = aModuleRecord;
 
   // Make module's host defined field point to this module script object.
-  // This is cleared in the UnlinkScript().
-  JS::SetModuleHostDefinedField(mScript, JS::PrivateValue(this));
+  // This is cleared in the UnlinkModuleRecord().
+  JS::SetModuleHostDefinedField(mModuleRecord, JS::PrivateValue(this));
   HoldJSObjects(this);
 }
 
 void
 ModuleScript::SetParseError(const JS::Value& aError)
 {
   MOZ_ASSERT(!aError.isUndefined());
   MOZ_ASSERT(!HasParseError());
   MOZ_ASSERT(!HasErrorToRethrow());
 
-  UnlinkScript();
+  UnlinkModuleRecord();
   mParseError = aError;
   HoldJSObjects(this);
 }
 
 void
 ModuleScript::SetErrorToRethrow(const JS::Value& aError)
 {
   MOZ_ASSERT(!aError.isUndefined());
   MOZ_ASSERT(!HasErrorToRethrow());
 
-  // This is only called after SetScript() or SetParseError() so we don't
+  // This is only called after SetModuleRecord() or SetParseError() so we don't
   // need to call HoldJSObjects() here.
-  MOZ_ASSERT(mScript || HasParseError());
+  MOZ_ASSERT(mModuleRecord || HasParseError());
 
   mErrorToRethrow = aError;
 }
 
 void
 ModuleScript::SetSourceElementAssociated()
 {
-  MOZ_ASSERT(mScript);
+  MOZ_ASSERT(mModuleRecord);
   MOZ_ASSERT(!mSourceElementAssociated);
 
   mSourceElementAssociated = true;
 }
 
 } // dom namespace
 } // mozilla namespace
--- a/dom/script/ModuleScript.h
+++ b/dom/script/ModuleScript.h
@@ -17,43 +17,43 @@ namespace mozilla {
 namespace dom {
 
 class ScriptLoader;
 
 class ModuleScript final : public nsISupports
 {
   RefPtr<ScriptLoader> mLoader;
   nsCOMPtr<nsIURI> mBaseURL;
-  JS::Heap<JSScript*> mScript;
+  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 SetScript(JS::Handle<JSScript*> aScript);
+  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; }
-  JSScript* Script() const { return mScript; }
+  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 UnlinkScript();
+  void UnlinkModuleRecord();
 };
 
 } // dom namespace
 } // mozilla namespace
 
 #endif // mozilla_dom_ModuleScript_h
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -476,60 +476,60 @@ ScriptLoader::CreateModuleScript(ModuleL
   AutoEntryScript aes(globalObject, "CompileModule", true);
 
   bool oldProcessingScriptTag = context->GetProcessingScriptTag();
   context->SetProcessingScriptTag(true);
 
   nsresult rv;
   {
     JSContext* cx = aes.cx();
-    JS::Rooted<JSScript*> script(cx);
+    JS::Rooted<JSObject*> module(cx);
 
     if (aRequest->mWasCompiledOMT) {
-      script = JS::FinishOffThreadModule(cx, aRequest->mOffThreadToken);
+      module = JS::FinishOffThreadModule(cx, aRequest->mOffThreadToken);
       aRequest->mOffThreadToken = nullptr;
-      rv = script ? NS_OK : NS_ERROR_FAILURE;
+      rv = module ? NS_OK : NS_ERROR_FAILURE;
     } else {
       JS::Rooted<JSObject*> global(cx, globalObject->GetGlobalJSObject());
 
       JS::CompileOptions options(cx);
       rv = FillCompileOptionsForRequest(aes, aRequest, global, &options);
 
       if (NS_SUCCEEDED(rv)) {
         auto srcBuf = GetScriptSource(cx, aRequest);
         if (srcBuf) {
-          rv = nsJSUtils::CompileModule(cx, *srcBuf, global, options, &script);
+          rv = nsJSUtils::CompileModule(cx, *srcBuf, global, options, &module);
         } else {
           rv = NS_ERROR_OUT_OF_MEMORY;
         }
       }
     }
 
-    MOZ_ASSERT(NS_SUCCEEDED(rv) == (script != nullptr));
+    MOZ_ASSERT(NS_SUCCEEDED(rv) == (module != nullptr));
 
     RefPtr<ModuleScript> moduleScript = new ModuleScript(this, aRequest->mBaseURL);
     aRequest->mModuleScript = moduleScript;
 
-    if (!script) {
+    if (!module) {
       LOG(("ScriptLoadRequest (%p):   compilation failed (%d)",
            aRequest, unsigned(rv)));
 
       MOZ_ASSERT(aes.HasException());
       JS::Rooted<JS::Value> error(cx);
       if (!aes.StealException(&error)) {
         aRequest->mModuleScript = nullptr;
         return NS_ERROR_FAILURE;
       }
 
       moduleScript->SetParseError(error);
       aRequest->ModuleErrored();
       return NS_OK;
     }
 
-    moduleScript->SetScript(script);
+    moduleScript->SetModuleRecord(module);
 
     // Validate requested modules and treat failure to resolve module specifiers
     // the same as a parse error.
     rv = ResolveRequestedModules(aRequest, nullptr);
     if (NS_FAILED(rv)) {
       aRequest->ModuleErrored();
       return NS_OK;
     }
@@ -612,24 +612,24 @@ ResolveModuleSpecifier(ModuleScript* aSc
 }
 
 static nsresult
 ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI>* aUrlsOut)
 {
   ModuleScript* ms = aRequest->mModuleScript;
 
   AutoJSAPI jsapi;
-  if (!jsapi.Init(JS::GetScriptGlobal(ms->Script()))) {
+  if (!jsapi.Init(ms->ModuleRecord())) {
     return NS_ERROR_FAILURE;
   }
 
   JSContext* cx = jsapi.cx();
-  JS::Rooted<JSScript*> script(cx, ms->Script());
+  JS::Rooted<JSObject*> moduleRecord(cx, ms->ModuleRecord());
   JS::Rooted<JSObject*> requestedModules(cx);
-  requestedModules = JS::GetRequestedModules(cx, script);
+  requestedModules = JS::GetRequestedModules(cx, moduleRecord);
   MOZ_ASSERT(requestedModules);
 
   uint32_t length;
   if (!JS_GetArrayLength(cx, requestedModules, &length)) {
     return NS_ERROR_FAILURE;
   }
 
   JS::Rooted<JS::Value> element(cx);
@@ -753,24 +753,24 @@ ScriptLoader::StartFetchingModuleAndDepe
     childRequest->mReady.Reject(rv, __func__);
     return ready;
   }
 
   return ready;
 }
 
 // 8.1.3.8.1 HostResolveImportedModule(referencingModule, specifier)
-JSScript*
-HostResolveImportedModule(JSContext* aCx, JS::Handle<JSScript*> aScript,
+JSObject*
+HostResolveImportedModule(JSContext* aCx, JS::Handle<JSObject*> aModule,
                           JS::Handle<JSString*> aSpecifier)
 {
   // Let referencing module script be referencingModule.[[HostDefined]].
-  JS::Value value = JS::GetModuleHostDefinedField(aScript);
+  JS::Value value = JS::GetModuleHostDefinedField(aModule);
   auto script = static_cast<ModuleScript*>(value.toPrivate());
-  MOZ_ASSERT(script->Script() == aScript);
+  MOZ_ASSERT(script->ModuleRecord() == aModule);
 
   // 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;
   }
 
@@ -781,35 +781,35 @@ HostResolveImportedModule(JSContext* aCx
   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);
   MOZ_ASSERT(ms, "Resolved module not found in module map");
 
   MOZ_ASSERT(!ms->HasParseError());
-  MOZ_ASSERT(ms->Script());
-
-  return ms->Script();
+  MOZ_ASSERT(ms->ModuleRecord());
+
+  return ms->ModuleRecord();
 }
 
 bool
-HostPopulateImportMeta(JSContext* aCx, JS::Handle<JSScript*> aScript,
+HostPopulateImportMeta(JSContext* aCx, JS::Handle<JSObject*> aModule,
                        JS::Handle<JSObject*> aMetaObject)
 {
-  MOZ_DIAGNOSTIC_ASSERT(aScript);
-
-  JS::Value value = JS::GetModuleHostDefinedField(aScript);
+  MOZ_DIAGNOSTIC_ASSERT(aModule);
+
+  JS::Value value = JS::GetModuleHostDefinedField(aModule);
   if (value.isUndefined()) {
     JS_ReportErrorASCII(aCx, "Module script not found");
     return false;
   }
 
   auto script = static_cast<ModuleScript*>(value.toPrivate());
-  MOZ_DIAGNOSTIC_ASSERT(script->Script() == aScript);
+  MOZ_DIAGNOSTIC_ASSERT(script->ModuleRecord() == aModule);
 
   nsAutoCString url;
   MOZ_DIAGNOSTIC_ASSERT(script->BaseURL());
   MOZ_ALWAYS_SUCCEEDS(script->BaseURL()->GetAsciiSpec(url));
 
   JS::Rooted<JSString*> urlString(aCx, JS_NewStringCopyZ(aCx, url.get()));
   if (!urlString) {
     JS_ReportOutOfMemory(aCx);
@@ -930,28 +930,28 @@ ScriptLoader::InstantiateModuleTree(Modu
 
   JS::Value parseError = FindFirstParseError(aRequest);
   if (!parseError.isUndefined()) {
     moduleScript->SetErrorToRethrow(parseError);
     LOG(("ScriptLoadRequest (%p):   found parse error", aRequest));
     return true;
   }
 
-  MOZ_ASSERT(moduleScript->Script());
+  MOZ_ASSERT(moduleScript->ModuleRecord());
 
   nsAutoMicroTask mt;
   AutoJSAPI jsapi;
-  if (NS_WARN_IF(!jsapi.Init(JS::GetScriptGlobal(moduleScript->Script())))) {
+  if (NS_WARN_IF(!jsapi.Init(moduleScript->ModuleRecord()))) {
     return false;
   }
 
   EnsureModuleResolveHook(jsapi.cx());
 
-  JS::Rooted<JSScript*> script(jsapi.cx(), moduleScript->Script());
-  bool ok = NS_SUCCEEDED(nsJSUtils::ModuleInstantiate(jsapi.cx(), script));
+  JS::Rooted<JSObject*> module(jsapi.cx(), moduleScript->ModuleRecord());
+  bool ok = NS_SUCCEEDED(nsJSUtils::ModuleInstantiate(jsapi.cx(), module));
 
   if (!ok) {
     LOG(("ScriptLoadRequest (%p): Instantiate failed", aRequest));
     MOZ_ASSERT(jsapi.HasException());
     JS::RootedValue exception(jsapi.cx());
     if (!jsapi.StealException(&exception)) {
       return false;
     }
@@ -977,24 +977,25 @@ ScriptLoader::AssociateSourceElementsFor
     return NS_OK;
   }
 
   for (ModuleLoadRequest* childRequest : aRequest->mImports) {
     nsresult rv = AssociateSourceElementsForModuleTree(aCx, childRequest);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  JS::Rooted<JSScript*> script(aCx, moduleScript->Script());
-  MOZ_ASSERT(script);
-
-  nsresult rv = nsJSUtils::InitModuleSourceElement(aCx, script, aRequest->Element());
+  JS::Rooted<JSObject*> module(aCx, moduleScript->ModuleRecord());
+  MOZ_ASSERT(module);
+
+  nsresult rv = nsJSUtils::InitModuleSourceElement(aCx, module, aRequest->Element());
   NS_ENSURE_SUCCESS(rv, rv);
   moduleScript->SetSourceElementAssociated();
 
   // The script is now ready to be exposed to the debugger.
+  JS::Rooted<JSScript*> script(aCx, JS::GetModuleScript(module));
   JS::ExposeScriptToDebugger(aCx, script);
 
   return NS_OK;
 }
 
 nsresult
 ScriptLoader::RestartLoad(ScriptLoadRequest* aRequest)
 {
@@ -2334,25 +2335,25 @@ ScriptLoader::EvaluateScript(ScriptLoadR
       ModuleScript* moduleScript = request->mModuleScript;
       if (moduleScript->HasErrorToRethrow()) {
         LOG(("ScriptLoadRequest (%p):   module has error to rethrow", aRequest));
         JS::Rooted<JS::Value> error(cx, moduleScript->ErrorToRethrow());
         JS_SetPendingException(cx, error);
         return NS_OK; // An error is reported by AutoEntryScript.
       }
 
-      JS::Rooted<JSScript*> script(cx, moduleScript->Script());
-      MOZ_ASSERT(script);
+      JS::Rooted<JSObject*> module(cx, moduleScript->ModuleRecord());
+      MOZ_ASSERT(module);
 
       if (!moduleScript->SourceElementAssociated()) {
         rv = AssociateSourceElementsForModuleTree(cx, request);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
-      rv = nsJSUtils::ModuleEvaluate(cx, script);
+      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;
     } else {
--- a/dom/script/ScriptLoader.h
+++ b/dom/script/ScriptLoader.h
@@ -515,18 +515,18 @@ private:
                                                       nsresult aResult);
 
   bool IsFetchingModule(ModuleLoadRequest* aRequest) const;
 
   bool ModuleMapContainsURL(nsIURI* aURL) const;
   RefPtr<mozilla::GenericPromise> WaitForModuleFetch(nsIURI* aURL);
   ModuleScript* GetFetchedModule(nsIURI* aURL) const;
 
-  friend JSScript*
-  HostResolveImportedModule(JSContext* aCx, JS::Handle<JSScript*> aScript,
+  friend JSObject*
+  HostResolveImportedModule(JSContext* aCx, JS::Handle<JSObject*> aModule,
                           JS::Handle<JSString*> aSpecifier);
 
   // Returns wether we should save the bytecode of this script after the
   // execution of the script.
   static bool
   ShouldCacheBytecode(ScriptLoadRequest* aRequest);
 
   nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
--- a/js/public/OffThreadScriptCompilation.h
+++ b/js/public/OffThreadScriptCompilation.h
@@ -70,17 +70,17 @@ FinishOffThreadScript(JSContext* cx, Off
 extern JS_PUBLIC_API(void)
 CancelOffThreadScript(JSContext* cx, OffThreadToken* token);
 
 extern JS_PUBLIC_API(bool)
 CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
                        SourceBufferHolder& srcBuf, OffThreadCompileCallback callback,
                        void* callbackData);
 
-extern JS_PUBLIC_API(JSScript*)
+extern JS_PUBLIC_API(JSObject*)
 FinishOffThreadModule(JSContext* cx, OffThreadToken* token);
 
 extern JS_PUBLIC_API(void)
 CancelOffThreadModule(JSContext* cx, OffThreadToken* token);
 
 extern JS_PUBLIC_API(bool)
 DecodeOffThreadScript(JSContext* cx, const ReadOnlyCompileOptions& options,
                       mozilla::Vector<uint8_t>& buffer /* TranscodeBuffer& */, size_t cursor,
--- a/js/public/Realm.h
+++ b/js/public/Realm.h
@@ -69,21 +69,16 @@ GetCompartmentForRealm(Realm* realm)
 }
 
 // Return an object's realm. All objects except cross-compartment wrappers are
 // created in a particular realm, which never changes. Returns null if obj is
 // a cross-compartment wrapper.
 extern JS_PUBLIC_API(Realm*)
 GetObjectRealmOrNull(JSObject* obj);
 
-// Return a script's realm. All scripts are created in a particular realm, which
-// never changes.
-extern JS_PUBLIC_API(Realm*)
-GetScriptRealm(JSScript* script);
-
 // Get the value of the "private data" internal field of the given Realm.
 // This field is initially null and is set using SetRealmPrivate.
 // It's a pointer to embeddding-specific data that SpiderMonkey never uses.
 extern JS_PUBLIC_API(void*)
 GetRealmPrivate(Realm* realm);
 
 // Set the "private data" internal field of the given Realm.
 extern JS_PUBLIC_API(void)
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -1768,35 +1768,34 @@ ArrayObject* ModuleBuilder::createArray(
     for (auto r = map.all(); !r.empty(); r.popFront()) {
         array->initDenseElement(i++, ObjectValue(*r.front().value()));
     }
 
     return array;
 }
 
 JSObject*
-js::GetOrCreateModuleMetaObject(JSContext* cx, HandleScript script)
+js::GetOrCreateModuleMetaObject(JSContext* cx, HandleObject moduleArg)
 {
-    MOZ_ASSERT(script->module());
-    RootedModuleObject module(cx, script->module());
+    HandleModuleObject module = moduleArg.as<ModuleObject>();
     if (JSObject* obj = module->metaObject()) {
         return obj;
     }
 
     RootedObject metaObject(cx, NewObjectWithGivenProto<PlainObject>(cx, nullptr));
     if (!metaObject) {
         return nullptr;
     }
 
     JS::ModuleMetadataHook func = cx->runtime()->moduleMetadataHook;
     if (!func) {
         JS_ReportErrorASCII(cx, "Module metadata hook not set");
         return nullptr;
     }
 
-    if (!func(cx, script, metaObject)) {
+    if (!func(cx, module, metaObject)) {
         return nullptr;
     }
 
     module->setMetaObject(metaObject);
 
     return metaObject;
 }
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -414,17 +414,17 @@ class MOZ_STACK_CLASS ModuleBuilder
 
     template <typename T>
     ArrayObject* createArray(const JS::Rooted<GCVector<T>>& vector);
     template <typename K, typename V>
     ArrayObject* createArray(const JS::Rooted<GCHashMap<K, V>>& map);
 };
 
 JSObject*
-GetOrCreateModuleMetaObject(JSContext* cx, HandleScript script);
+GetOrCreateModuleMetaObject(JSContext* cx, HandleObject module);
 
 } // namespace js
 
 template<>
 inline bool
 JSObject::is<js::ModuleNamespaceObject>() const
 {
     return js::IsDerivedProxyObject(this, &js::ModuleNamespaceObject::proxyHandler);
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -47,17 +47,17 @@ class MOZ_STACK_CLASS BytecodeCompiler
     BytecodeCompiler(JSContext* cx,
                      LifoAlloc& alloc,
                      const ReadOnlyCompileOptions& options,
                      SourceBufferHolder& sourceBuffer,
                      HandleScope enclosingScope);
 
     JSScript* compileGlobalScript(ScopeKind scopeKind);
     JSScript* compileEvalScript(HandleObject environment, HandleScope enclosingScope);
-    JSScript* compileModule();
+    ModuleObject* compileModule();
     bool compileStandaloneFunction(MutableHandleFunction fun, GeneratorKind generatorKind,
                                    FunctionAsyncKind asyncKind,
                                    const Maybe<uint32_t>& parameterListEnd);
 
     ScriptSourceObject* sourceObjectPtr() const;
 
   private:
     JSScript* compileScript(HandleObject environment, SharedContext* sc);
@@ -406,17 +406,17 @@ BytecodeCompiler::compileGlobalScript(Sc
 JSScript*
 BytecodeCompiler::compileEvalScript(HandleObject environment, HandleScope enclosingScope)
 {
     EvalSharedContext evalsc(cx, environment, enclosingScope,
                              directives, options.extraWarningsOption);
     return compileScript(environment, &evalsc);
 }
 
-JSScript*
+ModuleObject*
 BytecodeCompiler::compileModule()
 {
     if (!createSourceAndParser(ParseGoal::Module)) {
         return nullptr;
     }
 
     Rooted<ModuleObject*> module(cx, ModuleObject::create(cx));
     if (!module) {
@@ -457,17 +457,17 @@ BytecodeCompiler::compileModule()
     module->setInitialEnvironment(env);
 
     // Enqueue an off-thread source compression task after finishing parsing.
     if (!scriptSource->tryCompressOffThread(cx)) {
         return nullptr;
     }
 
     MOZ_ASSERT_IF(!cx->helperThread(), !cx->isExceptionPending());
-    return script;
+    return module;
 }
 
 // Compile a standalone JS function, which might appear as the value of an
 // event handler attribute in an HTML <INPUT> tag, or in a Function()
 // constructor.
 bool
 BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
                                             GeneratorKind generatorKind,
@@ -736,17 +736,17 @@ frontend::CompileEvalScript(JSContext* c
     if (!script) {
         return nullptr;
     }
     assertException.reset();
     return script;
 
 }
 
-JSScript*
+ModuleObject*
 frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& optionsInput,
                         SourceBufferHolder& srcBuf, LifoAlloc& alloc,
                         ScriptSourceObject** sourceObjectOut)
 {
     MOZ_ASSERT(srcBuf.get());
     MOZ_ASSERT_IF(sourceObjectOut, *sourceObjectOut == nullptr);
 
     AutoAssertReportedException assertException(cx);
@@ -754,50 +754,49 @@ frontend::CompileModule(JSContext* cx, c
     CompileOptions options(cx, optionsInput);
     options.maybeMakeStrictMode(true); // ES6 10.2.1 Module code is always strict mode code.
     options.setIsRunOnce(true);
     options.allowHTMLComments = false;
 
     RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
     BytecodeCompiler compiler(cx, alloc, options, srcBuf, emptyGlobalScope);
     AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut);
-    JSScript* script = compiler.compileModule();
-    if (!script) {
+    ModuleObject* module = compiler.compileModule();
+    if (!module) {
         return nullptr;
     }
 
     assertException.reset();
-    return script;
+    return module;
 }
 
-JSScript*
+ModuleObject*
 frontend::CompileModule(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
                         SourceBufferHolder& srcBuf)
 {
     AutoAssertReportedException assertException(cx);
 
     if (!GlobalObject::ensureModulePrototypesCreated(cx, cx->global())) {
         return nullptr;
     }
 
     LifoAlloc& alloc = cx->tempLifoAlloc();
-    RootedScript script(cx, CompileModule(cx, options, srcBuf, alloc));
-    if (!script) {
+    RootedModuleObject module(cx, CompileModule(cx, options, srcBuf, alloc));
+    if (!module) {
         return nullptr;
     }
 
     // This happens in GlobalHelperThreadState::finishModuleParseTask() when a
     // module is compiled off thread.
-    RootedModuleObject module(cx, script->module());
     if (!ModuleObject::Freeze(cx, module)) {
         return nullptr;
     }
 
     assertException.reset();
-    return script;
+    return module;
 }
 
 // When leaving this scope, the given function should either:
 //   * be linked to a fully compiled script
 //   * remain linking to a lazy script
 class MOZ_STACK_CLASS AutoAssertFunctionDelazificationCompletion
 {
 #ifdef DEBUG
--- a/js/src/frontend/BytecodeCompiler.h
+++ b/js/src/frontend/BytecodeCompiler.h
@@ -16,16 +16,17 @@
 #include "vm/TraceLogging.h"
 
 class JSLinearString;
 
 namespace js {
 
 class LazyScript;
 class LifoAlloc;
+class ModuleObject;
 class ScriptSourceObject;
 
 namespace frontend {
 
 class ErrorReporter;
 class FunctionBox;
 class ParseNode;
 
@@ -50,21 +51,21 @@ CompileLazyBinASTFunction(JSContext* cx,
 
 JSScript*
 CompileEvalScript(JSContext* cx, LifoAlloc& alloc,
                   HandleObject scopeChain, HandleScope enclosingScope,
                   const JS::ReadOnlyCompileOptions& options,
                   JS::SourceBufferHolder& srcBuf,
                   ScriptSourceObject** sourceObjectOut = nullptr);
 
-JSScript*
+ModuleObject*
 CompileModule(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
               JS::SourceBufferHolder& srcBuf);
 
-JSScript*
+ModuleObject*
 CompileModule(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
               JS::SourceBufferHolder& srcBuf, LifoAlloc& alloc,
               ScriptSourceObject** sourceObjectOut = nullptr);
 
 MOZ_MUST_USE bool
 CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const char16_t* chars, size_t length);
 
 //
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -5422,17 +5422,16 @@ BaselineCompiler::emit_JSOP_DERIVEDCONST
 }
 
 bool
 BaselineCompiler::emit_JSOP_IMPORTMETA()
 {
     RootedModuleObject module(cx, GetModuleObjectForScript(script));
     MOZ_ASSERT(module);
 
-    RootedScript moduleScript(cx, module->script());
-    JSObject* metaObject = GetOrCreateModuleMetaObject(cx, moduleScript);
+    JSObject* metaObject = GetOrCreateModuleMetaObject(cx, module);
     if (!metaObject) {
         return false;
     }
 
     frame.push(ObjectValue(*metaObject));
     return true;
 }
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1281,25 +1281,16 @@ JS::CurrentGlobalOrNull(JSContext* cx)
 JS_PUBLIC_API(JSObject*)
 JS::GetNonCCWObjectGlobal(JSObject* obj)
 {
     AssertHeapIsIdleOrIterating();
     MOZ_DIAGNOSTIC_ASSERT(!IsCrossCompartmentWrapper(obj));
     return &obj->nonCCWGlobal();
 }
 
-JS_PUBLIC_API(JSObject*)
-JS::GetScriptGlobal(JSScript* script)
-{
-    AssertHeapIsIdleOrIterating();
-    JSObject* global = script->realm()->maybeGlobal();
-    MOZ_ASSERT(global);
-    return global;
-}
-
 JS_PUBLIC_API(bool)
 JS::detail::ComputeThis(JSContext* cx, Value* vp, MutableHandleObject thisObject)
 {
     AssertHeapIsIdle();
     cx->check(vp[0], vp[1]);
 
     MutableHandleValue thisv = MutableHandleValue::fromMarkedLocation(&vp[1]);
     if (!BoxNonStrictThis(cx, thisv, thisv)) {
@@ -4145,71 +4136,63 @@ JS_PUBLIC_API(void)
 JS::SetModuleMetadataHook(JSRuntime* rt, JS::ModuleMetadataHook func)
 {
     AssertHeapIsIdle();
     rt->moduleMetadataHook = func;
 }
 
 JS_PUBLIC_API(bool)
 JS::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
-                  SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
+                  SourceBufferHolder& srcBuf, JS::MutableHandleObject module)
 {
     MOZ_ASSERT(!cx->zone()->isAtomsZone());
     AssertHeapIsIdle();
     CHECK_THREAD(cx);
 
-    script.set(frontend::CompileModule(cx, options, srcBuf));
-    return !!script;
+    module.set(frontend::CompileModule(cx, options, srcBuf));
+    return !!module;
 }
 
 JS_PUBLIC_API(void)
-JS::SetModuleHostDefinedField(JSScript* script, const JS::Value& value)
-{
-    MOZ_ASSERT(script->module());
-    script->module()->setHostDefinedField(value);
+JS::SetModuleHostDefinedField(JSObject* module, const JS::Value& value)
+{
+    module->as<ModuleObject>().setHostDefinedField(value);
 }
 
 JS_PUBLIC_API(JS::Value)
-JS::GetModuleHostDefinedField(JSScript* script)
-{
-    MOZ_ASSERT(script->module());
-    return script->module()->hostDefinedField();
-}
-
-JS_PUBLIC_API(bool)
-JS::ModuleInstantiate(JSContext* cx, JS::HandleScript script)
-{
-    AssertHeapIsIdle();
-    CHECK_THREAD(cx);
-    cx->check(script);
-    RootedModuleObject module(cx, script->module());
-    MOZ_ASSERT(module);
-    return ModuleObject::Instantiate(cx, module);
-}
-
-JS_PUBLIC_API(bool)
-JS::ModuleEvaluate(JSContext* cx, JS::HandleScript script)
-{
-    AssertHeapIsIdle();
-    CHECK_THREAD(cx);
-    cx->check(script);
-    RootedModuleObject module(cx, script->module());
-    MOZ_ASSERT(module);
-    return ModuleObject::Evaluate(cx, module);
+JS::GetModuleHostDefinedField(JSObject* module)
+{
+    return module->as<ModuleObject>().hostDefinedField();
+}
+
+JS_PUBLIC_API(bool)
+JS::ModuleInstantiate(JSContext* cx, JS::HandleObject moduleArg)
+{
+    AssertHeapIsIdle();
+    CHECK_THREAD(cx);
+    cx->check(moduleArg);
+    return ModuleObject::Instantiate(cx, moduleArg.as<ModuleObject>());
+}
+
+JS_PUBLIC_API(bool)
+JS::ModuleEvaluate(JSContext* cx, JS::HandleObject moduleArg)
+{
+    AssertHeapIsIdle();
+    CHECK_THREAD(cx);
+    cx->check(moduleArg);
+    return ModuleObject::Evaluate(cx, moduleArg.as<ModuleObject>());
 }
 
 JS_PUBLIC_API(JSObject*)
-JS::GetRequestedModules(JSContext* cx, JS::HandleScript script)
-{
-    AssertHeapIsIdle();
-    CHECK_THREAD(cx);
-    cx->check(script);
-    RootedModuleObject module(cx, script->module());
-    MOZ_ASSERT(module);
-    return &module->requestedModules();
+JS::GetRequestedModules(JSContext* cx, JS::HandleObject moduleArg)
+{
+    AssertHeapIsIdle();
+    CHECK_THREAD(cx);
+    cx->check(moduleArg);
+    return &moduleArg->as<ModuleObject>().requestedModules();
 }
 
 JS_PUBLIC_API(JSString*)
 JS::GetRequestedModuleSpecifier(JSContext* cx, JS::HandleValue value)
 {
     AssertHeapIsIdle();
     CHECK_THREAD(cx);
     cx->check(value);
@@ -4226,16 +4209,23 @@ JS::GetRequestedModuleSourcePos(JSContex
     cx->check(value);
     MOZ_ASSERT(lineNumber);
     MOZ_ASSERT(columnNumber);
     auto& requested = value.toObject().as<RequestedModuleObject>();
     *lineNumber = requested.lineNumber();
     *columnNumber = requested.columnNumber();
 }
 
+JS_PUBLIC_API(JSScript*)
+JS::GetModuleScript(JS::HandleObject moduleRecord)
+{
+    AssertHeapIsIdle();
+    return moduleRecord->as<ModuleObject>().script();
+}
+
 JS_PUBLIC_API(JSObject*)
 JS_New(JSContext* cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
 {
     AssertHeapIsIdle();
     CHECK_THREAD(cx);
     cx->check(ctor, inputArgs);
 
     RootedValue ctorVal(cx, ObjectValue(*ctor));
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1035,22 +1035,16 @@ CurrentGlobalOrNull(JSContext* cx);
 /**
  * Get the global object associated with an object's realm. The object must not
  * be a cross-compartment wrapper (because CCWs are shared by all realms in the
  * compartment).
  */
 extern JS_PUBLIC_API(JSObject*)
 GetNonCCWObjectGlobal(JSObject* obj);
 
-/**
- * Get the global object associated with a script's realm.
- */
-extern JS_PUBLIC_API(JSObject*)
-GetScriptGlobal(JSScript* script);
-
 } // namespace JS
 
 /**
  * Add 'Reflect.parse', a SpiderMonkey extension, to the Reflect object on the
  * given global.
  */
 extern JS_PUBLIC_API(bool)
 JS_InitReflectParse(JSContext* cx, JS::HandleObject global);
@@ -3019,88 +3013,88 @@ extern JS_PUBLIC_API(JSString*)
 JS_DecompileScript(JSContext* cx, JS::Handle<JSScript*> script);
 
 extern JS_PUBLIC_API(JSString*)
 JS_DecompileFunction(JSContext* cx, JS::Handle<JSFunction*> fun);
 
 
 namespace JS {
 
-using ModuleResolveHook = JSScript* (*)(JSContext*, HandleScript, HandleString);
+using ModuleResolveHook = JSObject* (*)(JSContext*, HandleObject, HandleString);
 
 /**
  * Get the HostResolveImportedModule hook for the runtime.
  */
 extern JS_PUBLIC_API(ModuleResolveHook)
 GetModuleResolveHook(JSRuntime* rt);
 
 /**
  * Set the HostResolveImportedModule hook for the runtime to the given function.
  */
 extern JS_PUBLIC_API(void)
 SetModuleResolveHook(JSRuntime* rt, ModuleResolveHook func);
 
-using ModuleMetadataHook = bool (*)(JSContext*, HandleScript, HandleObject);
+using ModuleMetadataHook = bool (*)(JSContext*, HandleObject, HandleObject);
 
 /**
  * Get the hook for populating the import.meta metadata object.
  */
 extern JS_PUBLIC_API(ModuleMetadataHook)
 GetModuleMetadataHook(JSRuntime* rt);
 
 /**
  * Set the hook for populating the import.meta metadata object to the given
  * function.
  */
 extern JS_PUBLIC_API(void)
 SetModuleMetadataHook(JSRuntime* rt, ModuleMetadataHook func);
 
 /**
  * Parse the given source buffer as a module in the scope of the current global
- * of cx.
+ * of cx and return a source text module record.
  */
 extern JS_PUBLIC_API(bool)
 CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
-              SourceBufferHolder& srcBuf, JS::MutableHandleScript script);
+              SourceBufferHolder& srcBuf, JS::MutableHandleObject moduleRecord);
 
 /**
  * Set the [[HostDefined]] field of a source text module record to the given
  * value.
  */
 extern JS_PUBLIC_API(void)
-SetModuleHostDefinedField(JSScript* module, const JS::Value& value);
+SetModuleHostDefinedField(JSObject* module, const JS::Value& value);
 
 /**
  * Get the [[HostDefined]] field of a source text module record.
  */
 extern JS_PUBLIC_API(JS::Value)
-GetModuleHostDefinedField(JSScript* script);
+GetModuleHostDefinedField(JSObject* module);
 
 /*
  * Perform the ModuleInstantiate operation on the given source text module
  * record.
  *
  * This transitively resolves all module dependencies (calling the
  * HostResolveImportedModule hook) and initializes the environment record for
  * the module.
  */
 extern JS_PUBLIC_API(bool)
-ModuleInstantiate(JSContext* cx, JS::HandleScript script);
+ModuleInstantiate(JSContext* cx, JS::HandleObject moduleRecord);
 
 /*
  * Perform the ModuleEvaluate operation on the given source text module record.
  *
  * This does nothing if this module has already been evaluated. Otherwise, it
  * transitively evaluates all dependences of this module and then evaluates this
  * module.
  *
  * ModuleInstantiate must have completed prior to calling this.
  */
 extern JS_PUBLIC_API(bool)
-ModuleEvaluate(JSContext* cx, JS::HandleScript script);
+ModuleEvaluate(JSContext* cx, JS::HandleObject moduleRecord);
 
 /*
  * Get a list of the module specifiers used by a source text module
  * record to request importation of modules.
  *
  * The result is a JavaScript array of object values.  To extract the individual
  * values use only JS_GetArrayLength and JS_GetElement with indices 0 to length
  * - 1.
@@ -3109,25 +3103,28 @@ ModuleEvaluate(JSContext* cx, JS::Handle
  *  - moduleSpecifier: the module specifier string
  *  - lineNumber: the line number of the import in the source text
  *  - columnNumber: the column number of the import in the source text
  *
  * These property values can be extracted with GetRequestedModuleSpecifier() and
  * GetRequestedModuleSourcePos()
  */
 extern JS_PUBLIC_API(JSObject*)
-GetRequestedModules(JSContext* cx, JS::HandleScript script);
+GetRequestedModules(JSContext* cx, JS::HandleObject moduleRecord);
 
 extern JS_PUBLIC_API(JSString*)
 GetRequestedModuleSpecifier(JSContext* cx, JS::HandleValue requestedModuleObject);
 
 extern JS_PUBLIC_API(void)
 GetRequestedModuleSourcePos(JSContext* cx, JS::HandleValue requestedModuleObject,
                             uint32_t* lineNumber, uint32_t* columnNumber);
 
+extern JS_PUBLIC_API(JSScript*)
+GetModuleScript(JS::HandleObject moduleRecord);
+
 } /* namespace JS */
 
 #if defined(JS_BUILD_BINAST)
 
 namespace JS {
 
 extern JS_PUBLIC_API(JSScript*)
 DecodeBinAST(JSContext* cx, const ReadOnlyCompileOptions& options,
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -4659,22 +4659,22 @@ ParseModule(JSContext* cx, unsigned argc
     if (!stableChars.initTwoByte(cx, scriptContents)) {
         return false;
     }
 
     const char16_t* chars = stableChars.twoByteRange().begin().get();
     JS::SourceBufferHolder srcBuf(chars, scriptContents->length(),
                                   JS::SourceBufferHolder::NoOwnership);
 
-    RootedScript script(cx, frontend::CompileModule(cx, options, srcBuf));
-    if (!script) {
-        return false;
-    }
-
-    args.rval().setObject(*script->module());
+    RootedObject module(cx, frontend::CompileModule(cx, options, srcBuf));
+    if (!module) {
+        return false;
+    }
+
+    args.rval().setObject(*module);
     return true;
 }
 
 static bool
 SetModuleLoadHook(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() != 1) {
@@ -4714,50 +4714,49 @@ SetModuleResolveHook(JSContext* cx, unsi
 
     Handle<GlobalObject*> global = cx->global();
     global->setReservedSlot(GlobalAppSlotModuleResolveHook, args[0]);
 
     args.rval().setUndefined();
     return true;
 }
 
-static JSScript*
-CallModuleResolveHook(JSContext* cx, HandleScript script, HandleString specifier)
-{
-    MOZ_ASSERT(script->module());
-
+static JSObject*
+CallModuleResolveHook(JSContext* cx, HandleObject module, HandleString specifier)
+{
     Handle<GlobalObject*> global = cx->global();
     RootedValue hookValue(cx, global->getReservedSlot(GlobalAppSlotModuleResolveHook));
     if (hookValue.isUndefined()) {
         JS_ReportErrorASCII(cx, "Module resolve hook not set");
         return nullptr;
     }
     MOZ_ASSERT(hookValue.toObject().is<JSFunction>());
 
     JS::AutoValueArray<2> args(cx);
-    args[0].setObject(*script->module());
+    args[0].setObject(*module);
     args[1].setString(specifier);
 
     RootedValue result(cx);
     if (!JS_CallFunctionValue(cx, nullptr, hookValue, args, &result)) {
         return nullptr;
     }
 
     if (!result.isObject() || !result.toObject().is<ModuleObject>()) {
          JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
          return nullptr;
     }
 
-    return result.toObject().as<ModuleObject>().script();
-}
-
-static bool
-ShellModuleMetadataHook(JSContext* cx, HandleScript script, HandleObject metaObject)
+    return &result.toObject();
+}
+
+static bool
+ShellModuleMetadataHook(JSContext* cx, HandleObject module, HandleObject metaObject)
 {
     // For the shell, just use the script's filename as the base URL.
+    RootedScript script(cx, module->as<ModuleObject>().script());
     const char* filename = script->scriptSource()->filename();
     MOZ_ASSERT(filename);
 
     RootedString url(cx, NewStringCopyZ<CanGC>(cx, filename));
     if (!url) {
         return false;
     }
 
@@ -5289,22 +5288,22 @@ FinishOffThreadModule(JSContext* cx, uns
         return false;
     }
 
     JS::OffThreadToken* token = job->waitUntilDone(cx);
     MOZ_ASSERT(token);
 
     DeleteOffThreadJob(cx, job);
 
-    RootedScript script(cx, JS::FinishOffThreadModule(cx, token));
-    if (!script) {
-        return false;
-    }
-
-    args.rval().setObject(*script->module());
+    RootedObject module(cx, JS::FinishOffThreadModule(cx, token));
+    if (!module) {
+        return false;
+    }
+
+    args.rval().setObject(*module);
     return true;
 }
 
 static bool
 OffThreadDecodeScript(JSContext* cx, unsigned argc, Value* vp)
 {
     if (!CanUseExtraThreads()) {
         JS_ReportErrorASCII(cx, "Can't use offThreadDecodeScript with --no-threads");
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -536,19 +536,19 @@ ModuleParseTask::ModuleParseTask(JSConte
 
 void
 ModuleParseTask::parse(JSContext* cx)
 {
     MOZ_ASSERT(cx->helperThread());
 
     Rooted<ScriptSourceObject*> sourceObject(cx);
 
-    JSScript* script = frontend::CompileModule(cx, options, data, cx->tempLifoAlloc(), &sourceObject.get());
-    if (script) {
-        scripts.infallibleAppend(script);
+    ModuleObject* module = frontend::CompileModule(cx, options, data, cx->tempLifoAlloc(), &sourceObject.get());
+    if (module) {
+        scripts.infallibleAppend(module->script());
         if (sourceObject) {
             sourceObjects.infallibleAppend(sourceObject);
         }
     }
 }
 
 ScriptDecodeTask::ScriptDecodeTask(JSContext* cx, const JS::TranscodeRange& range,
                                    JS::OffThreadCompileCallback callback, void* callbackData)
@@ -1911,33 +1911,33 @@ GlobalHelperThreadState::finishBinASTDec
 
 bool
 GlobalHelperThreadState::finishMultiScriptsDecodeTask(JSContext* cx, JS::OffThreadToken* token,
                                                       MutableHandle<ScriptVector> scripts)
 {
     return finishMultiParseTask(cx, ParseTaskKind::MultiScriptsDecode, token, scripts);
 }
 
-JSScript*
+JSObject*
 GlobalHelperThreadState::finishModuleParseTask(JSContext* cx, JS::OffThreadToken* token)
 {
-    RootedScript script(cx, finishSingleParseTask(cx, ParseTaskKind::Module, token));
+    JSScript* script = finishSingleParseTask(cx, ParseTaskKind::Module, token);
     if (!script) {
         return nullptr;
     }
 
     MOZ_ASSERT(script->module());
 
     RootedModuleObject module(cx, script->module());
     module->fixEnvironmentsAfterCompartmentMerge();
     if (!ModuleObject::Freeze(cx, module)) {
         return nullptr;
     }
 
-    return script;
+    return module;
 }
 
 void
 GlobalHelperThreadState::cancelParseTask(JSRuntime* rt, ParseTaskKind kind,
                                          JS::OffThreadToken* token)
 {
     destroyParseTask(rt, removeFinishedParseTask(kind, token));
 }
--- a/js/src/vm/HelperThreads.h
+++ b/js/src/vm/HelperThreads.h
@@ -297,17 +297,17 @@ class GlobalHelperThreadState
     void cancelParseTask(JSRuntime* rt, ParseTaskKind kind, JS::OffThreadToken* token);
     void destroyParseTask(JSRuntime* rt, ParseTask* parseTask);
 
     void trace(JSTracer* trc);
 
     JSScript* finishScriptParseTask(JSContext* cx, JS::OffThreadToken* token);
     JSScript* finishScriptDecodeTask(JSContext* cx, JS::OffThreadToken* token);
     bool finishMultiScriptsDecodeTask(JSContext* cx, JS::OffThreadToken* token, MutableHandle<ScriptVector> scripts);
-    JSScript* finishModuleParseTask(JSContext* cx, JS::OffThreadToken* token);
+    JSObject* finishModuleParseTask(JSContext* cx, JS::OffThreadToken* token);
 
 #if defined(JS_BUILD_BINAST)
     JSScript* finishBinASTDecodeTask(JSContext* cx, JS::OffThreadToken* token);
 #endif
 
     bool hasActiveThreads(const AutoLockHelperThreadState&);
     void waitForAllThreads();
     void waitForAllThreadsLocked(AutoLockHelperThreadState&);
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -4701,18 +4701,17 @@ CASE(JSOP_NEWTARGET)
     MOZ_ASSERT(REGS.sp[-1].isObject() || REGS.sp[-1].isUndefined());
 END_CASE(JSOP_NEWTARGET)
 
 CASE(JSOP_IMPORTMETA)
 {
     ReservedRooted<JSObject*> module(&rootObject0, GetModuleObjectForScript(script));
     MOZ_ASSERT(module);
 
-    ReservedRooted<JSScript*> script(&rootScript0, module->as<ModuleObject>().script());
-    JSObject* metaObject = GetOrCreateModuleMetaObject(cx, script);
+    JSObject* metaObject = GetOrCreateModuleMetaObject(cx, module);
     if (!metaObject) {
         goto error;
     }
 
     PUSH_OBJECT(*metaObject);
 }
 END_CASE(JSOP_NEWTARGET)
 
--- a/js/src/vm/OffThreadScriptCompilation.cpp
+++ b/js/src/vm/OffThreadScriptCompilation.cpp
@@ -116,17 +116,17 @@ JS_PUBLIC_API(bool)
 JS::CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
                            JS::SourceBufferHolder& srcBuf,
                            OffThreadCompileCallback callback, void* callbackData)
 {
     MOZ_ASSERT(CanCompileOffThread(cx, options, srcBuf.length()));
     return StartOffThreadParseModule(cx, options, srcBuf, callback, callbackData);
 }
 
-JS_PUBLIC_API(JSScript*)
+JS_PUBLIC_API(JSObject*)
 JS::FinishOffThreadModule(JSContext* cx, JS::OffThreadToken* token)
 {
     MOZ_ASSERT(cx);
     MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
     return HelperThreadState().finishModuleParseTask(cx, token);
 }
 
 JS_PUBLIC_API(void)
--- a/js/src/vm/Realm.cpp
+++ b/js/src/vm/Realm.cpp
@@ -1075,22 +1075,16 @@ JS::GetCurrentRealmOrNull(JSContext* cx)
 }
 
 JS_PUBLIC_API(JS::Realm*)
 JS::GetObjectRealmOrNull(JSObject* obj)
 {
     return IsCrossCompartmentWrapper(obj) ? nullptr : obj->nonCCWRealm();
 }
 
-JS_PUBLIC_API(JS::Realm*)
-JS::GetScriptRealm(JSScript* script)
-{
-    return script->realm();
-}
-
 JS_PUBLIC_API(void*)
 JS::GetRealmPrivate(JS::Realm* realm)
 {
     return realm->realmPrivate();
 }
 
 JS_PUBLIC_API(void)
 JS::SetRealmPrivate(JS::Realm* realm, void* data)
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -2187,29 +2187,28 @@ intrinsic_HostResolveImportedModule(JSCo
     RootedString specifier(cx, args[1].toString());
 
     JS::ModuleResolveHook moduleResolveHook = cx->runtime()->moduleResolveHook;
     if (!moduleResolveHook) {
         JS_ReportErrorASCII(cx, "Module resolve hook not set");
         return false;
     }
 
-    RootedScript script(cx, module->script());
-    RootedScript result(cx);
-    result = moduleResolveHook(cx, script, specifier);
+    RootedObject result(cx);
+    result = moduleResolveHook(cx, module, specifier);
     if (!result) {
         return false;
     }
 
-    if (!result->module()) {
-        JS_ReportErrorASCII(cx, "Module resolve hook did not return a module script");
+    if (!result->is<ModuleObject>()) {
+        JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
         return false;
     }
 
-    args.rval().setObject(*result->module());
+    args.rval().setObject(*result);
     return true;
 }
 
 static bool
 intrinsic_CreateImportBinding(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 4);
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -452,23 +452,16 @@ Scriptability::SetDocShellAllowsScript(b
 
 /* static */
 Scriptability&
 Scriptability::Get(JSObject* aScope)
 {
     return RealmPrivate::Get(aScope)->scriptability;
 }
 
-/* static */
-Scriptability&
-Scriptability::Get(JSScript* aScript)
-{
-    return RealmPrivate::Get(aScript)->scriptability;
-}
-
 bool
 IsContentXBLCompartment(JS::Compartment* compartment)
 {
     // We always eagerly create compartment privates for content XBL compartments.
     CompartmentPrivate* priv = CompartmentPrivate::Get(compartment);
     return priv && priv->isContentXBLCompartment;
 }
 
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -3118,23 +3118,16 @@ public:
     // cross-compartment wrapper, as CCWs aren't dedicated to a particular
     // realm.
     static RealmPrivate* Get(JSObject* object)
     {
         JS::Realm* realm = JS::GetObjectRealmOrNull(object);
         return Get(realm);
     }
 
-    // Get the RealmPrivate for a given script.
-    static RealmPrivate* Get(JSScript* script)
-    {
-        JS::Realm* realm = JS::GetScriptRealm(script);
-        return Get(realm);
-    }
-
     // The scriptability of this realm.
     Scriptability scriptability;
 
     // Our XPCWrappedNativeScope. This is non-null if and only if this is an
     // XPConnect realm.
     XPCWrappedNativeScope* scope;
 
     const nsACString& GetLocation() {
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -49,17 +49,16 @@ public:
     bool Allowed();
     bool IsImmuneToScriptPolicy();
 
     void Block();
     void Unblock();
     void SetDocShellAllowsScript(bool aAllowed);
 
     static Scriptability& Get(JSObject* aScope);
-    static Scriptability& Get(JSScript* aScript);
 
 private:
     // Whenever a consumer wishes to prevent script from running on a global,
     // it increments this value with a call to Block(). When it wishes to
     // re-enable it (if ever), it decrements this value with a call to Unblock().
     // Script may not run if this value is non-zero.
     uint32_t mScriptBlocks;