Backed out 9 changesets (bug 1688879) for bustages on ImportMap.cpp
Backed out changeset 44e9abe72a5e (bug 1688879) Backed out changeset 0503d2d2ae01 (bug 1688879) Backed out changeset 2cf08a51b184 (bug 1688879) Backed out changeset 6f0276c3ab0e (bug 1688879) Backed out changeset f16b14d8f677 (bug 1688879) Backed out changeset 03b772e02d07 (bug 1688879) Backed out changeset 39ed48a5ecc2 (bug 1688879) Backed out changeset d7b42d8312bb (bug 1688879) Backed out changeset 5e695bf5dd0d (bug 1688879)
This commit is contained in:
@@ -17539,11 +17539,6 @@ bool Document::ModuleScriptsEnabled() {
|
||||
StaticPrefs::dom_moduleScripts_enabled();
|
||||
}
|
||||
|
||||
bool Document::ImportMapsEnabled() {
|
||||
return nsContentUtils::IsChromeDoc(this) ||
|
||||
StaticPrefs::dom_importMaps_enabled();
|
||||
}
|
||||
|
||||
void Document::ReportShadowDOMUsage() {
|
||||
nsPIDOMWindowInner* inner = GetInnerWindow();
|
||||
if (NS_WARN_IF(!inner)) {
|
||||
|
||||
@@ -3986,8 +3986,6 @@ class Document : public nsINode,
|
||||
|
||||
bool ModuleScriptsEnabled();
|
||||
|
||||
bool ImportMapsEnabled();
|
||||
|
||||
/**
|
||||
* Find the (non-anonymous) content in this document for aFrame. It will
|
||||
* be aFrame's content node if that content is in this document and not
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
external_importMap.js
|
||||
module_setRan.js
|
||||
module_testSyntax.js
|
||||
module_badSyntax.js
|
||||
module_simpleImport.js
|
||||
module_simpleImportMap.js
|
||||
module_simpleImportMap_dir.js
|
||||
module_simpleImportMap_remap.js
|
||||
module_simpleImportMap_remap_https.js
|
||||
module_simpleExport.js
|
||||
module_sortedImportMap.js
|
||||
module_badImport.js
|
||||
module_simple1.js
|
||||
module_simple2.js
|
||||
@@ -20,10 +14,6 @@ support-files =
|
||||
module_cyclic3.js
|
||||
module_multiImports.js
|
||||
module_multiLargeImports.js
|
||||
scope1/module_simpleExport.js
|
||||
scope1/module_simpleImportMap.js
|
||||
scope1/scope2/module_simpleExport.js
|
||||
scope1/scope2/module_simpleImportMap.js
|
||||
script_simple2.js
|
||||
module_large1.js
|
||||
module_large2.js
|
||||
@@ -32,7 +22,6 @@ support-files =
|
||||
iframe_extractIntroType.html
|
||||
module_missingImport.js
|
||||
|
||||
[test_externalImportMap.html]
|
||||
[test_moduleScriptsRun.html]
|
||||
[test_moduleParsedAsModule.html]
|
||||
[test_scriptNotParsedAsModule.html]
|
||||
@@ -44,8 +33,6 @@ support-files =
|
||||
[test_syntaxErrorInline.html]
|
||||
[test_syntaxErrorInlineAsync.html]
|
||||
[test_simpleImport.html]
|
||||
[test_simpleImportMap.html]
|
||||
[test_sortedImportMap.html]
|
||||
[test_cyclicImport.html]
|
||||
[test_importResolveFailed.html]
|
||||
[test_multiTopLevelImports.html]
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
let imap = {
|
||||
imports: {
|
||||
foo: "./foo.js",
|
||||
},
|
||||
};
|
||||
@@ -1,2 +0,0 @@
|
||||
import { x } from "simple";
|
||||
result = x;
|
||||
@@ -1,2 +0,0 @@
|
||||
import { x } from "dir/module_simpleExport.js";
|
||||
result_dir = x + 1;
|
||||
@@ -1,2 +0,0 @@
|
||||
import { x } from "./module.js";
|
||||
result_remap = x + 2;
|
||||
@@ -1,2 +0,0 @@
|
||||
import { x } from "https://example.com/module.js";
|
||||
result_remap_https = x + 3;
|
||||
@@ -1,4 +0,0 @@
|
||||
import { x } from "scope1/scope2/module_simpleExport.js";
|
||||
import { x as y } from "scope1/scope2/scope3/scope4/module_simpleExport.js";
|
||||
sorted_result = x;
|
||||
sorted_result2 = y;
|
||||
@@ -1 +0,0 @@
|
||||
export let x = 84;
|
||||
@@ -1,2 +0,0 @@
|
||||
import { x } from "simple";
|
||||
result_scope1 = x;
|
||||
@@ -1 +0,0 @@
|
||||
export let x = 126;
|
||||
@@ -1,2 +0,0 @@
|
||||
import { x } from "simple";
|
||||
result_scope2 = x;
|
||||
@@ -1,23 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Test an external import map</title>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<!--Import maps spec doesn't clearly define the format of an external import map script.-->
|
||||
<script src="external_importMap.js" type="importmap" onload="scriptLoaded()" onerror="scriptError()"></script>
|
||||
|
||||
<script>
|
||||
function testLoaded() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function scriptLoaded() {
|
||||
ok(false, "Loading external import map script should have failed.");
|
||||
}
|
||||
|
||||
function scriptError() {
|
||||
ok(true, "Loading external import map script failed.");
|
||||
}
|
||||
</script>
|
||||
<body onload='testLoaded()'></body>
|
||||
@@ -1,62 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Test a simple import map</title>
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"simple": "./module_simpleExport.js",
|
||||
"dir/": "/content/chrome/dom/base/test/jsmodules/",
|
||||
"./module.js": "/content/chrome/dom/base/test/jsmodules/module_simpleExport.js",
|
||||
"https://example.com/module.js": "./module_simpleExport.js"
|
||||
},
|
||||
"scopes": {
|
||||
"chrome://mochitests/content/chrome/dom/base/test/jsmodules/scope1/": {
|
||||
"simple": "/content/chrome/dom/base/test/jsmodules/scope1/module_simpleExport.js"
|
||||
},
|
||||
"chrome://mochitests/content/chrome/dom/base/test/jsmodules/scope1/scope2/": {
|
||||
"simple": "/content/chrome/dom/base/test/jsmodules/scope1/scope2/module_simpleExport.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script>
|
||||
var result, result_dir, result_remap, result_remap_https;
|
||||
var result_scope1, result_scope2;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function testLoaded() {
|
||||
ok(result == 42, 'Check imported value result: ' + result);
|
||||
ok(result_dir == 43, 'Check imported value result_dir: ' + result_dir);
|
||||
ok(result_remap == 44, 'Check imported value result_remap: ' + result_remap);
|
||||
ok(result_remap_https == 45,
|
||||
'Check imported value result_remap_https: ' + result_remap_https);
|
||||
ok(result_scope1 == 84, 'Check imported value result_scope1: ' + result_scope1);
|
||||
ok(result_scope2 == 126, 'Check imported value result_scope2: ' + result_scope2);
|
||||
|
||||
import("simple").then((ns) => {
|
||||
ok(ns.x == 42, 'Check simple imported value result: ' + ns.x);
|
||||
return import("dir/module_simpleExport.js");
|
||||
}).then((ns) => {
|
||||
ok(ns.x == 42, 'Check dir imported value result: ' + ns.x);
|
||||
return import("./module.js");
|
||||
}).then((ns) => {
|
||||
ok(ns.x == 42, 'Check remap imported value result: ' + ns.x);
|
||||
return import("https://example.com/module.js");
|
||||
}).then((ns) => {
|
||||
ok(ns.x == 42, 'Check remap https imported value result: ' + ns.x);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<script type="module" src="module_simpleImportMap.js"></script>
|
||||
<script type="module" src="module_simpleImportMap_dir.js"></script>
|
||||
<script type="module" src="module_simpleImportMap_remap.js"></script>
|
||||
<script type="module" src="module_simpleImportMap_remap_https.js"></script>
|
||||
<script type="module" src="module_simpleImportMap_remap_https.js"></script>
|
||||
<script type="module" src="scope1/module_simpleImportMap.js"></script>
|
||||
<script type="module" src="scope1/scope2/module_simpleImportMap.js"></script>
|
||||
<body onload='testLoaded()'></body>
|
||||
@@ -1,62 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Test a sorted import map</title>
|
||||
|
||||
<!--
|
||||
According to Import maps spec, the entries in "imports" and "scopes" need to be
|
||||
sorted. Key with longest prefix should be chosen. So "a/b/" should take
|
||||
precendence over "a/".
|
||||
This test is verifying that requirement.
|
||||
|
||||
In "imports" below, "scope1/scope2/" and "scope1/scope2/scope3/scope4/" should
|
||||
be chosen over "scope1" and "scope1/scope2/scop3/" respectively.
|
||||
Also "scope1/scope2/" is listed _after_ "scope1/ and
|
||||
"scope1/scope2/scope3/scope4" is listed _before_ "scope1/scope2/scope3/" to make
|
||||
sure the map is sorted.
|
||||
|
||||
For "scopes" below, the "scope1/" is listed before "scope1/scope2/" in
|
||||
test_simpleImportMap.html, here we reverse the order, for example, we list
|
||||
"scope1/" after "scope1/scope2/" in this test.
|
||||
|
||||
See:
|
||||
https://wicg.github.io/import-maps/#sort-and-normalize-a-specifier-map, Step 3.
|
||||
https://wicg.github.io/import-maps/#sort-and-normalize-scopes, Step 3.
|
||||
-->
|
||||
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"scope1/": "/content/chrome/dom/base/test/jsmodules/",
|
||||
"scope1/scope2/": "/content/chrome/dom/base/test/jsmodules/scope1/scope2/",
|
||||
"scope1/scope2/scope3/scope4/": "/content/chrome/dom/base/test/jsmodules/scope1/scope2/",
|
||||
"scope1/scope2/scope3/": "/content/chrome/dom/base/test/jsmodules/"
|
||||
},
|
||||
"scopes": {
|
||||
"chrome://mochitests/content/chrome/dom/base/test/jsmodules/scope1/scope2/": {
|
||||
"simple": "/content/chrome/dom/base/test/jsmodules/scope1/scope2/module_simpleExport.js"
|
||||
},
|
||||
"chrome://mochitests/content/chrome/dom/base/test/jsmodules/scope1/": {
|
||||
"simple": "/content/chrome/dom/base/test/jsmodules/scope1/module_simpleExport.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script>
|
||||
var sorted_result, sorted_result2;
|
||||
var result_scope2;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function testLoaded() {
|
||||
ok(sorted_result == 126, 'Check imported value sorted_result: ' + sorted_result);
|
||||
ok(sorted_result2 == 126, 'Check imported value sorted_result: ' + sorted_result2);
|
||||
ok(result_scope2 == 126, 'Check imported value result_scope2: ' + result_scope2);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
<script type="module" src="module_sortedImportMap.js"></script>
|
||||
<script type="module" src="scope1/scope2/module_simpleImportMap.js"></script>
|
||||
<body onload='testLoaded()'></body>
|
||||
@@ -20,12 +20,9 @@
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "mozilla/dom/HTMLScriptElement.h"
|
||||
#include "mozilla/dom/HTMLScriptElementBinding.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
|
||||
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Script)
|
||||
|
||||
using JS::loader::ScriptKind;
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
JSObject* HTMLScriptElement::WrapNode(JSContext* aCx,
|
||||
@@ -170,27 +167,13 @@ void HTMLScriptElement::FreezeExecutionAttrs(Document* aOwnerDoc) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT((mKind != ScriptKind::eModule) &&
|
||||
(mKind != ScriptKind::eImportMap) && !mAsync && !mDefer &&
|
||||
!mExternal);
|
||||
MOZ_ASSERT(!mIsModule && !mAsync && !mDefer && !mExternal);
|
||||
|
||||
// Determine whether this is a(n) classic/module/importmap script.
|
||||
// Determine whether this is a classic script or a module script.
|
||||
nsAutoString type;
|
||||
GetScriptType(type);
|
||||
if (!type.IsEmpty()) {
|
||||
if (aOwnerDoc->ModuleScriptsEnabled() &&
|
||||
type.LowerCaseEqualsASCII("module")) {
|
||||
mKind = ScriptKind::eModule;
|
||||
}
|
||||
|
||||
// https://wicg.github.io/import-maps/#integration-prepare-a-script
|
||||
// If the script block’s type string is an ASCII case-insensitive match
|
||||
// for the string "importmap", the script’s type is "importmap".
|
||||
if (aOwnerDoc->ImportMapsEnabled() &&
|
||||
type.LowerCaseEqualsASCII("importmap")) {
|
||||
mKind = ScriptKind::eImportMap;
|
||||
}
|
||||
}
|
||||
mIsModule = aOwnerDoc->ModuleScriptsEnabled() && !type.IsEmpty() &&
|
||||
type.LowerCaseEqualsASCII("module");
|
||||
|
||||
// variation of this code in SVGScriptElement - check if changes
|
||||
// need to be transfered when modifying. Note that we don't use GetSrc here
|
||||
@@ -223,7 +206,7 @@ void HTMLScriptElement::FreezeExecutionAttrs(Document* aOwnerDoc) {
|
||||
mExternal = true;
|
||||
}
|
||||
|
||||
bool async = (mExternal || mKind == ScriptKind::eModule) && Async();
|
||||
bool async = (mExternal || mIsModule) && Async();
|
||||
bool defer = mExternal && Defer();
|
||||
|
||||
mDefer = !async && defer;
|
||||
@@ -249,10 +232,7 @@ bool HTMLScriptElement::HasScriptContent() {
|
||||
/* static */
|
||||
bool HTMLScriptElement::Supports(const GlobalObject& aGlobal,
|
||||
const nsAString& aType) {
|
||||
nsAutoString type(aType);
|
||||
return aType.EqualsLiteral("classic") || aType.EqualsLiteral("module") ||
|
||||
(StaticPrefs::dom_importMaps_enabled() &&
|
||||
aType.EqualsLiteral("importmap"));
|
||||
return aType.EqualsLiteral("classic") || aType.EqualsLiteral("module");
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
@@ -323,17 +323,6 @@ ScriptSourceNotAllowed=<script> source URI is not allowed in this document: “%
|
||||
ModuleSourceNotAllowed=Module source URI is not allowed in this document: “%S”.
|
||||
WebExtContentScriptModuleSourceNotAllowed=WebExtension content scripts may only load modules with moz-extension URLs and not: “%S”.
|
||||
ModuleResolveFailure=Error resolving module specifier “%S”. Relative module specifiers must start with “./”, “../” or “/”.
|
||||
ImportMapInvalidTopLevelKey=An invalid top-level key “%S” was present in the import map.
|
||||
ImportMapEmptySpecifierKeys=Specifier keys cannot be empty strings.
|
||||
ImportMapAddressesNotStrings=Addresses need to be strings.
|
||||
ImportMapInvalidAddress=Address “%S” was invalid.
|
||||
# %1$S is the specifier key, %2$S is the URL.
|
||||
ImportMapAddressNotEndsWithSlash=An invalid address was given for the specifier key “%1$S”; since “%1$S” ended in a slash, the address “%2$S” needs to as well.
|
||||
ImportMapScopePrefixNotParseable=The scope prefix URL “%S” was not parseable.
|
||||
ImportMapResolutionBlockedByNullEntry=Resolution of specifier “%S” was blocked by a null entry.
|
||||
ImportMapResolutionBlockedByAfterPrefix=Resolution of specifier “%S” was blocked since the substring after prefix could not be parsed as a URL relative to the address in the import map.
|
||||
ImportMapResolutionBlockedByBacktrackingPrefix=Resolution of specifier “%S” was blocked since the parsed URL does not start with the address in the import map.
|
||||
ImportMapResolveInvalidBareSpecifier=The specifier “%S” was a bare specifier, but was not remapped to anything.
|
||||
# LOCALIZATION NOTE: %1$S is the invalid property value and %2$S is the property name.
|
||||
InvalidKeyframePropertyValue=Keyframe property value “%1$S” is invalid according to the syntax for “%2$S”.
|
||||
# LOCALIZATION NOTE: Do not translate "ReadableStream".
|
||||
|
||||
@@ -113,17 +113,6 @@ nsresult ModuleLoader::StartFetch(ModuleLoadRequest* aRequest) {
|
||||
nsresult rv = GetScriptLoader()->StartLoadInternal(aRequest, securityFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// https://wicg.github.io/import-maps/#document-acquiring-import-maps
|
||||
//
|
||||
// An import map is accepted if and only if it is added (i.e., its
|
||||
// corresponding script element is added) before the first module load is
|
||||
// started, even if the loading of the import map file doesn’t finish before
|
||||
// the first module load is started.
|
||||
if (!aRequest->GetScriptLoadContext()->IsPreload()) {
|
||||
LOG(("ScriptLoadRequest (%p): SetAcquiringImportMaps false", aRequest));
|
||||
SetAcquiringImportMaps(false);
|
||||
}
|
||||
|
||||
LOG(("ScriptLoadRequest (%p): Start fetching module", aRequest));
|
||||
|
||||
return NS_OK;
|
||||
|
||||
@@ -822,7 +822,7 @@ already_AddRefed<ScriptLoadRequest> ScriptLoader::CreateLoadRequest(
|
||||
aCORSMode, aReferrerPolicy, aTriggeringPrincipal, domElement);
|
||||
RefPtr<ScriptLoadContext> context = new ScriptLoadContext();
|
||||
|
||||
if (aKind == ScriptKind::eClassic || aKind == ScriptKind::eImportMap) {
|
||||
if (aKind == ScriptKind::eClassic) {
|
||||
RefPtr<ScriptLoadRequest> aRequest = new ScriptLoadRequest(
|
||||
aKind, aURI, fetchOptions, aIntegrity, referrer, context);
|
||||
|
||||
@@ -851,14 +851,8 @@ bool ScriptLoader::ProcessScriptElement(nsIScriptElement* aElement) {
|
||||
nsAutoString type;
|
||||
bool hasType = aElement->GetScriptType(type);
|
||||
|
||||
ScriptKind scriptKind;
|
||||
if (aElement->GetScriptIsModule()) {
|
||||
scriptKind = ScriptKind::eModule;
|
||||
} else if (aElement->GetScriptIsImportMap()) {
|
||||
scriptKind = ScriptKind::eImportMap;
|
||||
} else {
|
||||
scriptKind = ScriptKind::eClassic;
|
||||
}
|
||||
ScriptKind scriptKind = aElement->GetScriptIsModule() ? ScriptKind::eModule
|
||||
: ScriptKind::eClassic;
|
||||
|
||||
// Step 13. Check that the script is not an eventhandler
|
||||
if (IsScriptEventHandler(scriptKind, scriptContent)) {
|
||||
@@ -913,14 +907,6 @@ bool ScriptLoader::ProcessExternalScript(nsIScriptElement* aElement,
|
||||
LOG(("ScriptLoader (%p): Process external script for element %p", this,
|
||||
aElement));
|
||||
|
||||
// Bug 1765745: Support external import maps.
|
||||
if (aScriptKind == ScriptKind::eImportMap) {
|
||||
NS_DispatchToCurrentThread(
|
||||
NewRunnableMethod("nsIScriptElement::FireErrorEvent", aElement,
|
||||
&nsIScriptElement::FireErrorEvent));
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI();
|
||||
if (!scriptURI) {
|
||||
// Asynchronously report the failure to create a URI object
|
||||
@@ -957,15 +943,6 @@ bool ScriptLoader::ProcessExternalScript(nsIScriptElement* aElement,
|
||||
|
||||
LOG(("ScriptLoadRequest (%p): Using preload request", request.get()));
|
||||
|
||||
// https://wicg.github.io/import-maps/#document-acquiring-import-maps
|
||||
// If this preload request is for a module load, set acquiring import maps
|
||||
// to false.
|
||||
if (request->IsModuleRequest()) {
|
||||
LOG(("ScriptLoadRequest (%p): Set acquiring import maps to false",
|
||||
request.get()));
|
||||
mModuleLoader->SetAcquiringImportMaps(false);
|
||||
}
|
||||
|
||||
// It's possible these attributes changed since we started the preload so
|
||||
// update them here.
|
||||
request->GetScriptLoadContext()->SetScriptMode(
|
||||
@@ -1183,46 +1160,6 @@ bool ScriptLoader::ProcessInlineScript(nsIScriptElement* aElement,
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request->IsImportMapRequest()) {
|
||||
// https://wicg.github.io/import-maps/#integration-prepare-a-script
|
||||
// If the script's type is "importmap":
|
||||
//
|
||||
// Step 1: If the element's node document's acquiring import maps is false,
|
||||
// then queue a task to fire an event named error at the element, and
|
||||
// return.
|
||||
if (!mModuleLoader->GetAcquiringImportMaps()) {
|
||||
NS_WARNING("ScriptLoader: acquiring import maps is false.");
|
||||
NS_DispatchToCurrentThread(
|
||||
NewRunnableMethod("nsIScriptElement::FireErrorEvent", aElement,
|
||||
&nsIScriptElement::FireErrorEvent));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 2: Set the element's node document's acquiring import maps to false.
|
||||
mModuleLoader->SetAcquiringImportMaps(false);
|
||||
|
||||
UniquePtr<ImportMap> importMap = mModuleLoader->ParseImportMap(request);
|
||||
|
||||
// https://wicg.github.io/import-maps/#register-an-import-map
|
||||
//
|
||||
// Step 1. If element’s the script’s result is null, then fire an event
|
||||
// named error at element, and return.
|
||||
if (!importMap) {
|
||||
NS_DispatchToCurrentThread(
|
||||
NewRunnableMethod("nsIScriptElement::FireErrorEvent", aElement,
|
||||
&nsIScriptElement::FireErrorEvent));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3. Assert: element’s the script’s type is "importmap".
|
||||
MOZ_ASSERT(aElement->GetScriptIsImportMap());
|
||||
|
||||
// Step 4 to step 9 is done in RegisterImportMap.
|
||||
mModuleLoader->RegisterImportMap(std::move(importMap));
|
||||
return false;
|
||||
}
|
||||
|
||||
request->mState = ScriptLoadRequest::State::Ready;
|
||||
if (aElement->GetParserCreated() == FROM_PARSER_XSLT &&
|
||||
(!ReadyToExecuteParserBlockingScripts() || !mXSLTRequests.isEmpty())) {
|
||||
@@ -2181,12 +2118,6 @@ nsresult ScriptLoader::EvaluateScriptElement(ScriptLoadRequest* aRequest) {
|
||||
setProcessingScriptTag.emplace(context);
|
||||
}
|
||||
|
||||
// https://wicg.github.io/import-maps/#integration-script-type
|
||||
// Switch on the script's type for scriptElement:
|
||||
// "importmap"
|
||||
// Assert: Never reached.
|
||||
MOZ_ASSERT(!aRequest->IsImportMapRequest());
|
||||
|
||||
if (aRequest->IsModuleRequest()) {
|
||||
return aRequest->AsModuleRequest()->EvaluateModule();
|
||||
}
|
||||
@@ -3057,19 +2988,6 @@ void ScriptLoader::ReportErrorToConsole(ScriptLoadRequest* aRequest,
|
||||
params, nullptr, u""_ns, lineNo, columnNo);
|
||||
}
|
||||
|
||||
void ScriptLoader::ReportWarningToConsole(
|
||||
ScriptLoadRequest* aRequest, const char* aMessageName,
|
||||
const nsTArray<nsString>& aParams) const {
|
||||
nsIScriptElement* element =
|
||||
aRequest->GetScriptLoadContext()->GetScriptElement();
|
||||
uint32_t lineNo = element ? element->GetScriptLineNumber() : 0;
|
||||
uint32_t columnNo = element ? element->GetScriptColumnNumber() : 0;
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
"Script Loader"_ns, mDocument,
|
||||
nsContentUtils::eDOM_PROPERTIES, aMessageName,
|
||||
aParams, nullptr, u""_ns, lineNo, columnNo);
|
||||
}
|
||||
|
||||
void ScriptLoader::ReportPreloadErrorsToConsole(ScriptLoadRequest* aRequest) {
|
||||
if (NS_FAILED(aRequest->GetScriptLoadContext()->mUnreportedPreloadError)) {
|
||||
ReportErrorToConsole(
|
||||
|
||||
@@ -551,11 +551,6 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface {
|
||||
|
||||
void ReportErrorToConsole(ScriptLoadRequest* aRequest,
|
||||
nsresult aResult) const override;
|
||||
|
||||
void ReportWarningToConsole(
|
||||
ScriptLoadRequest* aRequest, const char* aMessageName,
|
||||
const nsTArray<nsString>& aParams = nsTArray<nsString>()) const override;
|
||||
|
||||
void ReportPreloadErrorsToConsole(ScriptLoadRequest* aRequest);
|
||||
|
||||
nsresult AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest,
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#ifndef nsIScriptElement_h___
|
||||
#define nsIScriptElement_h___
|
||||
|
||||
#include "js/loader/ScriptKind.h"
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/CORSMode.h"
|
||||
@@ -56,10 +55,10 @@ class nsIScriptElement : public nsIScriptLoaderObserver {
|
||||
mForceAsync(aFromParser == mozilla::dom::NOT_FROM_PARSER ||
|
||||
aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT),
|
||||
mFrozen(false),
|
||||
mIsModule(false),
|
||||
mDefer(false),
|
||||
mAsync(false),
|
||||
mExternal(false),
|
||||
mKind(JS::loader::ScriptKind::eClassic),
|
||||
mParserCreated(aFromParser == mozilla::dom::FROM_PARSER_FRAGMENT
|
||||
? mozilla::dom::NOT_FROM_PARSER
|
||||
: aFromParser),
|
||||
@@ -99,7 +98,6 @@ class nsIScriptElement : public nsIScriptLoaderObserver {
|
||||
* Freezes the return values of the following methods so that subsequent
|
||||
* modifications to the attributes don't change execution behavior:
|
||||
* - GetScriptIsModule()
|
||||
* - GetScriptIsImportMap()
|
||||
* - GetScriptDeferred()
|
||||
* - GetScriptAsync()
|
||||
* - GetScriptURI()
|
||||
@@ -112,15 +110,7 @@ class nsIScriptElement : public nsIScriptLoaderObserver {
|
||||
*/
|
||||
bool GetScriptIsModule() {
|
||||
MOZ_ASSERT(mFrozen, "Not ready for this call yet!");
|
||||
return mKind == JS::loader::ScriptKind::eModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the script an import map. Currently only supported by HTML scripts.
|
||||
*/
|
||||
bool GetScriptIsImportMap() {
|
||||
MOZ_ASSERT(mFrozen, "Not ready for this call yet!");
|
||||
return mKind == JS::loader::ScriptKind::eImportMap;
|
||||
return mIsModule;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,10 +166,10 @@ class nsIScriptElement : public nsIScriptLoaderObserver {
|
||||
|
||||
// Reset state set by FreezeExecutionAttrs().
|
||||
mFrozen = false;
|
||||
mIsModule = false;
|
||||
mExternal = false;
|
||||
mAsync = false;
|
||||
mDefer = false;
|
||||
mKind = JS::loader::ScriptKind::eClassic;
|
||||
}
|
||||
|
||||
void SetCreatorParser(nsIParser* aParser);
|
||||
@@ -306,6 +296,11 @@ class nsIScriptElement : public nsIScriptLoaderObserver {
|
||||
*/
|
||||
bool mFrozen;
|
||||
|
||||
/**
|
||||
* The effective moduleness.
|
||||
*/
|
||||
bool mIsModule;
|
||||
|
||||
/**
|
||||
* The effective deferredness.
|
||||
*/
|
||||
@@ -322,11 +317,6 @@ class nsIScriptElement : public nsIScriptLoaderObserver {
|
||||
*/
|
||||
bool mExternal;
|
||||
|
||||
/**
|
||||
* The effective script kind.
|
||||
*/
|
||||
JS::loader::ScriptKind mKind;
|
||||
|
||||
/**
|
||||
* Whether this element was parser-created.
|
||||
*/
|
||||
|
||||
@@ -1,663 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "ImportMap.h"
|
||||
|
||||
#include "js/Array.h" // IsArrayObject
|
||||
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
||||
#include "js/JSON.h" // JS_ParseJSON
|
||||
#include "LoadedScript.h"
|
||||
#include "ModuleLoaderBase.h" // ScriptLoaderInterface
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIScriptElement.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsJSUtils.h" // nsAutoJSString
|
||||
#include "nsNetUtil.h" // NS_NewURI
|
||||
#include "ScriptLoadRequest.h"
|
||||
|
||||
using JS::SourceText;
|
||||
using mozilla::Err;
|
||||
using mozilla::LazyLogModule;
|
||||
using mozilla::MakeUnique;
|
||||
using mozilla::UniquePtr;
|
||||
using mozilla::WrapNotNull;
|
||||
|
||||
namespace JS::loader {
|
||||
|
||||
LazyLogModule ImportMap::gImportMapLog("ImportMap");
|
||||
|
||||
#undef LOG
|
||||
#define LOG(args) \
|
||||
MOZ_LOG(ImportMap::gImportMapLog, mozilla::LogLevel::Debug, args)
|
||||
|
||||
#define LOG_ENABLED() \
|
||||
MOZ_LOG_TEST(ImportMap::gImportMapLog, mozilla::LogLevel::Debug)
|
||||
|
||||
void ReportWarningHelper::Report(const char* aMessageName,
|
||||
const nsTArray<nsString>& aParams) const {
|
||||
mLoader->ReportWarningToConsole(mRequest, aMessageName, aParams);
|
||||
}
|
||||
|
||||
// https://wicg.github.io/import-maps/#parse-a-url-like-import-specifier
|
||||
static already_AddRefed<nsIURI> ParseURLLikeImportSpecifier(
|
||||
const nsAString& aSpecifier, nsIURI* aBaseURL) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv;
|
||||
|
||||
// Step 1. If specifier starts with "/", "./", or "../", then:
|
||||
if (StringBeginsWith(aSpecifier, u"/"_ns) ||
|
||||
StringBeginsWith(aSpecifier, u"./"_ns) ||
|
||||
StringBeginsWith(aSpecifier, u"../"_ns)) {
|
||||
// Step 1.1. Let url be the result of parsing specifier with baseURL as the
|
||||
// base URL.
|
||||
rv = NS_NewURI(getter_AddRefs(uri), aSpecifier, nullptr, aBaseURL);
|
||||
// Step 1.2. If url is failure, then return null.
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 1.3. Return url.
|
||||
return uri.forget();
|
||||
}
|
||||
|
||||
// Step 2. Let url be the result of parsing specifier (with no base URL).
|
||||
rv = NS_NewURI(getter_AddRefs(uri), aSpecifier);
|
||||
// Step 3. If url is failure, then return null.
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 4. Return url.
|
||||
return uri.forget();
|
||||
}
|
||||
|
||||
// https://wicg.github.io/import-maps/#normalize-a-specifier-key
|
||||
static void NormalizeSpecifierKey(const nsAString& aSpecifierKey,
|
||||
nsIURI* aBaseURL,
|
||||
const ReportWarningHelper& aWarning,
|
||||
nsAString& aRetVal) {
|
||||
// Step 1. If specifierKey is the empty string, then:
|
||||
if (aSpecifierKey.IsEmpty()) {
|
||||
// Step 1.1. Report a warning to the console that specifier keys cannot be
|
||||
// the empty string.
|
||||
aWarning.Report("ImportMapEmptySpecifierKeys");
|
||||
|
||||
// Step 1.2. Return null.
|
||||
aRetVal = EmptyString();
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 2. Let url be the result of parsing a URL-like import specifier, given
|
||||
// specifierKey and baseURL.
|
||||
nsCOMPtr<nsIURI> url = ParseURLLikeImportSpecifier(aSpecifierKey, aBaseURL);
|
||||
|
||||
// Step 3. If url is not null, then return the serialization of url.
|
||||
if (url) {
|
||||
aRetVal = NS_ConvertUTF8toUTF16(url->GetSpecOrDefault());
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 4. Return specifierKey.
|
||||
aRetVal = aSpecifierKey;
|
||||
}
|
||||
|
||||
// https://wicg.github.io/import-maps/#sort-and-normalize-a-specifier-map
|
||||
static UniquePtr<SpecifierMap> SortAndNormalizeSpecifierMap(
|
||||
JSContext* aCx, JS::HandleObject aOriginalMap, nsIURI* aBaseURL,
|
||||
const ReportWarningHelper& aWarning) {
|
||||
// Step 1. Let normalized be an empty map.
|
||||
UniquePtr<SpecifierMap> normalized = MakeUnique<SpecifierMap>();
|
||||
|
||||
JS::Rooted<JS::IdVector> specifierKeys(aCx, JS::IdVector(aCx));
|
||||
if (!JS_Enumerate(aCx, aOriginalMap, &specifierKeys)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 2. For each specifierKey → value of originalMap,
|
||||
for (size_t i = 0; i < specifierKeys.length(); i++) {
|
||||
const JS::RootedId specifierId(aCx, specifierKeys[i]);
|
||||
nsAutoJSString specifierKey;
|
||||
NS_ENSURE_TRUE(specifierKey.init(aCx, specifierId), nullptr);
|
||||
|
||||
// Step 2.1. Let normalizedSpecifierKey be the result of normalizing a
|
||||
// specifier key given specifierKey and baseURL.
|
||||
nsString normalizedSpecifierKey;
|
||||
NormalizeSpecifierKey(specifierKey, aBaseURL, aWarning,
|
||||
normalizedSpecifierKey);
|
||||
|
||||
// Step 2.2. If normalizedSpecifierKey is null, then continue.
|
||||
if (normalizedSpecifierKey.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JS::RootedValue idVal(aCx);
|
||||
NS_ENSURE_TRUE(JS_GetPropertyById(aCx, aOriginalMap, specifierId, &idVal),
|
||||
nullptr);
|
||||
// Step 2.3. If value is not a string, then:
|
||||
if (!idVal.isString()) {
|
||||
// Step 2.3.1. Report a warning to the console that addresses need to
|
||||
// be strings.
|
||||
aWarning.Report("ImportMapAddressesNotStrings");
|
||||
|
||||
// Step 2.3.2. Set normalized[normalizedSpecifierKey] to null.
|
||||
normalized->insert_or_assign(normalizedSpecifierKey, nullptr);
|
||||
|
||||
// Step 2.3.3. Continue.
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoJSString value;
|
||||
NS_ENSURE_TRUE(value.init(aCx, idVal), nullptr);
|
||||
|
||||
// Step 2.4. Let addressURL be the result of parsing a URL-like import
|
||||
// specifier given value and baseURL.
|
||||
nsCOMPtr<nsIURI> addressURL = ParseURLLikeImportSpecifier(value, aBaseURL);
|
||||
|
||||
// Step 2.5. If addressURL is null, then:
|
||||
if (!addressURL) {
|
||||
// Step 2.5.1. Report a warning to the console that the address was
|
||||
// invalid.
|
||||
AutoTArray<nsString, 1> params;
|
||||
params.AppendElement(value);
|
||||
aWarning.Report("ImportMapInvalidAddress", params);
|
||||
|
||||
// Step 2.5.2. Set normalized[normalizedSpecifierKey] to null.
|
||||
normalized->insert_or_assign(normalizedSpecifierKey, nullptr);
|
||||
|
||||
// Step 2.5.3. Continue.
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCString address = addressURL->GetSpecOrDefault();
|
||||
// Step 2.6. If specifierKey ends with U+002F (/), and the serialization
|
||||
// of addressURL does not end with U+002F (/), then:
|
||||
if (StringEndsWith(specifierKey, u"/"_ns) &&
|
||||
!StringEndsWith(address, "/"_ns)) {
|
||||
// Step 2.6.1. Report a warning to the console that an invalid address
|
||||
// was given for the specifier key specifierKey; since specifierKey
|
||||
// ended in a slash, the address needs to as well.
|
||||
AutoTArray<nsString, 2> params;
|
||||
params.AppendElement(specifierKey);
|
||||
params.AppendElement(NS_ConvertUTF8toUTF16(address));
|
||||
aWarning.Report("ImportMapAddressNotEndsWithSlash", params);
|
||||
|
||||
// Step 2.6.2. Set normalized[normalizedSpecifierKey] to null.
|
||||
normalized->insert_or_assign(normalizedSpecifierKey, nullptr);
|
||||
|
||||
// Step 2.6.3. Continue.
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG(("ImportMap::SortAndNormalizeSpecifierMap {%s, %s}",
|
||||
NS_ConvertUTF16toUTF8(normalizedSpecifierKey).get(),
|
||||
addressURL->GetSpecOrDefault().get()));
|
||||
|
||||
// Step 2.7. Set normalized[normalizedSpecifierKey] to addressURL.
|
||||
normalized->insert_or_assign(normalizedSpecifierKey, addressURL);
|
||||
}
|
||||
|
||||
// Step 3: Return the result of sorting normalized, with an entry a being
|
||||
// less than an entry b if b’s key is code unit less than a’s key.
|
||||
//
|
||||
// Impl note: The sorting is done when inserting the entry.
|
||||
return normalized;
|
||||
}
|
||||
|
||||
// Check if it's a map defined in
|
||||
// https://infra.spec.whatwg.org/#ordered-map
|
||||
//
|
||||
// If it is, *aIsMap will be set to true.
|
||||
static bool IsMapObject(JSContext* aCx, JS::HandleValue aMapVal, bool* aIsMap) {
|
||||
MOZ_ASSERT(aIsMap);
|
||||
|
||||
*aIsMap = false;
|
||||
if (!aMapVal.isObject()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isArray;
|
||||
if (!IsArrayObject(aCx, aMapVal, &isArray)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*aIsMap = !isArray;
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://wicg.github.io/import-maps/#sort-and-normalize-scopes
|
||||
static UniquePtr<ScopeMap> SortAndNormalizeScopes(
|
||||
JSContext* aCx, JS::HandleObject aOriginalMap, nsIURI* aBaseURL,
|
||||
const ReportWarningHelper& aWarning) {
|
||||
JS::Rooted<JS::IdVector> scopeKeys(aCx, JS::IdVector(aCx));
|
||||
if (!JS_Enumerate(aCx, aOriginalMap, &scopeKeys)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 1. Let normalized be an empty map.
|
||||
UniquePtr<ScopeMap> normalized = MakeUnique<ScopeMap>();
|
||||
|
||||
// Step 2. For each scopePrefix → potentialSpecifierMap of originalMap,
|
||||
for (size_t i = 0; i < scopeKeys.length(); i++) {
|
||||
const JS::RootedId scopeKey(aCx, scopeKeys[i]);
|
||||
nsAutoJSString scopePrefix;
|
||||
NS_ENSURE_TRUE(scopePrefix.init(aCx, scopeKey), nullptr);
|
||||
|
||||
// Step 2.1. If potentialSpecifierMap is not a map, then throw a TypeError
|
||||
// indicating that the value of the scope with prefix scopePrefix needs to
|
||||
// be a JSON object.
|
||||
JS::RootedValue mapVal(aCx);
|
||||
NS_ENSURE_TRUE(JS_GetPropertyById(aCx, aOriginalMap, scopeKey, &mapVal),
|
||||
nullptr);
|
||||
|
||||
bool isMap;
|
||||
if (!IsMapObject(aCx, mapVal, &isMap)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!isMap) {
|
||||
JS_ReportErrorNumberUC(aCx, js::GetErrorMessage, nullptr,
|
||||
JSMSG_IMPORT_MAPS_SCOPE_VALUE_NOT_A_MAP,
|
||||
scopePrefix.get());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 2.2. Let scopePrefixURL be the result of parsing scopePrefix with
|
||||
// baseURL as the base URL.
|
||||
nsCOMPtr<nsIURI> scopePrefixURL;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(scopePrefixURL), scopePrefix,
|
||||
nullptr, aBaseURL);
|
||||
|
||||
// Step 2.3. If scopePrefixURL is failure, then:
|
||||
if (NS_FAILED(rv)) {
|
||||
// Step 2.3.1. Report a warning to the console that the scope prefix URL
|
||||
// was not parseable.
|
||||
AutoTArray<nsString, 1> params;
|
||||
params.AppendElement(scopePrefix);
|
||||
aWarning.Report("ImportMapScopePrefixNotParseable", params);
|
||||
|
||||
// Step 2.3.2. Continue.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Step 2.4. Let normalizedScopePrefix be the serialization of
|
||||
// scopePrefixURL.
|
||||
nsCString normalizedScopePrefix = scopePrefixURL->GetSpecOrDefault();
|
||||
|
||||
// Step 2.5. Set normalized[normalizedScopePrefix] to the result of sorting
|
||||
// and normalizing a specifier map given potentialSpecifierMap and baseURL.
|
||||
JS::RootedObject potentialSpecifierMap(aCx, &mapVal.toObject());
|
||||
UniquePtr<SpecifierMap> specifierMap = SortAndNormalizeSpecifierMap(
|
||||
aCx, potentialSpecifierMap, aBaseURL, aWarning);
|
||||
if (!specifierMap) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
normalized->insert_or_assign(normalizedScopePrefix,
|
||||
std::move(specifierMap));
|
||||
}
|
||||
|
||||
// Step 3. Return the result of sorting normalized, with an entry a being less
|
||||
// than an entry b if b’s key is code unit less than a’s key.
|
||||
//
|
||||
// Impl note: The sorting is done when inserting the entry.
|
||||
return normalized;
|
||||
}
|
||||
|
||||
// https://wicg.github.io/import-maps/#parse-an-import-map-string
|
||||
// static
|
||||
UniquePtr<ImportMap> ImportMap::ParseString(
|
||||
JSContext* aCx, SourceText<char16_t>& aInput, nsIURI* aBaseURL,
|
||||
const ReportWarningHelper& aWarning) {
|
||||
// Step 1. Let parsed be the result of parsing JSON into Infra values given
|
||||
// input.
|
||||
JS::Rooted<JS::Value> parsedVal(aCx);
|
||||
if (!JS_ParseJSON(aCx, aInput.get(), aInput.length(), &parsedVal)) {
|
||||
// If JS_ParseJSON fail it will throw SyntaxError.
|
||||
NS_WARNING("Parsing Import map string failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 2. If parsed is not a map, then throw a TypeError indicating that
|
||||
// the top-level value needs to be a JSON object.
|
||||
bool isMap;
|
||||
if (!IsMapObject(aCx, parsedVal, &isMap)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!isMap) {
|
||||
JS_ReportErrorNumberASCII(aCx, js::GetErrorMessage, nullptr,
|
||||
JSMSG_IMPORT_MAPS_NOT_A_MAP);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JS::RootedObject parsedObj(aCx, &parsedVal.toObject());
|
||||
JS::RootedValue importsVal(aCx);
|
||||
if (!JS_GetProperty(aCx, parsedObj, "imports", &importsVal)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 3. Let sortedAndNormalizedImports be an empty map.
|
||||
//
|
||||
// Impl note: If parsed["imports"] doesn't exist, we will allocate
|
||||
// sortedAndNormalizedImports to an empty map in Step 8 below.
|
||||
UniquePtr<SpecifierMap> sortedAndNormalizedImports = nullptr;
|
||||
|
||||
// Step 4. If parsed["imports"] exists, then:
|
||||
if (!importsVal.isUndefined()) {
|
||||
// Step 4.1. If parsed["imports"] is not a map, then throw a TypeError
|
||||
// indicating that the "imports" top-level key needs to be a JSON object.
|
||||
bool isMap;
|
||||
if (!IsMapObject(aCx, importsVal, &isMap)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!isMap) {
|
||||
JS_ReportErrorNumberASCII(aCx, js::GetErrorMessage, nullptr,
|
||||
JSMSG_IMPORT_MAPS_IMPORTS_NOT_A_MAP);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 4.2. Set sortedAndNormalizedImports to the result of sorting and
|
||||
// normalizing a specifier map given parsed["imports"] and baseURL.
|
||||
JS::RootedObject importsObj(aCx, &importsVal.toObject());
|
||||
sortedAndNormalizedImports =
|
||||
SortAndNormalizeSpecifierMap(aCx, importsObj, aBaseURL, aWarning);
|
||||
if (!sortedAndNormalizedImports) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
JS::RootedValue scopesVal(aCx);
|
||||
if (!JS_GetProperty(aCx, parsedObj, "scopes", &scopesVal)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 5. Let sortedAndNormalizedScopes be an empty map.
|
||||
//
|
||||
// Impl note: If parsed["scopes"] doesn't exist, we will allocate
|
||||
// sortedAndNormalizedScopes to an empty map in Step 8 below.
|
||||
UniquePtr<ScopeMap> sortedAndNormalizedScopes = nullptr;
|
||||
|
||||
// Step 6. If parsed["scopes"] exists, then:
|
||||
if (!scopesVal.isUndefined()) {
|
||||
// Step 6.1. If parsed["scopes"] is not a map, then throw a TypeError
|
||||
// indicating that the "scopes" top-level key needs to be a JSON object.
|
||||
bool isMap;
|
||||
if (!IsMapObject(aCx, scopesVal, &isMap)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!isMap) {
|
||||
JS_ReportErrorNumberASCII(aCx, js::GetErrorMessage, nullptr,
|
||||
JSMSG_IMPORT_MAPS_SCOPES_NOT_A_MAP);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 6.2. Set sortedAndNormalizedScopes to the result of sorting and
|
||||
// normalizing scopes given parsed["scopes"] and baseURL.
|
||||
JS::RootedObject scopesObj(aCx, &scopesVal.toObject());
|
||||
sortedAndNormalizedScopes =
|
||||
SortAndNormalizeScopes(aCx, scopesObj, aBaseURL, aWarning);
|
||||
if (!sortedAndNormalizedScopes) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 7. If parsed’s keys contains any items besides "imports" or
|
||||
// "scopes", report a warning to the console that an invalid top-level key
|
||||
// was present in the import map.
|
||||
JS::Rooted<JS::IdVector> keys(aCx, JS::IdVector(aCx));
|
||||
if (!JS_Enumerate(aCx, parsedObj, &keys)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < keys.length(); i++) {
|
||||
const JS::RootedId key(aCx, keys[i]);
|
||||
nsAutoJSString val;
|
||||
NS_ENSURE_TRUE(val.init(aCx, key), nullptr);
|
||||
if (val.EqualsLiteral("imports") || val.EqualsLiteral("scopes")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AutoTArray<nsString, 1> params;
|
||||
params.AppendElement(val);
|
||||
aWarning.Report("ImportMapInvalidTopLevelKey", params);
|
||||
}
|
||||
|
||||
// Impl note: Create empty maps for sortedAndNormalizedImports and
|
||||
// sortedAndNormalizedImports if they aren't allocated.
|
||||
if (!sortedAndNormalizedImports) {
|
||||
sortedAndNormalizedImports = MakeUnique<SpecifierMap>();
|
||||
}
|
||||
if (!sortedAndNormalizedScopes) {
|
||||
sortedAndNormalizedScopes = MakeUnique<ScopeMap>();
|
||||
}
|
||||
|
||||
// Step 8. Return the import map whose imports are
|
||||
// sortedAndNormalizedImports and whose scopes scopes are
|
||||
// sortedAndNormalizedScopes.
|
||||
return MakeUnique<ImportMap>(std::move(sortedAndNormalizedImports),
|
||||
std::move(sortedAndNormalizedScopes));
|
||||
}
|
||||
|
||||
// https://url.spec.whatwg.org/#is-special
|
||||
static bool IsSpecialScheme(nsIURI* aURI) {
|
||||
nsAutoCString scheme;
|
||||
aURI->GetScheme(scheme);
|
||||
return scheme.EqualsLiteral("ftp") || scheme.EqualsLiteral("file") ||
|
||||
scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https") ||
|
||||
scheme.EqualsLiteral("ws") || scheme.EqualsLiteral("wss");
|
||||
}
|
||||
|
||||
// https://wicg.github.io/import-maps/#resolve-an-imports-match
|
||||
static mozilla::Result<nsCOMPtr<nsIURI>, ResolveError> ResolveImportsMatch(
|
||||
nsString& aNormalizedSpecifier, nsIURI* aAsURL,
|
||||
const SpecifierMap* aSpecifierMap) {
|
||||
// Step 1. For each specifierKey → resolutionResult of specifierMap,
|
||||
for (auto&& [specifierKey, resolutionResult] : *aSpecifierMap) {
|
||||
nsAutoString specifier{aNormalizedSpecifier};
|
||||
nsCString asURL = aAsURL ? aAsURL->GetSpecOrDefault() : EmptyCString();
|
||||
|
||||
// Step 1.1. If specifierKey is normalizedSpecifier, then:
|
||||
if (specifierKey.Equals(aNormalizedSpecifier)) {
|
||||
// Step 1.1.1. If resolutionResult is null, then throw a TypeError
|
||||
// indicating that resolution of specifierKey was blocked by a null entry.
|
||||
// This will terminate the entire resolve a module specifier algorithm,
|
||||
// without any further fallbacks.
|
||||
if (!resolutionResult) {
|
||||
LOG(
|
||||
("ImportMap::ResolveImportsMatch normalizedSpecifier: %s, "
|
||||
"specifierKey: %s, but resolution is null.",
|
||||
NS_ConvertUTF16toUTF8(aNormalizedSpecifier).get(),
|
||||
NS_ConvertUTF16toUTF8(specifierKey).get()));
|
||||
return Err(ResolveError::BlockedByNullEntry);
|
||||
}
|
||||
|
||||
// Step 1.1.2. Assert: resolutionResult is a URL.
|
||||
MOZ_ASSERT(resolutionResult);
|
||||
|
||||
// Step 1.1.3. Return resolutionResult.
|
||||
return resolutionResult;
|
||||
}
|
||||
|
||||
// Step 1.2. If all of the following are true:
|
||||
// specifierKey ends with U+002F (/),
|
||||
// normalizedSpecifier starts with specifierKey, and
|
||||
// either asURL is null, or asURL is special
|
||||
if (StringEndsWith(specifierKey, u"/"_ns) &&
|
||||
StringBeginsWith(aNormalizedSpecifier, specifierKey) &&
|
||||
(!aAsURL || IsSpecialScheme(aAsURL))) {
|
||||
// Step 1.2.1. If resolutionResult is null, then throw a TypeError
|
||||
// indicating that resolution of specifierKey was blocked by a null entry.
|
||||
// This will terminate the entire resolve a module specifier algorithm,
|
||||
// without any further fallbacks.
|
||||
if (!resolutionResult) {
|
||||
LOG(
|
||||
("ImportMap::ResolveImportsMatch normalizedSpecifier: %s, "
|
||||
"specifierKey: %s, but resolution is null.",
|
||||
NS_ConvertUTF16toUTF8(aNormalizedSpecifier).get(),
|
||||
NS_ConvertUTF16toUTF8(specifierKey).get()));
|
||||
return Err(ResolveError::BlockedByNullEntry);
|
||||
}
|
||||
|
||||
// Step 1.2.2. Assert: resolutionResult is a URL.
|
||||
MOZ_ASSERT(resolutionResult);
|
||||
|
||||
// Step 1.2.3. Let afterPrefix be the portion of normalizedSpecifier after
|
||||
// the initial specifierKey prefix.
|
||||
nsAutoString afterPrefix(
|
||||
Substring(aNormalizedSpecifier, specifierKey.Length()));
|
||||
|
||||
// Step 1.2.4. Assert: resolutionResult, serialized, ends with "/", as
|
||||
// enforced during parsing.
|
||||
MOZ_ASSERT(StringEndsWith(resolutionResult->GetSpecOrDefault(), "/"_ns));
|
||||
|
||||
// Step 1.2.5. Let url be the result of parsing afterPrefix relative to
|
||||
// the base URL resolutionResult.
|
||||
nsCOMPtr<nsIURI> url;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(url), afterPrefix, nullptr,
|
||||
resolutionResult);
|
||||
|
||||
// Step 1.2.6. If url is failure, then throw a TypeError indicating that
|
||||
// resolution of normalizedSpecifier was blocked since the afterPrefix
|
||||
// portion could not be URL-parsed relative to the resolutionResult mapped
|
||||
// to by the specifierKey prefix.
|
||||
//
|
||||
// This will terminate the entire resolve a module specifier algorithm,
|
||||
// without any further fallbacks.
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(
|
||||
("ImportMap::ResolveImportsMatch normalizedSpecifier: %s, "
|
||||
"specifierKey: %s, resolutionResult: %s, afterPrefix: %s, "
|
||||
"but URL is not parsable.",
|
||||
NS_ConvertUTF16toUTF8(aNormalizedSpecifier).get(),
|
||||
NS_ConvertUTF16toUTF8(specifierKey).get(),
|
||||
resolutionResult->GetSpecOrDefault().get(),
|
||||
NS_ConvertUTF16toUTF8(afterPrefix).get()));
|
||||
return Err(ResolveError::BlockedByAfterPrefix);
|
||||
}
|
||||
|
||||
// Step 1.2.7. Assert: url is a URL.
|
||||
MOZ_ASSERT(url);
|
||||
|
||||
// Step 1.2.8. If the serialization of url does not start with the
|
||||
// serialization of resolutionResult, then throw a TypeError indicating
|
||||
// that resolution of normalizedSpecifier was blocked due to it
|
||||
// backtracking above its prefix specifierKey.
|
||||
//
|
||||
// This will terminate the entire resolve a module specifier algorithm,
|
||||
// without any further fallbacks.
|
||||
if (!StringBeginsWith(url->GetSpecOrDefault(),
|
||||
resolutionResult->GetSpecOrDefault())) {
|
||||
LOG(
|
||||
("ImportMap::ResolveImportsMatch normalizedSpecifier: %s, "
|
||||
"specifierKey: %s, "
|
||||
"url %s does not start with resolutionResult %s.",
|
||||
NS_ConvertUTF16toUTF8(aNormalizedSpecifier).get(),
|
||||
NS_ConvertUTF16toUTF8(specifierKey).get(),
|
||||
url->GetSpecOrDefault().get(),
|
||||
resolutionResult->GetSpecOrDefault().get()));
|
||||
return Err(ResolveError::BlockedByBacktrackingPrefix);
|
||||
}
|
||||
|
||||
// Step 1.2.9. Return url.
|
||||
return std::move(url);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2. Return null.
|
||||
return nsCOMPtr<nsIURI>(nullptr);
|
||||
}
|
||||
|
||||
// https://wicg.github.io/import-maps/#resolve-a-module-specifier
|
||||
// static
|
||||
ResolveResult ImportMap::ResolveModuleSpecifier(ImportMap* aImportMap,
|
||||
ScriptLoaderInterface* aLoader,
|
||||
LoadedScript* aScript,
|
||||
const nsAString& aSpecifier) {
|
||||
LOG(("ImportMap::ResolveModuleSpecifier specifier: %s",
|
||||
NS_ConvertUTF16toUTF8(aSpecifier).get()));
|
||||
nsCOMPtr<nsIURI> baseURL;
|
||||
if (aScript) {
|
||||
baseURL = aScript->BaseURL();
|
||||
} else {
|
||||
baseURL = aLoader->GetBaseURI();
|
||||
}
|
||||
|
||||
// Step 6. Let asURL be the result of parsing a URL-like import specifier
|
||||
// given specifier and baseURL.
|
||||
//
|
||||
// Impl note: Step 5 is done below if aImportMap exists.
|
||||
nsCOMPtr<nsIURI> asURL = ParseURLLikeImportSpecifier(aSpecifier, baseURL);
|
||||
|
||||
if (aImportMap) {
|
||||
// Step 5. Let baseURLString be baseURL, serialized.
|
||||
nsCString baseURLString = baseURL->GetSpecOrDefault();
|
||||
|
||||
// Step 7. Let normalizedSpecifier be the serialization of asURL, if asURL
|
||||
// is non-null; otherwise, specifier.
|
||||
nsAutoString normalizedSpecifier =
|
||||
asURL ? NS_ConvertUTF8toUTF16(asURL->GetSpecOrDefault())
|
||||
: nsAutoString{aSpecifier};
|
||||
|
||||
// Step 8. For each scopePrefix → scopeImports of importMap’s scopes,
|
||||
for (auto&& [scopePrefix, scopeImports] : *aImportMap->mScopes) {
|
||||
// Step 8.1. If scopePrefix is baseURLString, or if scopePrefix ends with
|
||||
// U+002F (/) and baseURLString starts with scopePrefix, then:
|
||||
if (scopePrefix.Equals(baseURLString) ||
|
||||
(StringEndsWith(scopePrefix, "/"_ns) &&
|
||||
StringBeginsWith(baseURLString, scopePrefix))) {
|
||||
// Step 8.1.1. Let scopeImportsMatch be the result of resolving an
|
||||
// imports match given normalizedSpecifier, asURL, and scopeImports.
|
||||
auto result =
|
||||
ResolveImportsMatch(normalizedSpecifier, asURL, scopeImports.get());
|
||||
if (result.isErr()) {
|
||||
return result.propagateErr();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> scopeImportsMatch = result.unwrap();
|
||||
// Step 8.1.2. If scopeImportsMatch is not null, then return
|
||||
// scopeImportsMatch.
|
||||
if (scopeImportsMatch) {
|
||||
LOG((
|
||||
"ImportMap::ResolveModuleSpecifier returns scopeImportsMatch: %s",
|
||||
scopeImportsMatch->GetSpecOrDefault().get()));
|
||||
return WrapNotNull(scopeImportsMatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 9. Let topLevelImportsMatch be the result of resolving an imports
|
||||
// match given normalizedSpecifier, asURL, and importMap’s imports.
|
||||
auto result = ResolveImportsMatch(normalizedSpecifier, asURL,
|
||||
aImportMap->mImports.get());
|
||||
if (result.isErr()) {
|
||||
return result.propagateErr();
|
||||
}
|
||||
nsCOMPtr<nsIURI> topLevelImportsMatch = result.unwrap();
|
||||
|
||||
// Step 10. If topLevelImportsMatch is not null, then return
|
||||
// topLevelImportsMatch.
|
||||
if (topLevelImportsMatch) {
|
||||
LOG(("ImportMap::ResolveModuleSpecifier returns topLevelImportsMatch: %s",
|
||||
topLevelImportsMatch->GetSpecOrDefault().get()));
|
||||
return WrapNotNull(topLevelImportsMatch);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 11. At this point, the specifier was able to be turned in to a URL,
|
||||
// but it wasn’t remapped to anything by importMap. If asURL is not null, then
|
||||
// return asURL.
|
||||
if (asURL) {
|
||||
LOG(("ImportMap::ResolveModuleSpecifier returns asURL: %s",
|
||||
asURL->GetSpecOrDefault().get()));
|
||||
return WrapNotNull(asURL);
|
||||
}
|
||||
|
||||
// Step 12. Throw a TypeError indicating that specifier was a bare specifier,
|
||||
// but was not remapped to anything by importMap.
|
||||
return Err(ResolveError::InvalidBareSpecifier);
|
||||
}
|
||||
|
||||
#undef LOG
|
||||
#undef LOG_ENABLED
|
||||
} // namespace JS::loader
|
||||
@@ -1,107 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef js_loader_ImportMap_h
|
||||
#define js_loader_ImportMap_h
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
#include "js/SourceText.h"
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsStringFwd.h"
|
||||
#include "nsTArray.h"
|
||||
#include "ResolveResult.h"
|
||||
|
||||
struct JSContext;
|
||||
class nsIScriptElement;
|
||||
class nsIURI;
|
||||
|
||||
namespace JS::loader {
|
||||
class LoadedScript;
|
||||
class ScriptLoaderInterface;
|
||||
class ScriptLoadRequest;
|
||||
|
||||
/**
|
||||
* A helper class to report warning to ScriptLoaderInterface.
|
||||
*/
|
||||
class ReportWarningHelper {
|
||||
public:
|
||||
ReportWarningHelper(ScriptLoaderInterface* aLoader,
|
||||
ScriptLoadRequest* aRequest)
|
||||
: mLoader(aLoader), mRequest(aRequest) {}
|
||||
|
||||
void Report(const char* aMessageName,
|
||||
const nsTArray<nsString>& aParams = nsTArray<nsString>()) const;
|
||||
|
||||
private:
|
||||
RefPtr<ScriptLoaderInterface> mLoader;
|
||||
ScriptLoadRequest* mRequest;
|
||||
};
|
||||
|
||||
// Specifier map from import maps.
|
||||
// https://wicg.github.io/import-maps/#specifier-map
|
||||
using SpecifierMap =
|
||||
std::map<nsString, nsCOMPtr<nsIURI>, std::greater<nsString>>;
|
||||
|
||||
// Scope map from import maps.
|
||||
// https://wicg.github.io/import-maps/#import-map-scopes
|
||||
using ScopeMap = std::map<nsCString, mozilla::UniquePtr<SpecifierMap>,
|
||||
std::greater<nsCString>>;
|
||||
|
||||
/**
|
||||
* Implementation of Import maps.
|
||||
* https://wicg.github.io/import-maps
|
||||
*/
|
||||
class ImportMap {
|
||||
public:
|
||||
ImportMap(mozilla::UniquePtr<SpecifierMap> aImports,
|
||||
mozilla::UniquePtr<ScopeMap> aScopes)
|
||||
: mImports(std::move(aImports)), mScopes(std::move(aScopes)) {}
|
||||
|
||||
/**
|
||||
* Parse the JSON string from the Import map script.
|
||||
* This function will throw TypeError if there's any invalid key or value in
|
||||
* the JSON text according to the spec.
|
||||
*
|
||||
* See https://wicg.github.io/import-maps/#parse-an-import-map-string
|
||||
*/
|
||||
static mozilla::UniquePtr<ImportMap> ParseString(
|
||||
JSContext* aCx, JS::SourceText<char16_t>& aInput, nsIURI* aBaseURL,
|
||||
const ReportWarningHelper& aWarning);
|
||||
|
||||
/**
|
||||
* This implements "Resolve a module specifier" algorithm defined in the
|
||||
* Import maps spec.
|
||||
*
|
||||
* See https://wicg.github.io/import-maps/#resolve-a-module-specifier
|
||||
*/
|
||||
static ResolveResult ResolveModuleSpecifier(ImportMap* aImportMap,
|
||||
ScriptLoaderInterface* aLoader,
|
||||
LoadedScript* aScript,
|
||||
const nsAString& aSpecifier);
|
||||
|
||||
// Logging
|
||||
static mozilla::LazyLogModule gImportMapLog;
|
||||
|
||||
private:
|
||||
/**
|
||||
* https://wicg.github.io/import-maps/#import-map
|
||||
*
|
||||
* A import map is a struct with two items:
|
||||
* 1. imports, a specifier map, and
|
||||
* 2. scopes, an ordered map of URLs to specifier maps.
|
||||
*/
|
||||
mozilla::UniquePtr<SpecifierMap> mImports;
|
||||
mozilla::UniquePtr<ScopeMap> mScopes;
|
||||
};
|
||||
|
||||
} // namespace JS::loader
|
||||
|
||||
#endif // js_loader_ImportMap_h
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "LoadedScript.h"
|
||||
#include "ModuleLoadRequest.h"
|
||||
#include "ScriptLoadRequest.h"
|
||||
#include "mozilla/dom/ScriptSettings.h" // AutoJSAPI
|
||||
#include "mozilla/dom/ScriptTrace.h"
|
||||
|
||||
#include "js/Array.h" // JS::GetArrayLength
|
||||
@@ -30,11 +29,8 @@
|
||||
#include "nsThreadUtils.h" // GetMainThreadSerialEventTarget
|
||||
#include "xpcpublic.h"
|
||||
|
||||
using mozilla::Err;
|
||||
using mozilla::GetMainThreadSerialEventTarget;
|
||||
using mozilla::Preferences;
|
||||
using mozilla::UniquePtr;
|
||||
using mozilla::WrapNotNull;
|
||||
using mozilla::dom::AutoJSAPI;
|
||||
|
||||
namespace JS::loader {
|
||||
@@ -138,11 +134,10 @@ JSObject* ModuleLoaderBase::HostResolveImportedModule(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto result = loader->ResolveModuleSpecifier(script, string);
|
||||
nsCOMPtr<nsIURI> uri = loader->ResolveModuleSpecifier(script, string);
|
||||
|
||||
// This cannot fail because resolving a module specifier must have been
|
||||
// previously successful with these same two arguments.
|
||||
MOZ_ASSERT(result.isOk());
|
||||
nsCOMPtr<nsIURI> uri = result.unwrap();
|
||||
MOZ_ASSERT(uri, "Failed to resolve previously-resolved module specifier");
|
||||
|
||||
// Let resolved module script be moduleMap[url]. (This entry must exist for
|
||||
@@ -204,11 +199,11 @@ bool ModuleLoaderBase::HostImportModuleDynamically(
|
||||
return false;
|
||||
}
|
||||
|
||||
auto result = loader->ResolveModuleSpecifier(script, specifier);
|
||||
if (result.isErr()) {
|
||||
nsCOMPtr<nsIURI> uri = loader->ResolveModuleSpecifier(script, specifier);
|
||||
if (!uri) {
|
||||
JS::Rooted<JS::Value> error(aCx);
|
||||
nsresult rv = HandleResolveFailure(aCx, script, specifier,
|
||||
result.unwrapErr(), 0, 0, &error);
|
||||
nsresult rv = ModuleLoaderBase::HandleResolveFailure(aCx, script, specifier,
|
||||
0, 0, &error);
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_ReportOutOfMemory(aCx);
|
||||
return false;
|
||||
@@ -219,7 +214,6 @@ bool ModuleLoaderBase::HostImportModuleDynamically(
|
||||
}
|
||||
|
||||
// Create a new top-level load request.
|
||||
nsCOMPtr<nsIURI> uri = result.unwrap();
|
||||
RefPtr<ModuleLoadRequest> request = loader->CreateDynamicImport(
|
||||
aCx, uri, script, aReferencingPrivate, specifierString, aPromise);
|
||||
|
||||
@@ -539,8 +533,8 @@ nsresult ModuleLoaderBase::CreateModuleScript(ModuleLoadRequest* aRequest) {
|
||||
|
||||
nsresult ModuleLoaderBase::HandleResolveFailure(
|
||||
JSContext* aCx, LoadedScript* aScript, const nsAString& aSpecifier,
|
||||
ResolveError aError, uint32_t aLineNumber, uint32_t aColumnNumber,
|
||||
JS::MutableHandle<JS::Value> aErrorOut) {
|
||||
uint32_t aLineNumber, uint32_t aColumnNumber,
|
||||
JS::MutableHandle<JS::Value> errorOut) {
|
||||
JS::Rooted<JSString*> filename(aCx);
|
||||
if (aScript) {
|
||||
nsAutoCString url;
|
||||
@@ -559,8 +553,8 @@ nsresult ModuleLoaderBase::HandleResolveFailure(
|
||||
|
||||
nsAutoString errorText;
|
||||
nsresult rv = nsContentUtils::FormatLocalizedString(
|
||||
nsContentUtils::eDOM_PROPERTIES, ResolveErrorInfo::GetString(aError),
|
||||
errorParams, errorText);
|
||||
nsContentUtils::eDOM_PROPERTIES, "ModuleResolveFailure", errorParams,
|
||||
errorText);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS::Rooted<JSString*> string(aCx, JS_NewUCStringCopyZ(aCx, errorText.get()));
|
||||
@@ -570,47 +564,36 @@ nsresult ModuleLoaderBase::HandleResolveFailure(
|
||||
|
||||
if (!JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, filename, aLineNumber,
|
||||
aColumnNumber, nullptr, string, JS::NothingHandleValue,
|
||||
aErrorOut)) {
|
||||
errorOut)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ResolveResult ModuleLoaderBase::ResolveModuleSpecifier(
|
||||
already_AddRefed<nsIURI> ModuleLoaderBase::ResolveModuleSpecifier(
|
||||
LoadedScript* aScript, const nsAString& aSpecifier) {
|
||||
bool importMapsEnabled = Preferences::GetBool("dom.importMaps.enabled");
|
||||
// If import map is enabled, forward to the updated 'Resolve a module
|
||||
// specifier' algorithm defined in Import maps spec.
|
||||
//
|
||||
// Once import map is enabled by default,
|
||||
// ModuleLoaderBase::ResolveModuleSpecifier should be replaced by
|
||||
// ImportMap::ResolveModuleSpecifier.
|
||||
if (importMapsEnabled) {
|
||||
return ImportMap::ResolveModuleSpecifier(mImportMap.get(), mLoader, aScript,
|
||||
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 handled in Import maps.
|
||||
// Bareword module specifiers are currently disallowed as these may be given
|
||||
// special meanings in the future.
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), aSpecifier);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return WrapNotNull(uri);
|
||||
return uri.forget();
|
||||
}
|
||||
|
||||
if (rv != NS_ERROR_MALFORMED_URI) {
|
||||
return Err(ResolveError::ModuleResolveFailure);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!StringBeginsWith(aSpecifier, u"/"_ns) &&
|
||||
!StringBeginsWith(aSpecifier, u"./"_ns) &&
|
||||
!StringBeginsWith(aSpecifier, u"../"_ns)) {
|
||||
return Err(ResolveError::ModuleResolveFailure);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Get the document's base URL if we don't have a referencing script here.
|
||||
@@ -623,10 +606,10 @@ ResolveResult ModuleLoaderBase::ResolveModuleSpecifier(
|
||||
|
||||
rv = NS_NewURI(getter_AddRefs(uri), aSpecifier, nullptr, baseURL);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return WrapNotNull(uri);
|
||||
return uri.forget();
|
||||
}
|
||||
|
||||
return Err(ResolveError::ModuleResolveFailure);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsresult ModuleLoaderBase::ResolveRequestedModules(
|
||||
@@ -649,14 +632,13 @@ nsresult ModuleLoaderBase::ResolveRequestedModules(
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> requestedModule(cx);
|
||||
JS::Rooted<JS::Value> element(cx);
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
if (!JS_GetElement(cx, requestedModules, i, &requestedModule)) {
|
||||
if (!JS_GetElement(cx, requestedModules, i, &element)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JS::Rooted<JSString*> str(
|
||||
cx, JS::GetRequestedModuleSpecifier(cx, requestedModule));
|
||||
JS::Rooted<JSString*> str(cx, JS::GetRequestedModuleSpecifier(cx, element));
|
||||
MOZ_ASSERT(str);
|
||||
|
||||
nsAutoJSString specifier;
|
||||
@@ -667,23 +649,21 @@ nsresult ModuleLoaderBase::ResolveRequestedModules(
|
||||
// Let url be the result of resolving a module specifier given module script
|
||||
// and requested.
|
||||
ModuleLoaderBase* loader = aRequest->mLoader;
|
||||
auto result = loader->ResolveModuleSpecifier(ms, specifier);
|
||||
if (result.isErr()) {
|
||||
nsCOMPtr<nsIURI> uri = loader->ResolveModuleSpecifier(ms, specifier);
|
||||
if (!uri) {
|
||||
uint32_t lineNumber = 0;
|
||||
uint32_t columnNumber = 0;
|
||||
JS::GetRequestedModuleSourcePos(cx, requestedModule, &lineNumber,
|
||||
&columnNumber);
|
||||
JS::GetRequestedModuleSourcePos(cx, element, &lineNumber, &columnNumber);
|
||||
|
||||
JS::Rooted<JS::Value> error(cx);
|
||||
nsresult rv = HandleResolveFailure(cx, ms, specifier, result.unwrapErr(),
|
||||
lineNumber, columnNumber, &error);
|
||||
nsresult rv = HandleResolveFailure(cx, ms, specifier, lineNumber,
|
||||
columnNumber, &error);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ms->SetParseError(error);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri = result.unwrap();
|
||||
if (aUrlsOut) {
|
||||
aUrlsOut->AppendElement(uri.forget());
|
||||
}
|
||||
@@ -1119,50 +1099,6 @@ void ModuleLoaderBase::CancelAndClearDynamicImports() {
|
||||
mDynamicImportRequests.CancelRequestsAndClear();
|
||||
}
|
||||
|
||||
UniquePtr<ImportMap> ModuleLoaderBase::ParseImportMap(
|
||||
ScriptLoadRequest* aRequest) {
|
||||
AutoJSAPI jsapi;
|
||||
if (!jsapi.Init(GetGlobalObject())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aRequest->IsTextSource());
|
||||
MaybeSourceText maybeSource;
|
||||
nsresult rv = aRequest->GetScriptSource(jsapi.cx(), &maybeSource);
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JS::SourceText<char16_t>& text = maybeSource.ref<SourceText<char16_t>>();
|
||||
ReportWarningHelper warning{mLoader, aRequest};
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script
|
||||
// https://wicg.github.io/import-maps/#integration-prepare-a-script
|
||||
// Insert the following case to prepare a script step 25.2:
|
||||
// (Impl Note: the latest html spec is step 27.2)
|
||||
// Switch on the script's type:
|
||||
// "importmap"
|
||||
// Step 1. Let import map parse result be the result of create an import map
|
||||
// parse result, given source text, base URL and settings object.
|
||||
//
|
||||
// Impl note: According to the spec, ImportMap::ParseString will throw a
|
||||
// TypeError if there's any invalid key/value in the text. After the parsing
|
||||
// is done, we should report the error if there's any, this is done in
|
||||
// ~AutoJSAPI.
|
||||
//
|
||||
// See https://wicg.github.io/import-maps/#register-an-import-map, step 7.
|
||||
return ImportMap::ParseString(jsapi.cx(), text, aRequest->mBaseURL, warning);
|
||||
}
|
||||
|
||||
void ModuleLoaderBase::RegisterImportMap(UniquePtr<ImportMap> aImportMap) {
|
||||
// Check for aImportMap is done in ScriptLoader.
|
||||
MOZ_ASSERT(aImportMap);
|
||||
|
||||
// Step 8. Set element’s node document's import map to import map parse
|
||||
// result’s import map.
|
||||
mImportMap = std::move(aImportMap);
|
||||
}
|
||||
|
||||
#undef LOG
|
||||
#undef LOG_ENABLED
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "LoadedScript.h"
|
||||
#include "ScriptLoadRequest.h"
|
||||
|
||||
#include "ImportMap.h"
|
||||
#include "js/TypeDecls.h" // JS::MutableHandle, JS::Handle, JS::Root
|
||||
#include "js/Modules.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
@@ -23,8 +22,6 @@
|
||||
#include "mozilla/dom/JSExecutionContext.h"
|
||||
#include "mozilla/MaybeOneOf.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "ResolveResult.h"
|
||||
|
||||
class nsIURI;
|
||||
|
||||
@@ -63,10 +60,6 @@ class ScriptLoaderInterface : public nsISupports {
|
||||
virtual void ReportErrorToConsole(ScriptLoadRequest* aRequest,
|
||||
nsresult aResult) const = 0;
|
||||
|
||||
virtual void ReportWarningToConsole(
|
||||
ScriptLoadRequest* aRequest, const char* aMessageName,
|
||||
const nsTArray<nsString>& aParams = nsTArray<nsString>()) const = 0;
|
||||
|
||||
// Fill in CompileOptions, as well as produce the introducer script for
|
||||
// subsequent calls to UpdateDebuggerMetadata
|
||||
virtual nsresult FillCompileOptionsForRequest(
|
||||
@@ -151,16 +144,9 @@ class ModuleLoaderBase : public nsISupports {
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> mGlobalObject;
|
||||
|
||||
// https://wicg.github.io/import-maps/#document-acquiring-import-maps
|
||||
//
|
||||
// Each Document has an acquiring import maps boolean. It is initially true.
|
||||
bool mAcquiringImportMaps = true;
|
||||
|
||||
protected:
|
||||
RefPtr<ScriptLoaderInterface> mLoader;
|
||||
|
||||
mozilla::UniquePtr<ImportMap> mImportMap;
|
||||
|
||||
virtual ~ModuleLoaderBase();
|
||||
|
||||
public:
|
||||
@@ -241,20 +227,6 @@ class ModuleLoaderBase : public nsISupports {
|
||||
void ProcessDynamicImport(ModuleLoadRequest* aRequest);
|
||||
void CancelAndClearDynamicImports();
|
||||
|
||||
// Process <script type="importmap">
|
||||
mozilla::UniquePtr<ImportMap> ParseImportMap(ScriptLoadRequest* aRequest);
|
||||
|
||||
// Implements https://wicg.github.io/import-maps/#register-an-import-map
|
||||
void RegisterImportMap(mozilla::UniquePtr<ImportMap> aImportMap);
|
||||
|
||||
/**
|
||||
* Getter and Setter for mAcquiringImportMaps.
|
||||
*/
|
||||
bool GetAcquiringImportMaps() const { return mAcquiringImportMaps; }
|
||||
void SetAcquiringImportMaps(bool acquiring) {
|
||||
mAcquiringImportMaps = acquiring;
|
||||
}
|
||||
|
||||
// Internal methods.
|
||||
|
||||
private:
|
||||
@@ -281,15 +253,14 @@ class ModuleLoaderBase : public nsISupports {
|
||||
static bool HostGetSupportedImportAssertions(
|
||||
JSContext* aCx, JS::ImportAssertionVector& aValues);
|
||||
|
||||
ResolveResult ResolveModuleSpecifier(LoadedScript* aScript,
|
||||
const nsAString& aSpecifier);
|
||||
already_AddRefed<nsIURI> ResolveModuleSpecifier(LoadedScript* aScript,
|
||||
const nsAString& aSpecifier);
|
||||
|
||||
static nsresult HandleResolveFailure(JSContext* aCx, LoadedScript* aScript,
|
||||
const nsAString& aSpecifier,
|
||||
ResolveError aError,
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber,
|
||||
JS::MutableHandle<JS::Value> aErrorOut);
|
||||
JS::MutableHandle<JS::Value> errorOut);
|
||||
|
||||
enum class RestartRequest { No, Yes };
|
||||
nsresult StartOrRestartModuleLoad(ModuleLoadRequest* aRequest,
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef js_loader_ResolveResult_h
|
||||
#define js_loader_ResolveResult_h
|
||||
|
||||
#include "mozilla/ResultVariant.h"
|
||||
#include "mozilla/NotNull.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
namespace JS::loader {
|
||||
|
||||
enum class ResolveError : uint8_t {
|
||||
ModuleResolveFailure,
|
||||
BlockedByNullEntry,
|
||||
BlockedByAfterPrefix,
|
||||
BlockedByBacktrackingPrefix,
|
||||
InvalidBareSpecifier
|
||||
};
|
||||
|
||||
struct ResolveErrorInfo {
|
||||
static const char* GetString(ResolveError aError) {
|
||||
switch (aError) {
|
||||
case ResolveError::ModuleResolveFailure:
|
||||
return "ModuleResolveFailure";
|
||||
case ResolveError::BlockedByNullEntry:
|
||||
return "ImportMapResolutionBlockedByNullEntry";
|
||||
case ResolveError::BlockedByAfterPrefix:
|
||||
return "ImportMapResolutionBlockedByAfterPrefix";
|
||||
case ResolveError::BlockedByBacktrackingPrefix:
|
||||
return "ImportMapResolutionBlockedByBacktrackingPrefix";
|
||||
case ResolveError::InvalidBareSpecifier:
|
||||
return "ImportMapResolveInvalidBareSpecifier";
|
||||
default:
|
||||
MOZ_CRASH("Unexpected ResolveError value");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ResolveResult is used to store the result of 'resolving a module specifier',
|
||||
* which could be an URI on success or a ResolveError on failure.
|
||||
*/
|
||||
using ResolveResult =
|
||||
mozilla::Result<mozilla::NotNull<nsCOMPtr<nsIURI>>, ResolveError>;
|
||||
} // namespace JS::loader
|
||||
|
||||
#endif // js_loader_ResolveResult_h
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace JS::loader {
|
||||
|
||||
enum class ScriptKind { eClassic, eModule, eEvent, eImportMap };
|
||||
enum class ScriptKind { eClassic, eModule, eEvent };
|
||||
|
||||
} // namespace JS::loader
|
||||
|
||||
|
||||
@@ -181,7 +181,6 @@ class ScriptLoadRequest
|
||||
mozilla::MaybeOneOf<JS::SourceText<char16_t>, JS::SourceText<Utf8Unit>>;
|
||||
|
||||
bool IsModuleRequest() const { return mKind == ScriptKind::eModule; }
|
||||
bool IsImportMapRequest() const { return mKind == ScriptKind::eImportMap; }
|
||||
|
||||
ModuleLoadRequest* AsModuleRequest();
|
||||
const ModuleLoadRequest* AsModuleRequest() const;
|
||||
|
||||
@@ -5,18 +5,15 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXPORTS.js.loader += [
|
||||
"ImportMap.h",
|
||||
"LoadContextBase.h",
|
||||
"LoadedScript.h",
|
||||
"ModuleLoaderBase.h",
|
||||
"ModuleLoadRequest.h",
|
||||
"ResolveResult.h",
|
||||
"ScriptKind.h",
|
||||
"ScriptLoadRequest.h",
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
"ImportMap.cpp",
|
||||
"LoadContextBase.cpp",
|
||||
"LoadedScript.cpp",
|
||||
"ModuleLoaderBase.cpp",
|
||||
|
||||
@@ -725,12 +725,6 @@ MSG_DEF(JSMSG_MISSING_EXPORT, 1, JSEXN_SYNTAXERR, "local binding for
|
||||
MSG_DEF(JSMSG_BAD_MODULE_STATUS, 0, JSEXN_INTERNALERR, "module record has unexpected status")
|
||||
MSG_DEF(JSMSG_DYNAMIC_IMPORT_FAILED, 0, JSEXN_TYPEERR, "error loading dynamically imported module")
|
||||
|
||||
// Import maps
|
||||
MSG_DEF(JSMSG_IMPORT_MAPS_NOT_A_MAP, 0, JSEXN_TYPEERR, "the top-level value needs to be a JSON object")
|
||||
MSG_DEF(JSMSG_IMPORT_MAPS_IMPORTS_NOT_A_MAP, 0, JSEXN_TYPEERR, "the imports top-level key needs to be a JSON object")
|
||||
MSG_DEF(JSMSG_IMPORT_MAPS_SCOPES_NOT_A_MAP, 0, JSEXN_TYPEERR, "the scopes top-level key needs to be a JSON object")
|
||||
MSG_DEF(JSMSG_IMPORT_MAPS_SCOPE_VALUE_NOT_A_MAP, 1, JSEXN_TYPEERR, "the value of the scope with prefix '{0}' needs to be a JSON object")
|
||||
|
||||
// Promise
|
||||
MSG_DEF(JSMSG_CANNOT_RESOLVE_PROMISE_WITH_ITSELF, 0, JSEXN_TYPEERR, "A promise cannot be resolved with itself.")
|
||||
MSG_DEF(JSMSG_PROMISE_CAPABILITY_HAS_SOMETHING_ALREADY, 0, JSEXN_TYPEERR, "GetCapabilitiesExecutor function already invoked with non-undefined values.")
|
||||
|
||||
@@ -2797,12 +2797,6 @@
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
# Is support for import maps (<script type="importmap">) enabled for content?
|
||||
- name: dom.importMaps.enabled
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# Whether we disable triggering mutation events for changes to style
|
||||
# attribute via CSSOM.
|
||||
# NOTE: This preference is used in unit tests. If it is removed or its default
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
prefs: [dom.importMaps.enabled:true]
|
||||
@@ -0,0 +1,2 @@
|
||||
implementation-status: backlog
|
||||
bug: https://github.com/mozilla/standards-positions/issues/146
|
||||
@@ -0,0 +1,5 @@
|
||||
[dynamic-import.html]
|
||||
expected: TIMEOUT
|
||||
[After dynamic imports, import maps should fire error events]
|
||||
expected: NOTRUN
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[script-tag.html]
|
||||
expected: TIMEOUT
|
||||
[After <script type="module"> import maps should fire error events]
|
||||
expected: NOTRUN
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[worker-request.html]
|
||||
[After module worker creation import maps are still effective]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
[bare-specifiers.sub.html]
|
||||
[bare/to-data: dynamic import (from text/javascript)]
|
||||
expected: FAIL
|
||||
|
||||
[bare/cross-origin-bare: static import]
|
||||
expected: FAIL
|
||||
|
||||
[bare/to-data: dynamic import (from module)]
|
||||
expected: FAIL
|
||||
|
||||
[bare/bare: dynamic import (from text/javascript)]
|
||||
expected: FAIL
|
||||
|
||||
[bare/cross-origin-bare: dynamic import (from module)]
|
||||
expected: FAIL
|
||||
|
||||
[bare/bare: dynamic import (from module)]
|
||||
expected: FAIL
|
||||
|
||||
[bare/cross-origin-bare: dynamic import (from text/javascript)]
|
||||
expected: FAIL
|
||||
|
||||
[bare/bare: static import]
|
||||
expected: FAIL
|
||||
|
||||
[bare/to-data: static import]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
[applied-to-target-dynamic.sub.html]
|
||||
[The URL after mapping violates CSP (but not the URL before mapping)]
|
||||
expected: FAIL
|
||||
|
||||
[The URL before mapping violates CSP (but not the URL after mapping)]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
[applied-to-target.sub.html]
|
||||
[The URL after mapping violates CSP (but not the URL before mapping)]
|
||||
expected: FAIL
|
||||
|
||||
[The URL before mapping violates CSP (but not the URL after mapping)]
|
||||
expected: FAIL
|
||||
|
||||
4
testing/web-platform/meta/import-maps/csp/hash.html.ini
Normal file
4
testing/web-platform/meta/import-maps/csp/hash.html.ini
Normal file
@@ -0,0 +1,4 @@
|
||||
[hash.html]
|
||||
[Importmap should be accepted due to hash]
|
||||
expected: FAIL
|
||||
|
||||
4
testing/web-platform/meta/import-maps/csp/nonce.html.ini
Normal file
4
testing/web-platform/meta/import-maps/csp/nonce.html.ini
Normal file
@@ -0,0 +1,4 @@
|
||||
[nonce.html]
|
||||
[Importmap should be accepted according to its correct nonce]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[unsafe-inline.html]
|
||||
[Importmap should be accepted due to unsafe-inline]
|
||||
expected: FAIL
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
[parsing-internal.https.html]
|
||||
disabled: https://github.com/web-platform-tests/wpt/issues/32697
|
||||
[Relative URL scope keys should work with /s, ?s, and #s]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
[resolving-internal.https.html]
|
||||
disabled: https://github.com/web-platform-tests/wpt/issues/32697
|
||||
[non-fetch scheme absolute URLs: wss:non-fetch-scheme]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -0,0 +1,387 @@
|
||||
[resolving.https.html]
|
||||
[Entries with errors shouldn't allow fallback: No fallback to absolute URL parsing: https://example.com/null]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: package submodules: moment/foo]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: Import map entries just composed from / and .: https://example.com/app/]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: Import map entries just composed from / and .: /app/]
|
||||
expected: FAIL
|
||||
|
||||
[Entries with errors shouldn't allow fallback: No fallback to less-specific prefixes: prefix-resolution-error/b/c/x]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: Base URLs inside the scope fallback to toplevel: moment/foo]
|
||||
expected: FAIL
|
||||
|
||||
[Fallback to toplevel and between scopes: should use a direct scope override: c]
|
||||
expected: FAIL
|
||||
|
||||
[Exact vs. prefix based matching: Scope with trailing slash only: Subpath base URL (prefix match): moment/foo]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: specifier with punctuation: ..\\]
|
||||
expected: FAIL
|
||||
|
||||
[Entries with errors shouldn't allow fallback: No fallback to less-specific prefixes: invalid-url/b/c/x]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: Base URLs outside a scope shouldn't use the scope even if the scope has matching keys: lodash-dot]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: Import map entries just composed from / and .: /]
|
||||
expected: FAIL
|
||||
|
||||
[Entries with errors shouldn't allow fallback: No fallback to less-specific prefixes: null/b/c/x]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: Base URLs inside the scope should use the scope if the scope has matching keys: lodash-dot/foo]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: explicitly-mapped specifiers that happen to have a slash: package/withslash]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: Base URLs outside a scope shouldn't use the scope even if the scope has matching keys: lodash-dotdot/foo]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: package main modules: lodash-dot]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: prefix-matched by keys with trailing slashes: https://example.com/app/test/foo.mjs]
|
||||
expected: FAIL
|
||||
|
||||
[should favor the most-specific key: Overlapping entries with trailing slashes: a/x]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: Base URLs inside the scope fallback to less specific scope: moment]
|
||||
expected: FAIL
|
||||
|
||||
[should favor the most-specific key: Overlapping entries with trailing slashes: a/b]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: package main modules: moment]
|
||||
expected: FAIL
|
||||
|
||||
[Entries with errors shouldn't allow fallback: No fallback to less-specific prefixes: invalid-url/x]
|
||||
expected: FAIL
|
||||
|
||||
[should favor the most-specific key: Overlapping entries with trailing slashes: a]
|
||||
expected: FAIL
|
||||
|
||||
[should favor the most-specific key: Overlapping entries with trailing slashes: a/]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: Base URLs inside the scope should use the scope if the scope has matching keys: lodash-dotdot/foo]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: specifier with punctuation: %2F]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: specifier with punctuation: %2E]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: should use the last entry's address when URL-like specifiers parse to the same absolute URL: /test]
|
||||
expected: FAIL
|
||||
|
||||
[Exact vs. prefix based matching: Scopes with and without trailing slash: Trailing-slash base URL (exact match): moment/foo]
|
||||
expected: FAIL
|
||||
|
||||
[should favor the most-specific key: Overlapping entries with trailing slashes: a/b/]
|
||||
expected: FAIL
|
||||
|
||||
[should favor the most-specific key: Overlapping entries with trailing slashes: a/b/c]
|
||||
expected: FAIL
|
||||
|
||||
[Entries with errors shouldn't allow fallback: No fallback to absolute URL parsing: https://example.com/invalid-url]
|
||||
expected: FAIL
|
||||
|
||||
[Exact vs. prefix based matching: Scope without trailing slash only: Non-trailing-slash base URL (exact match): moment/foo]
|
||||
expected: FAIL
|
||||
|
||||
[Relative URL scope keys: '../' scope is a scope with import map base URL's parent directory: a]
|
||||
expected: FAIL
|
||||
|
||||
[Entries with errors shouldn't allow fallback: No fallback to less-specific prefixes: without-trailing-slashes/b/c/x]
|
||||
expected: FAIL
|
||||
|
||||
[Entries with errors shouldn't allow fallback: No fallback to less-specific prefixes: without-trailing-slashes/x]
|
||||
expected: FAIL
|
||||
|
||||
[Relative URL scope keys: An empty string scope is a scope with import map base URL: c]
|
||||
expected: FAIL
|
||||
|
||||
[Relative URL scope keys: An empty string scope is a scope with import map base URL: a]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: Fallback to toplevel or not, depending on trailing slash match: moment]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: package main modules: lodash-dotdot]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: Base URLs inside the scope fallback to less specific scope: vue]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: Base URLs outside a scope shouldn't use the scope even if the scope has matching keys: lodash-dot/foo]
|
||||
expected: FAIL
|
||||
|
||||
[Exact vs. prefix based matching: Scope with trailing slash only: Subpath base URL (prefix match): moment]
|
||||
expected: FAIL
|
||||
|
||||
[Exact vs. prefix based matching: Scope with trailing slash only: Trailing-slash base URL (exact match): moment]
|
||||
expected: FAIL
|
||||
|
||||
[Exact vs. prefix based matching: Scope with trailing slash only: Trailing-slash base URL (exact match): moment/foo]
|
||||
expected: FAIL
|
||||
|
||||
[Exact vs. prefix based matching: Scope without trailing slash only: Non-trailing-slash base URL (exact match): moment]
|
||||
expected: FAIL
|
||||
|
||||
[Relative URL scope keys: '../' scope is a scope with import map base URL's parent directory: c]
|
||||
expected: FAIL
|
||||
|
||||
[Relative URL scope keys: '../' scope is a scope with import map base URL's parent directory: b]
|
||||
expected: FAIL
|
||||
|
||||
[Entries with errors shouldn't allow fallback: No fallback to absolute URL parsing: https://example.com/prefix-resolution-error/x]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: Import map entries just composed from / and .: https://example.com/]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: Base URLs inside the scope should use the scope if the scope has matching keys: lodash-dot]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: package names that end in a slash should just pass through: moment/]
|
||||
expected: FAIL
|
||||
|
||||
[Exact vs. prefix based matching: Scopes with and without trailing slash: Subpath base URL (prefix match): moment/foo]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: package submodules: lodash-dot/foo]
|
||||
expected: FAIL
|
||||
|
||||
[Exact vs. prefix based matching: Scopes with and without trailing slash: Non-trailing-slash base URL (exact match): moment]
|
||||
expected: FAIL
|
||||
|
||||
[Entries with errors shouldn't allow fallback: No fallback to less-specific prefixes: null/x]
|
||||
expected: FAIL
|
||||
|
||||
[Entries with errors shouldn't allow fallback: No fallback to absolute URL parsing: https://example.com/without-trailing-slashes/x]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: Base URLs outside a scope shouldn't use the scope even if the scope has matching keys: lodash-dotdot]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: package submodules: lodash-dotdot/foo]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: Import map entries just composed from / and .: ../]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: specifier with punctuation: ..]
|
||||
expected: FAIL
|
||||
|
||||
[Fallback to toplevel and between scopes: should use an indirect scope override: d]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: Base URLs inside the scope should use the scope if the scope has matching keys: lodash-dotdot]
|
||||
expected: FAIL
|
||||
|
||||
[Fallback to toplevel and between scopes: should use an indirect scope override: a]
|
||||
expected: FAIL
|
||||
|
||||
[Fallback to toplevel and between scopes: should use an indirect scope override: b]
|
||||
expected: FAIL
|
||||
|
||||
[Fallback to toplevel and between scopes: should use an indirect scope override: c]
|
||||
expected: FAIL
|
||||
|
||||
[Relative URL scope keys: './' scope is a scope with import map base URL's directory: c]
|
||||
expected: FAIL
|
||||
|
||||
[Relative URL scope keys: './' scope is a scope with import map base URL's directory: b]
|
||||
expected: FAIL
|
||||
|
||||
[Relative URL scope keys: './' scope is a scope with import map base URL's directory: a]
|
||||
expected: FAIL
|
||||
|
||||
[Exact vs. prefix based matching: Scopes with and without trailing slash: Non-trailing-slash base URL (exact match): moment/foo]
|
||||
expected: FAIL
|
||||
|
||||
[Entries with errors shouldn't allow fallback: No fallback to less-specific prefixes: prefix-resolution-error/x]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: Import map entries just composed from / and .: ../app/]
|
||||
expected: FAIL
|
||||
|
||||
[Fallback to toplevel and between scopes: should fall back to `imports` when no scopes match: d]
|
||||
expected: FAIL
|
||||
|
||||
[Fallback to toplevel and between scopes: should fall back to `imports` when no scopes match: a]
|
||||
expected: FAIL
|
||||
|
||||
[Fallback to toplevel and between scopes: should fall back to `imports` when no scopes match: c]
|
||||
expected: FAIL
|
||||
|
||||
[Fallback to toplevel and between scopes: should fall back to `imports` when no scopes match: b]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: Fallback to toplevel or not, depending on trailing slash match: moment/foo]
|
||||
expected: FAIL
|
||||
|
||||
[Exact vs. prefix based matching: Scopes with and without trailing slash: Trailing-slash base URL (exact match): moment]
|
||||
expected: FAIL
|
||||
|
||||
[Exact vs. prefix based matching: Scopes with and without trailing slash: Subpath base URL (prefix match): moment]
|
||||
expected: FAIL
|
||||
|
||||
[Relative URL scope keys: An empty string scope is a scope with import map base URL: b]
|
||||
expected: FAIL
|
||||
|
||||
[Fallback to toplevel and between scopes: should use a direct scope override: b]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: specifier with punctuation: .]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: prefix-matched by keys with trailing slashes: /test/foo.mjs]
|
||||
expected: FAIL
|
||||
|
||||
[Fallback to toplevel and between scopes: should use a direct scope override: a]
|
||||
expected: FAIL
|
||||
|
||||
[Fallback to toplevel and between scopes: should use a direct scope override: d]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: Ordinary URL-like specifiers: https://example.com/lib/foo.mjs]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: Bare specifiers are not normalized: %E3%81%8D%E3%81%A4%E3%81%AD/bar]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: backtracking via ..: mapped/non-ascii-1/]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: Ordinary URL-like specifiers: /lib/foo.mjs]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: backtracking via ..: mapped/path/WICG/import-maps/issues/207/]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: Bare specifiers are not normalized: %E3%81%8D%E3%81%A4%E3%81%AD/fox/bar]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: backtracking via ..: mapped/path/]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: backtracking (absolute URLs): https://example.com/test/../../backtrack]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: backtracking (absolute URLs): https://example.com/test/..]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: URL-like specifiers are normalized: https://map.example/%E3%81%8D%E3%81%A4%E3%81%AD/fox/bar]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: Ordinary URL-like specifiers: https://example.com/app/dotrelative/foo.mjs]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: Ordinary URL-like specifiers: https://///example.com/lib/foo.mjs]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: backtracking via ..: mapped/non-ascii-2/../%E3%81%8D%E3%81%A4%E3%81%AD/]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: Ordinary URL-like specifiers: https://example.com/dotdotrelative/foo.mjs]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: URL-like specifiers are normalized: https://map.example/%E3%81%8D%E3%81%A4%E3%81%AD/fox/]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: URL-like specifiers are normalized: https://map.example/きつね/fox/]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: URL-like specifiers are normalized: https://map.example/きつね/fox/bar]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: Bare specifiers are not normalized: %E3%81%8D%E3%81%A4%E3%81%AD/]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: backtracking (relative URLs): /test/..]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: backtracking via ..: mapped/path]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: backtracking via ..: mapped/path/../207/]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: Ordinary URL-like specifiers: ../app/dotrelative/foo.mjs]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: Ordinary URL-like specifiers: ../dotdotrelative/foo.mjs]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: backtracking via ..: mapped/non-ascii-2/]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: backtracking (relative URLs): /test/../../backtrack]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: backtracking (absolute URLs): https://example.com/test/../backtrack]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: backtracking via ..: mapped/non-ascii-1/../%E3%81%8D%E3%81%A4%E3%81%AD/]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: backtracking via ..: mapped/non-ascii-1/../きつね/]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: backtracking (relative URLs): /test/../../../backtrack]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: backtracking (absolute URLs): https://example.com/test/../../../backtrack]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: Bare specifiers are not normalized: きつね/fox/bar]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: URL-like specifiers are normalized: https://map.example/きつね/bar]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: Bare specifiers are not normalized: %E3%81%8D%E3%81%A4%E3%81%AD/fox/]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: URL-like specifiers are normalized: https://map.example/%E3%81%8D%E3%81%A4%E3%81%AD/]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: backtracking via ..: mapped/path//WICG/import-maps/issues/207/]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: URL-like specifiers are normalized: https://map.example/きつね/]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: backtracking via ..: mapped/non-ascii-2/../きつね/]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: URL-like specifiers are normalized: https://map.example/%E3%81%8D%E3%81%A4%E3%81%AD/bar]
|
||||
expected: FAIL
|
||||
|
||||
[Tricky specifiers: Bare specifiers are not normalized: きつね/fox/]
|
||||
expected: FAIL
|
||||
|
||||
[URL-like specifiers: backtracking (relative URLs): /test/../backtrack]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: package submodules: moment/foo?query]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: package submodules: moment/foo#fragment]
|
||||
expected: FAIL
|
||||
|
||||
[Package-like scenarios: package submodules: moment/foo?query#fragment]
|
||||
expected: FAIL
|
||||
@@ -0,0 +1,37 @@
|
||||
[data-url-specifiers.sub.html]
|
||||
[data:text/javascript,log.push('data:cross-origin-foo'): dynamic import (from module)]
|
||||
expected: FAIL
|
||||
|
||||
[data:text/javascript,log.push('data:to-data'): dynamic import (from text/javascript)]
|
||||
expected: FAIL
|
||||
|
||||
[data:text/javascript,log.push('data:foo'): static import]
|
||||
expected: FAIL
|
||||
|
||||
[data:text/javascript,log.push('data:to-data'): dynamic import (from module)]
|
||||
expected: FAIL
|
||||
|
||||
[data:text/javascript,log.push('data:to-bare'): dynamic import (from module)]
|
||||
expected: FAIL
|
||||
|
||||
[data:text/javascript,log.push('data:foo'): dynamic import (from text/javascript)]
|
||||
expected: FAIL
|
||||
|
||||
[data:text/javascript,log.push('data:to-data'): static import]
|
||||
expected: FAIL
|
||||
|
||||
[data:text/javascript,log.push('data:cross-origin-foo'): dynamic import (from text/javascript)]
|
||||
expected: FAIL
|
||||
|
||||
[data:text/javascript,log.push('data:to-bare'): static import]
|
||||
expected: FAIL
|
||||
|
||||
[data:text/javascript,log.push('data:to-bare'): dynamic import (from text/javascript)]
|
||||
expected: FAIL
|
||||
|
||||
[data:text/javascript,log.push('data:cross-origin-foo'): static import]
|
||||
expected: FAIL
|
||||
|
||||
[data:text/javascript,log.push('data:foo'): dynamic import (from module)]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
[http-url-like-specifiers.sub.html]
|
||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=foo: static import]
|
||||
expected: FAIL
|
||||
|
||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=to-bare: dynamic import (from module)]
|
||||
expected: FAIL
|
||||
|
||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=to-bare: static import]
|
||||
expected: FAIL
|
||||
|
||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=to-data: static import]
|
||||
expected: FAIL
|
||||
|
||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=cross-origin-foo: dynamic import (from module)]
|
||||
expected: FAIL
|
||||
|
||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=foo: dynamic import (from module)]
|
||||
expected: FAIL
|
||||
|
||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=cross-origin-foo: static import]
|
||||
expected: FAIL
|
||||
|
||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=to-data: dynamic import (from text/javascript)]
|
||||
expected: FAIL
|
||||
|
||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=cross-origin-foo: dynamic import (from text/javascript)]
|
||||
expected: FAIL
|
||||
|
||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=to-data: dynamic import (from module)]
|
||||
expected: FAIL
|
||||
|
||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=to-bare: dynamic import (from text/javascript)]
|
||||
expected: FAIL
|
||||
|
||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=foo: dynamic import (from text/javascript)]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[module-map-key.html]
|
||||
[Module map's key is the URL after import map resolution]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[basic.html]
|
||||
[Second import map should be rejected]
|
||||
expected: FAIL
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
[with-errors.html]
|
||||
disabled: https://github.com/WICG/import-maps/issues/278
|
||||
[Second import map should be rejected after an import map with errors]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[script-supports-importmap.html]
|
||||
[HTMLScriptElement.supports returns true for 'importmap']
|
||||
expected: FAIL
|
||||
@@ -1,124 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
// Currently import maps are not supported for web extensions, neither for
|
||||
// content scripts nor moz-extension documents.
|
||||
// For content scripts that's because they use their own sandbox module loaders,
|
||||
// which is different from the DOM module loader.
|
||||
// As for moz-extension documents, that's because inline script tags is not
|
||||
// allowed by CSP. (Currently import maps can be only added through inline
|
||||
// script tag.)
|
||||
//
|
||||
// This test is used to verified import maps are not supported for web
|
||||
// extensions.
|
||||
// See Bug 1765275: Enable Import maps for web extension content scripts.
|
||||
Services.prefs.setBoolPref("dom.importMaps.enabled", true);
|
||||
|
||||
const server = createHttpServer({ hosts: ["example.com"] });
|
||||
|
||||
const importMapString = `
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"simple": "./simple.js",
|
||||
"simple2": "./simple2.js"
|
||||
}
|
||||
}
|
||||
</script>`;
|
||||
|
||||
const importMapHtml = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset=utf-8>
|
||||
<title>Test a simple import map in normal webpage</title>
|
||||
<body>
|
||||
${importMapString}
|
||||
</body></html>`;
|
||||
|
||||
// page.html will load page.js, which will call import();
|
||||
const pageHtml = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset=utf-8>
|
||||
<title>Test a simple import map in moz-extension documents</title>
|
||||
<body>
|
||||
${importMapString}
|
||||
<script src="page.js"></script>
|
||||
</body></html>`;
|
||||
|
||||
const simple2JS = `export let foo = 2;`;
|
||||
|
||||
server.registerPathHandler("/importmap.html", (request, response) => {
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
response.write(importMapHtml);
|
||||
});
|
||||
|
||||
server.registerPathHandler("/simple.js", (request, response) => {
|
||||
ok(false, "Unexpected request to /simple.js");
|
||||
});
|
||||
|
||||
server.registerPathHandler("/simple2.js", (request, response) => {
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.setHeader("Content-Type", "text/javascript", false);
|
||||
response.write(simple2JS);
|
||||
});
|
||||
|
||||
add_task(async function test_importMaps_not_supported() {
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
content_scripts: [
|
||||
{
|
||||
matches: ["http://example.com/importmap.html"],
|
||||
js: ["main.js"],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
files: {
|
||||
"main.js": async function() {
|
||||
// Content scripts shouldn't be able to use the bare specifier from
|
||||
// the import map.
|
||||
await browser.test.assertRejects(
|
||||
import("simple"),
|
||||
/The specifier “simple” was a bare specifier/,
|
||||
`should reject import("simple")`
|
||||
);
|
||||
|
||||
browser.test.sendMessage("done");
|
||||
},
|
||||
"page.html": pageHtml,
|
||||
"page.js": async function() {
|
||||
await browser.test.assertRejects(
|
||||
import("simple"),
|
||||
/The specifier “simple” was a bare specifier/,
|
||||
`should reject import("simple")`
|
||||
);
|
||||
browser.test.sendMessage("page-done");
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
let contentPage = await ExtensionTestUtils.loadContentPage(
|
||||
"http://example.com/importmap.html"
|
||||
);
|
||||
await extension.awaitMessage("done");
|
||||
|
||||
await contentPage.spawn(null, async () => {
|
||||
// Import maps should work for documents.
|
||||
let promise = content.eval(`import("simple2")`);
|
||||
let mod = (await promise.wrappedJSObject).wrappedJSObject;
|
||||
Assert.equal(mod.foo, 2, "mod.foo should be 2");
|
||||
});
|
||||
|
||||
// moz-extension documents doesn't allow inline scripts, so the import map
|
||||
// script tag won't be processed.
|
||||
let url = `moz-extension://${extension.uuid}/page.html`;
|
||||
let page = await ExtensionTestUtils.loadContentPage(url, { extension });
|
||||
await extension.awaitMessage("page-done");
|
||||
|
||||
await contentPage.close();
|
||||
await page.close();
|
||||
await extension.unload();
|
||||
});
|
||||
@@ -85,7 +85,6 @@ skip-if =
|
||||
os == "mac" && debug && fission # Bug 1762638
|
||||
[test_ext_contentscript_dynamic_registration.js]
|
||||
[test_ext_contentscript_exporthelpers.js]
|
||||
[test_ext_contentscript_importmap.js]
|
||||
[test_ext_contentscript_in_background.js]
|
||||
skip-if = os == "android" # Bug 1700482
|
||||
[test_ext_contentscript_json_api.js]
|
||||
|
||||
Reference in New Issue
Block a user