summaryrefslogtreecommitdiffstats
path: root/dom/base/test/jsmodules
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/base/test/jsmodules/.eslintrc.js7
-rw-r--r--dom/base/test/jsmodules/chrome.ini53
-rw-r--r--dom/base/test/jsmodules/iframe_extractIntroType.html14
-rw-r--r--dom/base/test/jsmodules/importmaps/chrome.ini29
-rw-r--r--dom/base/test/jsmodules/importmaps/external_importMap.js5
-rw-r--r--dom/base/test/jsmodules/importmaps/insert_a_base_element.js4
-rw-r--r--dom/base/test/jsmodules/importmaps/module_simpleExport.js1
-rw-r--r--dom/base/test/jsmodules/importmaps/module_simpleImportMap.js2
-rw-r--r--dom/base/test/jsmodules/importmaps/module_simpleImportMap_dir.js2
-rw-r--r--dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap.js2
-rw-r--r--dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap_https.js2
-rw-r--r--dom/base/test/jsmodules/importmaps/module_sortedImportMap.js4
-rw-r--r--dom/base/test/jsmodules/importmaps/moz.build7
-rw-r--r--dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.js1
-rw-r--r--dom/base/test/jsmodules/importmaps/scope1/module_simpleImportMap.js2
-rw-r--r--dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleExport.js1
-rw-r--r--dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleImportMap.js2
-rw-r--r--dom/base/test/jsmodules/importmaps/test_dynamic_import_reject_importMap.html46
-rw-r--r--dom/base/test/jsmodules/importmaps/test_externalImportMap.html43
-rw-r--r--dom/base/test/jsmodules/importmaps/test_import_meta_resolve_importMap.html49
-rw-r--r--dom/base/test/jsmodules/importmaps/test_inline_module_reject_importMap.html61
-rw-r--r--dom/base/test/jsmodules/importmaps/test_load_importMap_with_base.html51
-rw-r--r--dom/base/test/jsmodules/importmaps/test_load_importMap_with_base2.html51
-rw-r--r--dom/base/test/jsmodules/importmaps/test_module_script_reject_importMap.html45
-rw-r--r--dom/base/test/jsmodules/importmaps/test_parse_importMap_failed.html40
-rw-r--r--dom/base/test/jsmodules/importmaps/test_reject_multiple_importMaps.html64
-rw-r--r--dom/base/test/jsmodules/importmaps/test_simpleImportMap.html62
-rw-r--r--dom/base/test/jsmodules/importmaps/test_sortedImportMap.html62
-rw-r--r--dom/base/test/jsmodules/module_badImport.js1
-rw-r--r--dom/base/test/jsmodules/module_badSyntax.js3
-rw-r--r--dom/base/test/jsmodules/module_cyclic1.js8
-rw-r--r--dom/base/test/jsmodules/module_cyclic2.js8
-rw-r--r--dom/base/test/jsmodules/module_cyclic3.js8
-rw-r--r--dom/base/test/jsmodules/module_extractIntroType.js5
-rw-r--r--dom/base/test/jsmodules/module_large1.js78
-rw-r--r--dom/base/test/jsmodules/module_large2.js78
-rw-r--r--dom/base/test/jsmodules/module_large3.js78
-rw-r--r--dom/base/test/jsmodules/module_missingImport.js1
-rw-r--r--dom/base/test/jsmodules/module_multiImports.js4
-rw-r--r--dom/base/test/jsmodules/module_multiLargeImports.js4
-rw-r--r--dom/base/test/jsmodules/module_setRan.js2
-rw-r--r--dom/base/test/jsmodules/module_simple1.js1
-rw-r--r--dom/base/test/jsmodules/module_simple2.js1
-rw-r--r--dom/base/test/jsmodules/module_simple3.js1
-rw-r--r--dom/base/test/jsmodules/module_simpleExport.js1
-rw-r--r--dom/base/test/jsmodules/module_simpleImport.js2
-rw-r--r--dom/base/test/jsmodules/module_testSyntax.js3
-rw-r--r--dom/base/test/jsmodules/moz.build7
-rw-r--r--dom/base/test/jsmodules/script_simple2.js1
-rw-r--r--dom/base/test/jsmodules/test_asyncInlineModules.html36
-rw-r--r--dom/base/test/jsmodules/test_cyclicImport.html18
-rw-r--r--dom/base/test/jsmodules/test_dynamicImportErrorMessage.html16
-rw-r--r--dom/base/test/jsmodules/test_importIntroType.html22
-rw-r--r--dom/base/test/jsmodules/test_importNotFound.html27
-rw-r--r--dom/base/test/jsmodules/test_importResolveFailed.html21
-rw-r--r--dom/base/test/jsmodules/test_import_meta_resolve.html65
-rw-r--r--dom/base/test/jsmodules/test_importedModuleMemoization.html30
-rw-r--r--dom/base/test/jsmodules/test_linkErrorInCommon1.html32
-rw-r--r--dom/base/test/jsmodules/test_linkErrorInCommon2.html32
-rw-r--r--dom/base/test/jsmodules/test_moduleNotFound.html24
-rw-r--r--dom/base/test/jsmodules/test_moduleParsedAsModule.html23
-rw-r--r--dom/base/test/jsmodules/test_moduleScriptsRun.html19
-rw-r--r--dom/base/test/jsmodules/test_multiAsyncImports.html30
-rw-r--r--dom/base/test/jsmodules/test_multiModuleImports.html28
-rw-r--r--dom/base/test/jsmodules/test_multiModuleLargeImports.html28
-rw-r--r--dom/base/test/jsmodules/test_multiTopLevelImports.html30
-rw-r--r--dom/base/test/jsmodules/test_multiTopLevelLargeImports.html30
-rw-r--r--dom/base/test/jsmodules/test_scriptInsertedModule.html20
-rw-r--r--dom/base/test/jsmodules/test_scriptModuleOrder.html30
-rw-r--r--dom/base/test/jsmodules/test_scriptNotParsedAsModule.html23
-rw-r--r--dom/base/test/jsmodules/test_simpleImport.html16
-rw-r--r--dom/base/test/jsmodules/test_syntaxError.html30
-rw-r--r--dom/base/test/jsmodules/test_syntaxErrorAsync.html30
-rw-r--r--dom/base/test/jsmodules/test_syntaxErrorInline.html34
-rw-r--r--dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html34
-rw-r--r--dom/base/test/jsmodules/test_topLevelIntroType.html21
-rw-r--r--dom/base/test/jsmodules/test_toplevelModuleMemoization.html30
-rw-r--r--dom/base/test/jsmodules/test_typeAttrCaseInsensitive.html19
78 files changed, 1805 insertions, 0 deletions
diff --git a/dom/base/test/jsmodules/.eslintrc.js b/dom/base/test/jsmodules/.eslintrc.js
new file mode 100644
index 0000000000..f811aa790b
--- /dev/null
+++ b/dom/base/test/jsmodules/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+ parserOptions: {
+ sourceType: "module",
+ },
+};
diff --git a/dom/base/test/jsmodules/chrome.ini b/dom/base/test/jsmodules/chrome.ini
new file mode 100644
index 0000000000..2b75dab150
--- /dev/null
+++ b/dom/base/test/jsmodules/chrome.ini
@@ -0,0 +1,53 @@
+[DEFAULT]
+support-files =
+ module_setRan.js
+ module_testSyntax.js
+ module_badSyntax.js
+ module_simpleImport.js
+ module_simpleExport.js
+ module_badImport.js
+ module_simple1.js
+ module_simple2.js
+ module_simple3.js
+ module_cyclic1.js
+ module_cyclic2.js
+ module_cyclic3.js
+ module_multiImports.js
+ module_multiLargeImports.js
+ script_simple2.js
+ module_large1.js
+ module_large2.js
+ module_large3.js
+ module_extractIntroType.js
+ iframe_extractIntroType.html
+ module_missingImport.js
+
+[test_moduleScriptsRun.html]
+[test_moduleParsedAsModule.html]
+[test_scriptNotParsedAsModule.html]
+[test_typeAttrCaseInsensitive.html]
+[test_moduleNotFound.html]
+[test_import_meta_resolve.html]
+[test_importNotFound.html]
+[test_syntaxError.html]
+[test_syntaxErrorAsync.html]
+[test_syntaxErrorInline.html]
+[test_syntaxErrorInlineAsync.html]
+[test_simpleImport.html]
+[test_cyclicImport.html]
+[test_importResolveFailed.html]
+[test_multiTopLevelImports.html]
+[test_multiModuleImports.html]
+[test_multiAsyncImports.html]
+[test_scriptModuleOrder.html]
+[test_toplevelModuleMemoization.html]
+[test_importedModuleMemoization.html]
+[test_multiTopLevelLargeImports.html]
+[test_multiModuleLargeImports.html]
+[test_asyncInlineModules.html]
+[test_scriptInsertedModule.html]
+[test_linkErrorInCommon1.html]
+[test_linkErrorInCommon2.html]
+[test_topLevelIntroType.html]
+[test_importIntroType.html]
+[test_dynamicImportErrorMessage.html]
diff --git a/dom/base/test/jsmodules/iframe_extractIntroType.html b/dom/base/test/jsmodules/iframe_extractIntroType.html
new file mode 100644
index 0000000000..26c58aea6d
--- /dev/null
+++ b/dom/base/test/jsmodules/iframe_extractIntroType.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ // Hook up the debugger statement to extract the calling script's
+ // introductionType and set it in a property on the parent global.
+ const {addSandboxedDebuggerToGlobal} = ChromeUtils.importESModule("resource://gre/modules/jsdebugger.sys.mjs");
+ addSandboxedDebuggerToGlobal(globalThis);
+ var dbg = new Debugger;
+ dbg.addDebuggee(parent);
+ dbg.onDebuggerStatement = function (frame) {
+ parent.introType = frame.script.source.introductionType;
+ }
+</script>
diff --git a/dom/base/test/jsmodules/importmaps/chrome.ini b/dom/base/test/jsmodules/importmaps/chrome.ini
new file mode 100644
index 0000000000..4fca7e97fa
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/chrome.ini
@@ -0,0 +1,29 @@
+[DEFAULT]
+support-files =
+ external_importMap.js
+ insert_a_base_element.js
+ module_simpleImportMap.js
+ module_simpleImportMap_dir.js
+ module_simpleImportMap_remap.js
+ module_simpleImportMap_remap_https.js
+ module_simpleExport.js
+ module_sortedImportMap.js
+ scope1/module_simpleExport.js
+ scope1/module_simpleImportMap.js
+ scope1/scope2/module_simpleExport.js
+ scope1/scope2/module_simpleImportMap.js
+prefs =
+ dom.importMaps.enabled=true
+
+[test_dynamic_import_reject_importMap.html]
+[test_externalImportMap.html]
+[test_import_meta_resolve_importMap.html]
+[test_inline_module_reject_importMap.html]
+[test_load_importMap_with_base.html]
+[test_load_importMap_with_base2.html]
+[test_module_script_reject_importMap.html]
+[test_parse_importMap_failed.html]
+[test_reject_multiple_importMaps.html]
+[test_simpleImportMap.html]
+[test_sortedImportMap.html]
+
diff --git a/dom/base/test/jsmodules/importmaps/external_importMap.js b/dom/base/test/jsmodules/importmaps/external_importMap.js
new file mode 100644
index 0000000000..e89d9f618f
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/external_importMap.js
@@ -0,0 +1,5 @@
+let imap = {
+ imports: {
+ foo: "./foo.js",
+ },
+};
diff --git a/dom/base/test/jsmodules/importmaps/insert_a_base_element.js b/dom/base/test/jsmodules/importmaps/insert_a_base_element.js
new file mode 100644
index 0000000000..435af97d1e
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/insert_a_base_element.js
@@ -0,0 +1,4 @@
+const el = document.createElement("base");
+el.href =
+ "chrome://mochitests/content/chrome/dom/base/test/jsmodules/importmaps/scope1/";
+document.currentScript.after(el);
diff --git a/dom/base/test/jsmodules/importmaps/module_simpleExport.js b/dom/base/test/jsmodules/importmaps/module_simpleExport.js
new file mode 100644
index 0000000000..9714d6d0ab
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_simpleExport.js
@@ -0,0 +1 @@
+export let x = 42;
diff --git a/dom/base/test/jsmodules/importmaps/module_simpleImportMap.js b/dom/base/test/jsmodules/importmaps/module_simpleImportMap.js
new file mode 100644
index 0000000000..153b84e6de
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_simpleImportMap.js
@@ -0,0 +1,2 @@
+import { x } from "simple";
+result = x;
diff --git a/dom/base/test/jsmodules/importmaps/module_simpleImportMap_dir.js b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_dir.js
new file mode 100644
index 0000000000..554cc6a7bd
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_dir.js
@@ -0,0 +1,2 @@
+import { x } from "dir/module_simpleExport.js";
+result_dir = x + 1;
diff --git a/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap.js b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap.js
new file mode 100644
index 0000000000..5ebaa30188
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap.js
@@ -0,0 +1,2 @@
+import { x } from "./module.js";
+result_remap = x + 2;
diff --git a/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap_https.js b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap_https.js
new file mode 100644
index 0000000000..c047fd28c3
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap_https.js
@@ -0,0 +1,2 @@
+import { x } from "https://example.com/module.js";
+result_remap_https = x + 3;
diff --git a/dom/base/test/jsmodules/importmaps/module_sortedImportMap.js b/dom/base/test/jsmodules/importmaps/module_sortedImportMap.js
new file mode 100644
index 0000000000..41b2903097
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_sortedImportMap.js
@@ -0,0 +1,4 @@
+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;
diff --git a/dom/base/test/jsmodules/importmaps/moz.build b/dom/base/test/jsmodules/importmaps/moz.build
new file mode 100644
index 0000000000..1a7d5281ea
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/moz.build
@@ -0,0 +1,7 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+MOCHITEST_CHROME_MANIFESTS += ["chrome.ini"]
diff --git a/dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.js b/dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.js
new file mode 100644
index 0000000000..e6b0ed1c0c
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.js
@@ -0,0 +1 @@
+export let x = 84;
diff --git a/dom/base/test/jsmodules/importmaps/scope1/module_simpleImportMap.js b/dom/base/test/jsmodules/importmaps/scope1/module_simpleImportMap.js
new file mode 100644
index 0000000000..b1682e1900
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/scope1/module_simpleImportMap.js
@@ -0,0 +1,2 @@
+import { x } from "simple";
+result_scope1 = x;
diff --git a/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleExport.js b/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleExport.js
new file mode 100644
index 0000000000..ba2bbae16b
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleExport.js
@@ -0,0 +1 @@
+export let x = 126;
diff --git a/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleImportMap.js b/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleImportMap.js
new file mode 100644
index 0000000000..ecb38b7b21
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleImportMap.js
@@ -0,0 +1,2 @@
+import { x } from "simple";
+result_scope2 = x;
diff --git a/dom/base/test/jsmodules/importmaps/test_dynamic_import_reject_importMap.html b/dom/base/test/jsmodules/importmaps/test_dynamic_import_reject_importMap.html
new file mode 100644
index 0000000000..75471064f9
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/test_dynamic_import_reject_importMap.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<head>
+ <meta charset=utf-8>
+ <title>Test import map should be rejected.</title>
+</head>
+<body onload='testLoaded()'>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<!--There is a dynamic import before the import map tag, so the import map-->
+<!--cannot be accepted according to the spec.-->
+<!--And because the import map is rejected, so the module specifier-->
+<!--"./module_simpleExport.js" won't be remapped to-->
+<!--"./scope1/module_simpleExport.js".-->
+
+<script>
+ import("./module_simpleExport.js");
+</script>
+
+<script type="importmap" onerror='importMapError()'>
+{
+ "imports": {
+ "./module_simpleExport.js": "./scope1/module_simpleExport.js"
+ }
+}
+</script>
+
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ let hasError = false;
+ function importMapError() {
+ hasError = true;
+ }
+
+ function testLoaded() {
+ import("./module_simpleExport.js").then((ns) => {
+ ok(ns.x == 42, 'Check simple imported value result: ' + ns.x);
+ ok(hasError, "onerror of the import map should be called.");
+ }).catch((e) => {
+ ok(false, "throws " + e);
+ }).then(() => {
+ SimpleTest.finish();
+ });
+ }
+</script>
+</body>
diff --git a/dom/base/test/jsmodules/importmaps/test_externalImportMap.html b/dom/base/test/jsmodules/importmaps/test_externalImportMap.html
new file mode 100644
index 0000000000..1345f61947
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/test_externalImportMap.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test an external import map</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<script>
+let gotMsg = false;
+let console = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
+let listener = {
+ QueryInterface: ChromeUtils.generateQI(["nsIConsoleListener"]),
+ observe(msg) {
+ info("console message:" + msg);
+ ok(msg.logLevel == Ci.nsIConsoleMessage.warn, "log level should be 'warn'.");
+ // The message will be localized, so we just test the strings won't be
+ // localized.
+ ok(msg.message.match(/<script type='importmap'>.*src/),
+ "The error message should contain \"<script type='importmap'>\"");
+ console.unregisterListener(this);
+ gotMsg = true;
+ }
+};
+console.registerListener(listener);
+</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();
+ ok(gotMsg, "Should have got the console warning.");
+ 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>
diff --git a/dom/base/test/jsmodules/importmaps/test_import_meta_resolve_importMap.html b/dom/base/test/jsmodules/importmaps/test_import_meta_resolve_importMap.html
new file mode 100644
index 0000000000..df1bed2e56
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/test_import_meta_resolve_importMap.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<head>
+ <meta charset=utf-8>
+ <title>Test import.meta.resolve with import maps</title>
+</head>
+<body onload='testLoaded()'>
+
+<script type="importmap">
+{
+ "imports": {
+ "simple": "./module_simpleExport.js"
+ }
+}
+</script>
+
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var wasRun = false;
+ var hasThrown = false;
+ window.onerror = handleError;
+
+ function handleError(msg, url, line, col, error) {
+ ok(error instanceof TypeError, "Thrown error should be TypeError.");
+ hasThrown = true;
+ }
+</script>
+
+<script type="module">
+ ok(import.meta.resolve("simple") ==
+ "chrome://mochitests/content/chrome/dom/base/test/jsmodules/importmaps/module_simpleExport.js",
+ "calling import.meta.resolve with a specifier from import map.");
+ wasRun = true;
+</script>
+
+<script type="module">
+ // should throw a TypeError
+ import.meta.resolve("fail");
+</script>
+
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ function testLoaded() {
+ ok(wasRun, "Check inline module has run.");
+ ok(hasThrown, "Check inline module has thrown.");
+ SimpleTest.finish();
+ }
+</script>
+</body>
diff --git a/dom/base/test/jsmodules/importmaps/test_inline_module_reject_importMap.html b/dom/base/test/jsmodules/importmaps/test_inline_module_reject_importMap.html
new file mode 100644
index 0000000000..2001cbcfb9
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/test_inline_module_reject_importMap.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<head>
+ <meta charset=utf-8>
+ <title>Test import map should be rejected.</title>
+</head>
+<body onload='testLoaded()'>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<script>
+let gotMsg = false;
+let console = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
+let listener = {
+ QueryInterface: ChromeUtils.generateQI(["nsIConsoleListener"]),
+ observe(msg) {
+ info("console message:" + msg);
+ ok(msg.logLevel == Ci.nsIConsoleMessage.warn, "log level should be 'warn'.");
+ console.unregisterListener(this);
+ gotMsg = true;
+ }
+};
+console.registerListener(listener);
+</script>
+
+<!--There is an inline module before the import map tag, so the import map-->
+<!--cannot be accepted according to the spec.-->
+<!--And because the import map is rejected, so the module specifier-->
+<!--"./module_simpleExport.js" won't be remapped to-->
+<!--"./scope1/module_simpleExport.js".-->
+
+<script type="module">
+</script>
+
+<script type="importmap" onerror='importMapError()'>
+{
+ "imports": {
+ "./module_simpleExport.js": "./scope1/module_simpleExport.js"
+ }
+}
+</script>
+
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ let hasError = false;
+ function importMapError() {
+ hasError = true;
+ }
+
+ function testLoaded() {
+ import("./module_simpleExport.js").then((ns) => {
+ ok(ns.x == 42, 'Check simple imported value result: ' + ns.x);
+ ok(hasError, "onerror of the import map should be called.");
+ ok(gotMsg, "Should have got the console warning.");
+ }).catch((e) => {
+ ok(false, "throws " + e);
+ }).then(() => {
+ SimpleTest.finish();
+ });
+ }
+</script>
+</body>
diff --git a/dom/base/test/jsmodules/importmaps/test_load_importMap_with_base.html b/dom/base/test/jsmodules/importmaps/test_load_importMap_with_base.html
new file mode 100644
index 0000000000..3139a60d37
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/test_load_importMap_with_base.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<head>
+ <meta charset=utf-8>
+ <title>Test a simple import map with a base element</title>
+</head>
+<body onload='testLoaded()'>
+
+<!-- This will change the baseURL of the document.-->
+<base href="chrome://mochitests/content/chrome/dom/base/test/jsmodules/importmaps/scope1/">
+
+<!--
+With the <base> element, the correct "module_simpleExport.js" should be mapped
+to "scope1/module_simpleExport.js", instead of "./module_simpleExport.js".
+-->
+
+<script type="importmap">
+{
+ "imports": {
+ "simple": "./module_simpleExport.js"
+ }
+}
+</script>
+
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<script type="module">
+ import { x } from "simple";
+ result2 = x;
+</script>
+
+<script type="module" src="module_simpleImportMap.js"></script>
+
+<script>
+ var result_scope1, result2;
+
+ SimpleTest.waitForExplicitFinish();
+
+ function testLoaded() {
+ ok(result_scope1 == 84, 'Check imported value result_scope1: ' + result_scope1);
+ ok(result2 == 84, 'Check imported value result2: ' + result2);
+
+ import("simple").then((ns) => {
+ ok(ns.x == 84, 'Check simple imported value result: ' + ns.x);
+ }).catch((e) => {
+ ok(false, "throws " + e);
+ }).then(() => {
+ SimpleTest.finish();
+ });
+ }
+</script>
+</body>
diff --git a/dom/base/test/jsmodules/importmaps/test_load_importMap_with_base2.html b/dom/base/test/jsmodules/importmaps/test_load_importMap_with_base2.html
new file mode 100644
index 0000000000..ed000512fd
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/test_load_importMap_with_base2.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<head>
+ <meta charset=utf-8>
+ <title>Test a simple import map with a script creates a base element</title>
+</head>
+<body onload='testLoaded()'>
+
+<!--This script will create a base element.-->
+<script src="insert_a_base_element.js"></script>
+
+<!--
+With the <base> element, the correct "module_simpleExport.js" should be mapped
+to "scope1/module_simpleExport.js", instead of "./module_simpleExport.js".
+-->
+
+<script type="importmap">
+{
+ "imports": {
+ "simple": "./module_simpleExport.js"
+ }
+}
+</script>
+
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<script type="module">
+ import { x } from "simple";
+ result2 = x;
+</script>
+
+<script type="module" src="module_simpleImportMap.js"></script>
+
+<script>
+ var result_scope1, result2;
+
+ SimpleTest.waitForExplicitFinish();
+
+ function testLoaded() {
+ ok(result_scope1 == 84, 'Check imported value result_scope1: ' + result_scope1);
+ ok(result2 == 84, 'Check imported value result2: ' + result2);
+
+ import("simple").then((ns) => {
+ ok(ns.x == 84, 'Check simple imported value result: ' + ns.x);
+ }).catch((e) => {
+ ok(false, "throws " + e);
+ }).then(() => {
+ SimpleTest.finish();
+ });
+ }
+</script>
+</body>
diff --git a/dom/base/test/jsmodules/importmaps/test_module_script_reject_importMap.html b/dom/base/test/jsmodules/importmaps/test_module_script_reject_importMap.html
new file mode 100644
index 0000000000..bc73a60fc9
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/test_module_script_reject_importMap.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<head>
+ <meta charset=utf-8>
+ <title>Test import map should be rejected.</title>
+</head>
+<body onload='testLoaded()'>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<!--There is a module load before the import map tag, so the import map cannot-->
+<!--be accepted according to the spec.-->
+<!--And because the import map is rejected, so the module specifier-->
+<!--"./module_simpleExport.js" won't be remapped to-->
+<!--"./scope1/module_simpleExport.js".-->
+
+<script src="./module_simpleExport.js" type="module">
+</script>
+
+<script type="importmap" onerror='importMapError()'>
+{
+ "imports": {
+ "./module_simpleExport.js": "./scope1/module_simpleExport.js"
+ }
+}
+</script>
+
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ let hasError = false;
+ function importMapError() {
+ hasError = true;
+ }
+
+ function testLoaded() {
+ import("./module_simpleExport.js").then((ns) => {
+ ok(ns.x == 42, 'Check simple imported value result: ' + ns.x);
+ ok(hasError, "onerror of the import map should be called.");
+ }).catch((e) => {
+ ok(false, "throws " + e);
+ }).then(() => {
+ SimpleTest.finish();
+ });
+ }
+</script>
+</body>
diff --git a/dom/base/test/jsmodules/importmaps/test_parse_importMap_failed.html b/dom/base/test/jsmodules/importmaps/test_parse_importMap_failed.html
new file mode 100644
index 0000000000..b304acd943
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/test_parse_importMap_failed.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<head>
+ <meta charset=utf-8>
+ <title>Test the error message when parsing import maps failed</title>
+</head>
+<body onload='testLoaded()'>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<script>
+let gotMsg = false;
+window.onerror = function(event, src, lineno, colno, error) {
+ info("error: " + error.message);
+ ok(error instanceof SyntaxError, "error should be SyntaxError.");
+ ok(error.message.match(/import map/),
+ "error.message should contain 'import map'");
+ gotMsg = true;
+};
+</script>
+
+<!--
+An import map with invalid JSON format. A SyntaxError will be thrown when parsing
+the import map.
+ -->
+<script type="importmap" onerror='importMapError()'>
+{
+ "imports": {{
+ "foo": "./foo.js"
+ }
+}
+</script>
+
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ function testLoaded() {
+ ok(gotMsg, "Should have thrown a SyntaxError.");
+ SimpleTest.finish();
+ }
+</script>
+</body>
diff --git a/dom/base/test/jsmodules/importmaps/test_reject_multiple_importMaps.html b/dom/base/test/jsmodules/importmaps/test_reject_multiple_importMaps.html
new file mode 100644
index 0000000000..cc41163101
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/test_reject_multiple_importMaps.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<head>
+ <meta charset=utf-8>
+ <title>Test the 2nd import map should be rejected.</title>
+</head>
+<body onload='testLoaded()'>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<script>
+let gotMsg = false;
+let console = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
+let listener = {
+ QueryInterface: ChromeUtils.generateQI(["nsIConsoleListener"]),
+ observe(msg) {
+ info("console message:" + msg);
+ ok(msg.logLevel == Ci.nsIConsoleMessage.warn, "log level should be 'warn'.");
+ console.unregisterListener(this);
+ gotMsg = true;
+ }
+};
+console.registerListener(listener);
+</script>
+
+<script type="importmap" onerror='importMapError1()'>
+{
+ "imports": {
+ "./module_simpleExport.js": "./scope1/module_simpleExport.js"
+ }
+}
+</script>
+
+<!--The 2nd import map should be rejected.-->
+<script type="importmap" onerror='importMapError2()'>
+{
+ "imports": {
+ "./module_simpleExport.js": "./scope1/module_simpleExport.js"
+ }
+}
+</script>
+
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ let hasError = false;
+ function importMapError1() {
+ ok(false, "The first import map should be accepted.");
+ }
+ function importMapError2() {
+ hasError = true;
+ }
+
+ function testLoaded() {
+ import("./module_simpleExport.js").then((ns) => {
+ ok(ns.x == 84, 'Check simple imported value result: ' + ns.x);
+ ok(hasError, "onerror of the import map should be called.");
+ ok(gotMsg, "Should have got the console warning.");
+ }).catch((e) => {
+ ok(false, "throws " + e);
+ }).then(() => {
+ SimpleTest.finish();
+ });
+ }
+</script>
+</body>
diff --git a/dom/base/test/jsmodules/importmaps/test_simpleImportMap.html b/dom/base/test/jsmodules/importmaps/test_simpleImportMap.html
new file mode 100644
index 0000000000..6a46ff770e
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/test_simpleImportMap.html
@@ -0,0 +1,62 @@
+<!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/importmaps/",
+ "./module.js": "/content/chrome/dom/base/test/jsmodules/importmaps/module_simpleExport.js",
+ "https://example.com/module.js": "./module_simpleExport.js"
+ },
+ "scopes": {
+ "chrome://mochitests/content/chrome/dom/base/test/jsmodules/importmaps/scope1/": {
+ "simple": "/content/chrome/dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.js"
+ },
+ "chrome://mochitests/content/chrome/dom/base/test/jsmodules/importmaps/scope1/scope2/": {
+ "simple": "/content/chrome/dom/base/test/jsmodules/importmaps/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>
diff --git a/dom/base/test/jsmodules/importmaps/test_sortedImportMap.html b/dom/base/test/jsmodules/importmaps/test_sortedImportMap.html
new file mode 100644
index 0000000000..17e4049d1a
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/test_sortedImportMap.html
@@ -0,0 +1,62 @@
+<!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://html.spec.whatwg.org/multipage/webappapis.html#sorting-and-normalizing-a-module-specifier-map, Step 3.
+https://html.spec.whatwg.org/multipage/webappapis.html#sorting-and-normalizing-scopes, Step 3.
+-->
+
+<script type="importmap">
+{
+ "imports": {
+ "scope1/": "/content/chrome/dom/base/test/jsmodules/importmaps/",
+ "scope1/scope2/": "/content/chrome/dom/base/test/jsmodules/importmaps/scope1/scope2/",
+ "scope1/scope2/scope3/scope4/": "/content/chrome/dom/base/test/jsmodules/importmaps/scope1/scope2/",
+ "scope1/scope2/scope3/": "/content/chrome/dom/base/test/jsmodules/importmaps/"
+ },
+ "scopes": {
+ "chrome://mochitests/content/chrome/dom/base/test/jsmodules/importmaps/scope1/scope2/": {
+ "simple": "/content/chrome/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleExport.js"
+ },
+ "chrome://mochitests/content/chrome/dom/base/test/jsmodules/importmaps/scope1/": {
+ "simple": "/content/chrome/dom/base/test/jsmodules/importmaps/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>
diff --git a/dom/base/test/jsmodules/module_badImport.js b/dom/base/test/jsmodules/module_badImport.js
new file mode 100644
index 0000000000..ab18249156
--- /dev/null
+++ b/dom/base/test/jsmodules/module_badImport.js
@@ -0,0 +1 @@
+import "invalid specifier";
diff --git a/dom/base/test/jsmodules/module_badSyntax.js b/dom/base/test/jsmodules/module_badSyntax.js
new file mode 100644
index 0000000000..744158108c
--- /dev/null
+++ b/dom/base/test/jsmodules/module_badSyntax.js
@@ -0,0 +1,3 @@
+// Module with a syntax error.
+some invalid js syntax;
+wasRun = true;
diff --git a/dom/base/test/jsmodules/module_cyclic1.js b/dom/base/test/jsmodules/module_cyclic1.js
new file mode 100644
index 0000000000..480efee0ae
--- /dev/null
+++ b/dom/base/test/jsmodules/module_cyclic1.js
@@ -0,0 +1,8 @@
+import { func2 } from "./module_cyclic2.js";
+
+export function func1(x, y) {
+ if (x <= 0) {
+ return y;
+ }
+ return func2(x - 1, y + "1");
+}
diff --git a/dom/base/test/jsmodules/module_cyclic2.js b/dom/base/test/jsmodules/module_cyclic2.js
new file mode 100644
index 0000000000..5f17afbd0a
--- /dev/null
+++ b/dom/base/test/jsmodules/module_cyclic2.js
@@ -0,0 +1,8 @@
+import { func3 } from "./module_cyclic3.js";
+
+export function func2(x, y) {
+ if (x <= 0) {
+ return y;
+ }
+ return func3(x - 1, y + "2");
+}
diff --git a/dom/base/test/jsmodules/module_cyclic3.js b/dom/base/test/jsmodules/module_cyclic3.js
new file mode 100644
index 0000000000..4b4c1e4ff6
--- /dev/null
+++ b/dom/base/test/jsmodules/module_cyclic3.js
@@ -0,0 +1,8 @@
+import { func1 } from "./module_cyclic1.js";
+
+export function func3(x, y) {
+ if (x <= 0) {
+ return y;
+ }
+ return func1(x - 1, y + "3");
+}
diff --git a/dom/base/test/jsmodules/module_extractIntroType.js b/dom/base/test/jsmodules/module_extractIntroType.js
new file mode 100644
index 0000000000..b2e1f1c6cf
--- /dev/null
+++ b/dom/base/test/jsmodules/module_extractIntroType.js
@@ -0,0 +1,5 @@
+// Extract the introductionType for this module in conjunction with
+// iframe_extractIntroType.html.
+extractIntroType = function () {
+ debugger;
+};
diff --git a/dom/base/test/jsmodules/module_large1.js b/dom/base/test/jsmodules/module_large1.js
new file mode 100644
index 0000000000..d6933d298d
--- /dev/null
+++ b/dom/base/test/jsmodules/module_large1.js
@@ -0,0 +1,78 @@
+/*
+ * Scripts larger than 5KB may be compiled off main thread. This is such a
+ * script.
+ *
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ */
+
+results.push(1);
diff --git a/dom/base/test/jsmodules/module_large2.js b/dom/base/test/jsmodules/module_large2.js
new file mode 100644
index 0000000000..e1b6da4c91
--- /dev/null
+++ b/dom/base/test/jsmodules/module_large2.js
@@ -0,0 +1,78 @@
+/*
+ * Scripts larger than 5KB may be compiled off main thread. This is such a
+ * script.
+ *
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ */
+
+results.push(2);
diff --git a/dom/base/test/jsmodules/module_large3.js b/dom/base/test/jsmodules/module_large3.js
new file mode 100644
index 0000000000..c966a8eb20
--- /dev/null
+++ b/dom/base/test/jsmodules/module_large3.js
@@ -0,0 +1,78 @@
+/*
+ * Scripts larger than 5KB may be compiled off main thread. This is such a
+ * script.
+ *
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ * large large large large large large large large large large large large
+ */
+
+results.push(3);
diff --git a/dom/base/test/jsmodules/module_missingImport.js b/dom/base/test/jsmodules/module_missingImport.js
new file mode 100644
index 0000000000..28cf608de8
--- /dev/null
+++ b/dom/base/test/jsmodules/module_missingImport.js
@@ -0,0 +1 @@
+import { missing } from "./module_simple1.js";
diff --git a/dom/base/test/jsmodules/module_multiImports.js b/dom/base/test/jsmodules/module_multiImports.js
new file mode 100644
index 0000000000..0587ac5ca0
--- /dev/null
+++ b/dom/base/test/jsmodules/module_multiImports.js
@@ -0,0 +1,4 @@
+import "./module_simple1.js";
+import "./module_simple2.js";
+import "./module_simple3.js";
+results.push(4);
diff --git a/dom/base/test/jsmodules/module_multiLargeImports.js b/dom/base/test/jsmodules/module_multiLargeImports.js
new file mode 100644
index 0000000000..ddc5792d0d
--- /dev/null
+++ b/dom/base/test/jsmodules/module_multiLargeImports.js
@@ -0,0 +1,4 @@
+import "./module_large1.js";
+import "./module_large2.js";
+import "./module_large3.js";
+results.push(4);
diff --git a/dom/base/test/jsmodules/module_setRan.js b/dom/base/test/jsmodules/module_setRan.js
new file mode 100644
index 0000000000..4804382fdd
--- /dev/null
+++ b/dom/base/test/jsmodules/module_setRan.js
@@ -0,0 +1,2 @@
+// Set a global flag to indicate that this module was executed.
+moduleRan = true;
diff --git a/dom/base/test/jsmodules/module_simple1.js b/dom/base/test/jsmodules/module_simple1.js
new file mode 100644
index 0000000000..7594ac699e
--- /dev/null
+++ b/dom/base/test/jsmodules/module_simple1.js
@@ -0,0 +1 @@
+results.push(1);
diff --git a/dom/base/test/jsmodules/module_simple2.js b/dom/base/test/jsmodules/module_simple2.js
new file mode 100644
index 0000000000..f92a1c9d6e
--- /dev/null
+++ b/dom/base/test/jsmodules/module_simple2.js
@@ -0,0 +1 @@
+results.push(2);
diff --git a/dom/base/test/jsmodules/module_simple3.js b/dom/base/test/jsmodules/module_simple3.js
new file mode 100644
index 0000000000..71979926e6
--- /dev/null
+++ b/dom/base/test/jsmodules/module_simple3.js
@@ -0,0 +1 @@
+results.push(3);
diff --git a/dom/base/test/jsmodules/module_simpleExport.js b/dom/base/test/jsmodules/module_simpleExport.js
new file mode 100644
index 0000000000..9714d6d0ab
--- /dev/null
+++ b/dom/base/test/jsmodules/module_simpleExport.js
@@ -0,0 +1 @@
+export let x = 42;
diff --git a/dom/base/test/jsmodules/module_simpleImport.js b/dom/base/test/jsmodules/module_simpleImport.js
new file mode 100644
index 0000000000..9e459fef7a
--- /dev/null
+++ b/dom/base/test/jsmodules/module_simpleImport.js
@@ -0,0 +1,2 @@
+import { x } from "./module_simpleExport.js";
+result = x;
diff --git a/dom/base/test/jsmodules/module_testSyntax.js b/dom/base/test/jsmodules/module_testSyntax.js
new file mode 100644
index 0000000000..3d647ae0b4
--- /dev/null
+++ b/dom/base/test/jsmodules/module_testSyntax.js
@@ -0,0 +1,3 @@
+// Module that throws a syntax error if parsed as a script.
+export default 1;
+wasRun = true;
diff --git a/dom/base/test/jsmodules/moz.build b/dom/base/test/jsmodules/moz.build
new file mode 100644
index 0000000000..1a7d5281ea
--- /dev/null
+++ b/dom/base/test/jsmodules/moz.build
@@ -0,0 +1,7 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+MOCHITEST_CHROME_MANIFESTS += ["chrome.ini"]
diff --git a/dom/base/test/jsmodules/script_simple2.js b/dom/base/test/jsmodules/script_simple2.js
new file mode 100644
index 0000000000..f92a1c9d6e
--- /dev/null
+++ b/dom/base/test/jsmodules/script_simple2.js
@@ -0,0 +1 @@
+results.push(2);
diff --git a/dom/base/test/jsmodules/test_asyncInlineModules.html b/dom/base/test/jsmodules/test_asyncInlineModules.html
new file mode 100644
index 0000000000..188146e69c
--- /dev/null
+++ b/dom/base/test/jsmodules/test_asyncInlineModules.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test async inline modules</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var results = [];
+
+ SimpleTest.waitForExplicitFinish();
+
+ function arrayEquals(a, b) {
+ if (a.length != b.length) {
+ return false;
+ }
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ function testLoaded() {
+ ok(arrayEquals(results.sort(), [1, 2, 3]), 'Check modules imported');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" async>
+ results.push(1);
+</script>
+<script type="module" async>
+ import "./module_simple2.js";
+</script>
+<script type="module" async>
+ results.push(3);
+</script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/test_cyclicImport.html b/dom/base/test/jsmodules/test_cyclicImport.html
new file mode 100644
index 0000000000..d316a140d4
--- /dev/null
+++ b/dom/base/test/jsmodules/test_cyclicImport.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test cyclic module imports</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var result;
+
+ SimpleTest.waitForExplicitFinish();
+
+ function testLoaded() {
+ SimpleTest.finish();
+ }
+</script>
+<script type="module">
+ import { func1 } from "./module_cyclic1.js";
+ ok(func1(5, "") == "12312");
+</script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/test_dynamicImportErrorMessage.html b/dom/base/test/jsmodules/test_dynamicImportErrorMessage.html
new file mode 100644
index 0000000000..f5552d5a6b
--- /dev/null
+++ b/dom/base/test/jsmodules/test_dynamicImportErrorMessage.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test the error message from import()</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ async function testLoaded() {
+ await import("./404.js").catch((error) => {
+ ok(error instanceof TypeError, "Should be a TypeError.");
+ ok(error.message.match(/404.js/), "Should have the filename.");
+ SimpleTest.finish();
+ });
+ }
+</script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/test_importIntroType.html b/dom/base/test/jsmodules/test_importIntroType.html
new file mode 100644
index 0000000000..67c08bb5d7
--- /dev/null
+++ b/dom/base/test/jsmodules/test_importIntroType.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test introduction type of an imported module</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var introType;
+ var extractIntroType;
+
+ info('start');
+ SimpleTest.waitForExplicitFinish();
+
+ function testIntroductionType() {
+ extractIntroType();
+ ok(introType == "importedModule", 'Check introduction type');
+ SimpleTest.finish();
+ }
+</script>
+<iframe src="iframe_extractIntroType.html"></iframe>
+<script type="module">
+import "./module_extractIntroType.js";
+</script>
+<body onload='testIntroductionType()'></body>
diff --git a/dom/base/test/jsmodules/test_importNotFound.html b/dom/base/test/jsmodules/test_importNotFound.html
new file mode 100644
index 0000000000..fc624b6b68
--- /dev/null
+++ b/dom/base/test/jsmodules/test_importNotFound.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test what happens when a module import is not found</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var wasRun = false;
+ var errorCount = 0;
+ var eventCount = 0;
+
+ SimpleTest.waitForExplicitFinish();
+
+ window.onerror = function(message, url, line, column, error) {
+ errorCount++;
+ }
+
+ function testError() {
+ ok(!wasRun, 'Check script was not run');
+ ok(eventCount == 1, 'Check that an error event was fired');
+ ok(errorCount == 0, 'Check that no error was reported');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" onerror="eventCount++">
+import "./nonExistentModule.js";
+wasRun = true;
+</script>
+<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_importResolveFailed.html b/dom/base/test/jsmodules/test_importResolveFailed.html
new file mode 100644
index 0000000000..559de77dcd
--- /dev/null
+++ b/dom/base/test/jsmodules/test_importResolveFailed.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test error thrown when an import cannot be resolved</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var hadTypeError = false;
+
+ SimpleTest.waitForExplicitFinish();
+ window.onerror = handleError;
+
+ function handleError(message, url, line, column, error) {
+ hadTypeError = error instanceof TypeError;
+ }
+
+ function testError() {
+ ok(hadTypeError, 'Check that a TypeError was thrown');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="module_badImport.js"></script>
+<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_import_meta_resolve.html b/dom/base/test/jsmodules/test_import_meta_resolve.html
new file mode 100644
index 0000000000..66eedc95bc
--- /dev/null
+++ b/dom/base/test/jsmodules/test_import_meta_resolve.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<head>
+ <meta charset=utf-8>
+ <title>Test import.meta.resolve</title>
+</head>
+<body onload='testLoaded()'>
+
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ function assertThrowsTypeError(fn, msg) {
+ let hasThrown = false;
+ try {
+ fn();
+ } catch (error) {
+ hasThrown = true;
+ ok(error instanceof TypeError, "Thrown error should be TypeError.");
+ }
+ ok(hasThrown, msg);
+ }
+
+ function testLoaded() {
+ SimpleTest.finish();
+ }
+</script>
+
+<script type="module">
+ is(typeof import.meta.resolve, "function", "resolve should be a function.");
+ is(import.meta.resolve.name, "resolve", "resolve.name should be 'resolve'.");
+ is(import.meta.resolve.length, 1, "resolve.length should be 1.");
+ is(Object.getPrototypeOf(import.meta.resolve), Function.prototype,
+ "prototype of resolve should be Function.prototype.");
+</script>
+
+<script type="module">
+ is(import.meta.resolve("http://example.com/"), "http://example.com/",
+ "resolve specifiers with absolute path.");
+</script>
+
+<script type="module">
+ is(import.meta.resolve("./x"), (new URL("./x", import.meta.url)).href,
+ "resolve specifiers with relative path.");
+</script>
+
+<script type="module">
+ assertThrowsTypeError(() => new import.meta.resolve("./x"),
+ "import.meta.resolve is not a constructor.");
+</script>
+
+<script type="module">
+ // Fails to resolve the specifier should throw a TypeError.
+ assertThrowsTypeError(() => import.meta.resolve("failed"),
+ "import.meta.resolve should throw if fails to resolve");
+</script>
+
+<script type="module">
+ for (const name of Reflect.ownKeys(import.meta)) {
+ const desc = Object.getOwnPropertyDescriptor(import.meta, name);
+ is(desc.writable, true, name + ".writable should be true.");
+ is(desc.enumerable, true, name + ".enumerable should be true.");
+ is(desc.configurable, true, name + ".configurable should be true.");
+ }
+</script>
+</body>
diff --git a/dom/base/test/jsmodules/test_importedModuleMemoization.html b/dom/base/test/jsmodules/test_importedModuleMemoization.html
new file mode 100644
index 0000000000..37cb26752d
--- /dev/null
+++ b/dom/base/test/jsmodules/test_importedModuleMemoization.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test imported modules are momoized and only loaded once</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var results = [];
+
+ SimpleTest.waitForExplicitFinish();
+
+ function arrayEquals(a, b) {
+ if (a.length != b.length) {
+ return false;
+ }
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ function testLoaded() {
+ ok(arrayEquals(results, [1, 2, 3, 4]), 'Check modules only evaluated once');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="module_multiImports.js"></script>
+<script type="module" src="module_multiImports.js"></script>
+<script type="module" src="module_multiImports.js"></script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/test_linkErrorInCommon1.html b/dom/base/test/jsmodules/test_linkErrorInCommon1.html
new file mode 100644
index 0000000000..436493c75e
--- /dev/null
+++ b/dom/base/test/jsmodules/test_linkErrorInCommon1.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test handling of a link error in a common module</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var runCount = 0;
+ var hadSyntaxError = false;
+
+ SimpleTest.waitForExplicitFinish();
+ window.onerror = handleError;
+
+ function handleError(message, url, line, column, error) {
+ if (error instanceof SyntaxError) {
+ hadSyntaxError = true;
+ }
+ }
+
+ function testError() {
+ ok(runCount == 0, 'Check no modules were executed');
+ ok(hadSyntaxError, 'Check that an error was reported');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module">
+ import { missing } from "./module_simple1.js";
+ runCount++;
+</script>
+<script type="module">
+ import { missing } from "./module_simple1.js";
+ runCount++;
+</script>
+<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_linkErrorInCommon2.html b/dom/base/test/jsmodules/test_linkErrorInCommon2.html
new file mode 100644
index 0000000000..a882ec0992
--- /dev/null
+++ b/dom/base/test/jsmodules/test_linkErrorInCommon2.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test handling of a link error in a common module</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var runCount = 0;
+ var hadSyntaxError = false;
+
+ SimpleTest.waitForExplicitFinish();
+ window.onerror = handleError;
+
+ function handleError(message, url, line, column, error) {
+ if (error instanceof SyntaxError) {
+ hadSyntaxError = true;
+ }
+ }
+
+ function testError() {
+ ok(runCount == 0, 'Check no modules were executed');
+ ok(hadSyntaxError, 'Check that an error was reported');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module">
+ import "./module_missingImport.js";
+ runCount++;
+</script>
+<script type="module">
+ import "./module_missingImport.js";
+ runCount++;
+</script>
+<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_moduleNotFound.html b/dom/base/test/jsmodules/test_moduleNotFound.html
new file mode 100644
index 0000000000..f5e7c37364
--- /dev/null
+++ b/dom/base/test/jsmodules/test_moduleNotFound.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test what happens when a top-level module is not found</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var wasRun = false;
+ var errorCount = 0;
+ var eventCount = 0;
+
+ SimpleTest.waitForExplicitFinish();
+
+ window.onerror = function(message, url, line, column, error) {
+ errorCount++;
+ }
+
+ function testError() {
+ ok(eventCount == 1, 'Check that an error event was fired');
+ ok(errorCount == 0, 'Check that no error was reported');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="./nonExistentModule.js" onerror="eventCount++">
+</script>
+<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_moduleParsedAsModule.html b/dom/base/test/jsmodules/test_moduleParsedAsModule.html
new file mode 100644
index 0000000000..2cd4abbd57
--- /dev/null
+++ b/dom/base/test/jsmodules/test_moduleParsedAsModule.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test module script parsed as module</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var wasRun = false;
+ var hadSyntaxError = false;
+
+ SimpleTest.waitForExplicitFinish();
+ window.onerror = handleError;
+
+ function handleError(message, url, line, column, error) {
+ hadSyntaxError = error instanceof SyntaxError;
+ }
+
+ function testError() {
+ ok(wasRun, 'Check module was run');
+ ok(!hadSyntaxError, 'Check that no SyntaxError was thrown');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="module_testSyntax.js"></script>
+<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_moduleScriptsRun.html b/dom/base/test/jsmodules/test_moduleScriptsRun.html
new file mode 100644
index 0000000000..908f7ff46a
--- /dev/null
+++ b/dom/base/test/jsmodules/test_moduleScriptsRun.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test script elements with type="module" are run for chrome HTML</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var inlineModuleRan = false;
+ var moduleRan = false;
+
+ SimpleTest.waitForExplicitFinish();
+
+ function testLoaded() {
+ ok(moduleRan, 'Check module script was run');
+ ok(inlineModuleRan, 'Check inline module script was run');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="module_setRan.js"></script>
+<script type="module">inlineModuleRan = true;</script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/test_multiAsyncImports.html b/dom/base/test/jsmodules/test_multiAsyncImports.html
new file mode 100644
index 0000000000..dc318851c8
--- /dev/null
+++ b/dom/base/test/jsmodules/test_multiAsyncImports.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test a loading multiple modules with the async attribute from top level</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var results = [];
+
+ SimpleTest.waitForExplicitFinish();
+
+ function arrayEquals(a, b) {
+ if (a.length != b.length) {
+ return false;
+ }
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ function testLoaded() {
+ ok(arrayEquals(results.sort(), [1, 2, 3]), 'Check modules imported');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="module_simple1.js" async></script>
+<script type="module" src="module_simple2.js" async></script>
+<script type="module" src="module_simple3.js" async></script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/test_multiModuleImports.html b/dom/base/test/jsmodules/test_multiModuleImports.html
new file mode 100644
index 0000000000..003f7e6754
--- /dev/null
+++ b/dom/base/test/jsmodules/test_multiModuleImports.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test a importing multiple modules from a module</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var results = [];
+
+ SimpleTest.waitForExplicitFinish();
+
+ function arrayEquals(a, b) {
+ if (a.length != b.length) {
+ return false;
+ }
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ function testLoaded() {
+ ok(arrayEquals(results, [1, 2, 3, 4]), 'Check modules imported');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="module_multiImports.js"></script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/test_multiModuleLargeImports.html b/dom/base/test/jsmodules/test_multiModuleLargeImports.html
new file mode 100644
index 0000000000..f590bae449
--- /dev/null
+++ b/dom/base/test/jsmodules/test_multiModuleLargeImports.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test importing multiple large modules which may be compiled off main thread from a module</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var results = [];
+
+ SimpleTest.waitForExplicitFinish();
+
+ function arrayEquals(a, b) {
+ if (a.length != b.length) {
+ return false;
+ }
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ function testLoaded() {
+ ok(arrayEquals(results, [1, 2, 3, 4]), 'Check modules imported');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="module_multiLargeImports.js"></script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/test_multiTopLevelImports.html b/dom/base/test/jsmodules/test_multiTopLevelImports.html
new file mode 100644
index 0000000000..7cfe600959
--- /dev/null
+++ b/dom/base/test/jsmodules/test_multiTopLevelImports.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test importing multiple modules from top level</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var results = [];
+
+ SimpleTest.waitForExplicitFinish();
+
+ function arrayEquals(a, b) {
+ if (a.length != b.length) {
+ return false;
+ }
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ function testLoaded() {
+ ok(arrayEquals(results, [1, 2, 3]), 'Check modules imported');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="module_simple1.js"></script>
+<script type="module" src="module_simple2.js"></script>
+<script type="module" src="module_simple3.js"></script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/test_multiTopLevelLargeImports.html b/dom/base/test/jsmodules/test_multiTopLevelLargeImports.html
new file mode 100644
index 0000000000..8deee5479e
--- /dev/null
+++ b/dom/base/test/jsmodules/test_multiTopLevelLargeImports.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test a importing large modules which may be compiled off main thread</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var results = [];
+
+ SimpleTest.waitForExplicitFinish();
+
+ function arrayEquals(a, b) {
+ if (a.length != b.length) {
+ return false;
+ }
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ function testLoaded() {
+ ok(arrayEquals(results, [1, 2, 3]), 'Check modules imported');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="module_large1.js"></script>
+<script type="module" src="module_simple2.js"></script>
+<script type="module" src="module_large3.js"></script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/test_scriptInsertedModule.html b/dom/base/test/jsmodules/test_scriptInsertedModule.html
new file mode 100644
index 0000000000..3f00ab9684
--- /dev/null
+++ b/dom/base/test/jsmodules/test_scriptInsertedModule.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test a script-inserted module</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var result;
+
+ let script = document.createElement("script");
+ script.type = "module";
+ script.src = "./module_simpleImport.js";
+ document.head.appendChild(script);
+
+ SimpleTest.waitForExplicitFinish();
+
+ function testLoaded() {
+ ok(result == 42);
+ SimpleTest.finish();
+ }
+</script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/test_scriptModuleOrder.html b/dom/base/test/jsmodules/test_scriptModuleOrder.html
new file mode 100644
index 0000000000..bd8a4dcebe
--- /dev/null
+++ b/dom/base/test/jsmodules/test_scriptModuleOrder.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test execution order of deferred scripts and modules </title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var results = [];
+
+ SimpleTest.waitForExplicitFinish();
+
+ function arrayEquals(a, b) {
+ if (a.length != b.length) {
+ return false;
+ }
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ function testLoaded() {
+ ok(arrayEquals(results, [1, 2, 3]), 'Check execution order');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="module_simple1.js"></script>
+<script defer src="script_simple2.js"></script>
+<script type="module" src="module_simple3.js"></script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/test_scriptNotParsedAsModule.html b/dom/base/test/jsmodules/test_scriptNotParsedAsModule.html
new file mode 100644
index 0000000000..ba09503503
--- /dev/null
+++ b/dom/base/test/jsmodules/test_scriptNotParsedAsModule.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test classic script not parsed as module</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var wasRun = false;
+ var hadSyntaxError = false;
+
+ SimpleTest.waitForExplicitFinish();
+ window.onerror = handleError;
+
+ function handleError(message, url, line, column, error) {
+ hadSyntaxError = error instanceof SyntaxError;
+ }
+
+ function testError() {
+ ok(!wasRun, 'Check script was not run');
+ ok(hadSyntaxError, 'Check that a SyntaxError was thrown');
+ SimpleTest.finish();
+ }
+</script>
+<script src="module_testSyntax.js"></script>
+<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_simpleImport.html b/dom/base/test/jsmodules/test_simpleImport.html
new file mode 100644
index 0000000000..3c1af3f5b6
--- /dev/null
+++ b/dom/base/test/jsmodules/test_simpleImport.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test a simple module import</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var result;
+
+ SimpleTest.waitForExplicitFinish();
+
+ function testLoaded() {
+ ok(result == 42, 'Check imported value');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="module_simpleImport.js"></script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/test_syntaxError.html b/dom/base/test/jsmodules/test_syntaxError.html
new file mode 100644
index 0000000000..180c5aa445
--- /dev/null
+++ b/dom/base/test/jsmodules/test_syntaxError.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test syntax errors parsing a module are reported</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var wasRun = false;
+ var errorCount = 0;
+ var syntaxErrorCount = 0;
+ var eventCount = 0;
+
+ SimpleTest.waitForExplicitFinish();
+ window.onerror = handleError;
+
+ function handleError(message, url, line, column, error) {
+ errorCount++;
+ if (error instanceof SyntaxError) {
+ syntaxErrorCount++;
+ }
+ }
+
+ function testError() {
+ ok(!wasRun, 'Check script was not run');
+ ok(errorCount == 1, 'Check that an error was reported');
+ ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
+ ok(eventCount == 0, 'Check that no error event was fired');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="module_badSyntax.js" onerror="eventCount++"></script>
+<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_syntaxErrorAsync.html b/dom/base/test/jsmodules/test_syntaxErrorAsync.html
new file mode 100644
index 0000000000..64d8e6a21c
--- /dev/null
+++ b/dom/base/test/jsmodules/test_syntaxErrorAsync.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test syntax errors parsing an async module are reported</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var wasRun = false;
+ var errorCount = 0;
+ var syntaxErrorCount = 0;
+ var eventCount = 0;
+
+ SimpleTest.waitForExplicitFinish();
+ window.onerror = handleError;
+
+ function handleError(message, url, line, column, error) {
+ errorCount++;
+ if (error instanceof SyntaxError) {
+ syntaxErrorCount++;
+ }
+ }
+
+ function testError() {
+ ok(!wasRun, 'Check script was not run');
+ ok(errorCount == 1, 'Check that an error was reported');
+ ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
+ ok(eventCount == 0, 'Check that no error event was fired');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="module_badSyntax.js" async onerror="eventCount++"></script>
+<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_syntaxErrorInline.html b/dom/base/test/jsmodules/test_syntaxErrorInline.html
new file mode 100644
index 0000000000..4960f5358a
--- /dev/null
+++ b/dom/base/test/jsmodules/test_syntaxErrorInline.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test syntax errors parsing an inline module are reported</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var wasRun = false;
+ var errorCount = 0;
+ var syntaxErrorCount = 0;
+ var eventCount = 0;
+
+ SimpleTest.waitForExplicitFinish();
+ window.onerror = handleError;
+
+ function handleError(message, url, line, column, error) {
+ errorCount++;
+ if (error instanceof SyntaxError) {
+ syntaxErrorCount++;
+ }
+ }
+
+ function testError() {
+ ok(!wasRun, 'Check script was not run');
+ ok(errorCount == 1, 'Check that an error was reported');
+ ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
+ ok(eventCount == 0, 'Check that no error event was fired');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" onerror="eventCount++">
+// Module with a syntax error.
+some invalid js syntax;
+wasRun = true;
+</script>
+<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html b/dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html
new file mode 100644
index 0000000000..39b8a7354d
--- /dev/null
+++ b/dom/base/test/jsmodules/test_syntaxErrorInlineAsync.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test syntax errors parsing an inline async module are reported</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var wasRun = false;
+ var errorCount = 0;
+ var syntaxErrorCount = 0;
+ var eventCount = 0;
+
+ SimpleTest.waitForExplicitFinish();
+ window.onerror = handleError;
+
+ function handleError(message, url, line, column, error) {
+ errorCount++;
+ if (error instanceof SyntaxError) {
+ syntaxErrorCount++;
+ }
+ }
+
+ function testError() {
+ ok(!wasRun, 'Check script was not run');
+ ok(errorCount == 1, 'Check that an error was reported');
+ ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
+ ok(eventCount == 0, 'Check that no error event was fired');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" async onerror="eventCount++">
+// Module with a syntax error.
+some invalid js syntax;
+wasRun = true;
+</script>
+<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_topLevelIntroType.html b/dom/base/test/jsmodules/test_topLevelIntroType.html
new file mode 100644
index 0000000000..2c9c91b5bd
--- /dev/null
+++ b/dom/base/test/jsmodules/test_topLevelIntroType.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test introduction type of a top-level module</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var introType;
+ var extractIntroType;
+
+ info('start');
+ SimpleTest.waitForExplicitFinish();
+
+ function testIntroductionType() {
+ extractIntroType();
+ ok(introType == "srcScript", 'Check introduction type');
+ SimpleTest.finish();
+ }
+</script>
+<iframe src="iframe_extractIntroType.html"></iframe>
+<script type="module" src="module_extractIntroType.js">
+</script>
+<body onload='testIntroductionType()'></body>
diff --git a/dom/base/test/jsmodules/test_toplevelModuleMemoization.html b/dom/base/test/jsmodules/test_toplevelModuleMemoization.html
new file mode 100644
index 0000000000..ed4dee6f8b
--- /dev/null
+++ b/dom/base/test/jsmodules/test_toplevelModuleMemoization.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test toplevel modules are momoized and only loaded once</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var results = [];
+
+ SimpleTest.waitForExplicitFinish();
+
+ function arrayEquals(a, b) {
+ if (a.length != b.length) {
+ return false;
+ }
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ function testLoaded() {
+ ok(arrayEquals(results, [1]), 'Check execution order');
+ SimpleTest.finish();
+ }
+</script>
+<script type="module" src="module_simple1.js"></script>
+<script type="module" src="module_simple1.js"></script>
+<script type="module" src="module_simple1.js"></script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/test_typeAttrCaseInsensitive.html b/dom/base/test/jsmodules/test_typeAttrCaseInsensitive.html
new file mode 100644
index 0000000000..47ebc90dd6
--- /dev/null
+++ b/dom/base/test/jsmodules/test_typeAttrCaseInsensitive.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test script element's type attribute comparision is case-insensitive</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ var inlineModuleRan = false;
+ var moduleRan = false;
+
+ SimpleTest.waitForExplicitFinish();
+
+ function testLoaded() {
+ ok(moduleRan, 'Check module script was run');
+ ok(inlineModuleRan, 'Check inline module script was run');
+ SimpleTest.finish();
+ }
+</script>
+<script type="MODULE" src="module_setRan.js"></script>
+<script type="mOdUlE">inlineModuleRan = true;</script>
+<body onload='testLoaded()'></body>