diff --git a/.eslintignore b/.eslintignore index b11848f7acbd..58f1acb45c7c 100644 --- a/.eslintignore +++ b/.eslintignore @@ -156,6 +156,11 @@ dom/workers/test/importScripts_worker_imported3.js dom/workers/test/invalid.js dom/workers/test/threadErrors_worker1.js +# Tests the module loader's path handling. +# Dynamic imports contains non-optimal paths. +dom/workers/test/xpcshell/data/base_uri_worker.js +dom/workers/test/xpcshell/data/base_uri_module.mjs + # Bug 1527075: This directory is linted in github repository intl/l10n/ diff --git a/dom/quota/test/modules/system/worker/Utils.js b/dom/quota/test/modules/system/worker/Utils.js index ca9b54a92aa3..b8e6224bf4fd 100644 --- a/dom/quota/test/modules/system/worker/Utils.js +++ b/dom/quota/test/modules/system/worker/Utils.js @@ -10,25 +10,11 @@ async function ensureUtilsChild() { return; } - try { - const { UtilsChild: importedUtilsChild } = await import( - "/dom/quota/test/modules/worker/UtilsChild.js" - ); + const { UtilsChild: importedUtilsChild } = await import( + "/dom/quota/test/modules/worker/UtilsChild.mjs" + ); - UtilsChild = importedUtilsChild; - - throw Error("Please switch to dynamic module import"); - } catch (e) { - if (e.message == "Please switch to dynamic module import") { - throw e; - } - - importScripts("/dom/quota/test/modules/worker/UtilsChild.js"); - - const { UtilsChild: importedUtilsChild } = globalThis.importUtilsChild(); - - UtilsChild = importedUtilsChild; - } + UtilsChild = importedUtilsChild; } const Utils = { diff --git a/dom/quota/test/modules/system/worker/UtilsChild.js b/dom/quota/test/modules/system/worker/UtilsChild.mjs similarity index 91% rename from dom/quota/test/modules/system/worker/UtilsChild.js rename to dom/quota/test/modules/system/worker/UtilsChild.mjs index 4addd6b94809..d3b5455a59df 100644 --- a/dom/quota/test/modules/system/worker/UtilsChild.js +++ b/dom/quota/test/modules/system/worker/UtilsChild.mjs @@ -24,7 +24,7 @@ function _recvMessage() { }); } -const _UtilsChild = { +export const UtilsChild = { async getCachedOriginUsage() { _sendMessage({ op: "getCachedOriginUsage", @@ -50,7 +50,3 @@ const _UtilsChild = { return _recvMessage(); }, }; - -function importUtilsChild() { - return { UtilsChild: _UtilsChild }; -} diff --git a/dom/quota/test/moz.build b/dom/quota/test/moz.build index c01a46c55205..4f7fdc88c8cc 100644 --- a/dom/quota/test/moz.build +++ b/dom/quota/test/moz.build @@ -82,5 +82,5 @@ TESTING_JS_MODULES.dom.quota.test.modules.worker += [ "modules/system/worker/head.js", "modules/system/worker/ModuleLoader.js", "modules/system/worker/Utils.js", - "modules/system/worker/UtilsChild.js", + "modules/system/worker/UtilsChild.mjs", ] diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp index 4f1b1558601d..c847b133fde0 100644 --- a/dom/script/ScriptLoader.cpp +++ b/dom/script/ScriptLoader.cpp @@ -3675,11 +3675,6 @@ int32_t ScriptLoader::PhysicalSizeOfMemoryInGB() { return mPhysicalSizeOfMemory; } -static bool IsInternalURIScheme(nsIURI* uri) { - return uri->SchemeIs("moz-extension") || uri->SchemeIs("resource") || - uri->SchemeIs("chrome"); -} - bool ScriptLoader::ShouldApplyDelazifyStrategy(ScriptLoadRequest* aRequest) { // Full parse everything if negative. if (StaticPrefs::dom_script_loader_delazification_max_size() < 0) { @@ -3866,13 +3861,7 @@ nsresult ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest, 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)); - } + aRequest->SetBaseURLFromChannelAndOriginalURI(channel, uri); if (aRequest->IsModuleRequest()) { ModuleLoadRequest* request = aRequest->AsModuleRequest(); diff --git a/dom/workers/loader/NetworkLoadHandler.cpp b/dom/workers/loader/NetworkLoadHandler.cpp index 4157e6e3b9a3..9c2c24306650 100644 --- a/dom/workers/loader/NetworkLoadHandler.cpp +++ b/dom/workers/loader/NetworkLoadHandler.cpp @@ -188,7 +188,7 @@ nsresult NetworkLoadHandler::DataReceivedFromNetwork(nsIStreamLoader* aLoader, rv = channel->GetOriginalURI(getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); - channel->GetURI(getter_AddRefs(loadContext->mRequest->mBaseURL)); + loadContext->mRequest->SetBaseURLFromChannelAndOriginalURI(channel, uri); // Figure out what we actually loaded. nsCOMPtr finalURI; diff --git a/dom/workers/test/xpcshell/data/base_uri_module.mjs b/dom/workers/test/xpcshell/data/base_uri_module.mjs new file mode 100644 index 000000000000..7604baed8227 --- /dev/null +++ b/dom/workers/test/xpcshell/data/base_uri_module.mjs @@ -0,0 +1,23 @@ +// This file is for testing the module loader's path handling. +// ESLint rules that modifies path shouldn't be applied. + +export const obj = {}; + +export async function doImport() { + // This file is loaded as resource://test/data/base_uri_module.mjs + // Relative/absolute paths should be resolved based on the URI, instead of + // file: path. + + const namespaceWithURI = await import( + "resource://test/data/base_uri_module2.mjs" + ); + const namespaceWithCurrentDir = await import("./base_uri_module2.mjs"); + const namespaceWithParentDir = await import("../data/base_uri_module2.mjs"); + const namespaceWithAbsoluteDir = await import("/data/base_uri_module2.mjs"); + + return { + equal1: namespaceWithURI.obj2 == namespaceWithCurrentDir.obj2, + equal2: namespaceWithURI.obj2 == namespaceWithParentDir.obj2, + equal3: namespaceWithURI.obj2 == namespaceWithAbsoluteDir.obj2, + }; +} diff --git a/dom/workers/test/xpcshell/data/base_uri_module2.mjs b/dom/workers/test/xpcshell/data/base_uri_module2.mjs new file mode 100644 index 000000000000..2358d27a8360 --- /dev/null +++ b/dom/workers/test/xpcshell/data/base_uri_module2.mjs @@ -0,0 +1 @@ +export const obj2 = {}; diff --git a/dom/workers/test/xpcshell/data/base_uri_worker.js b/dom/workers/test/xpcshell/data/base_uri_worker.js new file mode 100644 index 000000000000..74137cc20b71 --- /dev/null +++ b/dom/workers/test/xpcshell/data/base_uri_worker.js @@ -0,0 +1,27 @@ +// This file is for testing the module loader's path handling. +// ESLint rules that modifies path shouldn't be applied. + +onmessage = async event => { + // This file is loaded as resource://test/data/base_uri_worker.js + // Relative/absolute paths should be resolved based on the URI, instead of + // file: path. + + const namespaceWithURI = await import( + "resource://test/data/base_uri_module.mjs" + ); + const namespaceWithCurrentDir = await import("./base_uri_module.mjs"); + const namespaceWithParentDir = await import("../data/base_uri_module.mjs"); + const namespaceWithAbsoluteDir = await import("/data/base_uri_module.mjs"); + + postMessage({ + scriptToModule: { + equal1: namespaceWithURI.obj == namespaceWithCurrentDir.obj, + equal2: namespaceWithURI.obj == namespaceWithParentDir.obj, + equal3: namespaceWithURI.obj == namespaceWithAbsoluteDir.obj, + }, + moduleToModuleURI: await namespaceWithURI.doImport(), + moduleToModuleCurrent: await namespaceWithCurrentDir.doImport(), + moduleToModuleParent: await namespaceWithParentDir.doImport(), + moduleToModuleAbsolute: await namespaceWithAbsoluteDir.doImport(), + }); +}; diff --git a/dom/workers/test/xpcshell/test_import_base_uri.js b/dom/workers/test/xpcshell/test_import_base_uri.js new file mode 100644 index 000000000000..7c88a946f4e2 --- /dev/null +++ b/dom/workers/test/xpcshell/test_import_base_uri.js @@ -0,0 +1,35 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(async function testSyncImportBeforeAsyncImportDependencyInWorker() { + const worker = new ChromeWorker("resource://test/data/base_uri_worker.js"); + + const { promise, resolve } = Promise.withResolvers(); + worker.onmessage = event => { + resolve(event.data); + }; + worker.postMessage(""); + + const result = await promise; + + Assert.ok(result.scriptToModule.equal1); + Assert.ok(result.scriptToModule.equal2); + Assert.ok(result.scriptToModule.equal3); + + Assert.ok(result.moduleToModuleURI.equal1); + Assert.ok(result.moduleToModuleURI.equal2); + Assert.ok(result.moduleToModuleURI.equal3); + + Assert.ok(result.moduleToModuleCurrent.equal1); + Assert.ok(result.moduleToModuleCurrent.equal2); + Assert.ok(result.moduleToModuleCurrent.equal3); + + Assert.ok(result.moduleToModuleParent.equal1); + Assert.ok(result.moduleToModuleParent.equal2); + Assert.ok(result.moduleToModuleParent.equal3); + + Assert.ok(result.moduleToModuleAbsolute.equal1); + Assert.ok(result.moduleToModuleAbsolute.equal2); + Assert.ok(result.moduleToModuleAbsolute.equal3); +}); diff --git a/dom/workers/test/xpcshell/xpcshell.toml b/dom/workers/test/xpcshell/xpcshell.toml index f8b171b89a4e..61b1eef0c25b 100644 --- a/dom/workers/test/xpcshell/xpcshell.toml +++ b/dom/workers/test/xpcshell/xpcshell.toml @@ -4,6 +4,9 @@ support-files = [ "data/worker.js", "data/worker_fileReader.js", "data/chrome.manifest", + "data/base_uri_worker.js", + "data/base_uri_module.mjs", + "data/base_uri_module2.mjs", ] ["test_ext_redirects_sw_scripts.js"] @@ -18,6 +21,8 @@ firefox-appdir = "browser" ["test_fileReader.js"] +["test_import_base_uri.js"] + ["test_remoteworker_launch_new_process.js"] # The following firefox-appdir make sure that this xpcshell test will run # with e10s enabled (which is needed to make sure that the test case is diff --git a/js/loader/ScriptLoadRequest.cpp b/js/loader/ScriptLoadRequest.cpp index 1b3cb52f7206..2c9a7ce8ae4e 100644 --- a/js/loader/ScriptLoadRequest.cpp +++ b/js/loader/ScriptLoadRequest.cpp @@ -197,6 +197,22 @@ bool ScriptLoadRequest::IsMarkedForBytecodeEncoding() const { return !!mScriptForBytecodeEncoding; } +static bool IsInternalURIScheme(nsIURI* uri) { + return uri->SchemeIs("moz-extension") || uri->SchemeIs("resource") || + uri->SchemeIs("chrome"); +} + +void ScriptLoadRequest::SetBaseURLFromChannelAndOriginalURI( + nsIChannel* aChannel, nsIURI* aOriginalURI) { + // Fixup moz-extension: and resource: URIs, because the channel URI will + // point to file:, which won't be allowed to load. + if (aOriginalURI && IsInternalURIScheme(aOriginalURI)) { + mBaseURL = aOriginalURI; + } else { + aChannel->GetURI(getter_AddRefs(mBaseURL)); + } +} + ////////////////////////////////////////////////////////////// // ScriptLoadRequestList ////////////////////////////////////////////////////////////// diff --git a/js/loader/ScriptLoadRequest.h b/js/loader/ScriptLoadRequest.h index ce19c94978d7..ea1467134c5c 100644 --- a/js/loader/ScriptLoadRequest.h +++ b/js/loader/ScriptLoadRequest.h @@ -203,6 +203,13 @@ class ScriptLoadRequest : public nsISupports, const LoadedScript* getLoadedScript() const { return mLoadedScript.get(); } LoadedScript* getLoadedScript() { return mLoadedScript.get(); } + /* + * Set the request's mBaseURL, based on aChannel. + * aOriginalURI is the result of aChannel->GetOriginalURI. + */ + void SetBaseURLFromChannelAndOriginalURI(nsIChannel* aChannel, + nsIURI* aOriginalURI); + const ScriptKind mKind; // Whether this is a classic script or a module // script.