summaryrefslogtreecommitdiffstats
path: root/dom/base/test/jsmodules
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /dom/base/test/jsmodules
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/base/test/jsmodules')
-rw-r--r--dom/base/test/jsmodules/.eslintrc.js15
-rw-r--r--dom/base/test/jsmodules/ambiguous_export.mjs3
-rw-r--r--dom/base/test/jsmodules/chrome.toml94
-rw-r--r--dom/base/test/jsmodules/exportA1.mjs1
-rw-r--r--dom/base/test/jsmodules/exportA2.mjs1
-rw-r--r--dom/base/test/jsmodules/export_ambiguous.mjs1
-rw-r--r--dom/base/test/jsmodules/iframe_extractIntroType.html14
-rw-r--r--dom/base/test/jsmodules/import_ambiguous.mjs1
-rw-r--r--dom/base/test/jsmodules/import_ambiguous_indirect_export.mjs1
-rw-r--r--dom/base/test/jsmodules/import_no_export.mjs1
-rw-r--r--dom/base/test/jsmodules/import_no_indirect_export.mjs2
-rw-r--r--dom/base/test/jsmodules/importmaps/bad/module_2.mjs1
-rw-r--r--dom/base/test/jsmodules/importmaps/bad/module_3.mjs8
-rw-r--r--dom/base/test/jsmodules/importmaps/bad/module_4.mjs1
-rw-r--r--dom/base/test/jsmodules/importmaps/bad/module_7.mjs1
-rw-r--r--dom/base/test/jsmodules/importmaps/bug_1865410_module_a.mjs2
-rw-r--r--dom/base/test/jsmodules/importmaps/bug_1865410_module_b.mjs1
-rw-r--r--dom/base/test/jsmodules/importmaps/bug_1873417.mjs2
-rw-r--r--dom/base/test/jsmodules/importmaps/chrome.toml37
-rw-r--r--dom/base/test/jsmodules/importmaps/circular_dependency.mjs6
-rw-r--r--dom/base/test/jsmodules/importmaps/external_importMap.js5
-rw-r--r--dom/base/test/jsmodules/importmaps/good/module_0.mjs1
-rw-r--r--dom/base/test/jsmodules/importmaps/good/module_1.mjs1
-rw-r--r--dom/base/test/jsmodules/importmaps/good/module_2.mjs1
-rw-r--r--dom/base/test/jsmodules/importmaps/good/module_3.mjs6
-rw-r--r--dom/base/test/jsmodules/importmaps/good/module_4.mjs1
-rw-r--r--dom/base/test/jsmodules/importmaps/good/module_7.mjs1
-rw-r--r--dom/base/test/jsmodules/importmaps/insert_a_base_element.js4
-rw-r--r--dom/base/test/jsmodules/importmaps/mochitest.toml33
-rw-r--r--dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_0.mjs3
-rw-r--r--dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_1.mjs3
-rw-r--r--dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_2.mjs3
-rw-r--r--dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_3.mjs3
-rw-r--r--dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_4.mjs3
-rw-r--r--dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs3
-rw-r--r--dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs^headers^2
-rw-r--r--dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs3
-rw-r--r--dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs^headers^2
-rw-r--r--dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_7.mjs3
-rw-r--r--dom/base/test/jsmodules/importmaps/module_simpleExport.mjs1
-rw-r--r--dom/base/test/jsmodules/importmaps/module_simpleImportMap.mjs4
-rw-r--r--dom/base/test/jsmodules/importmaps/module_simpleImportMap_dir.mjs4
-rw-r--r--dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap.mjs4
-rw-r--r--dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap_https.mjs4
-rw-r--r--dom/base/test/jsmodules/importmaps/module_sortedImportMap.mjs6
-rw-r--r--dom/base/test/jsmodules/importmaps/moz.build9
-rw-r--r--dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.mjs1
-rw-r--r--dom/base/test/jsmodules/importmaps/scope1/module_simpleImportMap.mjs4
-rw-r--r--dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleExport.mjs1
-rw-r--r--dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleImportMap.mjs4
-rw-r--r--dom/base/test/jsmodules/importmaps/test_bug_1865410.html27
-rw-r--r--dom/base/test/jsmodules/importmaps/test_bug_1873417.html39
-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_importMap_with_external_script.html75
-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.mjs2
-rw-r--r--dom/base/test/jsmodules/module_badSyntax.mjs3
-rw-r--r--dom/base/test/jsmodules/module_cyclic1.mjs8
-rw-r--r--dom/base/test/jsmodules/module_cyclic2.mjs8
-rw-r--r--dom/base/test/jsmodules/module_cyclic3.mjs8
-rw-r--r--dom/base/test/jsmodules/module_extractIntroType.mjs6
-rw-r--r--dom/base/test/jsmodules/module_large1.mjs78
-rw-r--r--dom/base/test/jsmodules/module_large2.mjs78
-rw-r--r--dom/base/test/jsmodules/module_large3.mjs78
-rw-r--r--dom/base/test/jsmodules/module_missingImport.mjs1
-rw-r--r--dom/base/test/jsmodules/module_multiImports.mjs6
-rw-r--r--dom/base/test/jsmodules/module_multiLargeImports.mjs6
-rw-r--r--dom/base/test/jsmodules/module_setRan.mjs2
-rw-r--r--dom/base/test/jsmodules/module_simple1.mjs1
-rw-r--r--dom/base/test/jsmodules/module_simple2.mjs1
-rw-r--r--dom/base/test/jsmodules/module_simple3.mjs1
-rw-r--r--dom/base/test/jsmodules/module_simpleExport.mjs1
-rw-r--r--dom/base/test/jsmodules/module_simpleImport.mjs3
-rw-r--r--dom/base/test/jsmodules/module_testSyntax.mjs3
-rw-r--r--dom/base/test/jsmodules/moz.build7
-rw-r--r--dom/base/test/jsmodules/no_export.mjs1
-rw-r--r--dom/base/test/jsmodules/no_indirect_export.mjs1
-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_errorMessage.html47
-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
117 files changed, 2180 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..25a38d20af
--- /dev/null
+++ b/dom/base/test/jsmodules/.eslintrc.js
@@ -0,0 +1,15 @@
+"use strict";
+
+module.exports = {
+ overrides: [
+ {
+ // eslint-plugin-html doesn't automatically detect module sections in
+ // html files. Enable these as a module here. JavaScript files can use
+ // the mjs extension.
+ files: ["*.html"],
+ parserOptions: {
+ sourceType: "module",
+ },
+ },
+ ],
+};
diff --git a/dom/base/test/jsmodules/ambiguous_export.mjs b/dom/base/test/jsmodules/ambiguous_export.mjs
new file mode 100644
index 0000000000..0018e1bc47
--- /dev/null
+++ b/dom/base/test/jsmodules/ambiguous_export.mjs
@@ -0,0 +1,3 @@
+/* eslint-disable import/export */
+export * from "./exportA1.mjs";
+export * from "./exportA2.mjs";
diff --git a/dom/base/test/jsmodules/chrome.toml b/dom/base/test/jsmodules/chrome.toml
new file mode 100644
index 0000000000..82d02ad4df
--- /dev/null
+++ b/dom/base/test/jsmodules/chrome.toml
@@ -0,0 +1,94 @@
+[DEFAULT]
+support-files = [
+ "ambiguous_export.mjs",
+ "import_ambiguous.mjs",
+ "import_ambiguous_indirect_export.mjs",
+ "import_no_export.mjs",
+ "import_no_indirect_export.mjs",
+ "exportA1.mjs",
+ "exportA2.mjs",
+ "export_ambiguous.mjs",
+ "module_setRan.mjs",
+ "module_testSyntax.mjs",
+ "module_badSyntax.mjs",
+ "module_simpleImport.mjs",
+ "module_simpleExport.mjs",
+ "module_badImport.mjs",
+ "module_simple1.mjs",
+ "module_simple2.mjs",
+ "module_simple3.mjs",
+ "module_cyclic1.mjs",
+ "module_cyclic2.mjs",
+ "module_cyclic3.mjs",
+ "module_multiImports.mjs",
+ "module_multiLargeImports.mjs",
+ "no_export.mjs",
+ "no_indirect_export.mjs",
+ "script_simple2.js",
+ "module_large1.mjs",
+ "module_large2.mjs",
+ "module_large3.mjs",
+ "module_extractIntroType.mjs",
+ "iframe_extractIntroType.html",
+ "module_missingImport.mjs",
+]
+
+["test_asyncInlineModules.html"]
+
+["test_cyclicImport.html"]
+
+["test_dynamicImportErrorMessage.html"]
+
+["test_importIntroType.html"]
+
+["test_importNotFound.html"]
+
+["test_importResolveFailed.html"]
+
+["test_import_errorMessage.html"]
+
+["test_import_meta_resolve.html"]
+
+["test_importedModuleMemoization.html"]
+
+["test_linkErrorInCommon1.html"]
+
+["test_linkErrorInCommon2.html"]
+
+["test_moduleNotFound.html"]
+
+["test_moduleParsedAsModule.html"]
+
+["test_moduleScriptsRun.html"]
+
+["test_multiAsyncImports.html"]
+
+["test_multiModuleImports.html"]
+
+["test_multiModuleLargeImports.html"]
+
+["test_multiTopLevelImports.html"]
+
+["test_multiTopLevelLargeImports.html"]
+
+["test_scriptInsertedModule.html"]
+
+["test_scriptModuleOrder.html"]
+
+["test_scriptNotParsedAsModule.html"]
+
+["test_simpleImport.html"]
+
+["test_syntaxError.html"]
+
+["test_syntaxErrorAsync.html"]
+
+["test_syntaxErrorInline.html"]
+
+["test_syntaxErrorInlineAsync.html"]
+
+["test_topLevelIntroType.html"]
+
+["test_toplevelModuleMemoization.html"]
+
+["test_typeAttrCaseInsensitive.html"]
diff --git a/dom/base/test/jsmodules/exportA1.mjs b/dom/base/test/jsmodules/exportA1.mjs
new file mode 100644
index 0000000000..cc798ff50d
--- /dev/null
+++ b/dom/base/test/jsmodules/exportA1.mjs
@@ -0,0 +1 @@
+export const a = 1;
diff --git a/dom/base/test/jsmodules/exportA2.mjs b/dom/base/test/jsmodules/exportA2.mjs
new file mode 100644
index 0000000000..66d48fc1e6
--- /dev/null
+++ b/dom/base/test/jsmodules/exportA2.mjs
@@ -0,0 +1 @@
+export const a = 2;
diff --git a/dom/base/test/jsmodules/export_ambiguous.mjs b/dom/base/test/jsmodules/export_ambiguous.mjs
new file mode 100644
index 0000000000..cca2dfd68a
--- /dev/null
+++ b/dom/base/test/jsmodules/export_ambiguous.mjs
@@ -0,0 +1 @@
+export { a } from "./ambiguous_export.mjs";
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/import_ambiguous.mjs b/dom/base/test/jsmodules/import_ambiguous.mjs
new file mode 100644
index 0000000000..f5c12ff086
--- /dev/null
+++ b/dom/base/test/jsmodules/import_ambiguous.mjs
@@ -0,0 +1 @@
+import { a } from "./ambiguous_export.mjs";
diff --git a/dom/base/test/jsmodules/import_ambiguous_indirect_export.mjs b/dom/base/test/jsmodules/import_ambiguous_indirect_export.mjs
new file mode 100644
index 0000000000..bbf9375e49
--- /dev/null
+++ b/dom/base/test/jsmodules/import_ambiguous_indirect_export.mjs
@@ -0,0 +1 @@
+import { a } from "./export_ambiguous.mjs";
diff --git a/dom/base/test/jsmodules/import_no_export.mjs b/dom/base/test/jsmodules/import_no_export.mjs
new file mode 100644
index 0000000000..47cabac557
--- /dev/null
+++ b/dom/base/test/jsmodules/import_no_export.mjs
@@ -0,0 +1 @@
+import x from "./no_export.mjs";
diff --git a/dom/base/test/jsmodules/import_no_indirect_export.mjs b/dom/base/test/jsmodules/import_no_indirect_export.mjs
new file mode 100644
index 0000000000..dd1ca847fc
--- /dev/null
+++ b/dom/base/test/jsmodules/import_no_indirect_export.mjs
@@ -0,0 +1,2 @@
+/* eslint-disable import/default */
+import x from "./no_indirect_export.mjs";
diff --git a/dom/base/test/jsmodules/importmaps/bad/module_2.mjs b/dom/base/test/jsmodules/importmaps/bad/module_2.mjs
new file mode 100644
index 0000000000..86c4251413
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/bad/module_2.mjs
@@ -0,0 +1 @@
+throw "Shouldn't load file bad/module_2.mjs";
diff --git a/dom/base/test/jsmodules/importmaps/bad/module_3.mjs b/dom/base/test/jsmodules/importmaps/bad/module_3.mjs
new file mode 100644
index 0000000000..f0595118d4
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/bad/module_3.mjs
@@ -0,0 +1,8 @@
+// eslint-disable-next-line import/no-unassigned-import, import/no-unresolved
+import {} from "../circular_depdendency.mjs";
+
+export function exportedFunction() {
+ throw "Wrong version of function called";
+}
+
+throw "Shouldn't laod file bad/module_3.mjs";
diff --git a/dom/base/test/jsmodules/importmaps/bad/module_4.mjs b/dom/base/test/jsmodules/importmaps/bad/module_4.mjs
new file mode 100644
index 0000000000..93dd8245ce
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/bad/module_4.mjs
@@ -0,0 +1 @@
+throw "Shouldn't load file bad/module_4.mjs";
diff --git a/dom/base/test/jsmodules/importmaps/bad/module_7.mjs b/dom/base/test/jsmodules/importmaps/bad/module_7.mjs
new file mode 100644
index 0000000000..8844bf862c
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/bad/module_7.mjs
@@ -0,0 +1 @@
+throw "Shouldn't load file bad/module_7.mjs";
diff --git a/dom/base/test/jsmodules/importmaps/bug_1865410_module_a.mjs b/dom/base/test/jsmodules/importmaps/bug_1865410_module_a.mjs
new file mode 100644
index 0000000000..07d43d115e
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/bug_1865410_module_a.mjs
@@ -0,0 +1,2 @@
+// eslint-disable-next-line import/no-unassigned-import
+import {} from "./bug_1865410_module_b.mjs";
diff --git a/dom/base/test/jsmodules/importmaps/bug_1865410_module_b.mjs b/dom/base/test/jsmodules/importmaps/bug_1865410_module_b.mjs
new file mode 100644
index 0000000000..2bd6dce476
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/bug_1865410_module_b.mjs
@@ -0,0 +1 @@
+// Empty.
diff --git a/dom/base/test/jsmodules/importmaps/bug_1873417.mjs b/dom/base/test/jsmodules/importmaps/bug_1873417.mjs
new file mode 100644
index 0000000000..339e6acf91
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/bug_1873417.mjs
@@ -0,0 +1,2 @@
+console.log("Module loaded successfully!");
+state = "loaded";
diff --git a/dom/base/test/jsmodules/importmaps/chrome.toml b/dom/base/test/jsmodules/importmaps/chrome.toml
new file mode 100644
index 0000000000..0b8afe0f25
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/chrome.toml
@@ -0,0 +1,37 @@
+[DEFAULT]
+support-files = [
+ "external_importMap.js",
+ "insert_a_base_element.js",
+ "module_simpleImportMap.mjs",
+ "module_simpleImportMap_dir.mjs",
+ "module_simpleImportMap_remap.mjs",
+ "module_simpleImportMap_remap_https.mjs",
+ "module_simpleExport.mjs",
+ "module_sortedImportMap.mjs",
+ "scope1/module_simpleExport.mjs",
+ "scope1/module_simpleImportMap.mjs",
+ "scope1/scope2/module_simpleExport.mjs",
+ "scope1/scope2/module_simpleImportMap.mjs",
+]
+
+["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/circular_dependency.mjs b/dom/base/test/jsmodules/importmaps/circular_dependency.mjs
new file mode 100644
index 0000000000..f28d24b75e
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/circular_dependency.mjs
@@ -0,0 +1,6 @@
+// Should be remapped to good/module_3.mjs.
+import { exportedFunction } from "./bad/module_3.mjs";
+
+if (exportedFunction()) {
+ success("circular_dependency.mjs");
+}
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/good/module_0.mjs b/dom/base/test/jsmodules/importmaps/good/module_0.mjs
new file mode 100644
index 0000000000..5c3c5e2ab1
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/good/module_0.mjs
@@ -0,0 +1 @@
+success("good/module_0.mjs");
diff --git a/dom/base/test/jsmodules/importmaps/good/module_1.mjs b/dom/base/test/jsmodules/importmaps/good/module_1.mjs
new file mode 100644
index 0000000000..9b902b266a
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/good/module_1.mjs
@@ -0,0 +1 @@
+success("good/module_1.mjs");
diff --git a/dom/base/test/jsmodules/importmaps/good/module_2.mjs b/dom/base/test/jsmodules/importmaps/good/module_2.mjs
new file mode 100644
index 0000000000..6756465905
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/good/module_2.mjs
@@ -0,0 +1 @@
+success("good/module_2.mjs");
diff --git a/dom/base/test/jsmodules/importmaps/good/module_3.mjs b/dom/base/test/jsmodules/importmaps/good/module_3.mjs
new file mode 100644
index 0000000000..95450e55f7
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/good/module_3.mjs
@@ -0,0 +1,6 @@
+// eslint-disable-next-line import/no-unassigned-import
+import {} from "../circular_dependency.mjs";
+
+export function exportedFunction() {
+ return true;
+}
diff --git a/dom/base/test/jsmodules/importmaps/good/module_4.mjs b/dom/base/test/jsmodules/importmaps/good/module_4.mjs
new file mode 100644
index 0000000000..eaec9eb760
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/good/module_4.mjs
@@ -0,0 +1 @@
+success("good/module_4.mjs");
diff --git a/dom/base/test/jsmodules/importmaps/good/module_7.mjs b/dom/base/test/jsmodules/importmaps/good/module_7.mjs
new file mode 100644
index 0000000000..6603e1300d
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/good/module_7.mjs
@@ -0,0 +1 @@
+success("good/module_7.mjs");
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/mochitest.toml b/dom/base/test/jsmodules/importmaps/mochitest.toml
new file mode 100644
index 0000000000..4229455722
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/mochitest.toml
@@ -0,0 +1,33 @@
+[DEFAULT]
+support-files = [
+ "bug_1865410_module_a.mjs",
+ "bug_1865410_module_b.mjs",
+ "bug_1873417.mjs",
+ "module_importMap_with_external_script_0.mjs",
+ "module_importMap_with_external_script_1.mjs",
+ "module_importMap_with_external_script_2.mjs",
+ "module_importMap_with_external_script_3.mjs",
+ "module_importMap_with_external_script_4.mjs",
+ "module_importMap_with_external_script_5.mjs",
+ "module_importMap_with_external_script_5.mjs^headers^",
+ "module_importMap_with_external_script_6.mjs",
+ "module_importMap_with_external_script_6.mjs^headers^",
+ "module_importMap_with_external_script_7.mjs",
+ "bad/module_2.mjs",
+ "bad/module_3.mjs",
+ "bad/module_4.mjs",
+ "bad/module_7.mjs",
+ "good/module_0.mjs",
+ "good/module_1.mjs",
+ "good/module_2.mjs",
+ "good/module_3.mjs",
+ "good/module_4.mjs",
+ "good/module_7.mjs",
+ "circular_dependency.mjs",
+]
+
+["test_bug_1865410.html"]
+
+["test_bug_1873417.html"]
+
+["test_importMap_with_external_script.html"]
diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_0.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_0.mjs
new file mode 100644
index 0000000000..e2ba9dee7e
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_0.mjs
@@ -0,0 +1,3 @@
+// Bareword specifier should be mapped to ./good/module_0.mjs.
+// eslint-disable-next-line import/no-unassigned-import, import/no-unresolved
+import {} from "bare";
diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_1.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_1.mjs
new file mode 100644
index 0000000000..9d763a678f
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_1.mjs
@@ -0,0 +1,3 @@
+// Missing file ./bad/module_1.mjs should be mapped to ./good/module_1.mjs.
+// eslint-disable-next-line import/no-unassigned-import, import/no-unresolved
+import {} from "./bad/module_1.mjs";
diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_2.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_2.mjs
new file mode 100644
index 0000000000..f0cb539a48
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_2.mjs
@@ -0,0 +1,3 @@
+// Existing file ./bad/module_2.mjs should be mapped to ./good/module_2.mjs.
+// eslint-disable-next-line import/no-unassigned-import
+import {} from "./bad/module_2.mjs";
diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_3.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_3.mjs
new file mode 100644
index 0000000000..851f6dc3bc
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_3.mjs
@@ -0,0 +1,3 @@
+// Existing file ./bad/module_3.mjs should be mapped to ./good/module_3.mjs.
+// eslint-disable-next-line import/no-unassigned-import
+import {} from "./bad/module_3.mjs";
diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_4.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_4.mjs
new file mode 100644
index 0000000000..8f46b73123
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_4.mjs
@@ -0,0 +1,3 @@
+// Existing file ./bad/module_4.mjs should be mapped to ./good/module_4.mjs.
+// eslint-disable-next-line import/no-unassigned-import
+import {} from "./bad/module_4.mjs";
diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs
new file mode 100644
index 0000000000..ac814c5e83
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs
@@ -0,0 +1,3 @@
+// Existing file ./bad/module_3.mjs should be mapped to ./good/module_3.mjs.
+//import {} from "./bad/module_3.mjs";
+throw "Error: script_5.mjs";
diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs^headers^ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs^headers^
new file mode 100644
index 0000000000..4cbbbc283d
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_5.mjs^headers^
@@ -0,0 +1,2 @@
+HTTP 301 Moved Permanently
+Location: module_importMap_with_external_script_4.mjs
diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs
new file mode 100644
index 0000000000..9e02aa6bf4
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs
@@ -0,0 +1,3 @@
+// Existing file ./bad/module_3.mjs should be mapped to ./good/module_3.mjs.
+//import {} from "./bad/module_3.mjs";
+throw "Error: script_6.mjs";
diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs^headers^ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs^headers^
new file mode 100644
index 0000000000..9f5e36c5a2
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_6.mjs^headers^
@@ -0,0 +1,2 @@
+HTTP 301 Moved Permanently
+Location: module_importMap_with_external_script_5.mjs
diff --git a/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_7.mjs b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_7.mjs
new file mode 100644
index 0000000000..b602217da5
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_importMap_with_external_script_7.mjs
@@ -0,0 +1,3 @@
+// Existing file ./bad/module_7.mjs should be mapped to ./good/module_4.mjs.
+// eslint-disable-next-line import/no-unassigned-import
+import {} from "./bad/module_7.mjs";
diff --git a/dom/base/test/jsmodules/importmaps/module_simpleExport.mjs b/dom/base/test/jsmodules/importmaps/module_simpleExport.mjs
new file mode 100644
index 0000000000..9714d6d0ab
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_simpleExport.mjs
@@ -0,0 +1 @@
+export let x = 42;
diff --git a/dom/base/test/jsmodules/importmaps/module_simpleImportMap.mjs b/dom/base/test/jsmodules/importmaps/module_simpleImportMap.mjs
new file mode 100644
index 0000000000..2f7e649dce
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_simpleImportMap.mjs
@@ -0,0 +1,4 @@
+// eslint-disable-next-line import/no-unresolved
+import { x } from "simple";
+
+result = x;
diff --git a/dom/base/test/jsmodules/importmaps/module_simpleImportMap_dir.mjs b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_dir.mjs
new file mode 100644
index 0000000000..3a8a2a63b8
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_dir.mjs
@@ -0,0 +1,4 @@
+// eslint-disable-next-line import/no-unresolved
+import { x } from "dir/module_simpleExport.mjs";
+
+result_dir = x + 1;
diff --git a/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap.mjs b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap.mjs
new file mode 100644
index 0000000000..54d22e5a5c
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap.mjs
@@ -0,0 +1,4 @@
+// eslint-disable-next-line import/no-unresolved
+import { x } from "./module.mjs";
+
+result_remap = x + 2;
diff --git a/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap_https.mjs b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap_https.mjs
new file mode 100644
index 0000000000..d9b82243b7
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_simpleImportMap_remap_https.mjs
@@ -0,0 +1,4 @@
+// eslint-disable-next-line import/no-unresolved
+import { x } from "https://example.com/module.mjs";
+
+result_remap_https = x + 3;
diff --git a/dom/base/test/jsmodules/importmaps/module_sortedImportMap.mjs b/dom/base/test/jsmodules/importmaps/module_sortedImportMap.mjs
new file mode 100644
index 0000000000..2b199ca272
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/module_sortedImportMap.mjs
@@ -0,0 +1,6 @@
+/* eslint-disable import/no-unresolved */
+import { x } from "scope1/scope2/module_simpleExport.mjs";
+import { x as y } from "scope1/scope2/scope3/scope4/module_simpleExport.mjs";
+
+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..ca4ef002b0
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/moz.build
@@ -0,0 +1,9 @@
+# -*- 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.toml"]
+
+MOCHITEST_MANIFESTS += ["mochitest.toml"]
diff --git a/dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.mjs b/dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.mjs
new file mode 100644
index 0000000000..e6b0ed1c0c
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.mjs
@@ -0,0 +1 @@
+export let x = 84;
diff --git a/dom/base/test/jsmodules/importmaps/scope1/module_simpleImportMap.mjs b/dom/base/test/jsmodules/importmaps/scope1/module_simpleImportMap.mjs
new file mode 100644
index 0000000000..a64a098b7b
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/scope1/module_simpleImportMap.mjs
@@ -0,0 +1,4 @@
+// eslint-disable-next-line import/no-unresolved
+import { x } from "simple";
+
+result_scope1 = x;
diff --git a/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleExport.mjs b/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleExport.mjs
new file mode 100644
index 0000000000..ba2bbae16b
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleExport.mjs
@@ -0,0 +1 @@
+export let x = 126;
diff --git a/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleImportMap.mjs b/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleImportMap.mjs
new file mode 100644
index 0000000000..00819aefd1
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleImportMap.mjs
@@ -0,0 +1,4 @@
+// eslint-disable-next-line import/no-unresolved
+import { x } from "simple";
+
+result_scope2 = x;
diff --git a/dom/base/test/jsmodules/importmaps/test_bug_1865410.html b/dom/base/test/jsmodules/importmaps/test_bug_1865410.html
new file mode 100644
index 0000000000..a59aba368d
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/test_bug_1865410.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Bug 1865410: Test interaction between speculative preload and import maps</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+<!-- Insert an import map after we have started preloading the modules. -->
+<div id="container"></div>
+<script>
+ let script = document.createElement("script");
+ script.type = "importmap";
+ script.textContent = "{}";
+ let container = document.getElementById("container");
+ container.appendChild(script);
+</script>
+
+<!-- Load the first module which will load the second via an import. -->
+<script type="module" src="bug_1865410_module_a.mjs" async></script>
+<script src="../../slow.sjs"></script>
+
+<!-- Load the second, already loaded module. -->
+<script type="module", src="bug_1865410_module_b.mjs"></script>
+
+<script>
+ ok(true, "Didn't crash");
+</script>
diff --git a/dom/base/test/jsmodules/importmaps/test_bug_1873417.html b/dom/base/test/jsmodules/importmaps/test_bug_1873417.html
new file mode 100644
index 0000000000..9ae689be3b
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/test_bug_1873417.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Bug 1873417: Test if import-maps will block module script execution</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ (function () {
+ const script = document.createElement('script');
+ script.type = 'importmap';
+ script.textContent = '{}';
+ document.head.appendChild(script);
+ }());
+</script>
+
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+<script>
+let hasError = false;
+var state;
+
+SimpleTest.waitForExplicitFinish();
+
+function scriptError() {
+ hasError = true;
+}
+
+function testLoaded() {
+ ok(!hasError, 'module script should be loaded');
+ info("state:" + state);
+ ok(state === "loaded", "'state' should be set to 'loaded'");
+ SimpleTest.finish();
+}
+
+</script>
+
+<body onload="testLoaded()">
+<script src="bug_1873417.mjs" type="module" onerror="scriptError()"></script>
+</body>
+
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..96744c9317
--- /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.mjs" won't be remapped to-->
+<!--"./scope1/module_simpleExport.mjs".-->
+
+<script>
+ import("./module_simpleExport.mjs");
+</script>
+
+<script type="importmap" onerror='importMapError()'>
+{
+ "imports": {
+ "./module_simpleExport.mjs": "./scope1/module_simpleExport.mjs"
+ }
+}
+</script>
+
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ let hasError = false;
+ function importMapError() {
+ hasError = true;
+ }
+
+ function testLoaded() {
+ import("./module_simpleExport.mjs").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_importMap_with_external_script.html b/dom/base/test/jsmodules/importmaps/test_importMap_with_external_script.html
new file mode 100644
index 0000000000..3b21003feb
--- /dev/null
+++ b/dom/base/test/jsmodules/importmaps/test_importMap_with_external_script.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<head>
+<title>Test speculative preload of external script doesn't conflict with import map</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<!--
+ These tests check that speculative preloading, which could happen before
+ the import map is installed, doesn't load the wrong modules.
+-->
+
+<script type="importmap">
+ {
+ "imports": {
+ "bare": "./good/module_0.mjs",
+ "./bad/module_1.mjs": "./good/module_1.mjs",
+ "./bad/module_2.mjs": "./good/module_2.mjs",
+ "./bad/module_3.mjs": "./good/module_3.mjs",
+ "./bad/module_4.mjs": "./good/module_4.mjs",
+ "./bad/module_7.mjs": "./good/module_7.mjs"
+ }
+ }
+</script>
+
+<!--
+Test bareword import (not supported before import map installed).
+-->
+<script type="module" src="module_importMap_with_external_script_0.mjs"></script>
+
+<!--
+Test mapping from missing resource to existing resource (not found before
+import map installed).
+-->
+<script type="module" src="module_importMap_with_external_script_1.mjs"></script>
+
+<!--
+Test mapping from one existing resource to another (would load wrong resource before
+import map installed).
+-->
+<script type="module" src="module_importMap_with_external_script_2.mjs"></script>
+
+<!--
+Test mapping from one existing resource to another with circular dependency.
+-->
+<script type="module" src="module_importMap_with_external_script_3.mjs"></script>
+
+<!--
+Test with redirect, script_6.mjs -> script_5.mjs -> script_4.mjs.
+We redirect twice here, as sometimes one redirect can't reproduce the crash
+from bug 1835468.
+-->
+<script type="module" src="module_importMap_with_external_script_6.mjs"></script>
+
+<!--
+Test with async attribute
+-->
+<script type="module" async src="module_importMap_with_external_script_7.mjs"></script>
+
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ let passCount = 0;
+ const expectedCount = 6;
+
+ function success(name) {
+ ok(true, "Test passed, loaded " + name);
+ passCount++;
+ if (passCount == expectedCount) {
+ SimpleTest.finish();
+ }
+ }
+</script>
+<body></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..5c81dd548e
--- /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.mjs"
+ }
+}
+</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.mjs",
+ "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..458601619a
--- /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.mjs" won't be remapped to-->
+<!--"./scope1/module_simpleExport.mjs".-->
+
+<script type="module">
+</script>
+
+<script type="importmap" onerror='importMapError()'>
+{
+ "imports": {
+ "./module_simpleExport.mjs": "./scope1/module_simpleExport.mjs"
+ }
+}
+</script>
+
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ let hasError = false;
+ function importMapError() {
+ hasError = true;
+ }
+
+ function testLoaded() {
+ import("./module_simpleExport.mjs").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..531431fcf0
--- /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.mjs" should be mapped
+to "scope1/module_simpleExport.mjs", instead of "./module_simpleExport.mjs".
+-->
+
+<script type="importmap">
+{
+ "imports": {
+ "simple": "./module_simpleExport.mjs"
+ }
+}
+</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.mjs"></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..7ab3fe96da
--- /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.mjs" should be mapped
+to "scope1/module_simpleExport.mjs", instead of "./module_simpleExport.mjs".
+-->
+
+<script type="importmap">
+{
+ "imports": {
+ "simple": "./module_simpleExport.mjs"
+ }
+}
+</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.mjs"></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..88db016e3d
--- /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.mjs" won't be remapped to-->
+<!--"./scope1/module_simpleExport.mjs".-->
+
+<script src="./module_simpleExport.mjs" type="module">
+</script>
+
+<script type="importmap" onerror='importMapError()'>
+{
+ "imports": {
+ "./module_simpleExport.mjs": "./scope1/module_simpleExport.mjs"
+ }
+}
+</script>
+
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ let hasError = false;
+ function importMapError() {
+ hasError = true;
+ }
+
+ function testLoaded() {
+ import("./module_simpleExport.mjs").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..2a3498094c
--- /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.mjs": "./scope1/module_simpleExport.mjs"
+ }
+}
+</script>
+
+<!--The 2nd import map should be rejected.-->
+<script type="importmap" onerror='importMapError2()'>
+{
+ "imports": {
+ "./module_simpleExport.mjs": "./scope1/module_simpleExport.mjs"
+ }
+}
+</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.mjs").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..5323da31a9
--- /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.mjs",
+ "dir/": "/content/chrome/dom/base/test/jsmodules/importmaps/",
+ "./module.mjs": "/content/chrome/dom/base/test/jsmodules/importmaps/module_simpleExport.mjs",
+ "https://example.com/module.mjs": "./module_simpleExport.mjs"
+ },
+ "scopes": {
+ "chrome://mochitests/content/chrome/dom/base/test/jsmodules/importmaps/scope1/": {
+ "simple": "/content/chrome/dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.mjs"
+ },
+ "chrome://mochitests/content/chrome/dom/base/test/jsmodules/importmaps/scope1/scope2/": {
+ "simple": "/content/chrome/dom/base/test/jsmodules/importmaps/scope1/scope2/module_simpleExport.mjs"
+ }
+ }
+}
+</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.mjs");
+ }).then((ns) => {
+ ok(ns.x == 42, 'Check dir imported value result: ' + ns.x);
+ return import("./module.mjs");
+ }).then((ns) => {
+ ok(ns.x == 42, 'Check remap imported value result: ' + ns.x);
+ return import("https://example.com/module.mjs");
+ }).then((ns) => {
+ ok(ns.x == 42, 'Check remap https imported value result: ' + ns.x);
+ SimpleTest.finish();
+ });
+ }
+</script>
+<script type="module" src="module_simpleImportMap.mjs"></script>
+<script type="module" src="module_simpleImportMap_dir.mjs"></script>
+<script type="module" src="module_simpleImportMap_remap.mjs"></script>
+<script type="module" src="module_simpleImportMap_remap_https.mjs"></script>
+<script type="module" src="module_simpleImportMap_remap_https.mjs"></script>
+<script type="module" src="scope1/module_simpleImportMap.mjs"></script>
+<script type="module" src="scope1/scope2/module_simpleImportMap.mjs"></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..f4b98fdf10
--- /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.mjs"
+ },
+ "chrome://mochitests/content/chrome/dom/base/test/jsmodules/importmaps/scope1/": {
+ "simple": "/content/chrome/dom/base/test/jsmodules/importmaps/scope1/module_simpleExport.mjs"
+ }
+ }
+}
+</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.mjs"></script>
+<script type="module" src="scope1/scope2/module_simpleImportMap.mjs"></script>
+<body onload='testLoaded()'></body>
diff --git a/dom/base/test/jsmodules/module_badImport.mjs b/dom/base/test/jsmodules/module_badImport.mjs
new file mode 100644
index 0000000000..9d72b27c43
--- /dev/null
+++ b/dom/base/test/jsmodules/module_badImport.mjs
@@ -0,0 +1,2 @@
+/* eslint-disable import/no-unassigned-import, import/no-unresolved */
+import "invalid specifier";
diff --git a/dom/base/test/jsmodules/module_badSyntax.mjs b/dom/base/test/jsmodules/module_badSyntax.mjs
new file mode 100644
index 0000000000..744158108c
--- /dev/null
+++ b/dom/base/test/jsmodules/module_badSyntax.mjs
@@ -0,0 +1,3 @@
+// Module with a syntax error.
+some invalid js syntax;
+wasRun = true;
diff --git a/dom/base/test/jsmodules/module_cyclic1.mjs b/dom/base/test/jsmodules/module_cyclic1.mjs
new file mode 100644
index 0000000000..197a94989a
--- /dev/null
+++ b/dom/base/test/jsmodules/module_cyclic1.mjs
@@ -0,0 +1,8 @@
+import { func2 } from "./module_cyclic2.mjs";
+
+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.mjs b/dom/base/test/jsmodules/module_cyclic2.mjs
new file mode 100644
index 0000000000..7ecec80c65
--- /dev/null
+++ b/dom/base/test/jsmodules/module_cyclic2.mjs
@@ -0,0 +1,8 @@
+import { func3 } from "./module_cyclic3.mjs";
+
+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.mjs b/dom/base/test/jsmodules/module_cyclic3.mjs
new file mode 100644
index 0000000000..9458391d2e
--- /dev/null
+++ b/dom/base/test/jsmodules/module_cyclic3.mjs
@@ -0,0 +1,8 @@
+import { func1 } from "./module_cyclic1.mjs";
+
+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.mjs b/dom/base/test/jsmodules/module_extractIntroType.mjs
new file mode 100644
index 0000000000..a5daa8f0ef
--- /dev/null
+++ b/dom/base/test/jsmodules/module_extractIntroType.mjs
@@ -0,0 +1,6 @@
+// Extract the introductionType for this module in conjunction with
+// iframe_extractIntroType.html.
+extractIntroType = function () {
+ // eslint-disable-next-line no-debugger
+ debugger;
+};
diff --git a/dom/base/test/jsmodules/module_large1.mjs b/dom/base/test/jsmodules/module_large1.mjs
new file mode 100644
index 0000000000..d6933d298d
--- /dev/null
+++ b/dom/base/test/jsmodules/module_large1.mjs
@@ -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.mjs b/dom/base/test/jsmodules/module_large2.mjs
new file mode 100644
index 0000000000..e1b6da4c91
--- /dev/null
+++ b/dom/base/test/jsmodules/module_large2.mjs
@@ -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.mjs b/dom/base/test/jsmodules/module_large3.mjs
new file mode 100644
index 0000000000..c966a8eb20
--- /dev/null
+++ b/dom/base/test/jsmodules/module_large3.mjs
@@ -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.mjs b/dom/base/test/jsmodules/module_missingImport.mjs
new file mode 100644
index 0000000000..3b2ee2bc73
--- /dev/null
+++ b/dom/base/test/jsmodules/module_missingImport.mjs
@@ -0,0 +1 @@
+import { missing } from "./module_simple1.mjs";
diff --git a/dom/base/test/jsmodules/module_multiImports.mjs b/dom/base/test/jsmodules/module_multiImports.mjs
new file mode 100644
index 0000000000..9fe9516f92
--- /dev/null
+++ b/dom/base/test/jsmodules/module_multiImports.mjs
@@ -0,0 +1,6 @@
+/* eslint-disable import/no-unassigned-import */
+import "./module_simple1.mjs";
+import "./module_simple2.mjs";
+import "./module_simple3.mjs";
+
+results.push(4);
diff --git a/dom/base/test/jsmodules/module_multiLargeImports.mjs b/dom/base/test/jsmodules/module_multiLargeImports.mjs
new file mode 100644
index 0000000000..c4f32baf4e
--- /dev/null
+++ b/dom/base/test/jsmodules/module_multiLargeImports.mjs
@@ -0,0 +1,6 @@
+/* eslint-disable import/no-unassigned-import */
+import "./module_large1.mjs";
+import "./module_large2.mjs";
+import "./module_large3.mjs";
+
+results.push(4);
diff --git a/dom/base/test/jsmodules/module_setRan.mjs b/dom/base/test/jsmodules/module_setRan.mjs
new file mode 100644
index 0000000000..4804382fdd
--- /dev/null
+++ b/dom/base/test/jsmodules/module_setRan.mjs
@@ -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.mjs b/dom/base/test/jsmodules/module_simple1.mjs
new file mode 100644
index 0000000000..7594ac699e
--- /dev/null
+++ b/dom/base/test/jsmodules/module_simple1.mjs
@@ -0,0 +1 @@
+results.push(1);
diff --git a/dom/base/test/jsmodules/module_simple2.mjs b/dom/base/test/jsmodules/module_simple2.mjs
new file mode 100644
index 0000000000..f92a1c9d6e
--- /dev/null
+++ b/dom/base/test/jsmodules/module_simple2.mjs
@@ -0,0 +1 @@
+results.push(2);
diff --git a/dom/base/test/jsmodules/module_simple3.mjs b/dom/base/test/jsmodules/module_simple3.mjs
new file mode 100644
index 0000000000..71979926e6
--- /dev/null
+++ b/dom/base/test/jsmodules/module_simple3.mjs
@@ -0,0 +1 @@
+results.push(3);
diff --git a/dom/base/test/jsmodules/module_simpleExport.mjs b/dom/base/test/jsmodules/module_simpleExport.mjs
new file mode 100644
index 0000000000..9714d6d0ab
--- /dev/null
+++ b/dom/base/test/jsmodules/module_simpleExport.mjs
@@ -0,0 +1 @@
+export let x = 42;
diff --git a/dom/base/test/jsmodules/module_simpleImport.mjs b/dom/base/test/jsmodules/module_simpleImport.mjs
new file mode 100644
index 0000000000..7a9d05325b
--- /dev/null
+++ b/dom/base/test/jsmodules/module_simpleImport.mjs
@@ -0,0 +1,3 @@
+import { x } from "./module_simpleExport.mjs";
+
+result = x;
diff --git a/dom/base/test/jsmodules/module_testSyntax.mjs b/dom/base/test/jsmodules/module_testSyntax.mjs
new file mode 100644
index 0000000000..3d647ae0b4
--- /dev/null
+++ b/dom/base/test/jsmodules/module_testSyntax.mjs
@@ -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..36ed046708
--- /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.toml"]
diff --git a/dom/base/test/jsmodules/no_export.mjs b/dom/base/test/jsmodules/no_export.mjs
new file mode 100644
index 0000000000..7d519cc264
--- /dev/null
+++ b/dom/base/test/jsmodules/no_export.mjs
@@ -0,0 +1 @@
+const y = 1;
diff --git a/dom/base/test/jsmodules/no_indirect_export.mjs b/dom/base/test/jsmodules/no_indirect_export.mjs
new file mode 100644
index 0000000000..1fcc87bf88
--- /dev/null
+++ b/dom/base/test/jsmodules/no_indirect_export.mjs
@@ -0,0 +1 @@
+export { a } from "./no_export.mjs";
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..47df5f1d03
--- /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.mjs";
+</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..8fb78c4f93
--- /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.mjs";
+ 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..f08aea1925
--- /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.mjs";
+</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..aac2f58bb5
--- /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.mjs";
+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..8b15a1762a
--- /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.mjs"></script>
+<body onload='testError()'></body>
diff --git a/dom/base/test/jsmodules/test_import_errorMessage.html b/dom/base/test/jsmodules/test_import_errorMessage.html
new file mode 100644
index 0000000000..6ab0b1dd74
--- /dev/null
+++ b/dom/base/test/jsmodules/test_import_errorMessage.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test module import error message</title>
+<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ let count = 0;
+
+ window.onerror = function (event, src, lineno, colno, error) {
+ info("window.onerror :" + error.message);
+ ok(error instanceof SyntaxError, "Should be a SyntaxError.");
+
+ // import_no_indirect_export.mjs and import_ambiguous_indirect_export.mjs
+ // are related to indirect import/export.
+ if (count < 2) {
+ ok(error.message.match("indirect"), "Should contain 'indirect'");
+ }
+
+ // import_ambiguous_indirect_export.mjs and import_ambiguous.mjs both
+ // have ambiguous import/export.
+ if (count % 2 === 1) {
+ ok(error.message.match("ambiguous"), "Should contain 'ambiguous'");
+ }
+
+ if (count === 2) {
+ ok(!error.message.match("ambiguous") && !error.message.match("indirect"),
+ "Should NOT contain 'indirect' nor 'ambiguous'");
+ }
+ count++;
+ };
+
+ function testLoaded() {
+ ok(count === 4, "Should have 4 SynaxErrors thrown.");
+ SimpleTest.finish();
+ }
+</script>
+
+<!--
+In window.onerror will test the error messages, so if the order is changed,
+the code in window.onerror should be updated as well.
+-->
+<script type="module" src="import_no_indirect_export.mjs"></script>
+<script type="module" src="import_ambiguous_indirect_export.mjs"></script>
+<script type="module" src="import_no_export.mjs"></script>
+<script type="module" src="import_ambiguous.mjs"></script>
+<body onload='testLoaded()'></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..df7686fb70
--- /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.mjs"></script>
+<script type="module" src="module_multiImports.mjs"></script>
+<script type="module" src="module_multiImports.mjs"></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..251b96d367
--- /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.mjs";
+ runCount++;
+</script>
+<script type="module">
+ import { missing } from "./module_simple1.mjs";
+ 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..77f0bab0b9
--- /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.mjs";
+ runCount++;
+</script>
+<script type="module">
+ import "./module_missingImport.mjs";
+ 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..d8662c9494
--- /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.mjs" 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..33000271dc
--- /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.mjs"></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..193b5ba386
--- /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.mjs"></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..07d9776b82
--- /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.mjs" async></script>
+<script type="module" src="module_simple2.mjs" async></script>
+<script type="module" src="module_simple3.mjs" 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..924b3bce55
--- /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.mjs"></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..2e788e1469
--- /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.mjs"></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..1e4652e827
--- /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.mjs"></script>
+<script type="module" src="module_simple2.mjs"></script>
+<script type="module" src="module_simple3.mjs"></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..3ec7241061
--- /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.mjs"></script>
+<script type="module" src="module_simple2.mjs"></script>
+<script type="module" src="module_large3.mjs"></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..09a03f3186
--- /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.mjs";
+ 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..bec30a3350
--- /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.mjs"></script>
+<script defer src="script_simple2.js"></script>
+<script type="module" src="module_simple3.mjs"></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..dbad1bc722
--- /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.mjs"></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..21d02fdb90
--- /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.mjs"></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..c35179579b
--- /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.mjs" 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..fedf7c1d5c
--- /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.mjs" 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..2cc7c12e09
--- /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.mjs">
+</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..0f1d57c6eb
--- /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.mjs"></script>
+<script type="module" src="module_simple1.mjs"></script>
+<script type="module" src="module_simple1.mjs"></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..106e0f9522
--- /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.mjs"></script>
+<script type="mOdUlE">inlineModuleRan = true;</script>
+<body onload='testLoaded()'></body>