summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/modules
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/modules')
-rw-r--r--js/src/jit-test/tests/modules/add-to-namespace-import.js3
-rw-r--r--js/src/jit-test/tests/modules/ambiguous-import.js2
-rw-r--r--js/src/jit-test/tests/modules/ambiguous-indirect-export.js2
-rw-r--r--js/src/jit-test/tests/modules/ambiguous-star-export.js43
-rw-r--r--js/src/jit-test/tests/modules/assign-to-import.js3
-rw-r--r--js/src/jit-test/tests/modules/assign-to-namespace-import.js3
-rw-r--r--js/src/jit-test/tests/modules/assign-to-namespace.js3
-rw-r--r--js/src/jit-test/tests/modules/bad-namespace-created.js15
-rw-r--r--js/src/jit-test/tests/modules/bug-1168666.js2
-rw-r--r--js/src/jit-test/tests/modules/bug-1217593.js6
-rw-r--r--js/src/jit-test/tests/modules/bug-1219044.js4
-rw-r--r--js/src/jit-test/tests/modules/bug-1219408.js2
-rw-r--r--js/src/jit-test/tests/modules/bug-1225346.js2
-rw-r--r--js/src/jit-test/tests/modules/bug-1233117.js2
-rw-r--r--js/src/jit-test/tests/modules/bug-1233179.js8
-rw-r--r--js/src/jit-test/tests/modules/bug-1233915.js11
-rw-r--r--js/src/jit-test/tests/modules/bug-1236875.js2
-rw-r--r--js/src/jit-test/tests/modules/bug-1245518.js15
-rw-r--r--js/src/jit-test/tests/modules/bug-1247934.js5
-rw-r--r--js/src/jit-test/tests/modules/bug-1251090.js3
-rw-r--r--js/src/jit-test/tests/modules/bug-1258097.js3
-rw-r--r--js/src/jit-test/tests/modules/bug-1283448.js6
-rw-r--r--js/src/jit-test/tests/modules/bug-1284486-2.js34
-rw-r--r--js/src/jit-test/tests/modules/bug-1284486.js33
-rw-r--r--js/src/jit-test/tests/modules/bug-1287406.js1
-rw-r--r--js/src/jit-test/tests/modules/bug-1287410.js17
-rw-r--r--js/src/jit-test/tests/modules/bug-1320993.js2
-rw-r--r--js/src/jit-test/tests/modules/bug-1372258.js25
-rw-r--r--js/src/jit-test/tests/modules/bug-1402535.js6
-rw-r--r--js/src/jit-test/tests/modules/bug-1402649.js14
-rw-r--r--js/src/jit-test/tests/modules/bug-1406452.js5
-rw-r--r--js/src/jit-test/tests/modules/bug-1420420-2.js17
-rw-r--r--js/src/jit-test/tests/modules/bug-1420420-3.js7
-rw-r--r--js/src/jit-test/tests/modules/bug-1420420-4.js18
-rw-r--r--js/src/jit-test/tests/modules/bug-1420420.js17
-rw-r--r--js/src/jit-test/tests/modules/bug-1435327.js27
-rw-r--r--js/src/jit-test/tests/modules/bug-1439416-2.js10
-rw-r--r--js/src/jit-test/tests/modules/bug-1439416.js10
-rw-r--r--js/src/jit-test/tests/modules/bug-1443555.js29
-rw-r--r--js/src/jit-test/tests/modules/bug-1462286.js8
-rw-r--r--js/src/jit-test/tests/modules/bug-1462326.js6
-rw-r--r--js/src/jit-test/tests/modules/bug-1466487.js7
-rw-r--r--js/src/jit-test/tests/modules/bug-1476921.js31
-rw-r--r--js/src/jit-test/tests/modules/bug-1498980.js29
-rw-r--r--js/src/jit-test/tests/modules/bug-1501154.js25
-rw-r--r--js/src/jit-test/tests/modules/bug-1501157.js2
-rw-r--r--js/src/jit-test/tests/modules/bug-1502669.js5
-rw-r--r--js/src/jit-test/tests/modules/bug-1503009.js1
-rw-r--r--js/src/jit-test/tests/modules/bug-1510598.js9
-rw-r--r--js/src/jit-test/tests/modules/bug-1519140.js3
-rw-r--r--js/src/jit-test/tests/modules/bug-1604792.js7
-rw-r--r--js/src/jit-test/tests/modules/bug-1657066.js3
-rw-r--r--js/src/jit-test/tests/modules/bug-1680878-a.js8
-rw-r--r--js/src/jit-test/tests/modules/bug-1680878.js7
-rw-r--r--js/src/jit-test/tests/modules/bug-1681256.js20
-rw-r--r--js/src/jit-test/tests/modules/bug1105608.js9
-rw-r--r--js/src/jit-test/tests/modules/bug1169850.js9
-rw-r--r--js/src/jit-test/tests/modules/bug1198673.js2
-rw-r--r--js/src/jit-test/tests/modules/bug1204857.js2
-rw-r--r--js/src/jit-test/tests/modules/bug1210391.js7
-rw-r--r--js/src/jit-test/tests/modules/bug1394492.js6
-rw-r--r--js/src/jit-test/tests/modules/bug1394493.js4
-rw-r--r--js/src/jit-test/tests/modules/bug1429031.js16
-rw-r--r--js/src/jit-test/tests/modules/bug1449153.js33
-rw-r--r--js/src/jit-test/tests/modules/bug1485698.js9
-rw-r--r--js/src/jit-test/tests/modules/bug1584034.js1
-rw-r--r--js/src/jit-test/tests/modules/bug1584309.js1
-rw-r--r--js/src/jit-test/tests/modules/bug1586599.js30
-rw-r--r--js/src/jit-test/tests/modules/bug1670236.js6
-rw-r--r--js/src/jit-test/tests/modules/bug1685992.js12
-rw-r--r--js/src/jit-test/tests/modules/cyclic-function-import.js7
-rw-r--r--js/src/jit-test/tests/modules/cyclic-import.js3
-rw-r--r--js/src/jit-test/tests/modules/debugger-frames.js83
-rw-r--r--js/src/jit-test/tests/modules/debugger-vars-function.js30
-rw-r--r--js/src/jit-test/tests/modules/debugger-vars-toplevel.js31
-rw-r--r--js/src/jit-test/tests/modules/delete-import.js3
-rw-r--r--js/src/jit-test/tests/modules/delete-namespace-import.js3
-rw-r--r--js/src/jit-test/tests/modules/delete-namespace.js3
-rw-r--r--js/src/jit-test/tests/modules/duplicate-exports.js32
-rw-r--r--js/src/jit-test/tests/modules/duplicate-imports.js27
-rw-r--r--js/src/jit-test/tests/modules/dynamic-import-error.js14
-rw-r--r--js/src/jit-test/tests/modules/dynamic-import-expression.js79
-rw-r--r--js/src/jit-test/tests/modules/dynamic-import-ion.js16
-rw-r--r--js/src/jit-test/tests/modules/dynamic-import-lazy.js4
-rw-r--r--js/src/jit-test/tests/modules/dynamic-import-module.js39
-rw-r--r--js/src/jit-test/tests/modules/dynamic-import-oom.js9
-rw-r--r--js/src/jit-test/tests/modules/dynamic-import-script.js45
-rw-r--r--js/src/jit-test/tests/modules/eval-module-oom.js23
-rw-r--r--js/src/jit-test/tests/modules/export-circular-nonexisting-binding.js3
-rw-r--r--js/src/jit-test/tests/modules/export-declaration.js480
-rw-r--r--js/src/jit-test/tests/modules/export-destructuring.js104
-rw-r--r--js/src/jit-test/tests/modules/export-entries.js121
-rw-r--r--js/src/jit-test/tests/modules/export-ns-from.js10
-rw-r--r--js/src/jit-test/tests/modules/export-star-cannot-rescue-missing-export.js4
-rw-r--r--js/src/jit-test/tests/modules/export-star-circular-dependencies.js6
-rw-r--r--js/src/jit-test/tests/modules/function-redeclaration.js94
-rw-r--r--js/src/jit-test/tests/modules/global-scope.js34
-rw-r--r--js/src/jit-test/tests/modules/import-declaration.js343
-rw-r--r--js/src/jit-test/tests/modules/import-default-async-asi.js7
-rw-r--r--js/src/jit-test/tests/modules/import-default-async-regexpy.js5
-rw-r--r--js/src/jit-test/tests/modules/import-default-class.js5
-rw-r--r--js/src/jit-test/tests/modules/import-default-function.js4
-rw-r--r--js/src/jit-test/tests/modules/import-entries.js49
-rw-r--r--js/src/jit-test/tests/modules/import-in-lazy-function.js11
-rw-r--r--js/src/jit-test/tests/modules/import-meta-expression.js91
-rw-r--r--js/src/jit-test/tests/modules/import-meta-oom.js3
-rw-r--r--js/src/jit-test/tests/modules/import-meta.js58
-rw-r--r--js/src/jit-test/tests/modules/import-namespace.js114
-rw-r--r--js/src/jit-test/tests/modules/import-not-found.js2
-rw-r--r--js/src/jit-test/tests/modules/inline-data.js17
-rw-r--r--js/src/jit-test/tests/modules/instanceof-error-message.js14
-rw-r--r--js/src/jit-test/tests/modules/let-tdz.js3
-rw-r--r--js/src/jit-test/tests/modules/many-exports.js17
-rw-r--r--js/src/jit-test/tests/modules/many-imports.js15
-rw-r--r--js/src/jit-test/tests/modules/many-namespace-imports.js15
-rw-r--r--js/src/jit-test/tests/modules/missing-export-offthread.js7
-rw-r--r--js/src/jit-test/tests/modules/missing-indirect-export.js2
-rw-r--r--js/src/jit-test/tests/modules/module-declaration-instantiation.js37
-rw-r--r--js/src/jit-test/tests/modules/module-environment.js34
-rw-r--r--js/src/jit-test/tests/modules/module-evaluation.js125
-rw-r--r--js/src/jit-test/tests/modules/module-this.js25
-rw-r--r--js/src/jit-test/tests/modules/namespace-import-compilation-2.js17
-rw-r--r--js/src/jit-test/tests/modules/namespace-import-compilation.js17
-rw-r--r--js/src/jit-test/tests/modules/off-thread-compile.js14
-rw-r--r--js/src/jit-test/tests/modules/recursive-star-export.js2
-rw-r--r--js/src/jit-test/tests/modules/requested-modules.js30
-rw-r--r--js/src/jit-test/tests/modules/shell-parse.js30
-rw-r--r--js/src/jit-test/tests/modules/simple-imports.js11
-rw-r--r--js/src/jit-test/tests/modules/unbound-export.js2
129 files changed, 3168 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/modules/add-to-namespace-import.js b/js/src/jit-test/tests/modules/add-to-namespace-import.js
new file mode 100644
index 0000000000..b5a6626bfc
--- /dev/null
+++ b/js/src/jit-test/tests/modules/add-to-namespace-import.js
@@ -0,0 +1,3 @@
+// |jit-test| module; error: TypeError
+import * as ns from "module1.js";
+ns.b = 2;
diff --git a/js/src/jit-test/tests/modules/ambiguous-import.js b/js/src/jit-test/tests/modules/ambiguous-import.js
new file mode 100644
index 0000000000..6a91f9537b
--- /dev/null
+++ b/js/src/jit-test/tests/modules/ambiguous-import.js
@@ -0,0 +1,2 @@
+// |jit-test| module; error: SyntaxError
+import { a } from "ambiguous.js";
diff --git a/js/src/jit-test/tests/modules/ambiguous-indirect-export.js b/js/src/jit-test/tests/modules/ambiguous-indirect-export.js
new file mode 100644
index 0000000000..17949955ea
--- /dev/null
+++ b/js/src/jit-test/tests/modules/ambiguous-indirect-export.js
@@ -0,0 +1,2 @@
+// |jit-test| module; error: SyntaxError
+export { a } from "ambiguous.js";
diff --git a/js/src/jit-test/tests/modules/ambiguous-star-export.js b/js/src/jit-test/tests/modules/ambiguous-star-export.js
new file mode 100644
index 0000000000..2542714061
--- /dev/null
+++ b/js/src/jit-test/tests/modules/ambiguous-star-export.js
@@ -0,0 +1,43 @@
+// Test ambigious export * statements.
+
+"use strict";
+
+load(libdir + "asserts.js");
+
+function checkModuleEval(source) {
+ let m = parseModule(source);
+ m.declarationInstantiation();
+ m.evaluation();
+ return m;
+}
+
+function checkModuleSyntaxError(source) {
+ let m = parseModule(source);
+ assertThrowsInstanceOf(() => m.declarationInstantiation(), SyntaxError);
+}
+
+let a = registerModule('a', parseModule("export var a = 1; export var b = 2;"));
+let b = registerModule('b', parseModule("export var b = 3; export var c = 4;"));
+let c = registerModule('c', parseModule("export * from 'a'; export * from 'b';"));
+c.declarationInstantiation();
+c.evaluation();
+
+// Check importing/exporting non-ambiguous name works.
+let d = checkModuleEval("import { a } from 'c';");
+assertEq(getModuleEnvironmentValue(d, "a"), 1);
+checkModuleEval("export { a } from 'c';");
+
+// Check importing/exporting ambiguous name is a syntax error.
+checkModuleSyntaxError("import { b } from 'c';");
+checkModuleSyntaxError("export { b } from 'c';");
+
+// Check that namespace objects include only non-ambiguous names.
+let m = parseModule("import * as ns from 'c';");
+m.declarationInstantiation();
+m.evaluation();
+let ns = c.namespace;
+let names = Object.keys(ns);
+assertEq(names.length, 2);
+assertEq('a' in ns, true);
+assertEq('b' in ns, false);
+assertEq('c' in ns, true);
diff --git a/js/src/jit-test/tests/modules/assign-to-import.js b/js/src/jit-test/tests/modules/assign-to-import.js
new file mode 100644
index 0000000000..42abd66c50
--- /dev/null
+++ b/js/src/jit-test/tests/modules/assign-to-import.js
@@ -0,0 +1,3 @@
+// |jit-test| module; error: TypeError
+import { a } from "module1.js";
+a = 2;
diff --git a/js/src/jit-test/tests/modules/assign-to-namespace-import.js b/js/src/jit-test/tests/modules/assign-to-namespace-import.js
new file mode 100644
index 0000000000..faa55b6198
--- /dev/null
+++ b/js/src/jit-test/tests/modules/assign-to-namespace-import.js
@@ -0,0 +1,3 @@
+// |jit-test| module; error: TypeError
+import * as ns from "module1.js";
+ns.a = 2;
diff --git a/js/src/jit-test/tests/modules/assign-to-namespace.js b/js/src/jit-test/tests/modules/assign-to-namespace.js
new file mode 100644
index 0000000000..396ec1b525
--- /dev/null
+++ b/js/src/jit-test/tests/modules/assign-to-namespace.js
@@ -0,0 +1,3 @@
+// |jit-test| module; error: TypeError
+import * as ns from "module1.js";
+ns = 2;
diff --git a/js/src/jit-test/tests/modules/bad-namespace-created.js b/js/src/jit-test/tests/modules/bad-namespace-created.js
new file mode 100644
index 0000000000..cc4a6e46a8
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bad-namespace-created.js
@@ -0,0 +1,15 @@
+// Prior to https://github.com/tc39/ecma262/pull/916 it was possible for a
+// module namespace object to be successfully created that was later found to be
+// erroneous. Test that this is no longer the case.
+
+"use strict";
+
+load(libdir + "asserts.js");
+
+let a = registerModule('A', parseModule('import "B"; export {x} from "C"'));
+registerModule('B', parseModule('import * as a from "A"'));
+registerModule('C', parseModule('export * from "D"; export * from "E"'));
+registerModule('D', parseModule('export let x'));
+registerModule('E', parseModule('export let x'));
+
+assertThrowsInstanceOf(() => a.declarationInstantiation(), SyntaxError);
diff --git a/js/src/jit-test/tests/modules/bug-1168666.js b/js/src/jit-test/tests/modules/bug-1168666.js
new file mode 100644
index 0000000000..32aea2983b
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1168666.js
@@ -0,0 +1,2 @@
+// |jit-test| error: SyntaxError
+export *
diff --git a/js/src/jit-test/tests/modules/bug-1217593.js b/js/src/jit-test/tests/modules/bug-1217593.js
new file mode 100644
index 0000000000..ebf210b38e
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1217593.js
@@ -0,0 +1,6 @@
+enableOsiPointRegisterChecks();
+function f() {
+ return this;
+}
+f();
+f();
diff --git a/js/src/jit-test/tests/modules/bug-1219044.js b/js/src/jit-test/tests/modules/bug-1219044.js
new file mode 100644
index 0000000000..3917d7ca9c
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1219044.js
@@ -0,0 +1,4 @@
+// |jit-test| skip-if: !('oomTest' in this)
+
+oomTest(() => parseModule('import v from "mod";'));
+fullcompartmentchecks(true);
diff --git a/js/src/jit-test/tests/modules/bug-1219408.js b/js/src/jit-test/tests/modules/bug-1219408.js
new file mode 100644
index 0000000000..85d7092894
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1219408.js
@@ -0,0 +1,2 @@
+// |jit-test| error: Error
+parseModule("").evaluation();
diff --git a/js/src/jit-test/tests/modules/bug-1225346.js b/js/src/jit-test/tests/modules/bug-1225346.js
new file mode 100644
index 0000000000..6d8908e981
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1225346.js
@@ -0,0 +1,2 @@
+// |jit-test| error: Error: expected filename string, got number
+parseModule("", 3);
diff --git a/js/src/jit-test/tests/modules/bug-1233117.js b/js/src/jit-test/tests/modules/bug-1233117.js
new file mode 100644
index 0000000000..a5a7ee872e
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1233117.js
@@ -0,0 +1,2 @@
+// |jit-test| module; --enable-top-level-await
+eval("1");
diff --git a/js/src/jit-test/tests/modules/bug-1233179.js b/js/src/jit-test/tests/modules/bug-1233179.js
new file mode 100644
index 0000000000..80e742b319
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1233179.js
@@ -0,0 +1,8 @@
+// |jit-test| --code-coverage
+
+let c = parseModule(`
+ function a(x) { return x; }
+ function b(x) { return i<40; }
+ function d(x) { return x + 3; }
+`);
+getLcovInfo();
diff --git a/js/src/jit-test/tests/modules/bug-1233915.js b/js/src/jit-test/tests/modules/bug-1233915.js
new file mode 100644
index 0000000000..e3f2b2788c
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1233915.js
@@ -0,0 +1,11 @@
+g = newGlobal({newCompartment: true});
+g.parent = this;
+g.eval("(" + function() {
+ Debugger(parent)
+ .onExceptionUnwind = function(frame) {
+ return frame.eval("");
+ };
+} + ")()");
+m = parseModule(` s1 `);
+m.declarationInstantiation();
+m.evaluation();
diff --git a/js/src/jit-test/tests/modules/bug-1236875.js b/js/src/jit-test/tests/modules/bug-1236875.js
new file mode 100644
index 0000000000..41751f9476
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1236875.js
@@ -0,0 +1,2 @@
+let m = parseModule(`{ function x() {} }`);
+m.declarationInstantiation();
diff --git a/js/src/jit-test/tests/modules/bug-1245518.js b/js/src/jit-test/tests/modules/bug-1245518.js
new file mode 100644
index 0000000000..0247453b23
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1245518.js
@@ -0,0 +1,15 @@
+evalInFrame = function(global) {
+ dbgGlobal = newGlobal({newCompartment: true});
+ dbg = new dbgGlobal.Debugger();
+ return function(upCount, code) {
+ dbg.addDebuggee(global);
+ frame = dbg.getNewestFrame().older;
+ frame.eval(code);
+ }
+}(this);
+m = parseModule(`
+ function g() { return this.hours = 0; }
+ evalInFrame.call(0, 0, "g()")
+`);
+m.declarationInstantiation();
+m.evaluation();
diff --git a/js/src/jit-test/tests/modules/bug-1247934.js b/js/src/jit-test/tests/modules/bug-1247934.js
new file mode 100644
index 0000000000..666607d1f5
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1247934.js
@@ -0,0 +1,5 @@
+setJitCompilerOption("ion.warmup.trigger", 50);
+s = "";
+for (i = 0; i < 1024; i++) s += "export let e" + i + "\n";
+registerModule('a', parseModule(s));
+parseModule("import * as ns from 'a'").declarationInstantiation();
diff --git a/js/src/jit-test/tests/modules/bug-1251090.js b/js/src/jit-test/tests/modules/bug-1251090.js
new file mode 100644
index 0000000000..5c98f20c03
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1251090.js
@@ -0,0 +1,3 @@
+// |jit-test| error: Error
+offThreadCompileScript("");
+finishOffThreadModule();
diff --git a/js/src/jit-test/tests/modules/bug-1258097.js b/js/src/jit-test/tests/modules/bug-1258097.js
new file mode 100644
index 0000000000..c7f8770436
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1258097.js
@@ -0,0 +1,3 @@
+// |jit-test| module; error:SyntaxError
+import x from 'y';
+function x() {}
diff --git a/js/src/jit-test/tests/modules/bug-1283448.js b/js/src/jit-test/tests/modules/bug-1283448.js
new file mode 100644
index 0000000000..9be2828ea4
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1283448.js
@@ -0,0 +1,6 @@
+// |jit-test| error: TypeError
+
+let a = registerModule('a', parseModule("var x = 1; export { x };"));
+let b = registerModule('b', parseModule("import { x as y } from 'a';"));
+a.__proto__ = {15: 1337};
+b.declarationInstantiation();
diff --git a/js/src/jit-test/tests/modules/bug-1284486-2.js b/js/src/jit-test/tests/modules/bug-1284486-2.js
new file mode 100644
index 0000000000..54270caa59
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1284486-2.js
@@ -0,0 +1,34 @@
+// This tests that attempting to perform ModuleDeclarationInstantation a
+// second time after a failure still fails. (It no longer stores and rethrows
+// the same error; the spec changed in that regard and the implementation was
+// updated in bug 1420420).
+//
+// The attempts fails becuase module 'a' is not available.
+//
+// This test exercises the path where the previously instantiated module is
+// re-instantiated directly.
+
+let b = registerModule('b', parseModule("export var b = 3; export var c = 4;"));
+let c = registerModule('c', parseModule("export * from 'a'; export * from 'b';"));
+
+let e1;
+let threw = false;
+try {
+ c.declarationInstantiation();
+} catch (exc) {
+ threw = true;
+ e1 = exc;
+}
+assertEq(threw, true);
+assertEq(typeof e1 === "undefined", false);
+
+threw = false;
+let e2;
+try {
+ c.declarationInstantiation();
+} catch (exc) {
+ threw = true;
+ e2 = exc;
+}
+assertEq(threw, true);
+assertEq(e1.toString(), e2.toString());
diff --git a/js/src/jit-test/tests/modules/bug-1284486.js b/js/src/jit-test/tests/modules/bug-1284486.js
new file mode 100644
index 0000000000..7489b5eb56
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1284486.js
@@ -0,0 +1,33 @@
+// This tests that module instantiation can succeed when executed a second
+// time after a failure.
+//
+// The first attempt fails becuase module 'a' is not available. The second
+// attempt succeeds as 'a' is now available.
+//
+// This test exercises the path where the previously instantiated module is
+// encountered as an import.
+
+let b = registerModule('b', parseModule("export var b = 3; export var c = 4;"));
+let c = registerModule('c', parseModule("export * from 'a'; export * from 'b';"));
+
+let e1;
+let threw = false;
+try {
+ c.declarationInstantiation();
+} catch (exc) {
+ threw = true;
+ e1 = exc;
+}
+assertEq(threw, true);
+assertEq(typeof e1 === "undefined", false);
+
+let a = registerModule('a', parseModule("export var a = 1; export var b = 2;"));
+let d = registerModule('d', parseModule("import { a } from 'c'; a;"));
+
+threw = false;
+try {
+ d.declarationInstantiation();
+} catch (exc) {
+ threw = true;
+}
+assertEq(threw, false);
diff --git a/js/src/jit-test/tests/modules/bug-1287406.js b/js/src/jit-test/tests/modules/bug-1287406.js
new file mode 100644
index 0000000000..8eef163886
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1287406.js
@@ -0,0 +1 @@
+parseModule("export default () => 1");
diff --git a/js/src/jit-test/tests/modules/bug-1287410.js b/js/src/jit-test/tests/modules/bug-1287410.js
new file mode 100644
index 0000000000..14df1b14e4
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1287410.js
@@ -0,0 +1,17 @@
+// |jit-test| error: InternalError
+
+let a = registerModule('a', parseModule("export var a = 1; export var b = 2;"));
+let b = registerModule('b', parseModule("export var b = 3; export var c = 4;"));
+let c = registerModule('c', parseModule("export * from 'a'; export * from 'b';"));
+c.declarationInstantiation();
+
+// Module 'a' is replaced with another module that has not been instantiated.
+// This should not happen and would be a bug in the module loader.
+a = registerModule('a', parseModule("export var a = 1; export var b = 2;"));
+
+let d = registerModule('d', parseModule("import { a } from 'c'; a;"));
+
+// Attempting to instantiate 'd' throws an error because depdency 'a' of
+// instantiated module 'c' is not instantiated.
+d.declarationInstantiation();
+d.evaluation();
diff --git a/js/src/jit-test/tests/modules/bug-1320993.js b/js/src/jit-test/tests/modules/bug-1320993.js
new file mode 100644
index 0000000000..bece5731a3
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1320993.js
@@ -0,0 +1,2 @@
+parseModule("export default (class {})");
+parseModule("export default (class A {})");
diff --git a/js/src/jit-test/tests/modules/bug-1372258.js b/js/src/jit-test/tests/modules/bug-1372258.js
new file mode 100644
index 0000000000..2764d38075
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1372258.js
@@ -0,0 +1,25 @@
+// |jit-test| skip-if: helperThreadCount() === 0
+
+// Overwrite built-in parseModule with off-thread module parser.
+function parseModule(source) {
+ offThreadCompileModule(source);
+ return finishOffThreadModule();
+}
+
+// Test case derived from: js/src/jit-test/tests/modules/many-imports.js
+
+// Test importing an import many times.
+
+const count = 1024;
+
+let a = registerModule('a', parseModule("export let a = 1;"));
+
+let s = "";
+for (let i = 0; i < count; i++) {
+ s += "import { a as i" + i + " } from 'a';\n";
+ s += "assertEq(i" + i + ", 1);\n";
+}
+let b = registerModule('b', parseModule(s));
+
+b.declarationInstantiation();
+b.evaluation();
diff --git a/js/src/jit-test/tests/modules/bug-1402535.js b/js/src/jit-test/tests/modules/bug-1402535.js
new file mode 100644
index 0000000000..1d689f2aa4
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1402535.js
@@ -0,0 +1,6 @@
+// |jit-test| skip-if: !('stackTest' in this)
+
+stackTest(function() {
+ let m = parseModule(``);
+ m.declarationInstantiation();
+});
diff --git a/js/src/jit-test/tests/modules/bug-1402649.js b/js/src/jit-test/tests/modules/bug-1402649.js
new file mode 100644
index 0000000000..cae48d3558
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1402649.js
@@ -0,0 +1,14 @@
+// |jit-test| skip-if: !('oomTest' in this)
+
+loadFile(`
+function parseAndEvaluate(source) {
+ let m = parseModule(source);
+ m.declarationInstantiation();
+}
+parseAndEvaluate("async function a() { await 2 + 3; }")
+`);
+function loadFile(lfVarx) {
+ oomTest(function() {
+ eval(lfVarx);
+ });
+}
diff --git a/js/src/jit-test/tests/modules/bug-1406452.js b/js/src/jit-test/tests/modules/bug-1406452.js
new file mode 100644
index 0000000000..7b8325aad7
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1406452.js
@@ -0,0 +1,5 @@
+// |jit-test| error: Error
+let m = parseModule(`for (var x of iterator) {}`);
+m.declarationInstantiation();
+try { m.evaluation(); } catch (e) {}
+getModuleEnvironmentValue(m, "r");
diff --git a/js/src/jit-test/tests/modules/bug-1420420-2.js b/js/src/jit-test/tests/modules/bug-1420420-2.js
new file mode 100644
index 0000000000..e67882300b
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1420420-2.js
@@ -0,0 +1,17 @@
+// Test re-instantiation module after failure.
+
+load(libdir + "asserts.js");
+
+registerModule("good", parseModule(`export let x`));
+
+registerModule("y1", parseModule(`export let y`));
+registerModule("y2", parseModule(`export let y`));
+registerModule("bad", parseModule(`export* from "y1"; export* from "y2";`));
+
+registerModule("a", parseModule(`import* as ns from "good"; import {y} from "bad";`));
+
+let b = registerModule("b", parseModule(`import "a";`));
+let c = registerModule("c", parseModule(`import "a";`));
+
+assertThrowsInstanceOf(() => b.declarationInstantiation(), SyntaxError);
+assertThrowsInstanceOf(() => c.declarationInstantiation(), SyntaxError);
diff --git a/js/src/jit-test/tests/modules/bug-1420420-3.js b/js/src/jit-test/tests/modules/bug-1420420-3.js
new file mode 100644
index 0000000000..bc0c5fdaca
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1420420-3.js
@@ -0,0 +1,7 @@
+// |jit-test| skip-if: !('stackTest' in this)
+
+let a = parseModule(`throw new Error`);
+a.declarationInstantiation();
+stackTest(function() {
+ a.evaluation();
+});
diff --git a/js/src/jit-test/tests/modules/bug-1420420-4.js b/js/src/jit-test/tests/modules/bug-1420420-4.js
new file mode 100644
index 0000000000..91f1784c1d
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1420420-4.js
@@ -0,0 +1,18 @@
+load(libdir + "asserts.js");
+
+registerModule("a", parseModule(`throw undefined`));
+
+let b = registerModule("b", parseModule(`import "a";`));
+let c = registerModule("c", parseModule(`import "a";`));
+
+b.declarationInstantiation();
+c.declarationInstantiation();
+
+(async () => {
+ let count = 0;
+ try { await b.evaluation() } catch (e) { count++; }
+ try { await c.evaluation() } catch (e) { count++; }
+ assertEq(count, 2);
+})();
+
+drainJobQueue();
diff --git a/js/src/jit-test/tests/modules/bug-1420420.js b/js/src/jit-test/tests/modules/bug-1420420.js
new file mode 100644
index 0000000000..3764d71a7a
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1420420.js
@@ -0,0 +1,17 @@
+// Test re-instantiation module after failure.
+
+load(libdir + "asserts.js");
+
+registerModule("good", parseModule(`export let x`));
+
+registerModule("y1", parseModule(`export let y`));
+registerModule("y2", parseModule(`export let y`));
+registerModule("bad", parseModule(`export* from "y1"; export* from "y2";`));
+
+registerModule("a", parseModule(`import {x} from "good"; import {y} from "bad";`));
+
+let b = registerModule("b", parseModule(`import "a";`));
+let c = registerModule("c", parseModule(`import "a";`));
+
+assertThrowsInstanceOf(() => b.declarationInstantiation(), SyntaxError);
+assertThrowsInstanceOf(() => c.declarationInstantiation(), SyntaxError);
diff --git a/js/src/jit-test/tests/modules/bug-1435327.js b/js/src/jit-test/tests/modules/bug-1435327.js
new file mode 100644
index 0000000000..356ccab31e
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1435327.js
@@ -0,0 +1,27 @@
+// |jit-test| skip-if: !('oomTest' in this)
+
+lfLogBuffer = `
+ let c = registerModule('c', parseModule(""));
+ let d = registerModule('d', parseModule("import { a } from 'c'; a;"));
+ d.declarationInstantiation();
+`;
+lfLogBuffer = lfLogBuffer.split('\n');
+var lfCodeBuffer = "";
+while (true) {
+ var line = lfLogBuffer.shift();
+ if (line == null) {
+ break;
+ } else {
+ lfCodeBuffer += line + "\n";
+ }
+}
+if (lfCodeBuffer) loadFile(lfCodeBuffer);
+function loadFile(lfVarx) {
+ try {
+ oomTest(function() {
+ let m = parseModule(lfVarx);
+ m.declarationInstantiation();
+ m.evaluation();
+ });
+ } catch (lfVare) {}
+}
diff --git a/js/src/jit-test/tests/modules/bug-1439416-2.js b/js/src/jit-test/tests/modules/bug-1439416-2.js
new file mode 100644
index 0000000000..b9202c112c
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1439416-2.js
@@ -0,0 +1,10 @@
+function parseAsModule(source) {
+ return Reflect.parse(source, {
+ target: "module",
+ line: 0x7FFFFFFF + 1,
+ });
+}
+parseAsModule(`
+ import {a} from "";
+ export {a};
+`);
diff --git a/js/src/jit-test/tests/modules/bug-1439416.js b/js/src/jit-test/tests/modules/bug-1439416.js
new file mode 100644
index 0000000000..9dfe55b49a
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1439416.js
@@ -0,0 +1,10 @@
+// Test that zero-based line numbers supplied by Reflect.parse don't cause
+// assertions.
+
+function parseAsModule(source) {
+ return Reflect.parse(source, {
+ target: "module",
+ line: 0
+ });
+}
+parseAsModule("import d from 'a'");
diff --git a/js/src/jit-test/tests/modules/bug-1443555.js b/js/src/jit-test/tests/modules/bug-1443555.js
new file mode 100644
index 0000000000..cbb1c5f5dd
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1443555.js
@@ -0,0 +1,29 @@
+// |jit-test| error: TypeError
+
+"use strict";
+
+setJitCompilerOption("baseline.warmup.trigger", 0);
+
+let mainSrc = `
+import A from "A";
+
+const a = A;
+
+function requestAnimationFrame(f) { Promise.resolve().then(f); };
+
+requestAnimationFrame(loopy);
+a = 2;
+function loopy() {
+ A;
+}
+`;
+
+let ASrc = `
+export default 1;
+`;
+
+registerModule('A', parseModule(ASrc));
+
+let m = parseModule(mainSrc);
+m.declarationInstantiation()
+m.evaluation();
diff --git a/js/src/jit-test/tests/modules/bug-1462286.js b/js/src/jit-test/tests/modules/bug-1462286.js
new file mode 100644
index 0000000000..312d2f34b0
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1462286.js
@@ -0,0 +1,8 @@
+let a = registerModule('a', parseModule(`
+ export var { ... get } = { x: "foo" };
+`));
+
+let m = parseModule("import { get } from 'a'; export { get };");
+m.declarationInstantiation();
+m.evaluation()
+assertEq(getModuleEnvironmentValue(m, "get").x, "foo");
diff --git a/js/src/jit-test/tests/modules/bug-1462326.js b/js/src/jit-test/tests/modules/bug-1462326.js
new file mode 100644
index 0000000000..1c43f160be
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1462326.js
@@ -0,0 +1,6 @@
+// |jit-test| error: Error
+
+let m = parseModule(`
+ import A from "A";
+`);
+m.declarationInstantiation();
diff --git a/js/src/jit-test/tests/modules/bug-1466487.js b/js/src/jit-test/tests/modules/bug-1466487.js
new file mode 100644
index 0000000000..f9c25fa4d3
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1466487.js
@@ -0,0 +1,7 @@
+// |jit-test| skip-if: helperThreadCount() === 0
+
+evalInWorker(`
+ let m = parseModule("import.meta;");
+ m.declarationInstantiation();
+ m.evaluation();
+`);
diff --git a/js/src/jit-test/tests/modules/bug-1476921.js b/js/src/jit-test/tests/modules/bug-1476921.js
new file mode 100644
index 0000000000..ce355078b0
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1476921.js
@@ -0,0 +1,31 @@
+// |jit-test| --enable-top-level-await;
+"use strict";
+
+load(libdir + "asserts.js");
+
+class UniqueError extends Error {}
+
+let a = registerModule('a', parseModule(`
+ throw new UniqueError();
+`));
+
+let b = registerModule('b', parseModule(`
+ import * as ns0 from "a";
+`));
+
+a.declarationInstantiation();
+a.evaluation()
+ .then(r => {
+ // We should not reach here, as we expect an error to be thrown.
+ assertEq(false, true);
+ })
+ .catch(e => assertEq(e instanceof UniqueError, true));
+b.declarationInstantiation();
+b.evaluation()
+ .then(r => {
+ // We should not reach here, as we expect an error to be thrown.
+ assertEq(false, true);
+ })
+ .catch(e => assertEq(e instanceof UniqueError, true));
+
+drainJobQueue();
diff --git a/js/src/jit-test/tests/modules/bug-1498980.js b/js/src/jit-test/tests/modules/bug-1498980.js
new file mode 100644
index 0000000000..753b174deb
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1498980.js
@@ -0,0 +1,29 @@
+// |jit-test| --enable-top-level-await;
+dbgGlobal = newGlobal({newCompartment: true});
+dbg = new dbgGlobal.Debugger;
+dbg.addDebuggee(this);
+
+function f() {
+ dbg.getNewestFrame().older.eval("");
+}
+
+function execModule(source) {
+ m = parseModule(source);
+ m.declarationInstantiation();
+ return m.evaluation();
+}
+
+execModule("f();").then(() => {
+ gc();
+
+ execModule("throw 'foo'")
+ .then(r => {
+ // We should not reach here.
+ assertEq(false, true);
+ })
+ .catch(e => {
+ assertEq(e, 'foo');
+ });
+})
+
+drainJobQueue();
diff --git a/js/src/jit-test/tests/modules/bug-1501154.js b/js/src/jit-test/tests/modules/bug-1501154.js
new file mode 100644
index 0000000000..48a506db2b
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1501154.js
@@ -0,0 +1,25 @@
+// Test using an empty string as a module specifier fails.
+let result = null;
+let error = null;
+let promise = import("");
+promise.then((ns) => {
+ result = ns;
+}).catch((e) => {
+ error = e;
+});
+
+drainJobQueue();
+assertEq(result, null);
+assertEq(error instanceof Error, true);
+
+// Test reading a directory as a file fails.
+result = null;
+error = null;
+try {
+ result = os.file.readFile(".");
+} catch (e) {
+ error = e;
+}
+
+assertEq(result, null);
+assertEq(error instanceof Error, true);
diff --git a/js/src/jit-test/tests/modules/bug-1501157.js b/js/src/jit-test/tests/modules/bug-1501157.js
new file mode 100644
index 0000000000..14885e9fde
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1501157.js
@@ -0,0 +1,2 @@
+// |jit-test| skip-if: helperThreadCount() === 0
+offThreadCompileScript('import("")', {});
diff --git a/js/src/jit-test/tests/modules/bug-1502669.js b/js/src/jit-test/tests/modules/bug-1502669.js
new file mode 100644
index 0000000000..4ac6e262cf
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1502669.js
@@ -0,0 +1,5 @@
+// |jit-test| error: ReferenceError
+var g = newGlobal({newCompartment: true});
+g.parent = this;
+g.eval("new Debugger(parent).onExceptionUnwind = function () { hits++; };");
+import('')();
diff --git a/js/src/jit-test/tests/modules/bug-1503009.js b/js/src/jit-test/tests/modules/bug-1503009.js
new file mode 100644
index 0000000000..f8dd8d384b
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1503009.js
@@ -0,0 +1 @@
+new Function("if (0) import('')")();
diff --git a/js/src/jit-test/tests/modules/bug-1510598.js b/js/src/jit-test/tests/modules/bug-1510598.js
new file mode 100644
index 0000000000..0701474f1a
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1510598.js
@@ -0,0 +1,9 @@
+g = newGlobal({newCompartment: true});
+g.parent = this;
+g.eval(`new Debugger(parent).onExceptionUnwind = () => null;`);
+let exc = "fail";
+// Module evaluation throws so we fire the onExceptionUnwind hook.
+import("javascript: throw 'foo'").catch(e => { exc = e; });
+drainJobQueue();
+assertEq(exc, undefined);
+
diff --git a/js/src/jit-test/tests/modules/bug-1519140.js b/js/src/jit-test/tests/modules/bug-1519140.js
new file mode 100644
index 0000000000..29871bd1a4
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1519140.js
@@ -0,0 +1,3 @@
+// |jit-test| --more-compartments;
+fullcompartmentchecks(true);
+newGlobal().eval(`import("javascript:")`).catch(() => {});
diff --git a/js/src/jit-test/tests/modules/bug-1604792.js b/js/src/jit-test/tests/modules/bug-1604792.js
new file mode 100644
index 0000000000..ce0ef2b750
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1604792.js
@@ -0,0 +1,7 @@
+var lfLogBuffer = `
+ eval("function f(){}; f();");
+`;
+
+let lfMod = parseModule(lfLogBuffer);
+lfMod.declarationInstantiation();
+lfMod.evaluation();
diff --git a/js/src/jit-test/tests/modules/bug-1657066.js b/js/src/jit-test/tests/modules/bug-1657066.js
new file mode 100644
index 0000000000..22c828ca68
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1657066.js
@@ -0,0 +1,3 @@
+let g = newGlobal({newCompartment: true});
+new Debugger(g).onExceptionUnwind = () => null;
+g.eval(`import("javascript: throw 1")`).catch(() => 0);
diff --git a/js/src/jit-test/tests/modules/bug-1680878-a.js b/js/src/jit-test/tests/modules/bug-1680878-a.js
new file mode 100644
index 0000000000..e86b67d261
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1680878-a.js
@@ -0,0 +1,8 @@
+// |jit-test| error: SyntaxError
+// Remove once Top-level await is enabled by default: Bug #1681046
+
+r = parseModule(`
+ for await (var x of this) {}
+`);
+r.declarationInstantiation();
+r.evaluation();
diff --git a/js/src/jit-test/tests/modules/bug-1680878.js b/js/src/jit-test/tests/modules/bug-1680878.js
new file mode 100644
index 0000000000..47dcf4736f
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1680878.js
@@ -0,0 +1,7 @@
+// |jit-test| --enable-top-level-await; error: TypeError
+
+r = parseModule(`
+ for await (var x of this) {}
+`);
+r.declarationInstantiation();
+r.evaluation();
diff --git a/js/src/jit-test/tests/modules/bug-1681256.js b/js/src/jit-test/tests/modules/bug-1681256.js
new file mode 100644
index 0000000000..577060543f
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1681256.js
@@ -0,0 +1,20 @@
+// |jit-test| --enable-top-level-await;--more-compartments;
+let lfCode = `
+ var g = newGlobal();
+ g.debuggeeGlobal = this;
+ g.eval("(" + function () {
+ dbg = new Debugger(debuggeeGlobal);
+ dbg.onExceptionUnwind = function (frame, exc) {};
+ } + ")();");
+`;
+loadFile(lfCode);
+// use "await" so the module is marked as TLA
+loadFile(lfCode + " await ''");
+async function loadFile(lfVarx) {
+ try {
+ try { evaluate(lfVarx); } catch(exc) {}
+ let lfMod = parseModule(lfVarx);
+ lfMod.declarationInstantiation();
+ await lfMod.evaluation();
+ } catch (lfVare) {}
+}
diff --git a/js/src/jit-test/tests/modules/bug1105608.js b/js/src/jit-test/tests/modules/bug1105608.js
new file mode 100644
index 0000000000..98e6aded08
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1105608.js
@@ -0,0 +1,9 @@
+// export-from should throw SyntaxError until it's implemented.
+
+var caught = false;
+try {
+ eval("export { a } from 'b';");
+} catch (e) {
+ caught = true;
+}
+assertEq(caught, true);
diff --git a/js/src/jit-test/tests/modules/bug1169850.js b/js/src/jit-test/tests/modules/bug1169850.js
new file mode 100644
index 0000000000..3f6fbeef93
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1169850.js
@@ -0,0 +1,9 @@
+// export-default should throw SyntaxError until it's implemented.
+
+var caught = false;
+try {
+ eval("export default 1;");
+} catch (e) {
+ caught = true;
+}
+assertEq(caught, true);
diff --git a/js/src/jit-test/tests/modules/bug1198673.js b/js/src/jit-test/tests/modules/bug1198673.js
new file mode 100644
index 0000000000..509adb8e59
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1198673.js
@@ -0,0 +1,2 @@
+// |jit-test| error: expected string to compile
+parseModule((1));
diff --git a/js/src/jit-test/tests/modules/bug1204857.js b/js/src/jit-test/tests/modules/bug1204857.js
new file mode 100644
index 0000000000..451da2e286
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1204857.js
@@ -0,0 +1,2 @@
+// |jit-test| error: SyntaxError: unexpected garbage after module
+parseModule(("}"));
diff --git a/js/src/jit-test/tests/modules/bug1210391.js b/js/src/jit-test/tests/modules/bug1210391.js
new file mode 100644
index 0000000000..e9006bf16f
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1210391.js
@@ -0,0 +1,7 @@
+let a = registerModule('a', parseModule("export var a = 1; export var b = 2;"));
+let b = registerModule('b', parseModule("export var b = 3; export var c = 4;"));
+let c = registerModule('c', parseModule("export * from 'a'; export * from 'b';"));
+let d = registerModule('d', parseModule("import { a } from 'c'; a;"));
+d.declarationInstantiation();
+d.evaluation();
+
diff --git a/js/src/jit-test/tests/modules/bug1394492.js b/js/src/jit-test/tests/modules/bug1394492.js
new file mode 100644
index 0000000000..a0e5d2ac39
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1394492.js
@@ -0,0 +1,6 @@
+// |jit-test| error: NaN
+let m = parseModule(`
+ throw i => { return 5; }, m-1;
+`);
+m.declarationInstantiation();
+m.evaluation();
diff --git a/js/src/jit-test/tests/modules/bug1394493.js b/js/src/jit-test/tests/modules/bug1394493.js
new file mode 100644
index 0000000000..1fc1899602
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1394493.js
@@ -0,0 +1,4 @@
+// |jit-test| error: ReferenceError
+
+let m = parseModule("export let r = y; y = 4;");
+getModuleEnvironmentValue(m, "r").toString()
diff --git a/js/src/jit-test/tests/modules/bug1429031.js b/js/src/jit-test/tests/modules/bug1429031.js
new file mode 100644
index 0000000000..95e0d4e375
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1429031.js
@@ -0,0 +1,16 @@
+// |jit-test| error: ReferenceError
+
+assertEq = function(a, b) {}
+evaluate(`
+let a = registerModule('a', parseModule(
+ 'export var a = 1;'
+));
+let b = registerModule('b', parseModule(
+ \`import * as ns from 'a';
+ export var x = ns.a + ns.b;\`
+));
+b.declarationInstantiation();
+let ns = getModuleEnvironmentValue(b, "ns");
+assertEq(ns.a, 1);
+while ( t.ArrayType() ) 1;
+`);
diff --git a/js/src/jit-test/tests/modules/bug1449153.js b/js/src/jit-test/tests/modules/bug1449153.js
new file mode 100644
index 0000000000..1e2c3b0d99
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1449153.js
@@ -0,0 +1,33 @@
+// Test performing GetModuleNamespace on an errored module.
+
+class MyError {}
+
+async function assertThrowsMyError(f)
+{
+ let caught = false;
+ try {
+ await f();
+ } catch (e) {
+ caught = true;
+ assertEq(e.constructor, MyError);
+ }
+ assertEq(caught, true);
+}
+
+registerModule("a", parseModule(`
+ throw new MyError();
+`));
+
+let c = registerModule("c", parseModule(`
+ import "a";
+`));
+c.declarationInstantiation();
+assertThrowsMyError(() => c.evaluation());
+
+let b = registerModule('b', parseModule(`
+ import * as ns0 from 'a'
+`));
+b.declarationInstantiation();
+assertThrowsMyError(() => b.evaluation(b));
+
+drainJobQueue();
diff --git a/js/src/jit-test/tests/modules/bug1485698.js b/js/src/jit-test/tests/modules/bug1485698.js
new file mode 100644
index 0000000000..7c03b402cf
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1485698.js
@@ -0,0 +1,9 @@
+let m = parseModule(`
+ function f(x,y,z) {
+ delete arguments[2];
+ import.meta[2]
+ }
+ f(1,2,3)
+`);
+m.declarationInstantiation();
+m.evaluation();
diff --git a/js/src/jit-test/tests/modules/bug1584034.js b/js/src/jit-test/tests/modules/bug1584034.js
new file mode 100644
index 0000000000..65597effc4
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1584034.js
@@ -0,0 +1 @@
+import('./asdf.js').then(() => {}, inJit)
diff --git a/js/src/jit-test/tests/modules/bug1584309.js b/js/src/jit-test/tests/modules/bug1584309.js
new file mode 100644
index 0000000000..3e5906ea64
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1584309.js
@@ -0,0 +1 @@
+import('./asdf.js').then(() => {}, inIon)
diff --git a/js/src/jit-test/tests/modules/bug1586599.js b/js/src/jit-test/tests/modules/bug1586599.js
new file mode 100644
index 0000000000..a38f53037f
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1586599.js
@@ -0,0 +1,30 @@
+let m1 = parseModule(`
+function x() {
+ return 1;
+}
+function y() {
+ x = function() { return 2; };
+}
+export { x, y };
+`);
+m1.declarationInstantiation();
+m1.evaluation();
+
+registerModule('m1', m1);
+
+let m2 = parseModule(`
+import {x, y} from "m1";
+
+function test(expected) {
+ for (var i = 0; i < 2000; i++) {
+ if (i > 1900) {
+ assertEq(x(), expected);
+ }
+ }
+}
+test(1);
+y();
+test(2);
+`);
+m2.declarationInstantiation();
+m2.evaluation();
diff --git a/js/src/jit-test/tests/modules/bug1670236.js b/js/src/jit-test/tests/modules/bug1670236.js
new file mode 100644
index 0000000000..35192c2b58
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1670236.js
@@ -0,0 +1,6 @@
+// |jit-test| skip-if: !('oomTest' in this)
+o0=r=/x/;
+this.toString=(function() {
+ evaluate("",({ element:o0 }));
+})
+oomTest(String.prototype.charCodeAt,{ keepFailing:true })
diff --git a/js/src/jit-test/tests/modules/bug1685992.js b/js/src/jit-test/tests/modules/bug1685992.js
new file mode 100644
index 0000000000..ea709965fd
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug1685992.js
@@ -0,0 +1,12 @@
+// |jit-test| --ion-offthread-compile=off; --enable-private-methods; skip-if: !('oomTest' in this)
+
+function oomModule(lfMod) {
+ oomTest(function () {
+ parseModule(lfMod);
+ });
+}
+oomModule(`
+ class B50 {
+ #priv() {}
+ }
+`) \ No newline at end of file
diff --git a/js/src/jit-test/tests/modules/cyclic-function-import.js b/js/src/jit-test/tests/modules/cyclic-function-import.js
new file mode 100644
index 0000000000..a7d61e9bdf
--- /dev/null
+++ b/js/src/jit-test/tests/modules/cyclic-function-import.js
@@ -0,0 +1,7 @@
+// |jit-test| module
+
+import { isOdd } from "isOdd.js"
+import { isEven } from "isEven.js"
+
+assertEq(isEven(4), true);
+assertEq(isOdd(5), true);
diff --git a/js/src/jit-test/tests/modules/cyclic-import.js b/js/src/jit-test/tests/modules/cyclic-import.js
new file mode 100644
index 0000000000..3ca7bf123e
--- /dev/null
+++ b/js/src/jit-test/tests/modules/cyclic-import.js
@@ -0,0 +1,3 @@
+// |jit-test| module; error: ReferenceError
+
+import { a } from "cyclicImport1.js";
diff --git a/js/src/jit-test/tests/modules/debugger-frames.js b/js/src/jit-test/tests/modules/debugger-frames.js
new file mode 100644
index 0000000000..5619df5e65
--- /dev/null
+++ b/js/src/jit-test/tests/modules/debugger-frames.js
@@ -0,0 +1,83 @@
+// Test debugger access to frames and environments work as expected inside a module.
+
+load(libdir + "asserts.js");
+
+function assertArrayEq(actual, expected)
+{
+ var eq = actual.length == expected.length;
+ if (eq) {
+ for (var i = 0; i < actual.length; i++) {
+ if (actual[i] !== expected[i]) {
+ eq = false;
+ break;
+ }
+ }
+ }
+ if (!eq) {
+ print("Assertion failed: got " + JSON.stringify(actual) +
+ ", expected " + JSON.stringify(expected));
+ quit(3);
+ }
+}
+
+var g2 = newGlobal({newCompartment: true});
+
+var dbg = Debugger(g2);
+dbg.onDebuggerStatement = function (frame) {
+ // The current frame is a module frame.
+ assertEq(frame.type, 'module');
+ assertEq(frame.this, undefined);
+
+ // The frame's environement is a module environment.
+ let env = frame.environment;
+ assertEq(env.type, 'declarative');
+ assertEq(env.calleeScript, null);
+
+ // Top level module definitions and imports are visible.
+ assertArrayEq(env.names().sort(), ['a', 'b', 'c', 'x', 'y', 'z']);
+ assertArrayEq(['a', 'b', 'c'].map(env.getVariable, env), [1, 2, 3]);
+ assertArrayEq(['x', 'y', 'z'].map(env.getVariable, env), [4, 5, 6]);
+
+ // Cannot set imports or const bindings.
+ assertThrowsInstanceOf(() => env.setVariable('a', 10), TypeError);
+ assertThrowsInstanceOf(() => env.setVariable('b', 11), TypeError);
+ assertThrowsInstanceOf(() => env.setVariable('c', 12), TypeError);
+ env.setVariable('x', 7);
+ env.setVariable('y', 8);
+ assertThrowsInstanceOf(() => env.setVariable('z', 9), TypeError);
+ assertArrayEq(['a', 'b', 'c'].map(env.getVariable, env), [1, 2, 3]);
+ assertArrayEq(['x', 'y', 'z'].map(env.getVariable, env), [7, 8, 6]);
+
+ // The global lexical is the next thing after the module on the scope chain,
+ // followed by the global.
+ assertEq(env.parent.type, 'declarative');
+ assertEq(env.parent.parent.type, 'object');
+ assertEq(env.parent.parent.parent, null);
+};
+
+f = g2.eval(
+`
+ // Set up a module to import from.
+ a = registerModule('a', parseModule(
+ \`
+ export var a = 1;
+ export let b = 2;
+ export const c = 3;
+ export function f(x) { return x + 1; }
+ \`));
+ a.declarationInstantiation();
+ a.evaluation();
+
+ let m = parseModule(
+ \`
+ import { a, b, c } from 'a';
+ var x = 4;
+ let y = 5;
+ const z = 6;
+
+ eval("");
+ debugger;
+ \`);
+ m.declarationInstantiation();
+ m.evaluation();
+`);
diff --git a/js/src/jit-test/tests/modules/debugger-vars-function.js b/js/src/jit-test/tests/modules/debugger-vars-function.js
new file mode 100644
index 0000000000..215953295c
--- /dev/null
+++ b/js/src/jit-test/tests/modules/debugger-vars-function.js
@@ -0,0 +1,30 @@
+// Test debugger access to aliased and unaliased bindings work correctly.
+
+load(libdir + "asserts.js");
+
+var g = newGlobal({newCompartment: true});
+var dbg = Debugger(g);
+dbg.onDebuggerStatement = function (frame) {
+ let env = frame.environment.parent;
+ assertEq(env.getVariable('a'), 1);
+ assertEq(env.getVariable('b'), 2);
+ assertEq(env.getVariable('c'), 3);
+ assertEq(env.getVariable('d'), 4);
+ assertEq(env.getVariable('e'), 5);
+};
+
+g.eval(
+`
+ let m = parseModule(
+ \`
+ var a = 1;
+ let b = 2;
+ export var c = 3;
+ export let d = 4;
+ let e = 5;
+ function f() { debugger; return e; }
+ \`);
+ m.declarationInstantiation();
+ m.evaluation();
+`);
+
diff --git a/js/src/jit-test/tests/modules/debugger-vars-toplevel.js b/js/src/jit-test/tests/modules/debugger-vars-toplevel.js
new file mode 100644
index 0000000000..5d657ca5a1
--- /dev/null
+++ b/js/src/jit-test/tests/modules/debugger-vars-toplevel.js
@@ -0,0 +1,31 @@
+// Test debugger access to aliased and unaliased bindings work correctly.
+
+load(libdir + "asserts.js");
+
+var g = newGlobal({newCompartment: true});
+var dbg = Debugger(g);
+dbg.onDebuggerStatement = function (frame) {
+ let env = frame.environment;
+ assertEq(env.getVariable('a'), 1);
+ assertEq(env.getVariable('b'), 2);
+ assertEq(env.getVariable('c'), 3);
+ assertEq(env.getVariable('d'), 4);
+ assertEq(env.getVariable('e'), 5);
+};
+
+g.eval(
+`
+ let m = parseModule(
+ \`
+ var a = 1;
+ let b = 2;
+ export var c = 3;
+ export let d = 4;
+ let e = 5;
+ function f() { return e; }
+ debugger;
+ \`);
+ m.declarationInstantiation();
+ m.evaluation();
+`);
+
diff --git a/js/src/jit-test/tests/modules/delete-import.js b/js/src/jit-test/tests/modules/delete-import.js
new file mode 100644
index 0000000000..b76c028f6f
--- /dev/null
+++ b/js/src/jit-test/tests/modules/delete-import.js
@@ -0,0 +1,3 @@
+// |jit-test| module; error: SyntaxError
+import { a } from "module1.js";
+delete a;
diff --git a/js/src/jit-test/tests/modules/delete-namespace-import.js b/js/src/jit-test/tests/modules/delete-namespace-import.js
new file mode 100644
index 0000000000..4b5f2d1c9d
--- /dev/null
+++ b/js/src/jit-test/tests/modules/delete-namespace-import.js
@@ -0,0 +1,3 @@
+// |jit-test| module; error: TypeError
+import * as ns from "module1.js";
+delete ns.a;
diff --git a/js/src/jit-test/tests/modules/delete-namespace.js b/js/src/jit-test/tests/modules/delete-namespace.js
new file mode 100644
index 0000000000..ef23e2afcb
--- /dev/null
+++ b/js/src/jit-test/tests/modules/delete-namespace.js
@@ -0,0 +1,3 @@
+// |jit-test| module; error: SyntaxError
+import * as ns from "module1.js";
+delete ns;
diff --git a/js/src/jit-test/tests/modules/duplicate-exports.js b/js/src/jit-test/tests/modules/duplicate-exports.js
new file mode 100644
index 0000000000..7e45ac6f37
--- /dev/null
+++ b/js/src/jit-test/tests/modules/duplicate-exports.js
@@ -0,0 +1,32 @@
+// Test errors due to duplicate exports
+load(libdir + "asserts.js");
+
+function testSyntaxError(source) {
+ assertThrowsInstanceOf(function () {
+ parseModule(source);
+ }, SyntaxError);
+}
+
+// SyntexError due to duplicate exports
+testSyntaxError("export var v; export var v;");
+testSyntaxError("export var x, y, z; export var y;");
+testSyntaxError("export let v; var w; export {w as v};");
+testSyntaxError("export const v; var w; export {w as v};");
+testSyntaxError("export var v; let w; export {w as v};");
+testSyntaxError("export var v; const w; export {w as v};");
+testSyntaxError("export default 1; export default 2;");
+testSyntaxError("export default 1; export default function() {};");
+testSyntaxError("export default 1; export default function foo() {};");
+testSyntaxError("var v; export {v}; export {v};");
+testSyntaxError("var v, x; export {v}; export {x as v};");
+testSyntaxError("export default 1; export default export class { constructor() {} };");
+testSyntaxError("export default 1; export default export class foo { constructor() {} };");
+
+// SyntaxError due to redeclared binding
+testSyntaxError("export let v; export let v;");
+testSyntaxError("export let x, y, z; export let y;");
+testSyntaxError("export const v = 0; export const v = 0;");
+testSyntaxError("export const x = 0, y = 0, z = 0; export const y = 0;");
+testSyntaxError("export var v; export let v;");
+testSyntaxError("export var v; export const v = 0;");
+testSyntaxError("export let v; export const v;");
diff --git a/js/src/jit-test/tests/modules/duplicate-imports.js b/js/src/jit-test/tests/modules/duplicate-imports.js
new file mode 100644
index 0000000000..fa87ba8ebd
--- /dev/null
+++ b/js/src/jit-test/tests/modules/duplicate-imports.js
@@ -0,0 +1,27 @@
+// Test errors due to duplicate lexically declared names.
+
+load(libdir + "asserts.js");
+
+function testNoError(source) {
+ parseModule(source);
+}
+
+function testSyntaxError(source) {
+ assertThrowsInstanceOf(() => parseModule(source), SyntaxError);
+}
+
+testNoError("import { a } from 'm';");
+testNoError("import { a as b } from 'm';");
+testNoError("import * as a from 'm';");
+testNoError("import a from 'm';");
+
+testSyntaxError("import { a } from 'm'; let a = 1;");
+testSyntaxError("let a = 1; import { a } from 'm';");
+testSyntaxError("import { a } from 'm'; var a = 1;");
+testSyntaxError("var a = 1; import { a } from 'm';");
+testSyntaxError("import { a, b } from 'm'; const b = 1;");
+testSyntaxError("import { a } from 'm'; import { a } from 'm2';");
+testSyntaxError("import { a } from 'm'; import { b as a } from 'm2';");
+testSyntaxError("import { a } from 'm'; import * as a from 'm2';");
+testSyntaxError("import { a } from 'm'; import a from 'm2';");
+
diff --git a/js/src/jit-test/tests/modules/dynamic-import-error.js b/js/src/jit-test/tests/modules/dynamic-import-error.js
new file mode 100644
index 0000000000..98a6af75d0
--- /dev/null
+++ b/js/src/jit-test/tests/modules/dynamic-import-error.js
@@ -0,0 +1,14 @@
+// |jit-test| module
+
+let result = null;
+let error = null;
+let promise = import("nonexistent.js");
+promise.then((ns) => {
+ result = ns;
+}).catch((e) => {
+ error = e;
+});
+
+drainJobQueue();
+assertEq(result, null);
+assertEq(error instanceof Error, true);
diff --git a/js/src/jit-test/tests/modules/dynamic-import-expression.js b/js/src/jit-test/tests/modules/dynamic-import-expression.js
new file mode 100644
index 0000000000..9cee4dd6e1
--- /dev/null
+++ b/js/src/jit-test/tests/modules/dynamic-import-expression.js
@@ -0,0 +1,79 @@
+load(libdir + "match.js");
+load(libdir + "asserts.js");
+
+var { Pattern, MatchError } = Match;
+
+program = (elts) => Pattern({
+ type: "Program",
+ body: elts
+});
+expressionStatement = (expression) => Pattern({
+ type: "ExpressionStatement",
+ expression: expression
+});
+assignmentExpression = (left, operator, right) => Pattern({
+ type: "AssignmentExpression",
+ operator: operator,
+ left: left,
+ right: right
+});
+ident = (name) => Pattern({
+ type: "Identifier",
+ name: name
+});
+importCall = (ident, singleArg) => Pattern({
+ type: "CallImport",
+ ident: ident,
+ arg: singleArg
+});
+
+function parseAsClassicScript(source)
+{
+ return Reflect.parse(source);
+}
+
+function parseAsModuleScript(source)
+{
+ return Reflect.parse(source, {target: "module"});
+}
+
+for (let parse of [parseAsModuleScript, parseAsClassicScript]) {
+ program([
+ expressionStatement(
+ importCall(
+ ident("import"),
+ ident("foo")
+ )
+ )
+ ]).assert(parse("import(foo);"));
+
+ program([
+ expressionStatement(
+ assignmentExpression(
+ ident("x"),
+ "=",
+ importCall(
+ ident("import"),
+ ident("foo")
+ )
+ )
+ )
+ ]).assert(parse("x = import(foo);"));
+}
+
+function assertParseThrowsSyntaxError(source)
+{
+ assertThrowsInstanceOf(() => parseAsClassicScript(source), SyntaxError);
+ assertThrowsInstanceOf(() => parseAsModuleScript(source), SyntaxError);
+}
+
+assertParseThrowsSyntaxError("import");
+assertParseThrowsSyntaxError("import(");
+assertParseThrowsSyntaxError("import(1,");
+assertParseThrowsSyntaxError("import(1, 2");
+assertParseThrowsSyntaxError("import(1, 2)");
+assertParseThrowsSyntaxError("x = import");
+assertParseThrowsSyntaxError("x = import(");
+assertParseThrowsSyntaxError("x = import(1,");
+assertParseThrowsSyntaxError("x = import(1, 2");
+assertParseThrowsSyntaxError("x = import(1, 2)");
diff --git a/js/src/jit-test/tests/modules/dynamic-import-ion.js b/js/src/jit-test/tests/modules/dynamic-import-ion.js
new file mode 100644
index 0000000000..9c8f5e0e40
--- /dev/null
+++ b/js/src/jit-test/tests/modules/dynamic-import-ion.js
@@ -0,0 +1,16 @@
+// Even with --ion-eager, this needs to be run twice before it executes the
+// ion-compiled version.
+for (let i = 0; i < 2; i++) {
+ let result = null;
+ let error = null;
+ let promise = import("../../modules/module1.js");
+ promise.then((ns) => {
+ result = ns;
+ }).catch((e) => {
+ error = e;
+ });
+
+ drainJobQueue();
+ assertEq(error, null);
+ assertEq(result.a, 1);
+}
diff --git a/js/src/jit-test/tests/modules/dynamic-import-lazy.js b/js/src/jit-test/tests/modules/dynamic-import-lazy.js
new file mode 100644
index 0000000000..ccbf90989d
--- /dev/null
+++ b/js/src/jit-test/tests/modules/dynamic-import-lazy.js
@@ -0,0 +1,4 @@
+function lazyilyParsedFunction()
+{
+ return import("/module1.js");
+}
diff --git a/js/src/jit-test/tests/modules/dynamic-import-module.js b/js/src/jit-test/tests/modules/dynamic-import-module.js
new file mode 100644
index 0000000000..3c004258a3
--- /dev/null
+++ b/js/src/jit-test/tests/modules/dynamic-import-module.js
@@ -0,0 +1,39 @@
+// |jit-test| module
+
+function testImport(path, name, value) {
+ let result = null;
+ let error = null;
+ let promise = import(path);
+ promise.then((ns) => {
+ result = ns;
+ }).catch((e) => {
+ error = e;
+ });
+
+ drainJobQueue();
+ assertEq(error, null);
+ assertEq(result[name], value);
+}
+
+// Resolved via module load path.
+testImport("module1.js", "a", 1);
+
+// Relative path resolved relative to this script.
+testImport("../../modules/module1a.js", "a", 2);
+
+// Import inside function.
+function f() {
+ testImport("../../modules/module2.js", "b", 2);
+}
+f();
+
+// Import inside direct eval.
+eval(`testImport("../../modules/module3.js", "c", 3)`);
+
+// Import inside indirect eval.
+const indirect = eval;
+const defineTestFunc = testImport.toString();
+indirect(defineTestFunc + `testImport("../../modules/module3.js");`);
+
+// Import inside dynamic function.
+Function(defineTestFunc + `testImport("../../modules/module3.js");`)();
diff --git a/js/src/jit-test/tests/modules/dynamic-import-oom.js b/js/src/jit-test/tests/modules/dynamic-import-oom.js
new file mode 100644
index 0000000000..9682c7560a
--- /dev/null
+++ b/js/src/jit-test/tests/modules/dynamic-import-oom.js
@@ -0,0 +1,9 @@
+// |jit-test| skip-if: !('oomTest' in this); --ion-offthread-compile=off
+//
+// Note: without --ion-offthread-compile=off this test takes a long time and
+// may timeout on some platforms. See bug 1507721.
+
+ignoreUnhandledRejections();
+
+oomTest(() => import("module1.js"));
+oomTest(() => import("cyclicImport1.js"));
diff --git a/js/src/jit-test/tests/modules/dynamic-import-script.js b/js/src/jit-test/tests/modules/dynamic-import-script.js
new file mode 100644
index 0000000000..e6986a42ec
--- /dev/null
+++ b/js/src/jit-test/tests/modules/dynamic-import-script.js
@@ -0,0 +1,45 @@
+function testImport(path, name, value) {
+ let result = null;
+ let error = null;
+ let promise = import(path);
+ promise.then((ns) => {
+ result = ns;
+ }).catch((e) => {
+ error = e;
+ });
+
+ drainJobQueue();
+ assertEq(error, null);
+ assertEq(result[name], value);
+}
+
+// Resolved via module load path.
+testImport("module1.js", "a", 1);
+
+// Relative path resolved relative to this script.
+testImport("../../modules/module1a.js", "a", 2);
+
+// Import inside function.
+function f() {
+ testImport("../../modules/module2.js", "b", 2);
+}
+f();
+
+// Import inside eval.
+eval(`testImport("../../modules/module3.js", "c", 3)`);
+
+// Import inside indirect eval.
+const indirect = eval;
+const defineTestFunc = testImport.toString();
+indirect(defineTestFunc + `testImport("../../modules/module3.js");`);
+
+// Import inside dynamic function.
+Function(defineTestFunc + `testImport("../../modules/module3.js");`)();
+
+// Import in eval in promise handler.
+let ran = false;
+Promise
+ .resolve(`import("../../modules/module3.js").then(() => { ran = true; })`)
+ .then(eval)
+drainJobQueue();
+assertEq(ran, true);
diff --git a/js/src/jit-test/tests/modules/eval-module-oom.js b/js/src/jit-test/tests/modules/eval-module-oom.js
new file mode 100644
index 0000000000..cd693105e1
--- /dev/null
+++ b/js/src/jit-test/tests/modules/eval-module-oom.js
@@ -0,0 +1,23 @@
+// |jit-test| skip-if: !('oomTest' in this)
+
+// OOM tests for module parsing.
+
+const sa =
+`export default 20;
+ export let a = 22;
+ export function f(x, y) { return x + y }
+`;
+
+const sb =
+`import x from "a";
+ import { a as y } from "a";
+ import * as ns from "a";
+ ns.f(x, y);
+`;
+
+oomTest(() => {
+ let a = registerModule('a', parseModule(sa));
+ let b = registerModule('b', parseModule(sb));
+ b.declarationInstantiation();
+ assertEq(b.evaluation(), 42);
+});
diff --git a/js/src/jit-test/tests/modules/export-circular-nonexisting-binding.js b/js/src/jit-test/tests/modules/export-circular-nonexisting-binding.js
new file mode 100644
index 0000000000..387c7c369a
--- /dev/null
+++ b/js/src/jit-test/tests/modules/export-circular-nonexisting-binding.js
@@ -0,0 +1,3 @@
+// |jit-test| module; error:SyntaxError
+
+import "export-circular-nonexisting-binding-1.js";
diff --git a/js/src/jit-test/tests/modules/export-declaration.js b/js/src/jit-test/tests/modules/export-declaration.js
new file mode 100644
index 0000000000..dc49b82ee6
--- /dev/null
+++ b/js/src/jit-test/tests/modules/export-declaration.js
@@ -0,0 +1,480 @@
+load(libdir + "match.js");
+load(libdir + "asserts.js");
+
+var { Pattern, MatchError } = Match;
+
+program = (elts) => Pattern({
+ type: "Program",
+ body: elts
+})
+exportDeclaration = (declaration, specifiers, source, isDefault) => Pattern({
+ type: "ExportDeclaration",
+ declaration: declaration,
+ specifiers: specifiers,
+ source: source,
+ isDefault: isDefault
+});
+exportSpecifier = (id, name) => Pattern({
+ type: "ExportSpecifier",
+ id: id,
+ name: name
+});
+exportBatchSpecifier = () => Pattern({
+ type: "ExportBatchSpecifier"
+});
+blockStatement = (body) => Pattern({
+ type: "BlockStatement",
+ body: body
+});
+functionDeclaration = (id, params, body) => Pattern({
+ type: "FunctionDeclaration",
+ id: id,
+ params: params,
+ defaults: [],
+ body: body,
+ rest: null,
+ generator: false
+});
+classDeclaration = (name) => Pattern({
+ type: "ClassStatement",
+ id: name
+});
+variableDeclaration = (decls) => Pattern({
+ type: "VariableDeclaration",
+ kind: "var",
+ declarations: decls
+});
+constDeclaration = (decls) => Pattern({
+ type: "VariableDeclaration",
+ kind: "const",
+ declarations: decls
+});
+letDeclaration = (decls) => Pattern({
+ type: "VariableDeclaration",
+ kind: "let",
+ declarations: decls
+});
+ident = (name) => Pattern({
+ type: "Identifier",
+ name: name
+});
+lit = (val) => Pattern({
+ type: "Literal",
+ value: val
+});
+
+function parseAsModule(source)
+{
+ return Reflect.parse(source, {target: "module"});
+}
+
+program([
+ exportDeclaration(
+ null,
+ [],
+ null,
+ false
+ )
+]).assert(parseAsModule("export {}"));
+
+program([
+ letDeclaration([
+ {
+ id: ident("a"),
+ init: lit(1)
+ }
+ ]),
+ exportDeclaration(
+ null,
+ [
+ exportSpecifier(
+ ident("a"),
+ ident("a")
+ )
+ ],
+ null,
+ false
+ )
+]).assert(parseAsModule("let a = 1; export { a }"));
+
+program([
+ letDeclaration([
+ {
+ id: ident("a"),
+ init: lit(1)
+ }
+ ]),
+ exportDeclaration(
+ null,
+ [
+ exportSpecifier(
+ ident("a"),
+ ident("b")
+ )
+ ],
+ null,
+ false
+ )
+]).assert(parseAsModule("let a = 1; export { a as b }"));
+
+program([
+ letDeclaration([
+ {
+ id: ident("as"),
+ init: lit(1)
+ }
+ ]),
+ exportDeclaration(
+ null,
+ [
+ exportSpecifier(
+ ident("as"),
+ ident("as")
+ )
+ ],
+ null,
+ false
+ )
+]).assert(parseAsModule("let as = 1; export { as as as }"));
+
+program([
+ letDeclaration([
+ {
+ id: ident("a"),
+ init: lit(1)
+ }
+ ]),
+ exportDeclaration(
+ null,
+ [
+ exportSpecifier(
+ ident("a"),
+ ident("true")
+ )
+ ],
+ null,
+ false
+ )
+]).assert(parseAsModule("let a = 1; export { a as true }"));
+
+program([
+ letDeclaration([
+ {
+ id: ident("a"),
+ init: lit(1)
+ },
+ {
+ id: ident("b"),
+ init: lit(2)
+ }
+ ]),
+ exportDeclaration(
+ null,
+ [
+ exportSpecifier(
+ ident("a"),
+ ident("a")
+ ),
+ exportSpecifier(
+ ident("b"),
+ ident("b")
+ ),
+ ],
+ null,
+ false
+ )
+]).assert(parseAsModule("let a = 1, b = 2; export { a, b }"));
+
+program([
+ letDeclaration([
+ {
+ id: ident("a"),
+ init: lit(1)
+ },
+ {
+ id: ident("c"),
+ init: lit(2)
+ }
+ ]),
+ exportDeclaration(
+ null,
+ [
+ exportSpecifier(
+ ident("a"),
+ ident("b")
+ ),
+ exportSpecifier(
+ ident("c"),
+ ident("d")
+ ),
+ ],
+ null,
+ false
+ )
+]).assert(parseAsModule("let a = 1, c = 2; export { a as b, c as d }"));
+
+program([
+ exportDeclaration(
+ null,
+ [
+ exportSpecifier(
+ ident("a"),
+ ident("a")
+ )
+ ],
+ lit("b"),
+ false
+ )
+]).assert(parseAsModule("export { a } from 'b'"));
+
+program([
+ exportDeclaration(
+ null,
+ [
+ exportBatchSpecifier()
+ ],
+ lit("a"),
+ false
+ )
+]).assert(parseAsModule("export * from 'a'"));
+
+program([
+ exportDeclaration(
+ functionDeclaration(
+ ident("f"),
+ [],
+ blockStatement([])
+ ),
+ null,
+ null,
+ false
+ )
+]).assert(parseAsModule("export function f() {}"));
+
+program([
+ exportDeclaration(
+ classDeclaration(
+ ident("Foo")
+ ),
+ null,
+ null,
+ false
+ )
+]).assert(parseAsModule("export class Foo { constructor() {} }"));
+
+program([
+ exportDeclaration(
+ variableDeclaration([
+ {
+ id: ident("a"),
+ init: lit(1)
+ }, {
+ id: ident("b"),
+ init: lit(2)
+ }
+ ]),
+ null,
+ null,
+ false
+ )
+]).assert(parseAsModule("export var a = 1, b = 2;"));
+
+program([
+ exportDeclaration(
+ constDeclaration([
+ {
+ id: ident("a"),
+ init: lit(1)
+ }, {
+ id: ident("b"),
+ init: lit(2)
+ }
+ ]),
+ null,
+ null,
+ false
+ )
+]).assert(parseAsModule("export const a = 1, b = 2;"));
+
+program([
+ exportDeclaration(
+ letDeclaration([
+ {
+ id: ident("a"),
+ init: lit(1)
+ }, {
+ id: ident("b"),
+ init: lit(2)
+ }
+ ]),
+ null,
+ null,
+ false
+ )
+]).assert(parseAsModule("export let a = 1, b = 2;"));
+
+program([
+ exportDeclaration(
+ functionDeclaration(
+ ident("default"),
+ [],
+ blockStatement([])
+ ),
+ null,
+ null,
+ true
+ )
+]).assert(parseAsModule("export default function() {}"));
+
+program([
+ exportDeclaration(
+ functionDeclaration(
+ ident("foo"),
+ [],
+ blockStatement([])
+ ),
+ null,
+ null,
+ true
+ )
+]).assert(parseAsModule("export default function foo() {}"));
+
+program([
+ exportDeclaration(
+ classDeclaration(
+ ident("default")
+ ),
+ null,
+ null,
+ true
+ )
+]).assert(parseAsModule("export default class { constructor() {} }"));
+
+program([
+ exportDeclaration(
+ classDeclaration(
+ ident("Foo")
+ ),
+ null,
+ null,
+ true
+ )
+]).assert(parseAsModule("export default class Foo { constructor() {} }"));
+
+program([
+ exportDeclaration(
+ lit(1234),
+ null,
+ null,
+ true
+ )
+]).assert(parseAsModule("export default 1234"));
+
+assertThrowsInstanceOf(function () {
+ parseAsModule("export default 1234 5678");
+}, SyntaxError);
+
+var loc = parseAsModule("export { a as b } from 'c'", {
+ loc: true
+}).body[0].loc;
+
+assertEq(loc.start.line, 1);
+assertEq(loc.start.column, 0);
+assertEq(loc.start.line, 1);
+assertEq(loc.end.column, 26);
+
+assertThrowsInstanceOf(function () {
+ parseAsModule("function f() { export a }");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function () {
+ parseAsModule("if (true) export a");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("export {");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("export {} from");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("export {,} from 'a'");
+}, SyntaxError);
+
+program([
+ exportDeclaration(
+ null,
+ [
+ exportSpecifier(
+ ident("true"),
+ ident("true")
+ ),
+ ],
+ lit("b"),
+ false
+ )
+]).assert(parseAsModule("export { true } from 'b'"));
+
+program([
+ exportDeclaration(
+ null,
+ [
+ exportSpecifier(
+ ident("true"),
+ ident("name")
+ ),
+ ],
+ lit("b"),
+ false
+ )
+]).assert(parseAsModule("export { true as name } from 'b'"));
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("export { true }");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("export { true as name }");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("export { static }");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("export { static as name }");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function () {
+ parseAsModule("export { name } from 'b' f();");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function () {
+ parseAsModule("export *");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function () {
+ parseAsModule("export * from 'b' f();");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("export {}\nfrom ()");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("function() {}");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("class() { constructor() {} }");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("export x");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("export foo = 5");
+}, SyntaxError);
diff --git a/js/src/jit-test/tests/modules/export-destructuring.js b/js/src/jit-test/tests/modules/export-destructuring.js
new file mode 100644
index 0000000000..115cec41a9
--- /dev/null
+++ b/js/src/jit-test/tests/modules/export-destructuring.js
@@ -0,0 +1,104 @@
+function assertArrayEq(value, expected)
+{
+ assertEq(value instanceof Array, true);
+ assertEq(value.length, expected.length);
+ for (let i = 0; i < value.length; i++)
+ assertEq(value[i], expected[i]);
+}
+
+registerModule('a', parseModule(`
+ export const [] = [];
+ export const [a=0] = [];
+ export const [b] = [1];
+ export const [c, d, e] = [2, 3, 4];
+ export const [, f, g] = [5, 6, 7];
+ export const [h,, i] = [8, 9, 10];
+ export const [,, j] = [11, 12, 13];
+ export const [...k] = [14, 15, 16];
+ export const [l, ...m] = [17, 18, 19];
+ export const [,, ...n] = [20, 21, 22];
+`));
+
+m = parseModule(`
+ import * as a from 'a';
+
+ assertEq(a.a, 0);
+ assertEq(a.b, 1);
+ assertEq(a.c, 2);
+ assertEq(a.d, 3);
+ assertEq(a.e, 4);
+ assertEq(a.f, 6);
+ assertEq(a.g, 7);
+ assertEq(a.h, 8);
+ assertEq(a.i, 10);
+ assertEq(a.j, 13);
+ assertArrayEq(a.k, [14, 15, 16]);
+ assertEq(a.l, 17);
+ assertArrayEq(a.m, [18, 19]);
+ assertArrayEq(a.n, [22]);
+`);
+
+m.declarationInstantiation();
+m.evaluation();
+
+registerModule('o', parseModule(`
+ export const {} = {};
+ export const {x: a=0} = {};
+ export const {x: b=0} = {x: 1};
+ export const {c, d, e} = {c: 2, d: 3, e: 4};
+ export const {x: f} = {x: 5};
+ export const {g} = {};
+ export const {h=6} = {};
+`));
+
+m = parseModule(`
+ import * as o from 'o';
+
+ assertEq(o.a, 0);
+ assertEq(o.b, 1);
+ assertEq(o.c, 2);
+ assertEq(o.d, 3);
+ assertEq(o.e, 4);
+ assertEq(o.f, 5);
+ assertEq(o.g, undefined);
+ assertEq(o.h, 6);
+`);
+
+m.declarationInstantiation();
+m.evaluation();
+
+registerModule('ao', parseModule(`
+ export const [{x: a}, {x: b}] = [{x: 1}, {x: 2}];
+ export const [{c}, {d}] = [{c: 3}, {d: 4}];
+ export const [,, {e}, ...f] = [5, 6, {e: 7}, 8, 9];
+
+ export const {x: [g, h, i]} = {x: [10, 11, 12]};
+
+ export const [[], [...j], [, k, l]] = [[], [13, 14], [15, 16, 17]];
+
+ export const {x: {m, n, o=20}, y: {z: p}} = {x: {m: 18, n: 19}, y: {z: 21}};
+`));
+
+m = parseModule(`
+ import * as ao from 'ao';
+
+ assertEq(ao.a, 1);
+ assertEq(ao.b, 2);
+ assertEq(ao.c, 3);
+ assertEq(ao.d, 4);
+ assertEq(ao.e, 7);
+ assertArrayEq(ao.f, [8, 9]);
+ assertEq(ao.g, 10);
+ assertEq(ao.h, 11);
+ assertEq(ao.i, 12);
+ assertArrayEq(ao.j, [13, 14]);
+ assertEq(ao.k, 16);
+ assertEq(ao.l, 17);
+ assertEq(ao.m, 18);
+ assertEq(ao.n, 19);
+ assertEq(ao.o, 20);
+ assertEq(ao.p, 21);
+`);
+
+m.declarationInstantiation();
+m.evaluation();
diff --git a/js/src/jit-test/tests/modules/export-entries.js b/js/src/jit-test/tests/modules/export-entries.js
new file mode 100644
index 0000000000..b383d9e1e9
--- /dev/null
+++ b/js/src/jit-test/tests/modules/export-entries.js
@@ -0,0 +1,121 @@
+// Test localExportEntries property
+
+function testArrayContents(actual, expected) {
+ assertEq(actual.length, expected.length);
+ for (var i = 0; i < actual.length; i++) {
+ for (var property in expected[i]) {
+ assertEq(actual[i][property], expected[i][property]);
+ }
+ }
+}
+
+function testLocalExportEntries(source, expected) {
+ var module = parseModule(source);
+ testArrayContents(module.localExportEntries, expected);
+}
+
+testLocalExportEntries(
+ 'export var v;',
+ [{exportName: 'v', moduleRequest: null, importName: null, localName: 'v'}]);
+
+testLocalExportEntries(
+ 'export var v = 0;',
+ [{exportName: 'v', moduleRequest: null, importName: null, localName: 'v'}]);
+
+testLocalExportEntries(
+ 'export let x = 1;',
+ [{exportName: 'x', moduleRequest: null, importName: null, localName: 'x'}]);
+
+testLocalExportEntries(
+ 'export const x = 1;',
+ [{exportName: 'x', moduleRequest: null, importName: null, localName: 'x'}]);
+
+testLocalExportEntries(
+ 'export class foo { constructor() {} };',
+ [{exportName: 'foo', moduleRequest: null, importName: null, localName: 'foo'}]);
+
+testLocalExportEntries(
+ 'export default function f() {};',
+ [{exportName: 'default', moduleRequest: null, importName: null, localName: 'f'}]);
+
+testLocalExportEntries(
+ 'export default function() {};',
+ [{exportName: 'default', moduleRequest: null, importName: null, localName: 'default'}]);
+
+testLocalExportEntries(
+ 'export default 42;',
+ [{exportName: 'default', moduleRequest: null, importName: null, localName: 'default'}]);
+
+testLocalExportEntries(
+ 'let x = 1; export {x};',
+ [{exportName: 'x', moduleRequest: null, importName: null, localName: 'x'}]);
+
+testLocalExportEntries(
+ 'let v = 1; export {v as x};',
+ [{exportName: 'x', moduleRequest: null, importName: null, localName: 'v'}]);
+
+testLocalExportEntries(
+ 'export {x} from "mod";',
+ []);
+
+testLocalExportEntries(
+ 'export {v as x} from "mod";',
+ []);
+
+testLocalExportEntries(
+ 'export * from "mod";',
+ []);
+
+// Test indirectExportEntries property
+
+function testIndirectExportEntries(source, expected) {
+ var module = parseModule(source);
+ testArrayContents(module.indirectExportEntries, expected);
+}
+
+testIndirectExportEntries(
+ 'export default function f() {};',
+ []);
+
+testIndirectExportEntries(
+ 'let x = 1; export {x};',
+ []);
+
+testIndirectExportEntries(
+ 'export {x} from "mod";',
+ [{exportName: 'x', moduleRequest: 'mod', importName: 'x', localName: null}]);
+
+testIndirectExportEntries(
+ 'export {v as x} from "mod";',
+ [{exportName: 'x', moduleRequest: 'mod', importName: 'v', localName: null}]);
+
+testIndirectExportEntries(
+ 'export * from "mod";',
+ []);
+
+testIndirectExportEntries(
+ 'import {v as x} from "mod"; export {x as y};',
+ [{exportName: 'y', moduleRequest: 'mod', importName: 'v', localName: null}]);
+
+// Test starExportEntries property
+
+function testStarExportEntries(source, expected) {
+ var module = parseModule(source);
+ testArrayContents(module.starExportEntries, expected);
+}
+
+testStarExportEntries(
+ 'export default function f() {};',
+ []);
+
+testStarExportEntries(
+ 'let x = 1; export {x};',
+ []);
+
+testStarExportEntries(
+ 'export {x} from "mod";',
+ []);
+
+testStarExportEntries(
+ 'export * from "mod";',
+ [{exportName: null, moduleRequest: 'mod', importName: '*', localName: null}]);
diff --git a/js/src/jit-test/tests/modules/export-ns-from.js b/js/src/jit-test/tests/modules/export-ns-from.js
new file mode 100644
index 0000000000..2e79d77f42
--- /dev/null
+++ b/js/src/jit-test/tests/modules/export-ns-from.js
@@ -0,0 +1,10 @@
+// |jit-test| module
+
+import { ns } from "export-ns.js";
+
+load(libdir + 'asserts.js');
+
+assertEq(isProxy(ns), true);
+assertEq(ns.a, 1);
+assertThrowsInstanceOf(function() { eval("delete ns"); }, SyntaxError);
+assertThrowsInstanceOf(function() { ns = null; }, TypeError);
diff --git a/js/src/jit-test/tests/modules/export-star-cannot-rescue-missing-export.js b/js/src/jit-test/tests/modules/export-star-cannot-rescue-missing-export.js
new file mode 100644
index 0000000000..f87829d89b
--- /dev/null
+++ b/js/src/jit-test/tests/modules/export-star-cannot-rescue-missing-export.js
@@ -0,0 +1,4 @@
+// |jit-test| module; error:SyntaxError
+
+export { a } from "empty.js";
+export* from "module1.js";
diff --git a/js/src/jit-test/tests/modules/export-star-circular-dependencies.js b/js/src/jit-test/tests/modules/export-star-circular-dependencies.js
new file mode 100644
index 0000000000..9aa612f087
--- /dev/null
+++ b/js/src/jit-test/tests/modules/export-star-circular-dependencies.js
@@ -0,0 +1,6 @@
+// |jit-test| module
+
+import { x, y } from "export-star-circular-1.js";
+
+assertEq(x, "pass");
+assertEq(y, "pass");
diff --git a/js/src/jit-test/tests/modules/function-redeclaration.js b/js/src/jit-test/tests/modules/function-redeclaration.js
new file mode 100644
index 0000000000..b84704641d
--- /dev/null
+++ b/js/src/jit-test/tests/modules/function-redeclaration.js
@@ -0,0 +1,94 @@
+load(libdir + "asserts.js");
+
+var functionDeclarations = [
+ "function f(){}",
+ "function* f(){}",
+ "async function f(){}",
+];
+
+var varDeclarations = [
+ "var f",
+ "{ var f; }",
+ "for (var f in null);",
+ "for (var f of null);",
+ "for (var f; ;);",
+];
+
+var lexicalDeclarations = [
+ "let f;",
+ "const f = 0;",
+ "class f {};",
+];
+
+var imports = [
+ "import f from '';",
+ "import f, {} from '';",
+ "import d, {f} from '';",
+ "import d, {f as f} from '';",
+ "import d, {foo as f} from '';",
+ "import f, * as d from '';",
+ "import d, * as f from '';",
+ "import {f} from '';",
+ "import {f as f} from '';",
+ "import {foo as f} from '';",
+ "import* as f from '';",
+];
+
+var exports = [
+ "export var f;",
+ ...functionDeclarations.map(fn => `export ${fn};`),
+ ...lexicalDeclarations.map(ld => `export ${ld};`),
+ ...functionDeclarations.map(fn => `export default ${fn};`),
+ "export default class f {};",
+];
+
+var redeclarations = [
+ ...functionDeclarations,
+ ...varDeclarations,
+ ...lexicalDeclarations,
+ ...imports,
+ ...exports,
+];
+
+var noredeclarations = [
+ ...functionDeclarations.map(fn => `{ ${fn} }`),
+ ...lexicalDeclarations.map(ld => `{ ${ld} }`),
+ ...["let", "const"].map(ld => `for (${ld} f in null);`),
+ ...["let", "const"].map(ld => `for (${ld} f of null);`),
+ ...["let", "const"].map(ld => `for (${ld} f = 0; ;);`),
+ "export {f};",
+ "export {f as f};",
+ "export {foo as f}; var foo;",
+ "export {f} from '';",
+ "export {f as f} from '';",
+ "export {foo as f} from '';",
+];
+
+for (var decl of functionDeclarations) {
+ for (var redecl of redeclarations) {
+ assertThrowsInstanceOf(() => {
+ parseModule(`
+ ${decl}
+ ${redecl}
+ `);
+ }, SyntaxError);
+
+ assertThrowsInstanceOf(() => {
+ parseModule(`
+ ${redecl}
+ ${decl}
+ `);
+ }, SyntaxError);
+ }
+
+ for (var redecl of noredeclarations) {
+ parseModule(`
+ ${decl}
+ ${redecl}
+ `);
+ parseModule(`
+ ${redecl}
+ ${decl}
+ `);
+ }
+}
diff --git a/js/src/jit-test/tests/modules/global-scope.js b/js/src/jit-test/tests/modules/global-scope.js
new file mode 100644
index 0000000000..b99019fa86
--- /dev/null
+++ b/js/src/jit-test/tests/modules/global-scope.js
@@ -0,0 +1,34 @@
+// Test interaction with global object and global lexical scope.
+
+function evalModuleAndCheck(source, expected) {
+ let m = parseModule(source);
+ m.declarationInstantiation();
+ m.evaluation();
+ assertEq(getModuleEnvironmentValue(m, "r"), expected);
+}
+
+var x = 1;
+evalModuleAndCheck("export let r = x; x = 2;", 1);
+assertEq(x, 2);
+
+let y = 3;
+evalModuleAndCheck("export let r = y; y = 4;", 3);
+assertEq(y, 4);
+
+if (helperThreadCount() == 0)
+ quit();
+
+function offThreadEvalModuleAndCheck(source, expected) {
+ offThreadCompileModule(source);
+ let m = finishOffThreadModule();
+ print("compiled");
+ m.declarationInstantiation();
+ m.evaluation();
+ assertEq(getModuleEnvironmentValue(m, "r"), expected);
+}
+
+offThreadEvalModuleAndCheck("export let r = x; x = 5;", 2);
+assertEq(x, 5);
+
+offThreadEvalModuleAndCheck("export let r = y; y = 6;", 4);
+assertEq(y, 6);
diff --git a/js/src/jit-test/tests/modules/import-declaration.js b/js/src/jit-test/tests/modules/import-declaration.js
new file mode 100644
index 0000000000..fd0881e4df
--- /dev/null
+++ b/js/src/jit-test/tests/modules/import-declaration.js
@@ -0,0 +1,343 @@
+load(libdir + "match.js");
+load(libdir + "asserts.js");
+
+var { Pattern, MatchError } = Match;
+
+program = (elts) => Pattern({
+ type: "Program",
+ body: elts
+})
+importDeclaration = (specifiers, source) => Pattern({
+ type: "ImportDeclaration",
+ specifiers: specifiers,
+ source: source
+});
+importSpecifier = (id, name) => Pattern({
+ type: "ImportSpecifier",
+ id: id,
+ name: name
+});
+ident = (name) => Pattern({
+ type: "Identifier",
+ name: name
+})
+lit = (val) => Pattern({
+ type: "Literal",
+ value: val
+})
+
+function parseAsModule(source)
+{
+ return Reflect.parse(source, {target: "module"});
+}
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("default"),
+ ident("a")
+ )
+ ],
+ lit("b")
+ )
+]).assert(parseAsModule("import a from 'b'"));
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("*"),
+ ident("a")
+ )
+ ],
+ lit("b")
+ )
+]).assert(parseAsModule("import * as a from 'b'"));
+
+program([
+ importDeclaration(
+ [],
+ lit("a")
+ )
+]).assert(parseAsModule("import {} from 'a'"));
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("a"),
+ ident("a")
+ )
+ ],
+ lit("b")
+ )
+]).assert(parseAsModule("import { a } from 'b'"));
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("a"),
+ ident("a")
+ )
+ ],
+ lit("b")
+ )
+]).assert(parseAsModule("import { a, } from 'b'"));
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("a"),
+ ident("b")
+ )
+ ],
+ lit("c")
+ )
+]).assert(parseAsModule("import { a as b } from 'c'"));
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("as"),
+ ident("as")
+ )
+ ],
+ lit("a")
+ )
+]).assert(parseAsModule("import { as as as } from 'a'"));
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("default"),
+ ident("a")
+ ),
+ importSpecifier(
+ ident("*"),
+ ident("b")
+ )
+ ],
+ lit("c")
+ )
+]).assert(parseAsModule("import a, * as b from 'c'"));
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("default"),
+ ident("d")
+ )
+ ],
+ lit("a")
+ )
+]).assert(parseAsModule("import d, {} from 'a'"));
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("default"),
+ ident("d")
+ ),
+ importSpecifier(
+ ident("a"),
+ ident("a")
+ )
+ ],
+ lit("b")
+ )
+]).assert(parseAsModule("import d, { a } from 'b'"));
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("default"),
+ ident("d")
+ ),
+ importSpecifier(
+ ident("a"),
+ ident("b")
+ )
+ ],
+ lit("c")
+ )
+]).assert(parseAsModule("import d, { a as b } from 'c'"));
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("default"),
+ ident("d")
+ ),
+ importSpecifier(
+ ident("a"),
+ ident("a")
+ ),
+ importSpecifier(
+ ident("b"),
+ ident("b")
+ ),
+ ],
+ lit("c")
+ )
+]).assert(parseAsModule("import d, { a, b } from 'c'"));
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("default"),
+ ident("d")
+ ),
+ importSpecifier(
+ ident("a"),
+ ident("b")
+ ),
+ importSpecifier(
+ ident("c"),
+ ident("f")
+ ),
+ ],
+ lit("e")
+ )
+]).assert(parseAsModule("import d, { a as b, c as f } from 'e'"));
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("true"),
+ ident("a")
+ )
+ ],
+ lit("b")
+ )
+]).assert(parseAsModule("import { true as a } from 'b'"));
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("a"),
+ ident("a")
+ ),
+ importSpecifier(
+ ident("b"),
+ ident("b")
+ ),
+ ],
+ lit("c")
+ )
+]).assert(parseAsModule("import { a, b } from 'c'"));
+
+program([
+ importDeclaration(
+ [
+ importSpecifier(
+ ident("a"),
+ ident("b")
+ ),
+ importSpecifier(
+ ident("c"),
+ ident("d")
+ ),
+ ],
+ lit("e")
+ )
+]).assert(parseAsModule("import { a as b, c as d } from 'e'"));
+
+program([
+ importDeclaration(
+ [],
+ lit("a")
+ )
+]).assert(parseAsModule("import 'a'"));
+
+var loc = parseAsModule("import { a as b } from 'c'", {
+ loc: true
+}).body[0].loc;
+
+assertEq(loc.start.line, 1);
+assertEq(loc.start.column, 0);
+assertEq(loc.start.line, 1);
+assertEq(loc.end.column, 26);
+
+assertThrowsInstanceOf(function () {
+ parseAsModule("function f() { import a from 'b' }");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function () {
+ parseAsModule("if (true) import a from 'b'");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import {");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import {}");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import {} from");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import {,} from 'a'");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import { a as true } from 'b'");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import { true } from 'a'");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import a,");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import a, b from 'a'");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import * as a,");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import * as a, {} from 'a'");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import as a from 'a'");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import * a from 'a'");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import * as from 'a'");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import , {} from 'a'");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import d, from 'a'");
+}, SyntaxError);
+
+assertThrowsInstanceOf(function() {
+ parseAsModule("import * as true from 'b'");
+}, SyntaxError);
diff --git a/js/src/jit-test/tests/modules/import-default-async-asi.js b/js/src/jit-test/tests/modules/import-default-async-asi.js
new file mode 100644
index 0000000000..96a4ea155f
--- /dev/null
+++ b/js/src/jit-test/tests/modules/import-default-async-asi.js
@@ -0,0 +1,7 @@
+// |jit-test| module
+
+import v from "export-default-async-asi.js";
+
+assertEq(typeof v, "function");
+assertEq(v.name, "async");
+assertEq(v(), 17);
diff --git a/js/src/jit-test/tests/modules/import-default-async-regexpy.js b/js/src/jit-test/tests/modules/import-default-async-regexpy.js
new file mode 100644
index 0000000000..10a769cf2c
--- /dev/null
+++ b/js/src/jit-test/tests/modules/import-default-async-regexpy.js
@@ -0,0 +1,5 @@
+// |jit-test| module
+
+import v from "export-default-async-regexpy.js";
+
+assertEq(v, 7);
diff --git a/js/src/jit-test/tests/modules/import-default-class.js b/js/src/jit-test/tests/modules/import-default-class.js
new file mode 100644
index 0000000000..ff87649ac6
--- /dev/null
+++ b/js/src/jit-test/tests/modules/import-default-class.js
@@ -0,0 +1,5 @@
+// |jit-test| module
+
+import c from "defaultClass.js";
+let o = new c();
+assertEq(o.triple(14), 42);
diff --git a/js/src/jit-test/tests/modules/import-default-function.js b/js/src/jit-test/tests/modules/import-default-function.js
new file mode 100644
index 0000000000..95e962448f
--- /dev/null
+++ b/js/src/jit-test/tests/modules/import-default-function.js
@@ -0,0 +1,4 @@
+// |jit-test| module
+
+import f from "defaultFunction.js";
+assertEq(f(21), 42);
diff --git a/js/src/jit-test/tests/modules/import-entries.js b/js/src/jit-test/tests/modules/import-entries.js
new file mode 100644
index 0000000000..e5f7066f10
--- /dev/null
+++ b/js/src/jit-test/tests/modules/import-entries.js
@@ -0,0 +1,49 @@
+// Test importEntries property
+
+function importEntryEq(a, b)
+{
+ return a['moduleRequest'] === b['moduleRequest'] &&
+ a['importName'] === b['importName'] &&
+ a['localName'] === b['localName'];
+}
+
+function findImportEntry(array, target)
+{
+ for (let i = 0; i < array.length; i++) {
+ if (importEntryEq(array[i], target))
+ return i;
+ }
+ return -1;
+}
+
+function testImportEntries(source, expected) {
+ var module = parseModule(source);
+ var actual = module.importEntries.slice(0);
+ assertEq(actual.length, expected.length);
+ for (var i = 0; i < expected.length; i++) {
+ let index = findImportEntry(actual, expected[i]);
+ assertEq(index >= 0, true);
+ actual.splice(index, 1);
+ }
+}
+
+testImportEntries('', []);
+
+testImportEntries('import v from "mod";',
+ [{moduleRequest: 'mod', importName: 'default', localName: 'v'}]);
+
+testImportEntries('import * as ns from "mod";',
+ [{moduleRequest: 'mod', importName: '*', localName: 'ns'}]);
+
+testImportEntries('import {x} from "mod";',
+ [{moduleRequest: 'mod', importName: 'x', localName: 'x'}]);
+
+testImportEntries('import {x as v} from "mod";',
+ [{moduleRequest: 'mod', importName: 'x', localName: 'v'}]);
+
+testImportEntries('import "mod";',
+ []);
+
+testImportEntries('import {x} from "a"; import {y} from "b";',
+ [{moduleRequest: 'a', importName: 'x', localName: 'x'},
+ {moduleRequest: 'b', importName: 'y', localName: 'y'}]);
diff --git a/js/src/jit-test/tests/modules/import-in-lazy-function.js b/js/src/jit-test/tests/modules/import-in-lazy-function.js
new file mode 100644
index 0000000000..cddacb1428
--- /dev/null
+++ b/js/src/jit-test/tests/modules/import-in-lazy-function.js
@@ -0,0 +1,11 @@
+// |jit-test| module
+
+// Test that accessing imports in lazily parsed functions works.
+
+import { a } from "module1.js";
+
+function add1(x) {
+ return x + a;
+}
+
+assertEq(add1(2), 3);
diff --git a/js/src/jit-test/tests/modules/import-meta-expression.js b/js/src/jit-test/tests/modules/import-meta-expression.js
new file mode 100644
index 0000000000..e7562afaed
--- /dev/null
+++ b/js/src/jit-test/tests/modules/import-meta-expression.js
@@ -0,0 +1,91 @@
+load(libdir + "match.js");
+load(libdir + "asserts.js");
+
+var { Pattern, MatchError } = Match;
+
+program = (elts) => Pattern({
+ type: "Program",
+ body: elts
+});
+expressionStatement = (expression) => Pattern({
+ type: "ExpressionStatement",
+ expression: expression
+});
+assignmentExpression = (left, operator, right) => Pattern({
+ type: "AssignmentExpression",
+ operator: operator,
+ left: left,
+ right: right
+});
+ident = (name) => Pattern({
+ type: "Identifier",
+ name: name
+});
+metaProperty = (meta, property) => Pattern({
+ type: "MetaProperty",
+ meta: meta,
+ property: property
+});
+memberExpression = (object, property) => Pattern({
+ type: "MemberExpression",
+ object: object,
+ property: property
+});
+
+function parseAsModule(source)
+{
+ return Reflect.parse(source, {target: "module"});
+}
+
+program([
+ expressionStatement(
+ metaProperty(
+ ident("import"),
+ ident("meta")
+ )
+ )
+]).assert(parseAsModule("import.meta;"));
+
+program([
+ expressionStatement(
+ assignmentExpression(
+ ident("x"),
+ "=",
+ metaProperty(
+ ident("import"),
+ ident("meta")
+ )
+ )
+ )
+]).assert(parseAsModule("x = import.meta;"));
+
+program([
+ expressionStatement(
+ assignmentExpression(
+ memberExpression(
+ metaProperty(
+ ident("import"),
+ ident("meta")
+ ),
+ ident("foo")
+ ),
+ "=",
+ ident("x"),
+ )
+ )
+]).assert(parseAsModule("import.meta.foo = x;"));
+
+function assertModuleParseThrowsSyntaxError(source)
+{
+ assertThrowsInstanceOf(() => parseAsModule(source), SyntaxError);
+}
+
+assertModuleParseThrowsSyntaxError("import");
+assertModuleParseThrowsSyntaxError("import.");
+assertModuleParseThrowsSyntaxError("import.met");
+assertModuleParseThrowsSyntaxError("import.metaa");
+assertModuleParseThrowsSyntaxError("x = import");
+assertModuleParseThrowsSyntaxError("x = import.");
+assertModuleParseThrowsSyntaxError("x = import.met");
+assertModuleParseThrowsSyntaxError("x = import.metaa");
+assertModuleParseThrowsSyntaxError("import.meta = x");
diff --git a/js/src/jit-test/tests/modules/import-meta-oom.js b/js/src/jit-test/tests/modules/import-meta-oom.js
new file mode 100644
index 0000000000..168f1102a1
--- /dev/null
+++ b/js/src/jit-test/tests/modules/import-meta-oom.js
@@ -0,0 +1,3 @@
+// |jit-test| module; skip-if: !('oomTest' in this)
+
+oomTest(() => import.meta);
diff --git a/js/src/jit-test/tests/modules/import-meta.js b/js/src/jit-test/tests/modules/import-meta.js
new file mode 100644
index 0000000000..aab134cd0b
--- /dev/null
+++ b/js/src/jit-test/tests/modules/import-meta.js
@@ -0,0 +1,58 @@
+// |jit-test| module
+
+// import.meta is an object.
+assertEq(typeof import.meta, "object");
+assertEq(import.meta !== null, true);
+
+// import.meta always returns the same object.
+let obj = import.meta;
+assertEq(import.meta, obj);
+
+// Test calling from lazily compile function.
+function get() {
+ return import.meta;
+}
+assertEq(get(), import.meta);
+
+// import.meta.url: This property will contain the module script's base URL,
+// serialized.
+
+assertEq("url" in import.meta, true);
+assertEq(import.meta.url.endsWith("import-meta.js"), true);
+
+import getOtherMetaObject from "exportImportMeta.js";
+
+let otherImportMeta = getOtherMetaObject();
+assertEq(otherImportMeta.url.endsWith("exportImportMeta.js"), true);
+
+// By default the import.meta object will be extensible, and its properties will
+// be writable, configurable, and enumerable.
+
+assertEq(Object.isExtensible(import.meta), true);
+
+var desc = Object.getOwnPropertyDescriptor(import.meta, "url");
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, true);
+assertEq(desc.configurable, true);
+assertEq(desc.value, import.meta.url);
+
+// The import.meta object's prototype is null.
+assertEq(Object.getPrototypeOf(import.meta), null);
+
+import.meta.url = 0;
+assertEq(import.meta.url, 0);
+
+import.meta.newProp = 42;
+assertEq(import.meta.newProp, 42);
+
+let found = new Set(Reflect.ownKeys(import.meta));
+
+assertEq(found.size, 2);
+assertEq(found.has("url"), true);
+assertEq(found.has("newProp"), true);
+
+delete import.meta.url;
+delete import.meta.newProp;
+
+found = new Set(Reflect.ownKeys(import.meta));
+assertEq(found.size, 0);
diff --git a/js/src/jit-test/tests/modules/import-namespace.js b/js/src/jit-test/tests/modules/import-namespace.js
new file mode 100644
index 0000000000..c5eee00fd1
--- /dev/null
+++ b/js/src/jit-test/tests/modules/import-namespace.js
@@ -0,0 +1,114 @@
+// |jit-test| --enable-top-level-await;
+// Test importing module namespaces
+
+"use strict";
+
+load(libdir + "asserts.js");
+load(libdir + "iteration.js");
+
+function parseAndEvaluate(source) {
+ let m = parseModule(source);
+ m.declarationInstantiation();
+ return m.evaluation();
+}
+
+function testHasNames(names, expected) {
+ assertEq(names.length, expected.length);
+ expected.forEach(function(name) {
+ assertEq(names.includes(name), true);
+ });
+}
+
+function testEqualArrays(actual, expected) {
+ assertEq(Array.isArray(actual), true);
+ assertEq(Array.isArray(expected), true);
+ assertEq(actual.length, expected.length);
+ for (let i = 0; i < expected.length; i++) {
+ assertEq(actual[i], expected[i]);
+ }
+}
+
+let a = registerModule('a', parseModule(
+ `// Reflection methods should return these exports alphabetically sorted.
+ export var b = 2;
+ export var a = 1;`
+));
+
+let b = registerModule('b', parseModule(
+ `import * as ns from 'a';
+ export { ns };
+ export var x = ns.a + ns.b;`
+));
+
+b.declarationInstantiation();
+b.evaluation();
+testHasNames(getModuleEnvironmentNames(b), ["ns", "x"]);
+let ns = getModuleEnvironmentValue(b, "ns");
+testHasNames(Object.keys(ns), ["a", "b"]);
+assertEq(ns.a, 1);
+assertEq(ns.b, 2);
+assertEq(ns.c, undefined);
+assertEq(getModuleEnvironmentValue(b, "x"), 3);
+
+// Test module namespace internal methods as defined in 9.4.6
+assertEq(Object.getPrototypeOf(ns), null);
+assertEq(Reflect.setPrototypeOf(ns, null), true);
+assertEq(Reflect.setPrototypeOf(ns, Object.prototype), false);
+assertThrowsInstanceOf(() => Object.setPrototypeOf(ns, {}), TypeError);
+assertThrowsInstanceOf(function() { ns.foo = 1; }, TypeError);
+assertEq(Object.isExtensible(ns), false);
+Object.preventExtensions(ns);
+let desc = Object.getOwnPropertyDescriptor(ns, "a");
+assertEq(desc.value, 1);
+assertEq(desc.writable, true);
+assertEq(desc.enumerable, true);
+assertEq(desc.configurable, false);
+assertEq(typeof desc.get, "undefined");
+assertEq(typeof desc.set, "undefined");
+assertThrowsInstanceOf(function() { ns.a = 1; }, TypeError);
+delete ns.foo;
+assertThrowsInstanceOf(function() { delete ns.a; }, TypeError);
+
+// Test @@toStringTag property
+desc = Object.getOwnPropertyDescriptor(ns, Symbol.toStringTag);
+assertEq(desc.value, "Module");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, false);
+assertEq(typeof desc.get, "undefined");
+assertEq(typeof desc.set, "undefined");
+assertEq(Object.prototype.toString.call(ns), "[object Module]");
+
+// Test [[OwnPropertyKeys]] internal method.
+testEqualArrays(Reflect.ownKeys(ns), ["a", "b", Symbol.toStringTag]);
+testEqualArrays(Object.getOwnPropertyNames(ns), ["a", "b"]);
+testEqualArrays(Object.getOwnPropertySymbols(ns), [Symbol.toStringTag]);
+
+// Test cyclic namespace import and access in module evaluation.
+let c = registerModule('c',
+ parseModule("export let c = 1; import * as ns from 'd'; let d = ns.d;"));
+let d = registerModule('d',
+ parseModule("export let d = 2; import * as ns from 'c'; let c = ns.c;"));
+c.declarationInstantiation();
+d.declarationInstantiation();
+c.evaluation()
+ .then(r => {
+ // We expect the evaluation to throw, so we should not reach this.
+ assertEq(false, true)
+ })
+ .catch(e => {
+ assertEq(e instanceof ReferenceError, true)
+ });
+
+// Test cyclic namespace import.
+let e = registerModule('e',
+ parseModule("export let e = 1; import * as ns from 'f'; export function f() { return ns.f }"));
+let f = registerModule('f',
+ parseModule("export let f = 2; import * as ns from 'e'; export function e() { return ns.e }"));
+e.declarationInstantiation();
+f.declarationInstantiation();
+e.evaluation();
+f.evaluation();
+assertEq(e.namespace.f(), 2);
+assertEq(f.namespace.e(), 1);
+drainJobQueue();
diff --git a/js/src/jit-test/tests/modules/import-not-found.js b/js/src/jit-test/tests/modules/import-not-found.js
new file mode 100644
index 0000000000..05e6e1e8d5
--- /dev/null
+++ b/js/src/jit-test/tests/modules/import-not-found.js
@@ -0,0 +1,2 @@
+// |jit-test| module; error: SyntaxError
+import { foo } from "module1.js";
diff --git a/js/src/jit-test/tests/modules/inline-data.js b/js/src/jit-test/tests/modules/inline-data.js
new file mode 100644
index 0000000000..9c56856f8d
--- /dev/null
+++ b/js/src/jit-test/tests/modules/inline-data.js
@@ -0,0 +1,17 @@
+// |jit-test| module
+
+import { a } from "javascript: export let a = 42;";
+assertEq(a, 42);
+
+let result = null;
+let error = null;
+let promise = import("javascript: export let b = 100;");
+promise.then((ns) => {
+ result = ns;
+}).catch((e) => {
+ error = e;
+});
+
+drainJobQueue();
+assertEq(error, null);
+assertEq(result.b, 100);
diff --git a/js/src/jit-test/tests/modules/instanceof-error-message.js b/js/src/jit-test/tests/modules/instanceof-error-message.js
new file mode 100644
index 0000000000..d78eb333b3
--- /dev/null
+++ b/js/src/jit-test/tests/modules/instanceof-error-message.js
@@ -0,0 +1,14 @@
+function getInstanceOfErrorMessage(x) {
+ try {
+ var result = {} instanceof x;
+ }
+ catch (e) {
+ return e.message;
+ }
+}
+
+// Error message for a Module Namespace Exotic Object should be same as normal
+// non-callable when using 'instanceof'
+import('empty.js').then(
+ m => assertEq(getInstanceOfErrorMessage(m),
+ getInstanceOfErrorMessage({})));
diff --git a/js/src/jit-test/tests/modules/let-tdz.js b/js/src/jit-test/tests/modules/let-tdz.js
new file mode 100644
index 0000000000..b426794340
--- /dev/null
+++ b/js/src/jit-test/tests/modules/let-tdz.js
@@ -0,0 +1,3 @@
+// |jit-test| module; error:ReferenceError
+foo = 1;
+let foo;
diff --git a/js/src/jit-test/tests/modules/many-exports.js b/js/src/jit-test/tests/modules/many-exports.js
new file mode 100644
index 0000000000..4ade0d957b
--- /dev/null
+++ b/js/src/jit-test/tests/modules/many-exports.js
@@ -0,0 +1,17 @@
+// Test many exports.
+
+const count = 1024;
+
+let s = "";
+for (let i = 0; i < count; i++)
+ s += "export let e" + i + " = " + (i * i) + ";\n";
+let a = registerModule('a', parseModule(s));
+
+let b = registerModule('b', parseModule("import * as ns from 'a'"));
+
+b.declarationInstantiation();
+b.evaluation();
+
+let ns = a.namespace;
+for (let i = 0; i < count; i++)
+ assertEq(ns["e" + i], i * i);
diff --git a/js/src/jit-test/tests/modules/many-imports.js b/js/src/jit-test/tests/modules/many-imports.js
new file mode 100644
index 0000000000..d8ff18d311
--- /dev/null
+++ b/js/src/jit-test/tests/modules/many-imports.js
@@ -0,0 +1,15 @@
+// Test importing an import many times.
+
+const count = 1024;
+
+let a = registerModule('a', parseModule("export let a = 1;"));
+
+let s = "";
+for (let i = 0; i < count; i++) {
+ s += "import { a as i" + i + " } from 'a';\n";
+ s += "assertEq(i" + i + ", 1);\n";
+}
+let b = registerModule('b', parseModule(s));
+
+b.declarationInstantiation();
+b.evaluation();
diff --git a/js/src/jit-test/tests/modules/many-namespace-imports.js b/js/src/jit-test/tests/modules/many-namespace-imports.js
new file mode 100644
index 0000000000..d6b23f7cd4
--- /dev/null
+++ b/js/src/jit-test/tests/modules/many-namespace-imports.js
@@ -0,0 +1,15 @@
+// Test importing a namespace many times.
+
+const count = 1024;
+
+let a = registerModule('a', parseModule("export let a = 1;"));
+
+let s = "";
+for (let i = 0; i < count; i++) {
+ s += "import * as ns" + i + " from 'a';\n";
+ s += "assertEq(ns" + i + ".a, 1);\n";
+}
+let b = registerModule('b', parseModule(s));
+
+b.declarationInstantiation();
+b.evaluation();
diff --git a/js/src/jit-test/tests/modules/missing-export-offthread.js b/js/src/jit-test/tests/modules/missing-export-offthread.js
new file mode 100644
index 0000000000..faaca860a9
--- /dev/null
+++ b/js/src/jit-test/tests/modules/missing-export-offthread.js
@@ -0,0 +1,7 @@
+// |jit-test| skip-if: helperThreadCount() === 0
+
+load(libdir + "asserts.js")
+
+// Don't assert.
+offThreadCompileModule("export { x };");
+assertThrowsInstanceOf(() => finishOffThreadModule(), SyntaxError);
diff --git a/js/src/jit-test/tests/modules/missing-indirect-export.js b/js/src/jit-test/tests/modules/missing-indirect-export.js
new file mode 100644
index 0000000000..207e49ba05
--- /dev/null
+++ b/js/src/jit-test/tests/modules/missing-indirect-export.js
@@ -0,0 +1,2 @@
+// |jit-test| module; error: SyntaxError
+export { foo } from "module1.js";
diff --git a/js/src/jit-test/tests/modules/module-declaration-instantiation.js b/js/src/jit-test/tests/modules/module-declaration-instantiation.js
new file mode 100644
index 0000000000..8fb557d58a
--- /dev/null
+++ b/js/src/jit-test/tests/modules/module-declaration-instantiation.js
@@ -0,0 +1,37 @@
+// Exercise ModuleDeclarationInstantiation() operation.
+
+function testModuleEnvironment(module, expected) {
+ var actual = getModuleEnvironmentNames(module).sort();
+ assertEq(actual.length, expected.length);
+ for (var i = 0; i < actual.length; i++) {
+ assertEq(actual[i], expected[i]);
+ }
+}
+
+// Check the environment of an empty module.
+let m = parseModule("");
+m.declarationInstantiation();
+testModuleEnvironment(m, []);
+
+let a = registerModule('a', parseModule("var x = 1; export { x };"));
+let b = registerModule('b', parseModule("import { x as y } from 'a';"));
+
+a.declarationInstantiation();
+b.declarationInstantiation();
+
+testModuleEnvironment(a, ['x']);
+testModuleEnvironment(b, ['y']);
+
+// Function bindings are initialized as well as instantiated.
+let c = parseModule(`function a(x) { return x; }
+ function b(x) { return x + 1; }
+ function c(x) { return x + 2; }
+ function d(x) { return x + 3; }`);
+const names = ['a', 'b', 'c', 'd'];
+testModuleEnvironment(c, names);
+names.forEach((n) => assertEq(typeof getModuleEnvironmentValue(c, n), "undefined"));
+c.declarationInstantiation();
+for (let i = 0; i < names.length; i++) {
+ let f = getModuleEnvironmentValue(c, names[i]);
+ assertEq(f(21), 21 + i);
+}
diff --git a/js/src/jit-test/tests/modules/module-environment.js b/js/src/jit-test/tests/modules/module-environment.js
new file mode 100644
index 0000000000..fc526cfdd7
--- /dev/null
+++ b/js/src/jit-test/tests/modules/module-environment.js
@@ -0,0 +1,34 @@
+// Test top-level module environment
+
+function testInitialEnvironment(source, expected) {
+ let module = parseModule(source);
+ let names = getModuleEnvironmentNames(module);
+ assertEq(names.length, expected.length);
+ expected.forEach(function(name) {
+ assertEq(names.includes(name), true);
+ });
+}
+
+// Non-exported bindings: only top-level functions are present in the
+// environment.
+testInitialEnvironment('', []);
+testInitialEnvironment('var x = 1;', []);
+testInitialEnvironment('let x = 1;', []);
+testInitialEnvironment("if (true) { let x = 1; }", []);
+testInitialEnvironment("if (true) { var x = 1; }", []);
+testInitialEnvironment('function x() {}', ['x']);
+testInitialEnvironment("class x { constructor() {} }", []);
+
+// Exported bindings must be present in the environment.
+testInitialEnvironment('export var x = 1;', ['x']);
+testInitialEnvironment('export let x = 1;', ['x']);
+testInitialEnvironment('export default function x() {};', ['x']);
+testInitialEnvironment('export default 1;', ['default']);
+testInitialEnvironment('export default function() {};', ['default']);
+testInitialEnvironment("export class x { constructor() {} }", ['x']);
+testInitialEnvironment('export default class x { constructor() {} };', ['x']);
+testInitialEnvironment('export default class { constructor() {} };', ['default']);
+
+// Imports: namespace imports are present.
+testInitialEnvironment('import { x } from "m";', []);
+testInitialEnvironment('import * as x from "m";', ['x']);
diff --git a/js/src/jit-test/tests/modules/module-evaluation.js b/js/src/jit-test/tests/modules/module-evaluation.js
new file mode 100644
index 0000000000..64b64c51a2
--- /dev/null
+++ b/js/src/jit-test/tests/modules/module-evaluation.js
@@ -0,0 +1,125 @@
+// |jit-test| --enable-top-level-await;
+// Exercise ModuleEvaluation() concrete method.
+
+load(libdir + "asserts.js");
+
+async function parseAndEvaluate(source) {
+ let m = parseModule(source);
+ m.declarationInstantiation();
+ await m.evaluation();
+ return m;
+}
+
+// Check the evaluation of an empty module succeeds.
+(async () => {
+ await parseAndEvaluate("");
+})();
+
+(async () => {
+ // Check that evaluation returns evaluation promise,
+ // and promise is always the same.
+ let m = parseModule("1");
+ m.declarationInstantiation();
+ assertEq(typeof m.evaluation(), "object");
+ assertEq(m.evaluation() instanceof Promise, true);
+ assertEq(m.evaluation(), m.evaluation());
+ await m.evaluation();
+})();
+
+(async () => {
+ // Check top level variables are initialized by evaluation.
+ let m = parseModule("export var x = 2 + 2;");
+ assertEq(typeof getModuleEnvironmentValue(m, "x"), "undefined");
+ m.declarationInstantiation();
+ await m.evaluation();
+ assertEq(getModuleEnvironmentValue(m, "x"), 4);
+})();
+
+(async () => {
+ let m = parseModule("export let x = 2 * 3;");
+ m.declarationInstantiation();
+ await m.evaluation();
+ assertEq(getModuleEnvironmentValue(m, "x"), 6);
+})();
+
+// Set up a module to import from.
+let a = registerModule('a',
+ parseModule(`var x = 1;
+ export { x };
+ export default 2;
+ export function f(x) { return x + 1; }`));
+
+(async () => {
+ // Check we can evaluate top level definitions.
+ await parseAndEvaluate("var foo = 1;");
+ await parseAndEvaluate("let foo = 1;");
+ await parseAndEvaluate("const foo = 1");
+ await parseAndEvaluate("function foo() {}");
+ await parseAndEvaluate("class foo { constructor() {} }");
+
+ // Check we can evaluate all module-related syntax.
+ await parseAndEvaluate("export var foo = 1;");
+ await parseAndEvaluate("export let foo = 1;");
+ await parseAndEvaluate("export const foo = 1;");
+ await parseAndEvaluate("var x = 1; export { x };");
+ await parseAndEvaluate("export default 1");
+ await parseAndEvaluate("export default function() {};");
+ await parseAndEvaluate("export default function foo() {};");
+ await parseAndEvaluate("import a from 'a';");
+ await parseAndEvaluate("import { x } from 'a';");
+ await parseAndEvaluate("import * as ns from 'a';");
+ await parseAndEvaluate("export * from 'a'");
+ await parseAndEvaluate("export default class { constructor() {} };");
+ await parseAndEvaluate("export default class foo { constructor() {} };");
+})();
+
+(async () => {
+ // Test default import
+ let m = parseModule("import a from 'a'; export { a };")
+ m.declarationInstantiation();
+ await m.evaluation()
+ assertEq(getModuleEnvironmentValue(m, "a"), 2);
+})();
+
+(async () => {
+ // Test named import
+ let m = parseModule("import { x as y } from 'a'; export { y };")
+ m.declarationInstantiation();
+ await m.evaluation();
+ assertEq(getModuleEnvironmentValue(m, "y"), 1);
+})();
+
+(async () => {
+ // Call exported function
+ let m = parseModule("import { f } from 'a'; export let x = f(3);")
+ m.declarationInstantiation();
+ await m.evaluation();
+ assertEq(getModuleEnvironmentValue(m, "x"), 4);
+})();
+
+(async () => {
+ // Test importing an indirect export
+ registerModule('b', parseModule("export { x as z } from 'a';"));
+ let m = await parseAndEvaluate("import { z } from 'b'; export { z }");
+ assertEq(getModuleEnvironmentValue(m, "z"), 1);
+})();
+
+(async () => {
+ // Test cyclic dependencies
+ registerModule('c1', parseModule("export var x = 1; export {y} from 'c2'"));
+ registerModule('c2', parseModule("export var y = 2; export {x} from 'c1'"));
+ let m = await parseAndEvaluate(`import { x as x1, y as y1 } from 'c1';
+ import { x as x2, y as y2 } from 'c2';
+ export let z = [x1, y1, x2, y2]`);
+ assertDeepEq(getModuleEnvironmentValue(m, "z"), [1, 2, 1, 2]);
+})();
+
+(async () => {
+ // Import access in functions
+ let m = await parseModule("import { x } from 'a'; function f() { return x; }")
+ m.declarationInstantiation();
+ m.evaluation();
+ let f = getModuleEnvironmentValue(m, "f");
+ assertEq(f(), 1);
+})();
+drainJobQueue();
diff --git a/js/src/jit-test/tests/modules/module-this.js b/js/src/jit-test/tests/modules/module-this.js
new file mode 100644
index 0000000000..9721ef4d95
--- /dev/null
+++ b/js/src/jit-test/tests/modules/module-this.js
@@ -0,0 +1,25 @@
+// |jit-test| --enable-top-level-await;
+// Test 'this' is undefined in modules.
+
+function parseAndEvaluate(source) {
+ let m = parseModule(source);
+ m.declarationInstantiation();
+ return m.evaluation();
+}
+
+parseAndEvaluate("this")
+ .then(value => assertEq(typeof(value), "undefined"))
+ .catch(error => {
+ // We shouldn't throw in this case.
+ assertEq(false, true)
+ });
+
+let m = parseModule("export function getThis() { return this; }");
+m.declarationInstantiation();
+m.evaluation()
+ .then(() => {
+ let f = getModuleEnvironmentValue(m, "getThis");
+ assertEq(typeof(f()), "undefined");
+ });
+
+drainJobQueue();
diff --git a/js/src/jit-test/tests/modules/namespace-import-compilation-2.js b/js/src/jit-test/tests/modules/namespace-import-compilation-2.js
new file mode 100644
index 0000000000..ae322246dd
--- /dev/null
+++ b/js/src/jit-test/tests/modules/namespace-import-compilation-2.js
@@ -0,0 +1,17 @@
+// |jit-test| module
+
+import * as ns from 'module1.js';
+
+let other = ns;
+
+const iterations = 2000;
+
+let x = 0;
+for (let i = 0; i < iterations; i++) {
+ if (i == iterations / 2)
+ other = 1;
+ x += other.a;
+}
+
+assertEq(other.a, undefined);
+assertEq(x, NaN);
diff --git a/js/src/jit-test/tests/modules/namespace-import-compilation.js b/js/src/jit-test/tests/modules/namespace-import-compilation.js
new file mode 100644
index 0000000000..42595b7095
--- /dev/null
+++ b/js/src/jit-test/tests/modules/namespace-import-compilation.js
@@ -0,0 +1,17 @@
+// |jit-test| module
+
+import * as ns from 'module1.js';
+
+let other = ns;
+
+const iterations = 10000;
+
+let x = 0;
+for (let i = 0; i < iterations; i++) {
+ if (i == iterations / 2)
+ other = { a: 0 };
+ x += other.a;
+}
+
+assertEq(other.a, 0);
+assertEq(x, iterations / 2);
diff --git a/js/src/jit-test/tests/modules/off-thread-compile.js b/js/src/jit-test/tests/modules/off-thread-compile.js
new file mode 100644
index 0000000000..65d85fe8fe
--- /dev/null
+++ b/js/src/jit-test/tests/modules/off-thread-compile.js
@@ -0,0 +1,14 @@
+// |jit-test| skip-if: helperThreadCount() === 0
+
+// Test off thread module compilation.
+
+load(libdir + "asserts.js");
+
+function offThreadParseAndEvaluate(source) {
+ offThreadCompileModule(source);
+ let m = finishOffThreadModule();
+ m.declarationInstantiation();
+ return m.evaluation();
+}
+
+offThreadParseAndEvaluate("export let x = 2 * 3;");
diff --git a/js/src/jit-test/tests/modules/recursive-star-export.js b/js/src/jit-test/tests/modules/recursive-star-export.js
new file mode 100644
index 0000000000..0313321c59
--- /dev/null
+++ b/js/src/jit-test/tests/modules/recursive-star-export.js
@@ -0,0 +1,2 @@
+// |jit-test| module;
+import * as ns from "recursiveStarExport.js";
diff --git a/js/src/jit-test/tests/modules/requested-modules.js b/js/src/jit-test/tests/modules/requested-modules.js
new file mode 100644
index 0000000000..acf58e5a6e
--- /dev/null
+++ b/js/src/jit-test/tests/modules/requested-modules.js
@@ -0,0 +1,30 @@
+// Test requestedModules property
+
+function testRequestedModules(source, expected) {
+ var module = parseModule(source);
+ var actual = module.requestedModules;
+ assertEq(actual.length, expected.length);
+ for (var i = 0; i < actual.length; i++) {
+ assertEq(actual[i].moduleSpecifier, expected[i]);
+ }
+}
+
+testRequestedModules("", []);
+
+testRequestedModules("import a from 'foo'",
+ ['foo']);
+
+testRequestedModules("import a from 'foo'; import b from 'bar'",
+ ['foo', 'bar']);
+
+testRequestedModules("import a from 'foo'; import b from 'bar'; import c from 'foo'",
+ ['foo', 'bar']);
+
+testRequestedModules("export {} from 'foo'",
+ ['foo']);
+
+testRequestedModules("export * from 'bar'",
+ ['bar']);
+
+testRequestedModules("import a from 'foo'; export {} from 'bar'; export * from 'baz'",
+ ['foo', 'bar', 'baz']);
diff --git a/js/src/jit-test/tests/modules/shell-parse.js b/js/src/jit-test/tests/modules/shell-parse.js
new file mode 100644
index 0000000000..d01f10aaa2
--- /dev/null
+++ b/js/src/jit-test/tests/modules/shell-parse.js
@@ -0,0 +1,30 @@
+// Exercise shell parseModule function.
+
+function testEvalError(source) {
+ // Test |source| throws when passed to eval.
+ var caught = false;
+ try {
+ eval(source);
+ } catch (e) {
+ caught = true;
+ }
+ assertEq(caught, true);
+}
+
+function testModuleSource(source) {
+ // Test |source| parses as a module, but throws when passed to eval.
+ testEvalError(source);
+ parseModule(source);
+}
+
+parseModule("");
+parseModule("const foo = 1;");
+parseModule("var foo = 1;");
+parseModule("let foo = 1; var bar = 2; const baz = 3");
+
+testModuleSource("import * as ns from 'bar';");
+testModuleSource("export { a } from 'b';");
+testModuleSource("export * from 'b';");
+testModuleSource("export const foo = 1;");
+testModuleSource("export default function() {};");
+testModuleSource("export default 1;");
diff --git a/js/src/jit-test/tests/modules/simple-imports.js b/js/src/jit-test/tests/modules/simple-imports.js
new file mode 100644
index 0000000000..a0c894ef63
--- /dev/null
+++ b/js/src/jit-test/tests/modules/simple-imports.js
@@ -0,0 +1,11 @@
+// |jit-test| module
+
+import { a } from "module1.js";
+import { b } from "module2.js";
+import { c } from "module3.js";
+import d from "module4.js";
+
+assertEq(a, 1);
+assertEq(b, 2);
+assertEq(c, 3);
+assertEq(d, 4);
diff --git a/js/src/jit-test/tests/modules/unbound-export.js b/js/src/jit-test/tests/modules/unbound-export.js
new file mode 100644
index 0000000000..f70405d56f
--- /dev/null
+++ b/js/src/jit-test/tests/modules/unbound-export.js
@@ -0,0 +1,2 @@
+// |jit-test| module; error: SyntaxError: local binding for export 'b' not found
+export { b };