Issue #1691 - Part 7d: Allow dynamic import in cases where there's no referencing script or module. Support dynamic import from classic scripts by creating ClassicScript objects and associating them with the compiled. https://bugzilla.mozilla.org/show_bug.cgi?id=1342012 This patch is incomplete, some code in ScriptLoader::EvaluateScript() could not be applied for missing dependencies. Part 7e will apply the missing dependencies and finish the patch.

(cherry picked from commit ce31a906e801b72f06385b0755710317ccf3658b)
This commit is contained in:
Brian Smith 2023-04-19 01:59:14 -05:00 • committed by roytam1
commit d5d7bb5e47
6 changed files with 188 additions and 88 deletions

View file

@ -20,13 +20,13 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(ModuleLoadRequest)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ModuleLoadRequest, NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ModuleLoadRequest,
ScriptLoadRequest) ScriptLoadRequest)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL, mLoader, mModuleScript, mImports) NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader, mModuleScript, mImports)
tmp->ClearDynamicImport(); tmp->ClearDynamicImport();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ModuleLoadRequest, NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ModuleLoadRequest,
ScriptLoadRequest) ScriptLoadRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBaseURL, mLoader, mModuleScript, mImports) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader, mModuleScript, mImports)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(ModuleLoadRequest, NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(ModuleLoadRequest,
@ -69,17 +69,18 @@ static VisitedURLSet* NewVisitedSetForTopLevelImport(nsIURI* aURI) {
} }
/* static */ ModuleLoadRequest* ModuleLoadRequest::CreateDynamicImport( /* static */ ModuleLoadRequest* ModuleLoadRequest::CreateDynamicImport(
nsIURI* aURI, ModuleScript* aScript, nsIURI* aURI, ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL,
JS::Handle<JS::Value> aReferencingPrivate, JS::Handle<JSString*> aSpecifier, ScriptLoader* aLoader, JS::Handle<JS::Value> aReferencingPrivate,
JS::Handle<JSObject*> aPromise) { JS::Handle<JSString*> aSpecifier, JS::Handle<JSObject*> aPromise)
{
MOZ_ASSERT(aSpecifier); MOZ_ASSERT(aSpecifier);
MOZ_ASSERT(aPromise); MOZ_ASSERT(aPromise);
auto request = new ModuleLoadRequest( auto request = new ModuleLoadRequest(
aURI, aScript->FetchOptions(), SRIMetadata(), aScript->BaseURL(), aURI, aFetchOptions, SRIMetadata(), aBaseURL,
true, /* is top level */ true, /* is top level */
true, /* is dynamic import */ true, /* is dynamic import */
aScript->Loader(), NewVisitedSetForTopLevelImport(aURI)); aLoader, NewVisitedSetForTopLevelImport(aURI));
request->mIsInline = false; request->mIsInline = false;
request->mScriptMode = ScriptMode::eAsync; request->mScriptMode = ScriptMode::eAsync;

View file

@ -60,8 +60,8 @@ public:
// Create a module load request for dynamic module import. // Create a module load request for dynamic module import.
static ModuleLoadRequest* CreateDynamicImport( static ModuleLoadRequest* CreateDynamicImport(
nsIURI* aURI, ModuleScript* aScript, nsIURI* aURI, ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL,
JS::Handle<JS::Value> aReferencingPrivate, ScriptLoader* aLoader, JS::Handle<JS::Value> aReferencingPrivate,
JS::Handle<JSString*> aSpecifier, JS::Handle<JSObject*> aPromise); JS::Handle<JSString*> aSpecifier, JS::Handle<JSObject*> aPromise);
bool IsTopLevel() const override { bool IsTopLevel() const override {
@ -90,9 +90,6 @@ public:
// Is this the top level request for a dynamic module import? // Is this the top level request for a dynamic module import?
const bool mIsDynamicImport; const bool mIsDynamicImport;
// The base URL used for resolving relative module imports.
nsCOMPtr<nsIURI> mBaseURL;
// Pointer to the script loader, used to trigger actions when the module load // Pointer to the script loader, used to trigger actions when the module load
// finishes. // finishes.
RefPtr<ScriptLoader> mLoader; RefPtr<ScriptLoader> mLoader;

View file

@ -26,13 +26,11 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_CLASS(LoadedScript) NS_IMPL_CYCLE_COLLECTION_CLASS(LoadedScript)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(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(mFetchOptions)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL) NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(LoadedScript) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(LoadedScript)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFetchOptions) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFetchOptions)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -42,28 +40,52 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(LoadedScript) NS_IMPL_CYCLE_COLLECTING_ADDREF(LoadedScript)
NS_IMPL_CYCLE_COLLECTING_RELEASE(LoadedScript) NS_IMPL_CYCLE_COLLECTING_RELEASE(LoadedScript)
LoadedScript::LoadedScript(ScriptKind aKind, ScriptLoader* aLoader, LoadedScript::LoadedScript(ScriptKind aKind,
ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL) ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL)
: mKind(aKind), : mKind(aKind),
mLoader(aLoader),
mFetchOptions(aFetchOptions), mFetchOptions(aFetchOptions),
mBaseURL(aBaseURL) mBaseURL(aBaseURL)
{ {
MOZ_ASSERT(mLoader);
MOZ_ASSERT(mFetchOptions); MOZ_ASSERT(mFetchOptions);
MOZ_ASSERT(mBaseURL); MOZ_ASSERT(mBaseURL);
} }
LoadedScript::~LoadedScript() { DropJSObjects(this); } LoadedScript::~LoadedScript() { DropJSObjects(this); }
void LoadedScript::AssociateWithScript(JSScript* aScript) {
// Set a JSScript's private value to point to this object and
// increment our reference count. This is decremented by
// HostFinalizeTopLevelScript() below when the JSScript dies.
MOZ_ASSERT(JS::GetScriptPrivate(aScript).isUndefined());
JS::SetScriptPrivate(aScript, JS::PrivateValue(this));
AddRef();
}
void HostFinalizeTopLevelScript(JSFreeOp* aFop, const JS::Value& aPrivate) {
// Decrement the reference count of a LoadedScript object that is
// pointed to by a dying JSScript. The reference count was
// originally incremented by AssociateWithScript() above.
auto script = static_cast<LoadedScript*>(aPrivate.toPrivate());
#ifdef DEBUG
if (script->IsModuleScript()) {
JSObject* module = script->AsModuleScript()->mModuleRecord.unbarrieredGet();
MOZ_ASSERT(JS::GetModulePrivate(module) == aPrivate);
}
#endif
script->Release();
}
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
// ClassicScript // ClassicScript
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
ClassicScript::ClassicScript(ScriptLoader* aLoader, ClassicScript::ClassicScript(ScriptFetchOptions* aFetchOptions,
ScriptFetchOptions* aFetchOptions,
nsIURI* aBaseURL) nsIURI* aBaseURL)
: LoadedScript(ScriptKind::Classic, aLoader, aFetchOptions, aBaseURL) {} : LoadedScript(ScriptKind::Classic, aFetchOptions, aBaseURL) {}
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
// ModuleScript // ModuleScript
@ -92,9 +114,8 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_ADDREF_INHERITED(ModuleScript, LoadedScript) NS_IMPL_ADDREF_INHERITED(ModuleScript, LoadedScript)
NS_IMPL_RELEASE_INHERITED(ModuleScript, LoadedScript) NS_IMPL_RELEASE_INHERITED(ModuleScript, LoadedScript)
ModuleScript::ModuleScript(ScriptLoader* aLoader, ModuleScript::ModuleScript(ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL)
ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL) : LoadedScript(ScriptKind::Module, aFetchOptions, aBaseURL) {
: LoadedScript(ScriptKind::Module, aLoader, aFetchOptions, aBaseURL) {
MOZ_ASSERT(!ModuleRecord()); MOZ_ASSERT(!ModuleRecord());
MOZ_ASSERT(!HasParseError()); MOZ_ASSERT(!HasParseError());
MOZ_ASSERT(!HasErrorToRethrow()); MOZ_ASSERT(!HasErrorToRethrow());
@ -150,15 +171,6 @@ ModuleScript::SetParseError(const JS::Value& aError)
AddRef(); AddRef();
} }
void HostFinalizeTopLevelScript(JSFreeOp* aFop, const JS::Value& aPrivate) {
auto script = static_cast<ModuleScript*>(aPrivate.toPrivate());
if (script) {
MOZ_ASSERT(JS::GetModulePrivate(script->mModuleRecord.unbarrieredGet()) ==
aPrivate);
script->UnlinkModuleRecord();
}
}
void void
ModuleScript::SetErrorToRethrow(const JS::Value& aError) ModuleScript::SetErrorToRethrow(const JS::Value& aError)
{ {

View file

@ -31,8 +31,8 @@ class LoadedScript : public nsISupports
nsCOMPtr<nsIURI> mBaseURL; nsCOMPtr<nsIURI> mBaseURL;
protected: protected:
LoadedScript(ScriptKind aKind, ScriptLoader* aLoader, LoadedScript(ScriptKind aKind,
ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL); ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL);
virtual ~LoadedScript(); virtual ~LoadedScript();
@ -45,9 +45,10 @@ class LoadedScript : public nsISupports
inline ClassicScript* AsClassicScript(); inline ClassicScript* AsClassicScript();
inline ModuleScript* AsModuleScript(); inline ModuleScript* AsModuleScript();
ScriptLoader* Loader() const { return mLoader; }
ScriptFetchOptions* FetchOptions() const { return mFetchOptions; } ScriptFetchOptions* FetchOptions() const { return mFetchOptions; }
nsIURI* BaseURL() const { return mBaseURL; } nsIURI* BaseURL() const { return mBaseURL; }
void AssociateWithScript(JSScript* aScript);
}; };
class ClassicScript final : public LoadedScript class ClassicScript final : public LoadedScript
@ -55,8 +56,7 @@ class ClassicScript final : public LoadedScript
~ClassicScript() = default; ~ClassicScript() = default;
public: public:
ClassicScript(ScriptLoader* aLoader, ScriptFetchOptions* aFetchOptions, ClassicScript(ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL);
nsIURI* aBaseURL);
}; };
// A single module script. May be used to satisfy multiple load requests. // A single module script. May be used to satisfy multiple load requests.
@ -74,8 +74,7 @@ public:
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ModuleScript, NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ModuleScript,
LoadedScript) LoadedScript)
ModuleScript(ScriptLoader* aLoader, ScriptFetchOptions* aFetchOptions, ModuleScript(ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL);
nsIURI* aBaseURL);
void SetModuleRecord(JS::Handle<JSObject*> aModuleRecord); void SetModuleRecord(JS::Handle<JSObject*> aModuleRecord);
void SetParseError(const JS::Value& aError); void SetParseError(const JS::Value& aError);

