summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/import-maps/resources
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
commit0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch)
treea31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /testing/web-platform/tests/import-maps/resources
parentInitial commit. (diff)
downloadfirefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz
firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/import-maps/resources')
-rw-r--r--testing/web-platform/tests/import-maps/resources/empty.js0
-rw-r--r--testing/web-platform/tests/import-maps/resources/inject-base.js3
-rw-r--r--testing/web-platform/tests/import-maps/resources/log.js1
-rw-r--r--testing/web-platform/tests/import-maps/resources/log.js.headers1
-rw-r--r--testing/web-platform/tests/import-maps/resources/test-helper.js246
5 files changed, 251 insertions, 0 deletions
diff --git a/testing/web-platform/tests/import-maps/resources/empty.js b/testing/web-platform/tests/import-maps/resources/empty.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/tests/import-maps/resources/empty.js
diff --git a/testing/web-platform/tests/import-maps/resources/inject-base.js b/testing/web-platform/tests/import-maps/resources/inject-base.js
new file mode 100644
index 0000000000..4d469aec89
--- /dev/null
+++ b/testing/web-platform/tests/import-maps/resources/inject-base.js
@@ -0,0 +1,3 @@
+const el = document.createElement("base");
+el.href = "{{GET[baseurl]}}";
+document.currentScript.after(el);
diff --git a/testing/web-platform/tests/import-maps/resources/log.js b/testing/web-platform/tests/import-maps/resources/log.js
new file mode 100644
index 0000000000..a024a29bf2
--- /dev/null
+++ b/testing/web-platform/tests/import-maps/resources/log.js
@@ -0,0 +1 @@
+log.push("log:{{GET[name]}}");
diff --git a/testing/web-platform/tests/import-maps/resources/log.js.headers b/testing/web-platform/tests/import-maps/resources/log.js.headers
new file mode 100644
index 0000000000..cb762eff80
--- /dev/null
+++ b/testing/web-platform/tests/import-maps/resources/log.js.headers
@@ -0,0 +1 @@
+Access-Control-Allow-Origin: *
diff --git a/testing/web-platform/tests/import-maps/resources/test-helper.js b/testing/web-platform/tests/import-maps/resources/test-helper.js
new file mode 100644
index 0000000000..f12e84c685
--- /dev/null
+++ b/testing/web-platform/tests/import-maps/resources/test-helper.js
@@ -0,0 +1,246 @@
+let log = [];
+
+function expect_log(test, expected_log) {
+ test.step_func_done(() => {
+ const actual_log = log;
+ log = [];
+ assert_array_equals(actual_log, expected_log, 'fallback log');
+ })();
+}
+
+// Results of resolving a specifier using import maps.
+const Result = {
+ // A failure considered as a fetch error in a module script tree.
+ // <script>'s error event is fired.
+ FETCH_ERROR: "fetch_error",
+
+ // A failure considered as a parse error in a module script tree.
+ // Window's error event is fired.
+ PARSE_ERROR: "parse_error",
+
+ // The specifier is considered as a relative or absolute URL.
+ // Specifier Expected log
+ // ------------------------- ----------------------
+ // ...?name=foo log:foo
+ // data:...log('foo') foo
+ // Others, e.g. bare/bare relative:bare/bare
+ // ------------------------- ----------------------
+ // (The last case assumes a file `bare/bare` that logs `relative:bare/bare`
+ // exists)
+ URL: "URL",
+};
+
+const Handler = {
+ // Handlers for <script> element cases.
+ // Note that on a parse error both WindowErrorEvent and ScriptLoadEvent are
+ // called.
+ ScriptLoadEvent: "<script> element's load event handler",
+ ScriptErrorEvent: "<script> element's error event handler",
+ WindowErrorEvent: "window's error event handler",
+
+ // Handlers for dynamic imports.
+ DynamicImportResolve: "dynamic import resolve",
+ DynamicImportReject: "dynamic import reject",
+};
+
+// Returns a map with Handler.* as the keys.
+function getHandlers(t, specifier, expected) {
+ let handlers = {};
+ handlers[Handler.ScriptLoadEvent] = t.unreached_func("Shouldn't load");
+ handlers[Handler.ScriptErrorEvent] =
+ t.unreached_func("script's error event shouldn't be fired");
+ handlers[Handler.WindowErrorEvent] =
+ t.unreached_func("window's error event shouldn't be fired");
+ handlers[Handler.DynamicImportResolve] =
+ t.unreached_func("dynamic import promise shouldn't be resolved");
+ handlers[Handler.DynamicImportReject] =
+ t.unreached_func("dynamic import promise shouldn't be rejected");
+
+ if (expected === Result.FETCH_ERROR) {
+ handlers[Handler.ScriptErrorEvent] = () => expect_log(t, []);
+ handlers[Handler.DynamicImportReject] = () => expect_log(t, []);
+ } else if (expected === Result.PARSE_ERROR) {
+ let error_occurred = false;
+ handlers[Handler.WindowErrorEvent] = () => { error_occurred = true; };
+ handlers[Handler.ScriptLoadEvent] = t.step_func(() => {
+ // Even if a parse error occurs, load event is fired (after
+ // window.onerror is called), so trigger the load handler only if
+ // there was no previous window.onerror call.
+ assert_true(error_occurred, "window.onerror should be fired");
+ expect_log(t, []);
+ });
+ handlers[Handler.DynamicImportReject] = t.step_func(() => {
+ assert_false(error_occurred,
+ "window.onerror shouldn't be fired for dynamic imports");
+ expect_log(t, []);
+ });
+ } else {
+ let expected_log;
+ if (expected === Result.URL) {
+ const match_data_url = specifier.match(/data:.*log\.push\('(.*)'\)/);
+ const match_log_js = specifier.match(/name=(.*)/);
+ if (match_data_url) {
+ expected_log = [match_data_url[1]];
+ } else if (match_log_js) {
+ expected_log = ["log:" + match_log_js[1]];
+ } else {
+ expected_log = ["relative:" + specifier];
+ }
+ } else {
+ expected_log = [expected];
+ }
+ handlers[Handler.ScriptLoadEvent] = () => expect_log(t, expected_log);
+ handlers[Handler.DynamicImportResolve] = () => expect_log(t, expected_log);
+ }
+ return handlers;
+}
+
+// Creates an <iframe> and run a test inside the <iframe>
+// to separate the module maps and import maps in each test.
+function testInIframe(importMapString, importMapBaseURL, testScript) {
+ const iframe = document.createElement('iframe');
+ document.body.appendChild(iframe);
+ if (!importMapBaseURL) {
+ importMapBaseURL = document.baseURI;
+ }
+ let content = `
+ <script src="/resources/testharness.js"></script>
+ <script src="/import-maps/resources/test-helper.js"></script>
+ <base href="${importMapBaseURL}">
+ <script type="importmap">${importMapString}</script>
+ <body>
+ <script>
+ setup({ allow_uncaught_exception: true });
+ ${testScript}
+ </sc` + `ript>
+ `;
+ iframe.contentDocument.write(content);
+ iframe.contentDocument.close();
+ return fetch_tests_from_window(iframe.contentWindow);
+}
+
+function testScriptElement(importMapString, importMapBaseURL, specifier, expected, type) {
+ return testInIframe(importMapString, importMapBaseURL, `
+ const t = async_test("${specifier}: <script src type=${type}>");
+ const handlers = getHandlers(t, "${specifier}", "${expected}");
+ const script = document.createElement("script");
+ script.setAttribute("type", "${type}");
+ script.setAttribute("src", "${specifier}");
+ script.addEventListener("load", handlers[Handler.ScriptLoadEvent]);
+ script.addEventListener("error", handlers[Handler.ScriptErrorEvent]);
+ window.addEventListener("error", handlers[Handler.WindowErrorEvent]);
+ document.body.appendChild(script);
+ `);
+}
+
+function testStaticImport(importMapString, importMapBaseURL, specifier, expected) {
+ return testInIframe(importMapString, importMapBaseURL, `
+ const t = async_test("${specifier}: static import");
+ const handlers = getHandlers(t, "${specifier}", "${expected}");
+ const script = document.createElement("script");
+ script.setAttribute("type", "module");
+ script.setAttribute("src",
+ "/import-maps/static-import.py?url=" +
+ encodeURIComponent("${specifier}"));
+ script.addEventListener("load", handlers[Handler.ScriptLoadEvent]);
+ script.addEventListener("error", handlers[Handler.ScriptErrorEvent]);
+ window.addEventListener("error", handlers[Handler.WindowErrorEvent]);
+ document.body.appendChild(script);
+ `);
+}
+
+function testDynamicImport(importMapString, importMapBaseURL, specifier, expected, type) {
+ return testInIframe(importMapString, importMapBaseURL, `
+ const t = async_test("${specifier}: dynamic import (from ${type})");
+ const handlers = getHandlers(t, "${specifier}", "${expected}");
+ const script = document.createElement("script");
+ script.setAttribute("type", "${type}");
+ script.innerText =
+ "import(\\"${specifier}\\")" +
+ ".then(handlers[Handler.DynamicImportResolve], " +
+ "handlers[Handler.DynamicImportReject]);";
+ script.addEventListener("error",
+ t.unreached_func("top-level inline script shouldn't error"));
+ document.body.appendChild(script);
+ `);
+}
+
+function testInIframeInjectBase(importMapString, importMapBaseURL, testScript) {
+ const iframe = document.createElement('iframe');
+ document.body.appendChild(iframe);
+ let content = `
+ <script src="/resources/testharness.js"></script>
+ <script src="/import-maps/resources/test-helper.js"></script>
+ <script src="/import-maps/resources/inject-base.js?pipe=sub&baseurl=${importMapBaseURL}"></script>
+ <script type="importmap">
+ ${importMapString}
+ </script>
+ <body>
+ <script>
+ setup({ allow_uncaught_exception: true });
+ ${testScript}
+ </sc` + `ript>
+ `;
+ iframe.contentDocument.write(content);
+ iframe.contentDocument.close();
+ return fetch_tests_from_window(iframe.contentWindow);
+}
+
+function testStaticImportInjectBase(importMapString, importMapBaseURL, specifier, expected) {
+ return testInIframeInjectBase(importMapString, importMapBaseURL, `
+ const t = async_test("${specifier}: static import with inject <base>");
+ const handlers = getHandlers(t, "${specifier}", "${expected}");
+ const script = document.createElement("script");
+ script.setAttribute("type", "module");
+ script.setAttribute("src",
+ "/import-maps/static-import.py?url=" +
+ encodeURIComponent("${specifier}"));
+ script.addEventListener("load", handlers[Handler.ScriptLoadEvent]);
+ script.addEventListener("error", handlers[Handler.ScriptErrorEvent]);
+ window.addEventListener("error", handlers[Handler.WindowErrorEvent]);
+ document.body.appendChild(script);
+ `);
+}
+
+function testDynamicImportInjectBase(importMapString, importMapBaseURL, specifier, expected, type) {
+ return testInIframeInjectBase(importMapString, importMapBaseURL, `
+ const t = async_test("${specifier}: dynamic import (from ${type}) with inject <base>");
+ const handlers = getHandlers(t, "${specifier}", "${expected}");
+ const script = document.createElement("script");
+ script.setAttribute("type", "${type}");
+ script.innerText =
+ "import(\\"${specifier}\\")" +
+ ".then(handlers[Handler.DynamicImportResolve], " +
+ "handlers[Handler.DynamicImportReject]);";
+ script.addEventListener("error",
+ t.unreached_func("top-level inline script shouldn't error"));
+ document.body.appendChild(script);
+ `);
+}
+
+function doTests(importMapString, importMapBaseURL, tests) {
+ promise_setup(function () {
+ return new Promise((resolve) => {
+ window.addEventListener("load", async () => {
+ for (const specifier in tests) {
+ // <script src> (module scripts)
+ await testScriptElement(importMapString, importMapBaseURL, specifier, tests[specifier][0], "module");
+
+ // <script src> (classic scripts)
+ await testScriptElement(importMapString, importMapBaseURL, specifier, tests[specifier][1], "text/javascript");
+
+ // static imports.
+ await testStaticImport(importMapString, importMapBaseURL, specifier, tests[specifier][2]);
+
+ // dynamic imports from a module script.
+ await testDynamicImport(importMapString, importMapBaseURL, specifier, tests[specifier][3], "module");
+
+ // dynamic imports from a classic script.
+ await testDynamicImport(importMapString, importMapBaseURL, specifier, tests[specifier][3], "text/javascript");
+ }
+ done();
+ resolve();
+ });
+ });
+ }, { explicit_done: true });
+}