View file

@ -20,6 +20,7 @@
#include "mozilla/dom/SRILogHelper.h" #include "mozilla/dom/SRILogHelper.h"
#include "nsGkAtoms.h" #include "nsGkAtoms.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsGlobalWindow.h"
#include "nsIScriptGlobalObject.h" #include "nsIScriptGlobalObject.h"
#include "nsIScriptContext.h" #include "nsIScriptContext.h"
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"
@ -638,7 +639,7 @@ ScriptLoader::CreateModuleScript(ModuleLoadRequest* aRequest)
MOZ_ASSERT(NS_SUCCEEDED(rv) == (module != nullptr)); MOZ_ASSERT(NS_SUCCEEDED(rv) == (module != nullptr));
RefPtr<ModuleScript> moduleScript = RefPtr<ModuleScript> moduleScript =
new ModuleScript(this, aRequest->mFetchOptions, aRequest->mBaseURL); new ModuleScript(aRequest->mFetchOptions, aRequest->mBaseURL);
aRequest->mModuleScript = moduleScript; aRequest->mModuleScript = moduleScript;
if (!module) { if (!module) {
@ -711,8 +712,7 @@ HandleResolveFailure(JSContext* aCx, ModuleScript* aScript,
} }
static already_AddRefed<nsIURI> static already_AddRefed<nsIURI>
ResolveModuleSpecifier(ModuleScript* aScript, ResolveModuleSpecifier(ScriptLoader* aLoader, LoadedScript* aScript, const nsAString& aSpecifier)
const nsAString& aSpecifier)
{ {
// The following module specifiers are allowed by the spec: // The following module specifiers are allowed by the spec:
// - a valid absolute URL // - a valid absolute URL
@ -737,7 +737,15 @@ ResolveModuleSpecifier(ModuleScript* aScript,
return nullptr; 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)) { if (NS_SUCCEEDED(rv)) {
return uri.forget(); return uri.forget();
} }
@ -776,7 +784,8 @@ ResolveRequestedModules(ModuleLoadRequest* aRequest, nsCOMArray<nsIURI>* aUrlsOu
} }
// Let url be the result of resolving a module specifier given module script and requested. // 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) { if (!uri) {
nsresult rv = HandleResolveFailure(cx, ms, specifier); nsresult rv = HandleResolveFailure(cx, ms, specifier);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -869,34 +878,83 @@ ScriptLoader::StartFetchingModuleAndDependencies(ModuleLoadRequest* aParent,
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);
nsGlobalWindow* window = nsGlobalWindow::Cast(win);
if (!window) {
return nullptr;
}
nsIDocument* document = window->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) // 8.1.3.8.1 HostResolveImportedModule(referencingModule, specifier)
JSObject* JSObject*
HostResolveImportedModule(JSContext* aCx, HostResolveImportedModule(JSContext* aCx,
JS::Handle<JS::Value> aReferencingPrivate, JS::Handle<JS::Value> aReferencingPrivate,
JS::Handle<JSString*> aSpecifier) JS::Handle<JSString*> aSpecifier)
{ {
// Let referencing module script be referencingModule.[[HostDefined]]. JS::Rooted<JSObject*> module(aCx);
if (aReferencingPrivate.isUndefined()) { ScriptLoader::ResolveImportedModule(aCx, aReferencingPrivate, aSpecifier,
JS_ReportErrorNumberUC(aCx, js::GetErrorMessage, nullptr, &module);
JSMSG_IMPORT_SCRIPT_NOT_FOUND); return module;
return nullptr; }
}
auto script = static_cast<ModuleScript*>(aReferencingPrivate.toPrivate()); /* static */ void ScriptLoader::ResolveImportedModule(
MOZ_ASSERT(JS::GetModulePrivate(script->ModuleRecord()) == aReferencingPrivate); 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 // Let url be the result of resolving a module specifier given referencing
// module script and specifier. // module script and specifier.
nsAutoJSString string; nsAutoJSString string;
if (!string.init(aCx, aSpecifier)) { if (!string.init(aCx, aSpecifier)) {
return nullptr; return;
}
if (!script || !aCx) {
// Our module context was ripped out from under us...
return nullptr;
} }
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 // This cannot fail because resolving a module specifier must have been
// previously successful with these same two arguments. // previously successful with these same two arguments.
@ -905,17 +963,13 @@ HostResolveImportedModule(JSContext* aCx,
// Let resolved module script be moduleMap[url]. (This entry must exist for us // Let resolved module script be moduleMap[url]. (This entry must exist for us
// to have gotten to this point.) // 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, "Resolved module not found in module map");
if (!ms) {
// Already-resolved module has been removed from the map/unloaded...
return nullptr;
}
MOZ_ASSERT(!ms->HasParseError()); MOZ_ASSERT(!ms->HasParseError());
MOZ_ASSERT(ms->ModuleRecord()); MOZ_ASSERT(ms->ModuleRecord());
return ms->ModuleRecord(); aModuleOut.set(ms->ModuleRecord());
} }
bool bool
@ -950,15 +1004,7 @@ bool HostImportModuleDynamically(JSContext* aCx,
JS::Handle<JS::Value> aReferencingPrivate, JS::Handle<JS::Value> aReferencingPrivate,
JS::Handle<JSString*> aSpecifier, JS::Handle<JSString*> aSpecifier,
JS::Handle<JSObject*> aPromise) { JS::Handle<JSObject*> aPromise) {
if (aReferencingPrivate.isUndefined()) { RefPtr<LoadedScript> script(GetLoadedScriptOrNull(aCx, aReferencingPrivate));
JS_ReportErrorNumberUC(aCx, js::GetErrorMessage, nullptr,
JSMSG_IMPORT_SCRIPT_NOT_FOUND);
return false;
}
auto script = static_cast<ModuleScript*>(aReferencingPrivate.toPrivate());
MOZ_ASSERT(JS::GetModulePrivate(script->ModuleRecord()) ==
aReferencingPrivate);
// Attempt to resolve the module specifier. // Attempt to resolve the module specifier.
nsAutoJSString string; nsAutoJSString string;
@ -966,7 +1012,12 @@ bool HostImportModuleDynamically(JSContext* aCx,
return false; 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) { if (!uri) {
JS_ReportErrorNumberUC(aCx, js::GetErrorMessage, nullptr, JS_ReportErrorNumberUC(aCx, js::GetErrorMessage, nullptr,
JSMSG_BAD_MODULE_SPECIFIER, string.get()); JSMSG_BAD_MODULE_SPECIFIER, string.get());
@ -974,10 +1025,27 @@ bool HostImportModuleDynamically(JSContext* aCx,
} }
// Create a new top-level load request. // Create a new top-level load request.
RefPtr<ModuleLoadRequest> request = ModuleLoadRequest::CreateDynamicImport( ScriptFetchOptions* options;
uri, script, aReferencingPrivate, aSpecifier, aPromise); 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();
}
script->Loader()->StartDynamicImport(request); RefPtr<ModuleLoadRequest> request = ModuleLoadRequest::CreateDynamicImport(
uri, options, baseURL, loader, aReferencingPrivate, aSpecifier, aPromise);
loader->StartDynamicImport(request);
return true; return true;
} }
@ -1700,7 +1768,8 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
if (request->IsModuleRequest()) { if (request->IsModuleRequest()) {
ModuleLoadRequest* modReq = request->AsModuleRequest(); ModuleLoadRequest* modReq = request->AsModuleRequest();
modReq->mBaseURL = mDocument->GetDocBaseURI();
request->mBaseURL = mDocument->GetDocBaseURI();
if (aElement->GetScriptAsync()) { if (aElement->GetScriptAsync()) {
AddAsyncRequest(modReq); AddAsyncRequest(modReq);
@ -2801,6 +2870,18 @@ ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest,
mParserBlockingRequest == aRequest, mParserBlockingRequest == aRequest,
"aRequest should be pending!"); "aRequest should be pending!");
nsCOMPtr<nsIURI> uri;
rv = channel->GetOriginalURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
// Fixup moz-extension: and resource: URIs, because the channel URI will
// point to file:, which won't be allowed to load.
if (uri && IsInternalURIScheme(uri)) {
aRequest->mBaseURL = uri;
} else {
channel->GetURI(getter_AddRefs(aRequest->mBaseURL));
}
if (aRequest->IsModuleRequest()) { if (aRequest->IsModuleRequest()) {
ModuleLoadRequest* request = aRequest->AsModuleRequest(); ModuleLoadRequest* request = aRequest->AsModuleRequest();
@ -2813,18 +2894,6 @@ ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
nsCOMPtr<nsIURI> uri;
rv = channel->GetOriginalURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
// Fixup internal scheme URIs like resource:, because the channel URI
// will point to file: which won't be allowed to load.
if (uri && IsInternalURIScheme(uri)) {
request->mBaseURL = uri;
} else {
channel->GetURI(getter_AddRefs(request->mBaseURL));
}
// Attempt to compile off main thread. // Attempt to compile off main thread.
rv = AttemptAsyncScriptCompile(request); rv = AttemptAsyncScriptCompile(request);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {

View file

@ -258,6 +258,9 @@ public:
// Holds the top-level JSScript that corresponds to the current source, once // Holds the top-level JSScript that corresponds to the current source, once
// it is parsed, and planned to be saved in the bytecode cache. // it is parsed, and planned to be saved in the bytecode cache.
JS::Heap<JSScript*> mScript; JS::Heap<JSScript*> mScript;
// The base URL used for resolving relative module imports.
nsCOMPtr<nsIURI> mBaseURL;
}; };
class ScriptLoadRequestList : private mozilla::LinkedList<ScriptLoadRequest> class ScriptLoadRequestList : private mozilla::LinkedList<ScriptLoadRequest>
@ -561,11 +564,30 @@ public:
*/ */
void ClearModuleMap(); void ClearModuleMap();
/**
* 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 StartDynamicImport(ModuleLoadRequest* aRequest);
void FinishDynamicImport(ModuleLoadRequest* aRequest, nsresult aResult); void FinishDynamicImport(ModuleLoadRequest* aRequest, nsresult aResult);
void FinishDynamicImport(JSContext* aCx, ModuleLoadRequest* aRequest, void FinishDynamicImport(JSContext* aCx, ModuleLoadRequest* aRequest,
nsresult aResult); nsresult aResult);
nsIDocument* GetDocument() const { return mDocument; }
private: private:
virtual ~ScriptLoader(); virtual ~ScriptLoader();