summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/parser
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /js/src/jit-test/tests/parser
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/jit-test/tests/parser')
-rw-r--r--js/src/jit-test/tests/parser/arrow-rest.js204
-rw-r--r--js/src/jit-test/tests/parser/arrow-with-block.js92
-rw-r--r--js/src/jit-test/tests/parser/break-continue-errors.js22
-rw-r--r--js/src/jit-test/tests/parser/bug-1090096.js12
-rw-r--r--js/src/jit-test/tests/parser/bug-1161312.js3
-rw-r--r--js/src/jit-test/tests/parser/bug-1250192.js5
-rw-r--r--js/src/jit-test/tests/parser/bug-1254164.js6
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-1.js5
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-10.js4
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-11.js6
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-12.js6
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-13.js26
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-14.js28
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-15.js4
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-16.js11
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-17.js4
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-18.js4
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-19.js4
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-2.js2
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-20.js2
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-21.js7
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-22.js16
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-23.js7
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-24.js3
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-26.js7
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-27.js5
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-28.js3
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-29.js6
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-3.js4
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-30.js19
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-31.js6
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-32.js4
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-33.js22
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-34.js4
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-35.js7
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-36.js9
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-37.js7
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-38.js9
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-39.js8
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-4.js2
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-40.js5
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-41.js5
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-42.js11
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-43.js4
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-44.js8
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-45.js8
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-46.js23
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-47.js6
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-48.js18
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-49.js4
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-5.js3
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-50.js4
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-51.js9
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-52.js11
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-6.js3
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-7.js5
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-8.js5
-rw-r--r--js/src/jit-test/tests/parser/bug-1263355-9.js5
-rw-r--r--js/src/jit-test/tests/parser/bug-1263881-1.js6
-rw-r--r--js/src/jit-test/tests/parser/bug-1263881-2.js5
-rw-r--r--js/src/jit-test/tests/parser/bug-1263881-3.js6
-rw-r--r--js/src/jit-test/tests/parser/bug-1264568.js6
-rw-r--r--js/src/jit-test/tests/parser/bug-1316832.js10
-rw-r--r--js/src/jit-test/tests/parser/bug-1319443.js11
-rw-r--r--js/src/jit-test/tests/parser/bug-1324773-2.js15
-rw-r--r--js/src/jit-test/tests/parser/bug-1324773.js15
-rw-r--r--js/src/jit-test/tests/parser/bug-1355046.js8
-rw-r--r--js/src/jit-test/tests/parser/bug-1357075.js10
-rw-r--r--js/src/jit-test/tests/parser/bug-1363191.js2
-rw-r--r--js/src/jit-test/tests/parser/bug-1364648.js1
-rw-r--r--js/src/jit-test/tests/parser/bug-1366927.js1
-rw-r--r--js/src/jit-test/tests/parser/bug-1385112.js1
-rw-r--r--js/src/jit-test/tests/parser/bug-1431353-2.js57
-rw-r--r--js/src/jit-test/tests/parser/bug-1431353.js165
-rw-r--r--js/src/jit-test/tests/parser/bug-1433014.js5
-rw-r--r--js/src/jit-test/tests/parser/bug-1465695.js3
-rw-r--r--js/src/jit-test/tests/parser/bug-1470992.js4
-rw-r--r--js/src/jit-test/tests/parser/bug-1566974.js5
-rw-r--r--js/src/jit-test/tests/parser/bug-1576865-1.js49
-rw-r--r--js/src/jit-test/tests/parser/bug-1576865-2.js44
-rw-r--r--js/src/jit-test/tests/parser/bug-1662260.js12
-rw-r--r--js/src/jit-test/tests/parser/bug-1764737.js9
-rw-r--r--js/src/jit-test/tests/parser/bug-844805-1.js1
-rw-r--r--js/src/jit-test/tests/parser/bug-844805-2.js10
-rw-r--r--js/src/jit-test/tests/parser/bug-888002-1.js1
-rw-r--r--js/src/jit-test/tests/parser/bug-888002-2.js12
-rw-r--r--js/src/jit-test/tests/parser/bug-888002-3.js18
-rw-r--r--js/src/jit-test/tests/parser/bug-888002.js1
-rw-r--r--js/src/jit-test/tests/parser/bug-889628.js33
-rw-r--r--js/src/jit-test/tests/parser/bug-896126.js11
-rw-r--r--js/src/jit-test/tests/parser/bug-975484.js7
-rw-r--r--js/src/jit-test/tests/parser/bug1461034.js2
-rw-r--r--js/src/jit-test/tests/parser/bug1547655.js2
-rw-r--r--js/src/jit-test/tests/parser/bug1604952.js4
-rw-r--r--js/src/jit-test/tests/parser/bug1605254.js4
-rw-r--r--js/src/jit-test/tests/parser/bug1657557.js7
-rw-r--r--js/src/jit-test/tests/parser/bug1661454.js12
-rw-r--r--js/src/jit-test/tests/parser/bug1750935.js11
-rw-r--r--js/src/jit-test/tests/parser/bug1764715.js4
-rw-r--r--js/src/jit-test/tests/parser/bug1803036.js22
-rw-r--r--js/src/jit-test/tests/parser/bug1835785.js8
-rw-r--r--js/src/jit-test/tests/parser/bytecode-sharing.js103
-rw-r--r--js/src/jit-test/tests/parser/columnNumber.js50
-rw-r--r--js/src/jit-test/tests/parser/compile-script.js50
-rw-r--r--js/src/jit-test/tests/parser/dumpStencil-01.js24
-rw-r--r--js/src/jit-test/tests/parser/fold-constant-index-access.js47
-rw-r--r--js/src/jit-test/tests/parser/home-object-getter.js4
-rw-r--r--js/src/jit-test/tests/parser/lazy-flag-consistency.js65
-rw-r--r--js/src/jit-test/tests/parser/lazy-parse-bad-offset.js4
-rw-r--r--js/src/jit-test/tests/parser/let-after-directive.js6
-rw-r--r--js/src/jit-test/tests/parser/letContextualKeyword.js110
-rw-r--r--js/src/jit-test/tests/parser/lineNumber.js37
-rw-r--r--js/src/jit-test/tests/parser/missing-closing-brace.js90
-rw-r--r--js/src/jit-test/tests/parser/modifier-arrow-rest.js11
-rw-r--r--js/src/jit-test/tests/parser/modifier-do-while.js12
-rw-r--r--js/src/jit-test/tests/parser/modifier-regexp-vs-div.js12
-rw-r--r--js/src/jit-test/tests/parser/modifier-semicolon-insertion.js48
-rw-r--r--js/src/jit-test/tests/parser/modifier-yield-without-operand-1.js12
-rw-r--r--js/src/jit-test/tests/parser/modifier-yield-without-operand-2.js13
-rw-r--r--js/src/jit-test/tests/parser/module-line-0.js18
-rw-r--r--js/src/jit-test/tests/parser/off_thread_compile_oom.js4
-rw-r--r--js/src/jit-test/tests/parser/off_thread_compile_throws_error.js7
-rw-r--r--js/src/jit-test/tests/parser/oom-tracking-line-starts-in-tokenizer.js143
-rw-r--r--js/src/jit-test/tests/parser/optimized-out-functions.js7
-rw-r--r--js/src/jit-test/tests/parser/parse-module.js1
-rw-r--r--js/src/jit-test/tests/parser/parse-non-ascii-latin1.js5
-rw-r--r--js/src/jit-test/tests/parser/redeclaration-message.js10
-rw-r--r--js/src/jit-test/tests/parser/redeclaration.js229
-rw-r--r--js/src/jit-test/tests/parser/regexp-after-do-while.js8
-rw-r--r--js/src/jit-test/tests/parser/regexp-after-variable.js8
-rw-r--r--js/src/jit-test/tests/parser/regexp-error-location.js16
-rw-r--r--js/src/jit-test/tests/parser/script-source-extent.js337
-rw-r--r--js/src/jit-test/tests/parser/standalone-function-name.js22
-rw-r--r--js/src/jit-test/tests/parser/stencil-asmjs.js28
-rw-r--r--js/src/jit-test/tests/parser/stencil-compile-invalid-argument.js14
-rw-r--r--js/src/jit-test/tests/parser/stencil-eager-delazify-certviewer.js35
-rw-r--r--js/src/jit-test/tests/parser/stencil-eager-delazify-empty.js22
-rw-r--r--js/src/jit-test/tests/parser/stencil-eager-delazify.js75
-rw-r--r--js/src/jit-test/tests/parser/stencil-laziness-validate.js29
-rw-r--r--js/src/jit-test/tests/parser/stencil-scope.js134
-rw-r--r--js/src/jit-test/tests/parser/stencil.js111
-rw-r--r--js/src/jit-test/tests/parser/strict-with-asi-and-deprecated-octal.js4
-rw-r--r--js/src/jit-test/tests/parser/syntax-error-illegal-character.js22
-rw-r--r--js/src/jit-test/tests/parser/syntax-parse-error.js4
-rw-r--r--js/src/jit-test/tests/parser/truncation.js73
-rw-r--r--js/src/jit-test/tests/parser/warning-oom.js7
-rw-r--r--js/src/jit-test/tests/parser/yield-in-formal-destructuring.js1
147 files changed, 3434 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/parser/arrow-rest.js b/js/src/jit-test/tests/parser/arrow-rest.js
new file mode 100644
index 0000000000..52db6eb867
--- /dev/null
+++ b/js/src/jit-test/tests/parser/arrow-rest.js
@@ -0,0 +1,204 @@
+// The parser should throw SyntaxError immediately if it finds "..." in a
+// context where it's not allowed.
+
+function testThrow(code, column) {
+ var caught = false;
+ try {
+ eval(code);
+ } catch (e) {
+ caught = true;
+ assertEq(e.columnNumber, column);
+ }
+ assertEq(caught, true,
+ "failed to throw evaluating <" + code + ">");
+}
+
+// expression statement
+
+testThrow(`
+...a)=>
+`, 1);
+
+// default parameter
+
+testThrow(`
+function f(x=...a) =>
+`, 14);
+
+// rest parameter
+
+testThrow(`
+function f(... ...a) =>
+`, 16);
+
+// destructuring parameter
+
+testThrow(`
+([... ...a)=>
+`, 7);
+
+testThrow(`
+({...a)=>
+`, 7);
+
+testThrow(`
+function f([... ...a)=>
+`, 17);
+
+testThrow(`
+function f({...a)=>
+`, 17);
+
+// arrow
+
+testThrow(`
+x => ...a)=>
+`, 6);
+
+// template literal
+
+testThrow("`${ ...a)=>}`", 5);
+
+// destructing assignment
+
+testThrow(`
+var [... ...a)=>
+`, 10);
+
+testThrow(`
+var {...a)=>
+`, 10);
+
+// initializer
+
+testThrow(`
+var [a] = ...a)=>
+`, 11);
+
+testThrow(`
+var {a:a} = ...a)=>
+`, 13);
+
+testThrow(`
+var a = ...a)=>
+`, 9);
+
+// if statement
+
+testThrow(`
+if (...a) =>
+`, 5);
+
+// for statement
+
+testThrow(`
+for (...a)=>
+`, 6);
+
+testThrow(`
+for (let a in ...a)=>
+`, 15);
+
+testThrow(`
+for (let a of ...a)=>
+`, 15);
+
+testThrow(`
+for (; ...a)=>
+`, 8);
+
+testThrow(`
+for (;; ...a)=>
+`, 9);
+
+// case
+
+testThrow(`
+switch (x) { case ...a)=>
+`, 19);
+
+// return statement
+
+testThrow(`
+function f(x) { return ...a)=>
+`, 24);
+
+// yield expression
+
+testThrow(`
+function* f(x) { yield ...a)=>
+`, 24);
+
+// throw statement
+
+testThrow(`
+throw ...a) =>
+`, 7);
+
+// class
+
+testThrow(`
+class A extends ...a) =>
+`, 17);
+
+// conditional expression
+
+testThrow(`
+1 ? ...a) =>
+`, 5);
+
+testThrow(`
+1 ? 2 : ...a) =>
+`, 9);
+
+// unary operators
+
+testThrow(`
+void ...a) =>
+`, 6);
+
+testThrow(`
+typeof ...a) =>
+`, 8);
+
+testThrow(`
+++ ...a) =>
+`, 4);
+
+testThrow(`
+delete ...a) =>
+`, 8);
+
+// new
+
+testThrow(`
+new ...a) =>
+`, 5);
+
+// member expression
+
+testThrow(`
+x[...a) =>
+`, 3);
+
+// array literal
+
+testThrow(`
+[... ...a) =>
+`, 6);
+
+// object literal
+
+testThrow(`
+({[...a) =>
+`, 4);
+
+testThrow(`
+({x: ...a) =>
+`, 6);
+
+// assignment
+
+testThrow(`
+x = ...a) =>
+`, 5);
diff --git a/js/src/jit-test/tests/parser/arrow-with-block.js b/js/src/jit-test/tests/parser/arrow-with-block.js
new file mode 100644
index 0000000000..de6f34c314
--- /dev/null
+++ b/js/src/jit-test/tests/parser/arrow-with-block.js
@@ -0,0 +1,92 @@
+load(libdir + "asserts.js");
+
+let x = 10;
+let g = 4;
+
+assertEq(eval(`
+a => {}
+/x/g;
+`).toString(), "/x/g");
+assertEq(eval(`
+a => {}
+/x/;
+`).toString(), "/x/");
+assertThrowsInstanceOf(() => eval(`
+a => {} /x/g;
+`), SyntaxError);
+
+assertEq(eval(`
+a => {},
+/x/;
+`).toString(), "/x/");
+assertEq(eval(`
+a => {}
+,
+/x/;
+`).toString(), "/x/");
+
+assertEq(eval(`
+false ?
+a => {} :
+/x/;
+`).toString(), "/x/");
+assertEq(eval(`
+false ?
+a => {}
+:
+/x/;
+`).toString(), "/x/");
+
+assertEq(eval(`
+a => {};
+/x/;
+`).toString(), "/x/");
+assertEq(eval(`
+a => {}
+;
+/x/;
+`).toString(), "/x/");
+
+assertEq(eval(`
+a => 200
+/x/g;
+`) instanceof Function, true);
+assertEq(eval(`
+a => 200
+/x/g;
+`)(), 5);
+assertEq(eval(`
+a => 200 /x/g;
+`)(), 5);
+
+assertEq(eval(`
+a => 1,
+/x/;
+`).toString(), "/x/");
+assertEq(eval(`
+a => 1
+,
+/x/;
+`).toString(), "/x/");
+
+assertEq(eval(`
+false ?
+a => 1 :
+/x/;
+`).toString(), "/x/");
+assertEq(eval(`
+false ?
+a => 1
+:
+/x/;
+`).toString(), "/x/");
+
+assertEq(eval(`
+a => 1;
+/x/;
+`).toString(), "/x/");
+assertEq(eval(`
+a => 1
+;
+/x/;
+`).toString(), "/x/");
diff --git a/js/src/jit-test/tests/parser/break-continue-errors.js b/js/src/jit-test/tests/parser/break-continue-errors.js
new file mode 100644
index 0000000000..9d484506e9
--- /dev/null
+++ b/js/src/jit-test/tests/parser/break-continue-errors.js
@@ -0,0 +1,22 @@
+load(libdir + "asserts.js");
+
+function test(s, expected) {
+ assertErrorMessage(() => Function(s), SyntaxError, expected);
+}
+
+test("A: continue;", "continue must be inside loop");
+test("A: continue B;", "continue must be inside loop");
+test("A: if (false) { continue; }", "continue must be inside loop");
+test("A: if (false) { continue B; }", "continue must be inside loop");
+test("while (false) { (() => { continue B; })(); }", "continue must be inside loop");
+test("B: while (false) { (() => { continue B; })(); }", "continue must be inside loop");
+
+test("do { continue B; } while (false);", "label not found");
+test("A: for (;;) { continue B; }", "label not found");
+test("A: while (false) { if (x) { continue B; } }", "label not found");
+test("A: while (false) { B: if (x) { continue B; } }", "label not found");
+
+test("A: if (false) { break B; }", "label not found");
+test("A: while (false) { break B; }", "label not found");
+test("A: while (true) { if (x) { break B; } }", "label not found");
+test("B: while (false) { (() => { break B; })(); }", "label not found");
diff --git a/js/src/jit-test/tests/parser/bug-1090096.js b/js/src/jit-test/tests/parser/bug-1090096.js
new file mode 100644
index 0000000000..3894630afe
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1090096.js
@@ -0,0 +1,12 @@
+load(libdir + "asserts.js");
+
+assertThrowsInstanceOf(
+ () => Function(`
+for (let {
+ [
+ function(x) {;
+ }
+ ]: {}
+} in 0
+`),
+ SyntaxError)
diff --git a/js/src/jit-test/tests/parser/bug-1161312.js b/js/src/jit-test/tests/parser/bug-1161312.js
new file mode 100644
index 0000000000..ef7f7905c1
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1161312.js
@@ -0,0 +1,3 @@
+// Test that lazy scripts can handle OOB column numbers.
+
+assertEq(evaluate(`var f = x=>saveStack().column; f()`, { columnNumber: 1730 }), 1741);
diff --git a/js/src/jit-test/tests/parser/bug-1250192.js b/js/src/jit-test/tests/parser/bug-1250192.js
new file mode 100644
index 0000000000..39b0ff0f54
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1250192.js
@@ -0,0 +1,5 @@
+(function * YearFromTime(x, ... get) {
+try {} catch (x) {
+ for (var x;;);
+}
+})();
diff --git a/js/src/jit-test/tests/parser/bug-1254164.js b/js/src/jit-test/tests/parser/bug-1254164.js
new file mode 100644
index 0000000000..3b08180a78
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1254164.js
@@ -0,0 +1,6 @@
+// |jit-test| slow;
+
+var s = '';
+for (var i = 0; i < 70000; i++)
+ s += 'function x' + i + '() { x' + i + '(); }\n';
+eval("(function() { " + s + " })();");
diff --git a/js/src/jit-test/tests/parser/bug-1263355-1.js b/js/src/jit-test/tests/parser/bug-1263355-1.js
new file mode 100644
index 0000000000..e5dbb56450
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-1.js
@@ -0,0 +1,5 @@
+// |jit-test| error: ReferenceError
+
+for (let b in [0]) {
+ let b = b ? 0 : 1
+}
diff --git a/js/src/jit-test/tests/parser/bug-1263355-10.js b/js/src/jit-test/tests/parser/bug-1263355-10.js
new file mode 100644
index 0000000000..1b7888d861
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-10.js
@@ -0,0 +1,4 @@
+// |jit-test| error: TypeError
+
+function f(m, k = class C extends Array { }, p = m()) { }
+f()
diff --git a/js/src/jit-test/tests/parser/bug-1263355-11.js b/js/src/jit-test/tests/parser/bug-1263355-11.js
new file mode 100644
index 0000000000..1e363dc79d
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-11.js
@@ -0,0 +1,6 @@
+function assertNotSame(expected, actual, message = "") { }
+function g3(h = () => arguments) {
+ function arguments() { }
+ assertNotSame(arguments, h());
+}
+g3();
diff --git a/js/src/jit-test/tests/parser/bug-1263355-12.js b/js/src/jit-test/tests/parser/bug-1263355-12.js
new file mode 100644
index 0000000000..d2049bfa22
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-12.js
@@ -0,0 +1,6 @@
+
+
+syntaxParse(`
+if (scriptArgs.length === 0) { }
+var file = scriptArgs[0];
+`);
diff --git a/js/src/jit-test/tests/parser/bug-1263355-13.js b/js/src/jit-test/tests/parser/bug-1263355-13.js
new file mode 100644
index 0000000000..96997c2dc0
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-13.js
@@ -0,0 +1,26 @@
+// |jit-test| error: ReferenceError
+
+// jsfunfuzz-generated
+gczeal(9);
+for (var i in function(){});
+s = newGlobal({newCompartment: true});
+aa = f();
+function f(x) {
+ evalcx(x, s)
+}
+function h(x) {
+ f(x)
+}
+// Adapted from randomly chosen test: js/src/jit-test/tests/debug/resumption-05.js
+h("\
+ var g = newGlobal({newCompartment: true});\
+ g.debuggeeGlobal = this;\
+ g.eval(\"(\" + function() {\
+ var dbg = Debugger(debuggeeGlobal);\
+ dbg.onDebuggerStatement = function(frame) {\
+ frame.eval(\"f\")\
+ }\
+ } + \")()\");\
+ debugger;\
+");
+z;
diff --git a/js/src/jit-test/tests/parser/bug-1263355-14.js b/js/src/jit-test/tests/parser/bug-1263355-14.js
new file mode 100644
index 0000000000..23f7c160e8
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-14.js
@@ -0,0 +1,28 @@
+// |jit-test| allow-unhandlable-oom
+gczeal(0);
+function g() {
+ for (var j = 0; j < 999; ++j) {
+ try {
+ k
+ } catch (e) {
+ try {
+ r
+ } catch (e) {}
+ }
+ }
+}
+function h(code) {
+ try {
+ f = Function(code)
+ } catch (r) {};
+ try {
+ f()
+ } catch (r) {}
+ eval("")
+}
+h("m=function(){};g(m,[,])")
+h("=")
+h("=")
+h("=")
+h("startgc(1,'shrinking')")
+h("gcparam(\"maxBytes\",gcparam(\"gcBytes\")+4);for(r;;i++){}")
diff --git a/js/src/jit-test/tests/parser/bug-1263355-15.js b/js/src/jit-test/tests/parser/bug-1263355-15.js
new file mode 100644
index 0000000000..409ead51d5
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-15.js
@@ -0,0 +1,4 @@
+// Adapted from randomly chosen test: js/src/jit-test/tests/parser/yield-in-formal-destructuring.js
+function f({
+ [e]: {}
+}) {}
diff --git a/js/src/jit-test/tests/parser/bug-1263355-16.js b/js/src/jit-test/tests/parser/bug-1263355-16.js
new file mode 100644
index 0000000000..9bf1a2412e
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-16.js
@@ -0,0 +1,11 @@
+// |jit-test| error: ReferenceError
+
+let m = parseModule(`
+var i = 0;
+addThis();
+function addThis() {
+ return statusmessages[i] = Number;
+}
+`);
+moduleLink(m);
+moduleEvaluate(m);
diff --git a/js/src/jit-test/tests/parser/bug-1263355-17.js b/js/src/jit-test/tests/parser/bug-1263355-17.js
new file mode 100644
index 0000000000..f472efcd34
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-17.js
@@ -0,0 +1,4 @@
+let m = parseModule(`
+ var expect = '';
+ var [ ... of ] = ( ... of ) => expect;
+`);
diff --git a/js/src/jit-test/tests/parser/bug-1263355-18.js b/js/src/jit-test/tests/parser/bug-1263355-18.js
new file mode 100644
index 0000000000..683c248514
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-18.js
@@ -0,0 +1,4 @@
+function f14(g = 0) {
+ { function g() { return "g" } }
+}
+f14();
diff --git a/js/src/jit-test/tests/parser/bug-1263355-19.js b/js/src/jit-test/tests/parser/bug-1263355-19.js
new file mode 100644
index 0000000000..c3d118635b
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-19.js
@@ -0,0 +1,4 @@
+(function(p = null){
+ var q;
+ (function() { q })();
+})();
diff --git a/js/src/jit-test/tests/parser/bug-1263355-2.js b/js/src/jit-test/tests/parser/bug-1263355-2.js
new file mode 100644
index 0000000000..bb37715b61
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-2.js
@@ -0,0 +1,2 @@
+eval();
+try {} catch (abc) {};
diff --git a/js/src/jit-test/tests/parser/bug-1263355-20.js b/js/src/jit-test/tests/parser/bug-1263355-20.js
new file mode 100644
index 0000000000..f98cf7b44f
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-20.js
@@ -0,0 +1,2 @@
+{ function c() {} }
+class c { }
diff --git a/js/src/jit-test/tests/parser/bug-1263355-21.js b/js/src/jit-test/tests/parser/bug-1263355-21.js
new file mode 100644
index 0000000000..9dfa94e691
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-21.js
@@ -0,0 +1,7 @@
+// |jit-test| error: TypeError
+
+(function() {
+ "use asm";
+ var [] = 0;
+})()
+
diff --git a/js/src/jit-test/tests/parser/bug-1263355-22.js b/js/src/jit-test/tests/parser/bug-1263355-22.js
new file mode 100644
index 0000000000..69b7e77092
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-22.js
@@ -0,0 +1,16 @@
+// |jit-test| error: ReferenceError
+
+// Adapted from randomly chosen test: js/src/jit-test/tests/debug/Frame-onPop-error-scope-unwind-02.js
+var g = newGlobal({newCompartment: true});
+var dbg = new Debugger(g);
+dbg.onEnterFrame = function(f) {
+ (f.environment.getVariable("e") == 0);
+};
+g.eval("" + function f() {
+ try {
+ throw 42;
+ } catch (e) {
+ noSuchFn(e);
+ }
+});
+g.eval("f();");
diff --git a/js/src/jit-test/tests/parser/bug-1263355-23.js b/js/src/jit-test/tests/parser/bug-1263355-23.js
new file mode 100644
index 0000000000..802e58a785
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-23.js
@@ -0,0 +1,7 @@
+let m = parseModule(`
+ const root = newGlobal();
+ minorgc();
+ root.eval();
+`);
+moduleLink(m);
+moduleEvaluate(m);
diff --git a/js/src/jit-test/tests/parser/bug-1263355-24.js b/js/src/jit-test/tests/parser/bug-1263355-24.js
new file mode 100644
index 0000000000..0c33ec3530
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-24.js
@@ -0,0 +1,3 @@
+function TestFunction_4(get, b, [] = status, d, e) {
+ var arguments = "FAIL";
+}
diff --git a/js/src/jit-test/tests/parser/bug-1263355-26.js b/js/src/jit-test/tests/parser/bug-1263355-26.js
new file mode 100644
index 0000000000..a3c09459ab
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-26.js
@@ -0,0 +1,7 @@
+// |jit-test| error: TypeError
+
+function test(a, b, c, d, e, {} = "zmi") {
+ var r = 0
+ r += Math.min(a, b, c, r.script.getLineOffsets(g.line0 + 3), e);
+}
+test();
diff --git a/js/src/jit-test/tests/parser/bug-1263355-27.js b/js/src/jit-test/tests/parser/bug-1263355-27.js
new file mode 100644
index 0000000000..ba334a3eb8
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-27.js
@@ -0,0 +1,5 @@
+// |jit-test| error: ReferenceError
+
+load(libdir + "evalInFrame.js");
+evalInFrame(1, "a = 43");
+let a = 42;
diff --git a/js/src/jit-test/tests/parser/bug-1263355-28.js b/js/src/jit-test/tests/parser/bug-1263355-28.js
new file mode 100644
index 0000000000..88c7b0653e
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-28.js
@@ -0,0 +1,3 @@
+for (var i = 0; i < 1; i++) {
+ L: break;
+}
diff --git a/js/src/jit-test/tests/parser/bug-1263355-29.js b/js/src/jit-test/tests/parser/bug-1263355-29.js
new file mode 100644
index 0000000000..ace3e5faa9
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-29.js
@@ -0,0 +1,6 @@
+// |jit-test| error: ReferenceError
+
+{
+ for (var x = 0; i < 100; i++) a >>= i
+ let i = 1;
+}
diff --git a/js/src/jit-test/tests/parser/bug-1263355-3.js b/js/src/jit-test/tests/parser/bug-1263355-3.js
new file mode 100644
index 0000000000..00a1cef382
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-3.js
@@ -0,0 +1,4 @@
+// |jit-test| error: ReferenceError
+
+f = ([a = class b extends b {}, b] = [void 0]) => {};
+f()
diff --git a/js/src/jit-test/tests/parser/bug-1263355-30.js b/js/src/jit-test/tests/parser/bug-1263355-30.js
new file mode 100644
index 0000000000..f3339ee5fa
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-30.js
@@ -0,0 +1,19 @@
+// |jit-test| error: ReferenceError
+
+var g = newGlobal({newCompartment: true});
+var dbg = new Debugger;
+g.toggle = function toggle(d) {
+ if (d) {
+ dbg.addDebuggee(g);
+ frame1.onPop = function() {
+ onPopExecuted = setJitCompilerOption('offthread-compilation.enable', 0) >> toggle('#2: x = null; x ^= true; x === 1. Actual: ' + (getObjectMetadata)) + (this);
+ };
+ }
+};
+g.eval("" + function f(d) {
+ toggle(d);
+});
+g.eval("(" + function test() {
+ for (var i = 0; i < 5; i++) f(false);
+ f(true);
+} + ")();");
diff --git a/js/src/jit-test/tests/parser/bug-1263355-31.js b/js/src/jit-test/tests/parser/bug-1263355-31.js
new file mode 100644
index 0000000000..2ffe295d0c
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-31.js
@@ -0,0 +1,6 @@
+try {
+ eval('"use strict"; var x = "a\\4";');
+} catch (e) {
+ var e = '';
+ let arguments;
+}
diff --git a/js/src/jit-test/tests/parser/bug-1263355-32.js b/js/src/jit-test/tests/parser/bug-1263355-32.js
new file mode 100644
index 0000000000..db31a6b12d
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-32.js
@@ -0,0 +1,4 @@
+// |jit-test| error: ReferenceError
+
+f = ([a = class target extends b {}, b] = [void 0]) => {};
+f()
diff --git a/js/src/jit-test/tests/parser/bug-1263355-33.js b/js/src/jit-test/tests/parser/bug-1263355-33.js
new file mode 100644
index 0000000000..e1732de594
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-33.js
@@ -0,0 +1,22 @@
+// |jit-test| error: InternalError
+
+var lfLogBuffer = `
+if (lfCodeBuffer) loadFile(lfCodeBuffer);
+function loadFile(await ) {
+ eval(lfVarx);
+}
+`;
+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) {
+ eval(lfVarx);
+}
diff --git a/js/src/jit-test/tests/parser/bug-1263355-34.js b/js/src/jit-test/tests/parser/bug-1263355-34.js
new file mode 100644
index 0000000000..975c6d33dc
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-34.js
@@ -0,0 +1,4 @@
+eval(`
+var of;
+let expect =false , assertEq;
+`);
diff --git a/js/src/jit-test/tests/parser/bug-1263355-35.js b/js/src/jit-test/tests/parser/bug-1263355-35.js
new file mode 100644
index 0000000000..1bb5f44dd0
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-35.js
@@ -0,0 +1,7 @@
+function f({get
+} = (0), y) {
+ var stack = getBacktrace({
+ args: true,
+ });
+}
+f(1, 2);
diff --git a/js/src/jit-test/tests/parser/bug-1263355-36.js b/js/src/jit-test/tests/parser/bug-1263355-36.js
new file mode 100644
index 0000000000..b6d07c3ce9
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-36.js
@@ -0,0 +1,9 @@
+// |jit-test| error: ReferenceError
+
+(function f() {
+ let x = (new function() {
+ x(() => {
+ f.ArrayType(1, 2);
+ }, "first argument of ctypes.cast must be a CData");
+ })
+})();
diff --git a/js/src/jit-test/tests/parser/bug-1263355-37.js b/js/src/jit-test/tests/parser/bug-1263355-37.js
new file mode 100644
index 0000000000..c9829c01e7
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-37.js
@@ -0,0 +1,7 @@
+// |jit-test| error: ReferenceError
+
+{
+ while (x && 0)
+ if (!((x = 1) === x)) {}
+ let x = () => sym()
+}
diff --git a/js/src/jit-test/tests/parser/bug-1263355-38.js b/js/src/jit-test/tests/parser/bug-1263355-38.js
new file mode 100644
index 0000000000..4a42642762
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-38.js
@@ -0,0 +1,9 @@
+// |jit-test| error: SyntaxError
+
+function crashMe2(n) {
+ var nasty = [],
+ fn
+ while (n--) nasty[n] = "a" + 1234567890
+ fn = Function(nasty.join(), "void 0")
+}
+crashMe2(0x10000);
diff --git a/js/src/jit-test/tests/parser/bug-1263355-39.js b/js/src/jit-test/tests/parser/bug-1263355-39.js
new file mode 100644
index 0000000000..85d0f8aaef
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-39.js
@@ -0,0 +1,8 @@
+function f() {
+ var init, first;
+ for (let i = (init = () => i = 1, 0); (first = () => i, i) < 0; ++i);
+ assertEq(init(), 1);
+ assertEq(first(), 0);
+}
+
+f();
diff --git a/js/src/jit-test/tests/parser/bug-1263355-4.js b/js/src/jit-test/tests/parser/bug-1263355-4.js
new file mode 100644
index 0000000000..f2b855f7df
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-4.js
@@ -0,0 +1,2 @@
+function f(a = (eval("var b"))) {}
+f()
diff --git a/js/src/jit-test/tests/parser/bug-1263355-40.js b/js/src/jit-test/tests/parser/bug-1263355-40.js
new file mode 100644
index 0000000000..0142054d4a
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-40.js
@@ -0,0 +1,5 @@
+
+
+function test(get, [] = Bool16x8(...w), ...of) {
+ var f;
+}
diff --git a/js/src/jit-test/tests/parser/bug-1263355-41.js b/js/src/jit-test/tests/parser/bug-1263355-41.js
new file mode 100644
index 0000000000..6c79054174
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-41.js
@@ -0,0 +1,5 @@
+for (var i = 0; i < 200; i++) {
+ (function* get(undefined, ...get) {
+ g.apply(this, arguments);
+ })();
+}
diff --git a/js/src/jit-test/tests/parser/bug-1263355-42.js b/js/src/jit-test/tests/parser/bug-1263355-42.js
new file mode 100644
index 0000000000..b874006a4b
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-42.js
@@ -0,0 +1,11 @@
+// |jit-test| error: ReferenceError
+
+function f() {
+ switch (2) {
+ case 1:
+ x = 1;
+ case (x, 2):
+ let x;
+ }
+}
+f();
diff --git a/js/src/jit-test/tests/parser/bug-1263355-43.js b/js/src/jit-test/tests/parser/bug-1263355-43.js
new file mode 100644
index 0000000000..8605108aca
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-43.js
@@ -0,0 +1,4 @@
+// |jit-test| error: ReferenceError
+
+function f(a = x, x = x) {}
+f(/y/)
diff --git a/js/src/jit-test/tests/parser/bug-1263355-44.js b/js/src/jit-test/tests/parser/bug-1263355-44.js
new file mode 100644
index 0000000000..c2de49fd49
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-44.js
@@ -0,0 +1,8 @@
+// |jit-test| skip-if: !('oomTest' in this)
+
+// Adapted from randomly chosen test: js/src/jit-test/tests/profiler/bug1231925.js
+"use strict";
+enableGeckoProfiling();
+oomTest(function() {
+ eval("(function() {})()");
+});
diff --git a/js/src/jit-test/tests/parser/bug-1263355-45.js b/js/src/jit-test/tests/parser/bug-1263355-45.js
new file mode 100644
index 0000000000..968c595664
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-45.js
@@ -0,0 +1,8 @@
+// |jit-test| error: ReferenceError
+
+gczeal(4, 10);
+f = ([a = class target extends b {}, b] = [void 0]) => {
+ class dbg {}
+ class get {}
+};
+f()
diff --git a/js/src/jit-test/tests/parser/bug-1263355-46.js b/js/src/jit-test/tests/parser/bug-1263355-46.js
new file mode 100644
index 0000000000..e5c3ec1db1
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-46.js
@@ -0,0 +1,23 @@
+setJitCompilerOption("ion.warmup.trigger", 4);
+var lfLogBuffer = `
+function logProxy(object = {}, handler = {}) {
+ var log = [];
+ var proxy = new WeakMap(object, new Proxy(handler, {
+ get(proto) {
+ log.push(propertyKey);
+ }
+ }));
+}
+var {proxy, log} = logProxy();
+`;
+loadFile(lfLogBuffer);
+loadFile(lfLogBuffer);
+loadFile(lfLogBuffer);
+function loadFile(lfVarx) {
+ try {
+ function newFunc(x) {
+ new Function(x)();
+ };
+ newFunc(lfVarx);
+ } catch (lfVare) {}
+}
diff --git a/js/src/jit-test/tests/parser/bug-1263355-47.js b/js/src/jit-test/tests/parser/bug-1263355-47.js
new file mode 100644
index 0000000000..da6575e3f4
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-47.js
@@ -0,0 +1,6 @@
+
+for (let x = 0; x < 4; ++x) {
+ (function() {
+ for (var set = 0, get, get; eval("\tvar\tx\t=\t1\t");) {}
+ })()
+};
diff --git a/js/src/jit-test/tests/parser/bug-1263355-48.js b/js/src/jit-test/tests/parser/bug-1263355-48.js
new file mode 100644
index 0000000000..149db99878
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-48.js
@@ -0,0 +1,18 @@
+// |jit-test| skip-if: helperThreadCount() === 0
+
+function eval(source) {
+ offThreadCompileModuleToStencil(source);
+ let stencil = finishOffThreadStencil();
+ let m = instantiateModuleStencil(stencil);
+ moduleLink(m);
+ return moduleEvaluate(m);
+}
+function runTestCase(testcase) {
+ if (testcase() !== true) {}
+}
+eval(`
+ function testcase() {
+ function set () {}
+ }
+ runTestCase(testcase);
+`);
diff --git a/js/src/jit-test/tests/parser/bug-1263355-49.js b/js/src/jit-test/tests/parser/bug-1263355-49.js
new file mode 100644
index 0000000000..e5fad35322
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-49.js
@@ -0,0 +1,4 @@
+load(libdir + "iteration.js");
+function* f4(get = [1], f2, ...each) {}
+it = f4();
+assertIteratorResult(it.return(2), 2, true);
diff --git a/js/src/jit-test/tests/parser/bug-1263355-5.js b/js/src/jit-test/tests/parser/bug-1263355-5.js
new file mode 100644
index 0000000000..89fff8ea0e
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-5.js
@@ -0,0 +1,3 @@
+// |jit-test| error: ReferenceError
+
+new class extends Object { constructor(a = (()=>{delete super[super()]})()) { } }
diff --git a/js/src/jit-test/tests/parser/bug-1263355-50.js b/js/src/jit-test/tests/parser/bug-1263355-50.js
new file mode 100644
index 0000000000..0416249ec1
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-50.js
@@ -0,0 +1,4 @@
+// |jit-test| error: TypeError
+
+function* of([d] = eval("var MYVAR=new String('0Xf');++MYVAR"), ...get) { var x = 42;}
+of();
diff --git a/js/src/jit-test/tests/parser/bug-1263355-51.js b/js/src/jit-test/tests/parser/bug-1263355-51.js
new file mode 100644
index 0000000000..b2bdb680d0
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-51.js
@@ -0,0 +1,9 @@
+// TDZ checks work in destructuring default expressions,
+// even after the variables are initialized the first time.
+
+load(libdir + "asserts.js");
+
+assertThrowsInstanceOf(() => {
+ // should throw the second time through: b is uninitialized
+ for (const {a=b, b} of [{a:1, b:2}, {b:3}]) {}
+}, ReferenceError);
diff --git a/js/src/jit-test/tests/parser/bug-1263355-52.js b/js/src/jit-test/tests/parser/bug-1263355-52.js
new file mode 100644
index 0000000000..0b0cb4fa21
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-52.js
@@ -0,0 +1,11 @@
+// |jit-test| error: ReferenceError
+
+(function() {
+ if ({}) {}
+ else if (x) {}
+ else {}
+
+ return "" + x;
+
+ let x;
+})()
diff --git a/js/src/jit-test/tests/parser/bug-1263355-6.js b/js/src/jit-test/tests/parser/bug-1263355-6.js
new file mode 100644
index 0000000000..4297e33fba
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-6.js
@@ -0,0 +1,3 @@
+// |jit-test| error: TypeError
+
+(new class extends Array {constructor(a=()=>eval("super()")){ var f = ()=>super(); f() }})(0)
diff --git a/js/src/jit-test/tests/parser/bug-1263355-7.js b/js/src/jit-test/tests/parser/bug-1263355-7.js
new file mode 100644
index 0000000000..b45f1a97ac
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-7.js
@@ -0,0 +1,5 @@
+// |jit-test| error: ReferenceError
+
+let a;
+for(let {a = new class extends Array { constructor(){super(a)} }} of [[]]) {
+}
diff --git a/js/src/jit-test/tests/parser/bug-1263355-8.js b/js/src/jit-test/tests/parser/bug-1263355-8.js
new file mode 100644
index 0000000000..c6d01da9e9
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-8.js
@@ -0,0 +1,5 @@
+// |jit-test| error: ReferenceError
+
+let a;
+for(let {a = new class extends Array { constructor(){super[a]} }} of [[]]) {
+}
diff --git a/js/src/jit-test/tests/parser/bug-1263355-9.js b/js/src/jit-test/tests/parser/bug-1263355-9.js
new file mode 100644
index 0000000000..80e991eb05
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263355-9.js
@@ -0,0 +1,5 @@
+// |jit-test| error: ReferenceError
+
+let a;
+for(let {a = new class extends Array { constructor(b = (a = eval("()=>super()"))){} }} of [[]]) {
+}
diff --git a/js/src/jit-test/tests/parser/bug-1263881-1.js b/js/src/jit-test/tests/parser/bug-1263881-1.js
new file mode 100644
index 0000000000..f105946098
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263881-1.js
@@ -0,0 +1,6 @@
+registerModule('a', parseModule("export let a = 1;"));
+let s = "";
+let max = 65536;
+for (let i = 0; i < max; i++)
+ s += "import * as ns" + i + " from 'a';\n";
+parseModule(s);
diff --git a/js/src/jit-test/tests/parser/bug-1263881-2.js b/js/src/jit-test/tests/parser/bug-1263881-2.js
new file mode 100644
index 0000000000..06c3049085
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263881-2.js
@@ -0,0 +1,5 @@
+let s = "";
+let max = 65536;
+for (let i = 0; i < max; i++)
+ s += "let ns" + i + " = "+ i +";\n";
+eval(s);
diff --git a/js/src/jit-test/tests/parser/bug-1263881-3.js b/js/src/jit-test/tests/parser/bug-1263881-3.js
new file mode 100644
index 0000000000..4d3573b6c5
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1263881-3.js
@@ -0,0 +1,6 @@
+let s = "function foo() {\n";
+let max = 65536;
+for (let i = 0; i < max; i++)
+ s += "let ns" + i + " = "+ i +";\n";
+s += "};";
+eval(s);
diff --git a/js/src/jit-test/tests/parser/bug-1264568.js b/js/src/jit-test/tests/parser/bug-1264568.js
new file mode 100644
index 0000000000..086a04aa94
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1264568.js
@@ -0,0 +1,6 @@
+// |jit-test| error: SyntaxError
+f = (function(stdlib, foreign, heap) {
+ "use asm";
+ ({ "0"
+ ()
+ { eval }
diff --git a/js/src/jit-test/tests/parser/bug-1316832.js b/js/src/jit-test/tests/parser/bug-1316832.js
new file mode 100644
index 0000000000..8b299dd00e
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1316832.js
@@ -0,0 +1,10 @@
+
+(function(x, x) {
+ eval(`
+ var y = 1;
+ function f() {
+ return delete y;
+ }
+ f();
+ `);
+})()
diff --git a/js/src/jit-test/tests/parser/bug-1319443.js b/js/src/jit-test/tests/parser/bug-1319443.js
new file mode 100644
index 0000000000..c2f01c3a8e
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1319443.js
@@ -0,0 +1,11 @@
+// |jit-test| error: TypeError
+
+var global = newGlobal({ cloneSingletons: true });
+
+var code = cacheEntry(`
+function f() {}
+Object.freeze(this);
+`);
+
+evaluate(code, { global, saveIncrementalBytecode: true });
+evaluate(code, { global, saveIncrementalBytecode: true });
diff --git a/js/src/jit-test/tests/parser/bug-1324773-2.js b/js/src/jit-test/tests/parser/bug-1324773-2.js
new file mode 100644
index 0000000000..bf485ee602
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1324773-2.js
@@ -0,0 +1,15 @@
+// |jit-test| skip-if: !('gczeal' in this)
+
+var lfGlobal = newGlobal();
+lfGlobal.evaluate(`
+ for (var i = 0; i < 600; i++)
+ eval('function f' + i + '() {}');
+`);
+var lfGlobal = newGlobal();
+lfGlobal.evaluate(`
+ if (!('gczeal' in this))
+ quit();
+ var dbg = new Debugger();
+ gczeal(9, 10);
+ dbg.findScripts({});
+`);
diff --git a/js/src/jit-test/tests/parser/bug-1324773.js b/js/src/jit-test/tests/parser/bug-1324773.js
new file mode 100644
index 0000000000..1ab1a3fb9a
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1324773.js
@@ -0,0 +1,15 @@
+// |jit-test| skip-if: !('gczeal' in this)
+
+var lfGlobal = newGlobal();
+lfGlobal.evaluate(`
+ for (var i = 0; i < 600; i++)
+ eval('function f' + i + '() {}');
+`);
+var lfGlobal = newGlobal();
+lfGlobal.evaluate(`
+ if (!('gczeal' in this))
+ quit();
+ var dbg = new Debugger();
+ gczeal(9, 1);
+ dbg.findScripts({});
+`);
diff --git a/js/src/jit-test/tests/parser/bug-1355046.js b/js/src/jit-test/tests/parser/bug-1355046.js
new file mode 100644
index 0000000000..86bf7bec92
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1355046.js
@@ -0,0 +1,8 @@
+// |jit-test| error: ReferenceError
+
+var localstr = "";
+for (var i = 0; i < 0xFFFC; ++i)
+ localstr += ('\f') + i + "; ";
+var arg = "x";
+var body = localstr + "for (var i = 0; i < 4; ++i) arr[i](x-1);";
+(new Function(arg, body))(1000);
diff --git a/js/src/jit-test/tests/parser/bug-1357075.js b/js/src/jit-test/tests/parser/bug-1357075.js
new file mode 100644
index 0000000000..47482e372b
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1357075.js
@@ -0,0 +1,10 @@
+// |jit-test| error: TypeError
+
+var iterable = {};
+var iterator = {
+ return: 1
+};
+iterable[Symbol.iterator] = function() {
+ return iterator;
+};
+for ([ class get {} ().iterator ] of [iterable]) {}
diff --git a/js/src/jit-test/tests/parser/bug-1363191.js b/js/src/jit-test/tests/parser/bug-1363191.js
new file mode 100644
index 0000000000..779e1a5d1a
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1363191.js
@@ -0,0 +1,2 @@
+eval("{ function f() {} }");
+let f;
diff --git a/js/src/jit-test/tests/parser/bug-1364648.js b/js/src/jit-test/tests/parser/bug-1364648.js
new file mode 100644
index 0000000000..e9b7b1a4ea
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1364648.js
@@ -0,0 +1 @@
+assertEq(evaluate("var f = x=>class { }; f()", { columnNumber: 1729 }).toString(), "class { }");
diff --git a/js/src/jit-test/tests/parser/bug-1366927.js b/js/src/jit-test/tests/parser/bug-1366927.js
new file mode 100644
index 0000000000..45eb3e69f0
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1366927.js
@@ -0,0 +1 @@
+evaluate("\n(y => 1)()", { columnNumber: 1729 })
diff --git a/js/src/jit-test/tests/parser/bug-1385112.js b/js/src/jit-test/tests/parser/bug-1385112.js
new file mode 100644
index 0000000000..a84ecd1d26
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1385112.js
@@ -0,0 +1 @@
+eval(`let \\u{${"0".repeat(0x8000)}65} = 123;`);
diff --git a/js/src/jit-test/tests/parser/bug-1431353-2.js b/js/src/jit-test/tests/parser/bug-1431353-2.js
new file mode 100644
index 0000000000..67e05d77a1
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1431353-2.js
@@ -0,0 +1,57 @@
+// |jit-test| skip-if: helperThreadCount() === 0
+
+// Test off-thread parsing correctly fixes up prototypes of special objects when
+// merging back to the target compartment.
+
+function execOffThread(source)
+{
+ offThreadCompileToStencil(source);
+ var stencil = finishOffThreadStencil();
+ return evalStencil(stencil);
+}
+
+function parseModuleOffThread(source)
+{
+ offThreadCompileModuleToStencil(source);
+ var stencil = finishOffThreadStencil();
+ return instantiateModuleStencil(stencil);
+}
+
+let a = { x: 1 };
+let b = execOffThread("undefined, { x: 1 }")
+let c = execOffThread("undefined, { x: 1 }")
+
+assertEq(Object.getPrototypeOf(a), Object.prototype);
+assertEq(Object.getPrototypeOf(b), Object.prototype);
+assertEq(Object.getPrototypeOf(c), Object.prototype);
+
+a = () => 1;
+b = execOffThread("() => 1")
+c = execOffThread("() => 1")
+
+assertEq(Object.getPrototypeOf(a), Function.prototype);
+assertEq(Object.getPrototypeOf(b), Function.prototype);
+assertEq(Object.getPrototypeOf(c), Function.prototype);
+
+a = [1, 2, 3];
+b = execOffThread("[1, 2, 3]")
+c = execOffThread("[1, 2, 3]")
+
+assertEq(Object.getPrototypeOf(a), Array.prototype);
+assertEq(Object.getPrototypeOf(b), Array.prototype);
+assertEq(Object.getPrototypeOf(c), Array.prototype);
+
+a = /a/;
+b = execOffThread("/a/")
+c = execOffThread("/a/")
+
+assertEq(Object.getPrototypeOf(a), RegExp.prototype);
+assertEq(Object.getPrototypeOf(b), RegExp.prototype);
+assertEq(Object.getPrototypeOf(c), RegExp.prototype);
+
+a = parseModule("");
+b = parseModuleOffThread("");
+c = parseModuleOffThread("");
+
+assertEq(Object.getPrototypeOf(b), Object.getPrototypeOf(a));
+assertEq(Object.getPrototypeOf(c), Object.getPrototypeOf(a));
diff --git a/js/src/jit-test/tests/parser/bug-1431353.js b/js/src/jit-test/tests/parser/bug-1431353.js
new file mode 100644
index 0000000000..61c83136f2
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1431353.js
@@ -0,0 +1,165 @@
+// |jit-test| skip-if: helperThreadCount() === 0
+
+// Test multiple concurrent off-thread parse jobs.
+
+function assertFails(f) {
+ let failed = false;
+ try {
+ f();
+ } catch (e) {
+ failed = true;
+ }
+ assertEq(failed, true);
+}
+
+function encodeScript(source)
+{
+ let entry = cacheEntry(source);
+ let global = newGlobal({ cloneSingletons: true });
+ evaluate(entry, { global: global, saveIncrementalBytecode: true });
+ return entry;
+}
+
+let a, b, c;
+let stencil, stencilA, stencilB, stencilC;
+
+// Calling run functions without arguments assumes a single off-thread job.
+
+// Test run functions fail when no jobs exist.
+
+assertFails(() => finishOffThreadStencil());
+
+assertFails(() => finishOffThreadStencil());
+
+assertFails(() => finishOffThreadStencil());
+
+// Test run functions fail when multiple jobs exist and no ID specified.
+
+a = offThreadCompileToStencil("");
+b = offThreadCompileToStencil("");
+assertFails(() => finishOffThreadStencil());
+stencilA = finishOffThreadStencil(a);
+stencilB = finishOffThreadStencil(b);
+evalStencil(stencilA);
+evalStencil(stencilB);
+
+a = offThreadCompileModuleToStencil("");
+b = offThreadCompileModuleToStencil("");
+assertFails(() => finishOffThreadStencil());
+stencilA = finishOffThreadStencil(a);
+stencilB = finishOffThreadStencil(b);
+instantiateModuleStencil(stencilA);
+instantiateModuleStencil(stencilB);
+
+a = offThreadDecodeStencil(encodeScript(""));
+b = offThreadDecodeStencil(encodeScript(""));
+assertFails(() => finishOffThreadStencil());
+stencilA = finishOffThreadStencil(a);
+stencilB = finishOffThreadStencil(b);
+evalStencil(stencilA);
+evalStencil(stencilB);
+
+// Test fun functions succeed when a single job exist and no ID specified.
+
+offThreadCompileToStencil("42");
+stencil = finishOffThreadStencil();
+assertEq(evalStencil(stencil), 42);
+
+offThreadCompileModuleToStencil("");
+stencil = finishOffThreadStencil();
+assertEq(typeof instantiateModuleStencil(stencil), "object");
+
+offThreadDecodeStencil(encodeScript("23"));
+stencil = finishOffThreadStencil();
+assertEq(evalStencil(stencil), 23);
+
+// Run functions take an ID argument returned from the compile function.
+
+// Test bad ID type and unknown ID.
+
+offThreadCompileToStencil("");
+assertFails(() => finishOffThreadStencil("foo"));
+assertFails(() => finishOffThreadStencil(42));
+stencil = finishOffThreadStencil();
+evalStencil(stencil);
+
+offThreadCompileModuleToStencil("");
+assertFails(() => finishOffThreadStencil("foo"));
+assertFails(() => finishOffThreadStencil(42));
+stencil = finishOffThreadStencil();
+instantiateModuleStencil(stencil);
+
+offThreadDecodeStencil(encodeScript(""));
+assertFails(() => finishOffThreadStencil("foo"));
+assertFails(() => finishOffThreadStencil(42));
+stencil = finishOffThreadStencil();
+evalStencil(stencil);
+
+// Test stale ID.
+
+a = offThreadCompileToStencil("");
+stencilA = finishOffThreadStencil(a);
+evalStencil(stencilA);
+assertFails(() => finishOffThreadStencil(a));
+
+a = offThreadCompileModuleToStencil("");
+stencilA = finishOffThreadStencil(a);
+assertFails(() => finishOffThreadStencil(a));
+instantiateModuleStencil(stencilA);
+
+a = offThreadDecodeStencil(encodeScript(""));
+stencilA = finishOffThreadStencil(a);
+evalStencil(stencilA);
+assertFails(() => finishOffThreadStencil(a));
+
+// Test running multiple jobs.
+
+a = offThreadCompileToStencil("1");
+b = offThreadCompileToStencil("2");
+stencilA = finishOffThreadStencil(a);
+stencilB = finishOffThreadStencil(b);
+assertEq(evalStencil(stencilA), 1);
+assertEq(evalStencil(stencilB), 2);
+
+a = offThreadCompileModuleToStencil("");
+b = offThreadCompileModuleToStencil("");
+stencilA = finishOffThreadStencil(a);
+stencilB = finishOffThreadStencil(b);
+assertEq(typeof instantiateModuleStencil(stencilA), "object");
+assertEq(typeof instantiateModuleStencil(stencilB), "object");
+
+a = offThreadDecodeStencil(encodeScript("3"));
+b = offThreadDecodeStencil(encodeScript("4"));
+stencilA = finishOffThreadStencil(a);
+stencilB = finishOffThreadStencil(b);
+assertEq(evalStencil(stencilA), 3);
+assertEq(evalStencil(stencilB), 4);
+
+// Test many jobs.
+
+const count = 100;
+let jobs;
+
+jobs = new Array(count);
+for (let i = 0; i < jobs.length; i++)
+ jobs[i] = offThreadCompileToStencil(`${i} * ${i}`);
+for (let i = 0; i < jobs.length; i++) {
+ stencil = finishOffThreadStencil(jobs[i]);
+ assertEq(evalStencil(stencil), i * i);
+}
+
+jobs = new Array(count);
+for (let i = 0; i < jobs.length; i++)
+ jobs[i] = offThreadCompileModuleToStencil("");
+for (let i = 0; i < jobs.length; i++) {
+ stencil = finishOffThreadStencil(jobs[i]);
+ assertEq(typeof instantiateModuleStencil(stencil), "object");
+}
+
+jobs = new Array(count);
+for (let i = 0; i < jobs.length; i++)
+ jobs[i] = offThreadDecodeStencil(encodeScript(`${i} * ${i}`));
+for (let i = 0; i < jobs.length; i++) {
+ stencil = finishOffThreadStencil(jobs[i]);
+ assertEq(evalStencil(stencil), i * i);
+}
diff --git a/js/src/jit-test/tests/parser/bug-1433014.js b/js/src/jit-test/tests/parser/bug-1433014.js
new file mode 100644
index 0000000000..efb8ab98d3
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1433014.js
@@ -0,0 +1,5 @@
+// |jit-test| skip-if: helperThreadCount() === 0 || !('oomTest' in this)
+evaluate(`
+ oomTest(() => {
+ offThreadCompileToStencil("");
+ });`);
diff --git a/js/src/jit-test/tests/parser/bug-1465695.js b/js/src/jit-test/tests/parser/bug-1465695.js
new file mode 100644
index 0000000000..9c63fcfd1b
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1465695.js
@@ -0,0 +1,3 @@
+// |jit-test| skip-if: helperThreadCount() === 0
+for (let x = 0; x < 99; ++x)
+ evalInWorker("newGlobal().offThreadCompileToStencil(\"{}\");");
diff --git a/js/src/jit-test/tests/parser/bug-1470992.js b/js/src/jit-test/tests/parser/bug-1470992.js
new file mode 100644
index 0000000000..6be1548590
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1470992.js
@@ -0,0 +1,4 @@
+// |jit-test| skip-if: helperThreadCount() === 0
+
+offThreadCompileModuleToStencil("export { x };");
+gcslice(10);
diff --git a/js/src/jit-test/tests/parser/bug-1566974.js b/js/src/jit-test/tests/parser/bug-1566974.js
new file mode 100644
index 0000000000..efd176daf0
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1566974.js
@@ -0,0 +1,5 @@
+(() => {
+ (function() {
+ eval('');
+ }());
+})();
diff --git a/js/src/jit-test/tests/parser/bug-1576865-1.js b/js/src/jit-test/tests/parser/bug-1576865-1.js
new file mode 100644
index 0000000000..f31539b8ea
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1576865-1.js
@@ -0,0 +1,49 @@
+// |jit-test| skip-if: !('oomTest' in this)
+var sourceText = `
+ function Outer() {
+ var X00, X01, X02, X03, X04, X05, X06, X07;
+ var X08, X09, X10, X11, X12, X13, X14, X15;
+ var X16, X17, X18, X19, X20, X21, X22, X23;
+ var X24, X25, X26, X27, X28, X29, X30, X31;
+
+ function LazyFunction() {
+ // Lots of closed-over bindings.
+ { X00 = true; };
+ { X01 = true; };
+ { X02 = true; };
+ { X03 = true; };
+ { X04 = true; };
+ { X05 = true; };
+ { X06 = true; };
+ { X07 = true; };
+ { X08 = true; };
+ { X09 = true; };
+ { X10 = true; };
+ { X11 = true; };
+ { X12 = true; };
+ { X13 = true; };
+ { X14 = true; };
+ { X15 = true; };
+ { X16 = true; };
+ { X17 = true; };
+ { X18 = true; };
+ { X19 = true; };
+ { X20 = true; };
+ { X21 = true; };
+ { X22 = true; };
+ { X23 = true; };
+ { X24 = true; };
+ { X25 = true; };
+ { X26 = true; };
+ { X27 = true; };
+ { X28 = true; };
+ { X29 = true; };
+ { X30 = true; };
+ { X31 = true; };
+ }
+ }
+`;
+
+oomTest(function() {
+ evaluate(sourceText);
+ });
diff --git a/js/src/jit-test/tests/parser/bug-1576865-2.js b/js/src/jit-test/tests/parser/bug-1576865-2.js
new file mode 100644
index 0000000000..d053c24728
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1576865-2.js
@@ -0,0 +1,44 @@
+// |jit-test| skip-if: !('oomTest' in this)
+var sourceText = `
+ function Outer() {
+ function LazyFunction() {
+ // Lots of inner functions.
+ function F00() { }
+ function F01() { }
+ function F02() { }
+ function F03() { }
+ function F04() { }
+ function F05() { }
+ function F06() { }
+ function F07() { }
+ function F08() { }
+ function F09() { }
+ function F10() { }
+ function F11() { }
+ function F12() { }
+ function F13() { }
+ function F14() { }
+ function F15() { }
+ function F16() { }
+ function F17() { }
+ function F18() { }
+ function F19() { }
+ function F20() { }
+ function F21() { }
+ function F22() { }
+ function F23() { }
+ function F24() { }
+ function F25() { }
+ function F26() { }
+ function F27() { }
+ function F28() { }
+ function F29() { }
+ function F30() { }
+ function F31() { }
+ }
+ }
+`;
+
+oomTest(function() {
+ evaluate(sourceText);
+ });
diff --git a/js/src/jit-test/tests/parser/bug-1662260.js b/js/src/jit-test/tests/parser/bug-1662260.js
new file mode 100644
index 0000000000..235737657e
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1662260.js
@@ -0,0 +1,12 @@
+// |jit-test| skip-if: !('oomTest' in this)
+
+function loadX(lfVarx) {
+ oomTest(function() {
+ let m55 = parseModule(lfVarx);
+ });
+}
+loadX(`
+ class B50 {
+ #priv() {}
+ }
+`)
diff --git a/js/src/jit-test/tests/parser/bug-1764737.js b/js/src/jit-test/tests/parser/bug-1764737.js
new file mode 100644
index 0000000000..0fcc39e276
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-1764737.js
@@ -0,0 +1,9 @@
+// |jit-test| skip-if: !('oomTest' in this); --fuzzing-safe; --ion-offthread-compile=off
+
+function r(src) {
+ oomTest(function() {
+ parseModule(src);
+ });
+}
+r("export * from 'y';");
+r("export * from 'y';");
diff --git a/js/src/jit-test/tests/parser/bug-844805-1.js b/js/src/jit-test/tests/parser/bug-844805-1.js
new file mode 100644
index 0000000000..b6bad21059
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-844805-1.js
@@ -0,0 +1 @@
+if (Math["key"]) {}
diff --git a/js/src/jit-test/tests/parser/bug-844805-2.js b/js/src/jit-test/tests/parser/bug-844805-2.js
new file mode 100644
index 0000000000..5a278ef9b1
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-844805-2.js
@@ -0,0 +1,10 @@
+// Constant folding does not affect strict delete.
+
+function f(x) {
+ "use strict";
+
+ // This senseless delete-expression is legal even in strict mode. Per ES5.1
+ // 11.4.1 step 2, it does nothing and returns true.
+ return delete (1 ? x : x);
+}
+assertEq(f(), true);
diff --git a/js/src/jit-test/tests/parser/bug-888002-1.js b/js/src/jit-test/tests/parser/bug-888002-1.js
new file mode 100644
index 0000000000..44333e0bcf
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-888002-1.js
@@ -0,0 +1 @@
+Function("var e = delete(false ? e : e)")();
diff --git a/js/src/jit-test/tests/parser/bug-888002-2.js b/js/src/jit-test/tests/parser/bug-888002-2.js
new file mode 100644
index 0000000000..f0ccfca998
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-888002-2.js
@@ -0,0 +1,12 @@
+// Constant folding doesn't affect non-strict delete.
+
+(function (x) {
+ // These senseless delete-expressions are legal. Per ES5.1 11.4.1 step 2,
+ // each one does nothing and returns true.
+ assertEq(delete (1 ? x : x), true);
+ assertEq(delete (0 || x), true);
+ assertEq(delete (1 && x), true);
+
+ // This one is legal too, but returns false.
+ assertEq(delete x, false);
+}());
diff --git a/js/src/jit-test/tests/parser/bug-888002-3.js b/js/src/jit-test/tests/parser/bug-888002-3.js
new file mode 100644
index 0000000000..964ae2e1b9
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-888002-3.js
@@ -0,0 +1,18 @@
+// Constant folding doesn't affect strict delete either.
+// In particular, it doesn't affect whether |delete x| is a strict error.
+
+load(libdir + "asserts.js");
+
+(function (x) {
+ "use strict";
+
+ // These senseless delete-expressions are legal even in strict mode.
+ // Per ES5.1 11.4.1 step 2, each one does nothing and returns true.
+ assertEq(delete (1 ? x : x), true);
+ assertEq(delete (0 || x), true);
+ assertEq(delete (1 && x), true);
+
+ // Plain `delete x` is a SyntaxError though.
+ assertThrowsInstanceOf(() => eval('delete x'), SyntaxError);
+ assertThrowsInstanceOf(() => Function('"use strict"; delete x'), SyntaxError);
+}());
diff --git a/js/src/jit-test/tests/parser/bug-888002.js b/js/src/jit-test/tests/parser/bug-888002.js
new file mode 100644
index 0000000000..44333e0bcf
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-888002.js
@@ -0,0 +1 @@
+Function("var e = delete(false ? e : e)")();
diff --git a/js/src/jit-test/tests/parser/bug-889628.js b/js/src/jit-test/tests/parser/bug-889628.js
new file mode 100644
index 0000000000..bb337c35d7
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-889628.js
@@ -0,0 +1,33 @@
+// Destructuring assignment to eval or arguments in destructuring is a SyntaxError
+// in strict mode
+
+load(libdir + "asserts.js");
+
+var patterns = [
+ "[_]",
+ "[a, b, _]",
+ "[[_]]",
+ "[[], [{}, [_]]]",
+ "{x:_}",
+ "{x:y, z:_}",
+ "{0:_}",
+ "{_}",
+ "[..._]"
+];
+
+for (var pattern of patterns) {
+ var stmt = pattern + " = obj";
+ if (stmt[0] == "{")
+ stmt = "(" + stmt + ")";
+ stmt += ";"
+
+ // stmt is a legal statement...
+ Function(stmt);
+
+ // ...but not if you replace _ with one of these two names.
+ for (var name of ["eval", "arguments"]) {
+ var s = stmt.replace("_", name);
+ Function(s);
+ assertThrowsInstanceOf(() => Function("'use strict'; " + s), SyntaxError);
+ }
+}
diff --git a/js/src/jit-test/tests/parser/bug-896126.js b/js/src/jit-test/tests/parser/bug-896126.js
new file mode 100644
index 0000000000..334ea33b92
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-896126.js
@@ -0,0 +1,11 @@
+// |jit-test| error: SyntaxError
+({
+ r: function() {
+ function f() {
+ w[0xe56241c6 >> 3]
+ }
+ },
+ s: function() {
+ "use asm"
+ return (1 for
+
diff --git a/js/src/jit-test/tests/parser/bug-975484.js b/js/src/jit-test/tests/parser/bug-975484.js
new file mode 100644
index 0000000000..dfbd0818d1
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-975484.js
@@ -0,0 +1,7 @@
+var loc = Reflect.parse("f()").body[0].expression.loc;
+assertEq(loc.start.column, 1);
+assertEq(loc.end.column, 4);
+
+loc = Reflect.parse("f(x)").body[0].expression.loc;
+assertEq(loc.start.column, 1);
+assertEq(loc.end.column, 5);
diff --git a/js/src/jit-test/tests/parser/bug1461034.js b/js/src/jit-test/tests/parser/bug1461034.js
new file mode 100644
index 0000000000..84d6ae88ca
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug1461034.js
@@ -0,0 +1,2 @@
+// |jit-test| skip-if: !('oomTest' in this)
+oomTest(function(){s[-1]});
diff --git a/js/src/jit-test/tests/parser/bug1547655.js b/js/src/jit-test/tests/parser/bug1547655.js
new file mode 100644
index 0000000000..540e011d9a
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug1547655.js
@@ -0,0 +1,2 @@
+// |jit-test| allow-unhandlable-oom; allow-oom; skip-if: !('oomTest' in this)
+oomTest(() => evaluate(`meta: { with({}) {} }`));
diff --git a/js/src/jit-test/tests/parser/bug1604952.js b/js/src/jit-test/tests/parser/bug1604952.js
new file mode 100644
index 0000000000..66ccfe76e5
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug1604952.js
@@ -0,0 +1,4 @@
+// This is a leak test to ensure that a folded
+// RegExp parse node doesn't leak data.
+
+/x/
diff --git a/js/src/jit-test/tests/parser/bug1605254.js b/js/src/jit-test/tests/parser/bug1605254.js
new file mode 100644
index 0000000000..b8b1794785
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug1605254.js
@@ -0,0 +1,4 @@
+// This is a leak test to ensure that a folded
+// BigInt parse node doesn't leak data.
+
+128n
diff --git a/js/src/jit-test/tests/parser/bug1657557.js b/js/src/jit-test/tests/parser/bug1657557.js
new file mode 100644
index 0000000000..6035035166
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug1657557.js
@@ -0,0 +1,7 @@
+setImmutablePrototype(Function.__proto__);
+
+if (helperThreadCount() > 0) {
+ offThreadCompileToStencil("function f() {}");
+ var stencil = finishOffThreadStencil();
+ evalStencil(stencil);
+}
diff --git a/js/src/jit-test/tests/parser/bug1661454.js b/js/src/jit-test/tests/parser/bug1661454.js
new file mode 100644
index 0000000000..ca7792f4bc
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug1661454.js
@@ -0,0 +1,12 @@
+// |jit-test| skip-if: !('oomTest' in this)
+
+function oomTestEval(lfVarx) {
+ oomTest(() => eval(lfVarx));
+}
+
+oomTestEval(``);
+oomTestEval(`
+ {
+ function bug1661454() { }
+ }
+`);
diff --git a/js/src/jit-test/tests/parser/bug1750935.js b/js/src/jit-test/tests/parser/bug1750935.js
new file mode 100644
index 0000000000..e4f7440848
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug1750935.js
@@ -0,0 +1,11 @@
+// Parse-time static string lookup.
+var s = "\ue531\ue531\ue531";
+assertEq(s.codePointAt(0), 0xe531);
+assertEq(s.codePointAt(1), 0xe531);
+assertEq(s.codePointAt(2), 0xe531);
+
+// Runtime static string lookup.
+s = "\ue531\ue531\ue5310n".split(/\d[^]/)[0];
+assertEq(s.codePointAt(0), 0xe531);
+assertEq(s.codePointAt(1), 0xe531);
+assertEq(s.codePointAt(2), 0xe531);
diff --git a/js/src/jit-test/tests/parser/bug1764715.js b/js/src/jit-test/tests/parser/bug1764715.js
new file mode 100644
index 0000000000..b203925aa8
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug1764715.js
@@ -0,0 +1,4 @@
+// |jit-test| skip-if: !('oomTest' in this)
+oomTest(function() {
+ let m = parseModule(`x = a?.b; x = a?.b; x = a?.b;`);
+});
diff --git a/js/src/jit-test/tests/parser/bug1803036.js b/js/src/jit-test/tests/parser/bug1803036.js
new file mode 100644
index 0000000000..bb3e237990
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug1803036.js
@@ -0,0 +1,22 @@
+// Test that parsing the given source text will throw an error with location set
+// to last character in source, rather than after it.
+function testErrorPosition(src) {
+ let failed = false;
+
+ try {
+ parse(src)
+ }
+ catch (e) {
+ failed = true;
+ assertEq(e.lineNumber, 1)
+ assertEq(e.columnNumber, src.length)
+ }
+
+ assertEq(failed, true);
+}
+
+testErrorPosition("0_") // No trailing separator - Zero
+testErrorPosition("00_") // No trailing separator - Octal
+testErrorPosition("1_") // No trailing separator - Number
+testErrorPosition("1__") // No repeated separator
+testErrorPosition("00n") // No octal BigInt
diff --git a/js/src/jit-test/tests/parser/bug1835785.js b/js/src/jit-test/tests/parser/bug1835785.js
new file mode 100644
index 0000000000..25317757ec
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug1835785.js
@@ -0,0 +1,8 @@
+// |jit-test| allow-unhandlable-oom; allow-oom; skip-if: !('oomAtAllocation' in this)
+function main() {
+ this
+ oomAtAllocation(7);
+ var v7 = /a/
+ disassemble();
+}
+main();
diff --git a/js/src/jit-test/tests/parser/bytecode-sharing.js b/js/src/jit-test/tests/parser/bytecode-sharing.js
new file mode 100644
index 0000000000..26f0ac429c
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bytecode-sharing.js
@@ -0,0 +1,103 @@
+// Test that bytecode is still shared when expected. The expectations can be
+// updated if necessary.
+
+
+// Check the testing function.
+evaluate(`function a01(){ return a + b; }`)
+evaluate(`function a02(){ return a + b; }`)
+evaluate(`function a03(){ return a + b + c; }`)
+assertEq(hasSameBytecodeData(a01, a02), true)
+assertEq(hasSameBytecodeData(a01, a03), false)
+
+
+// Check effect of whitespace.
+evaluate(`function b(){}`)
+evaluate(`function b01(){}`)
+evaluate(`function b02 (){}`)
+evaluate(`function b03( ){}`)
+evaluate(`function b04() {}`)
+evaluate(`function b05(){ }`)
+assertEq(hasSameBytecodeData(b, b01), true)
+assertEq(hasSameBytecodeData(b, b02), true)
+assertEq(hasSameBytecodeData(b, b03), false)
+assertEq(hasSameBytecodeData(b, b04), false)
+assertEq(hasSameBytecodeData(b, b05), false)
+
+
+// Check effect of binding names.
+evaluate(`function c01(){ return a; }`)
+evaluate(`function c02(){ return b; }`)
+evaluate(`function c03(){ return cc; }`)
+assertEq(hasSameBytecodeData(c01, c02), true)
+assertEq(hasSameBytecodeData(c01, c03), false)
+
+
+// Check effect of string literals.
+evaluate(`function d01(){ return "AA"; }`)
+evaluate(`function d02(){ return "BB"; }`)
+assertEq(hasSameBytecodeData(d01, d02), true)
+
+
+// Check effect of string template literals.
+evaluate("function e01(){ return a`AA`; }")
+evaluate("function e02(){ return b`BB`; }")
+assertEq(hasSameBytecodeData(e01, e02), true)
+
+
+// Check effect of object literals.
+evaluate(`function f01(){ return { a: 1 }; }`)
+evaluate(`function f02(){ return { b: 1 }; }`)
+evaluate(`function f03(){ return { b: 2 }; }`)
+assertEq(hasSameBytecodeData(f01, f02), true)
+assertEq(hasSameBytecodeData(f01, f03), false)
+
+
+// Check effect of inner functions.
+evaluate(`function g01(){ return () => 0; }`)
+evaluate(`function g02(){ return () => 0; }`)
+evaluate(`function g03(){ return () => a; }`)
+assertEq(hasSameBytecodeData(g01, g02), true)
+assertEq(hasSameBytecodeData(g01, g03), true)
+
+
+// Check effect of line number.
+evaluate(`function h01(){ return 0; }`)
+evaluate(`\nfunction h02(){ return 0; }`)
+evaluate(`\n\n\n\n\n\n\nfunction h03(){ return 0; }`)
+assertEq(hasSameBytecodeData(h01, h02), true)
+assertEq(hasSameBytecodeData(h01, h03), true)
+
+
+// Check effect of line number when function has large gaps in it. This
+// corresponds to SetLine source-notes.
+evaluate(`function i01(){ return\n\n\n\n\n\n\n\n0; }`)
+evaluate(`\nfunction i02(){ return\n\n\n\n\n\n\n\n0; }`)
+evaluate(`\n\n\n\n\n\n\nfunction i03(){ return\n\n\n\n\n\n\n\n0; }`)
+assertEq(hasSameBytecodeData(i01, i02), true)
+assertEq(hasSameBytecodeData(i01, i03), true)
+
+
+// Check effect of column number.
+evaluate(`function j01(){ return 0; }`)
+evaluate(` function j02(){ return 0; }`)
+evaluate(` \tfunction j03(){ return 0; }`)
+assertEq(hasSameBytecodeData(j01, j02), true)
+assertEq(hasSameBytecodeData(j01, j03), true)
+
+
+// Check different forms of functions.
+evaluate(`function k01 () { return 0; }`)
+evaluate(`var k02 = function() { return 0; }`)
+evaluate(`var k03 = () => { return 0; }`)
+assertEq(hasSameBytecodeData(k01, k02), true)
+assertEq(hasSameBytecodeData(k01, k03), true)
+
+
+// Check sharing across globals / compartments.
+let l02_global = newGlobal({newCompartment: false});
+let l03_global = newGlobal({newCompartment: true});
+evaluate(`function l01() { return 0; }`)
+l02_global.evaluate(`function l02() { return 0; }`)
+l03_global.evaluate(`function l03() { return 0; }`)
+assertEq(hasSameBytecodeData(l01, l02_global.l02), true)
+assertEq(hasSameBytecodeData(l01, l03_global.l03), true)
diff --git a/js/src/jit-test/tests/parser/columnNumber.js b/js/src/jit-test/tests/parser/columnNumber.js
new file mode 100644
index 0000000000..122309dc4b
--- /dev/null
+++ b/js/src/jit-test/tests/parser/columnNumber.js
@@ -0,0 +1,50 @@
+// Simple tests for evaluate's "columnNumber" option.
+
+load(libdir + 'asserts.js');
+
+assertEq(evaluate("saveStack().column"), 1);
+assertEq(evaluate("saveStack().column", { columnNumber: 1729 }), 1729);
+assertEq(evaluate("\nsaveStack().column", { columnNumber: 1729 }), 1);
+assertEq(evaluate("saveStack().column", { columnNumber: "42" }), 42);
+// columnNumber < 1 is fixed to 1.
+assertEq(evaluate("saveStack().column", { columnNumber: -10 }), 1);
+assertThrowsInstanceOf(() => evaluate("saveStack().column", { columnNumber: Math.pow(2,30) }),
+ RangeError);
+
+if (helperThreadCount() > 0) {
+ print("offThreadCompileToStencil 1");
+ offThreadCompileToStencil("saveStack().column", { columnNumber: -10 });
+ var stencil = finishOffThreadStencil();
+ assertEq(evalStencil(stencil), 1);
+
+ print("offThreadCompileToStencil 2");
+ offThreadCompileToStencil("saveStack().column", { columnNumber: Math.pow(2,30) });
+ assertThrowsInstanceOf(() => {
+ var stencil = finishOffThreadStencil();
+ evalStencil();
+ }, RangeError);
+
+ print("offThreadCompileToStencil 3");
+ offThreadCompileToStencil("saveStack().column", { columnNumber: 10000 });
+ stencil = finishOffThreadStencil();
+ assertEq(evalStencil(stencil), 10000);
+}
+
+// Check handling of columns near the limit of our ability to represent them.
+// (This is hardly thorough, but since web content can't set column numbers,
+// it's probably not worth it to be thorough.)
+const maxColumn = Math.pow(2, 30) - 2;
+assertEq(evaluate("saveStack().column", { columnNumber: maxColumn }),
+ maxColumn);
+
+// Check the saturation behavior when we reach the limit of the column
+// representation.
+assertEq(evaluate(" saveStack().column", { columnNumber: maxColumn }),
+ maxColumn + 1);
+
+// Gathering source text for inclusion in error messages should not try to reach
+// outside the buffer to find the start of the source line. The below should
+// report the error without crashing.
+assertThrowsInstanceOf(() => evaluate("function x(y,y) { 'use strict'; } x()",
+ { columnNumber: 10 }),
+ SyntaxError);
diff --git a/js/src/jit-test/tests/parser/compile-script.js b/js/src/jit-test/tests/parser/compile-script.js
new file mode 100644
index 0000000000..293d25632e
--- /dev/null
+++ b/js/src/jit-test/tests/parser/compile-script.js
@@ -0,0 +1,50 @@
+// |jit-test| skip-if: !('oomTest' in this)
+
+load(libdir + "asserts.js");
+
+let stencil = compileToStencil('314;');
+assertEq(evalStencil(stencil), 314);
+
+stencil = compileToStencil('let o = { a: 42, b: 2718 }["b"]; o', { prepareForInstantiate: true });
+assertEq(evalStencil(stencil), 2718);
+
+assertThrowsInstanceOf(() => compileToStencil('let fail ='), SyntaxError);
+assertThrowsInstanceOf(() => compileToStencil('42;', 42), Error);
+
+oomTest(function() {
+ compileToStencil('"hello stencil!";', { prepareForInstantiate: false });
+});
+
+oomTest(function() {
+ compileToStencil('"hello stencil!";', { prepareForInstantiate: true });
+});
+
+// Modules
+function compileAndEvaluateModule(script, options) {
+ if (!options) {
+ options = {};
+ }
+ options.module = true;
+ let stencil = compileToStencil(script, options);
+ let m = instantiateModuleStencil(stencil);
+ moduleLink(m);
+ moduleEvaluate(m);
+ return m;
+}
+
+var m = compileAndEvaluateModule('export let r = 314;');
+assertEq(getModuleEnvironmentValue(m, "r"), 314);
+
+m = compileAndEvaluateModule('export let r = { a: 42, b: 2718 }["b"];', { prepareForInstantiate: true });
+assertEq(getModuleEnvironmentValue(m, "r"), 2718);
+
+assertThrowsInstanceOf(() => compileAndEvaluateModule('let fail ='), SyntaxError);
+assertThrowsInstanceOf(() => compileToStencil('42;', 42), Error);
+
+oomTest(function() {
+ compileAndEvaluateModule('export let r = "hello stencil!";', { prepareForInstantiate: false });
+});
+
+oomTest(function() {
+ compileAndEvaluateModule('export let r = "hello stencil!";', { prepareForInstantiate: true });
+});
diff --git a/js/src/jit-test/tests/parser/dumpStencil-01.js b/js/src/jit-test/tests/parser/dumpStencil-01.js
new file mode 100644
index 0000000000..5c06d579c0
--- /dev/null
+++ b/js/src/jit-test/tests/parser/dumpStencil-01.js
@@ -0,0 +1,24 @@
+dumpStencil("a");
+dumpStencil("ab");
+dumpStencil("abc");
+dumpStencil("/a/");
+dumpStencil("/ab/");
+dumpStencil("/abc/");
+dumpStencil("1");
+dumpStencil("1.2");
+dumpStencil("true");
+dumpStencil("[]");
+dumpStencil("[1]");
+dumpStencil("[1, 2]");
+dumpStencil("({})");
+dumpStencil("({x: 10})");
+dumpStencil("({x: a})");
+dumpStencil("({x:10, y: 20})");
+dumpStencil("({x:10, y: a})");
+dumpStencil("({x:10, [y]: a})");
+dumpStencil("function y() {}");
+dumpStencil("(function y() {})");
+dumpStencil("(function() {})");
+dumpStencil("1n");
+dumpStencil("100n");
+dumpStencil("export var z;", { module : true });
diff --git a/js/src/jit-test/tests/parser/fold-constant-index-access.js b/js/src/jit-test/tests/parser/fold-constant-index-access.js
new file mode 100644
index 0000000000..eabe2c5787
--- /dev/null
+++ b/js/src/jit-test/tests/parser/fold-constant-index-access.js
@@ -0,0 +1,47 @@
+// Constant folding optimizes the element access with string that contains
+// 32-bit unsignned integer.
+// The result shouldn't be visible to the script, and the optimization shouldn't
+// change the behavior.
+
+// Asserts that the property name and the value are same.
+var validator = new Proxy({}, {
+ set(that, prop, value) {
+ assertEq(prop, value);
+ }
+});
+
+// Optimizable cases.
+validator["0"] = "0";
+validator["1"] = "1";
+validator["10"] = "10";
+validator["123"] = "123";
+
+// Not optimizable cases.
+
+// More than UINT32_MAX.
+validator["4294967296"] = "4294967296";
+validator["10000000000000"] = "10000000000000";
+
+// Leading 0.
+validator["01"] = "01";
+validator["0000001"] = "0000001";
+
+// Sign.
+validator["+1"] = "+1";
+validator["-1"] = "-1";
+
+// Non-decimal
+validator["0b1"] = "0b1";
+validator["0o1"] = "0o1";
+validator["0x1"] = "0x1";
+
+// Non-integer.
+validator["1.1"] = "1.1";
+validator["1."] = "1.";
+validator[".1"] = ".1";
+validator["0.1"] = "0.1";
+
+// Extra character.
+validator["1a"] = "1a";
+validator["1 "] = "1 ";
+validator[" 1"] = " 1";
diff --git a/js/src/jit-test/tests/parser/home-object-getter.js b/js/src/jit-test/tests/parser/home-object-getter.js
new file mode 100644
index 0000000000..d4ee62acc9
--- /dev/null
+++ b/js/src/jit-test/tests/parser/home-object-getter.js
@@ -0,0 +1,4 @@
+var o = {get a() {
+ return eval("5");
+}}
+assertEq(o.a, 5);
diff --git a/js/src/jit-test/tests/parser/lazy-flag-consistency.js b/js/src/jit-test/tests/parser/lazy-flag-consistency.js
new file mode 100644
index 0000000000..06096beaa6
--- /dev/null
+++ b/js/src/jit-test/tests/parser/lazy-flag-consistency.js
@@ -0,0 +1,65 @@
+// These tests highlight potential differences between the lazy and non-lazy
+// parse modes. The delazification process should be able to assert that script
+// flags are consistent.
+
+function dead_inner_function_1() {
+ (function() {})
+}
+dead_inner_function_1();
+
+function dead_inner_function_2() {
+ if (false) {
+ function inner() {}
+ }
+}
+dead_inner_function_2();
+
+function inner_eval_1() {
+ eval("");
+}
+inner_eval_1();
+
+function inner_eval_2() {
+ (function() {
+ eval("");
+ })
+}
+inner_eval_2();
+
+function inner_eval_3() {
+ (() => eval(""));
+}
+inner_eval_3();
+
+function inner_delete_1() {
+ var x;
+ (function() { delete x; })
+}
+inner_delete_1();
+
+function inner_delete_2() {
+ var x;
+ (() => delete x);
+}
+inner_delete_2();
+
+function inner_this_1() {
+ (() => this);
+}
+inner_this_1();
+
+function inner_arguments_1() {
+ (() => arguments);
+}
+inner_arguments_1();
+
+function constructor_wrapper_1() {
+ return (function() {
+ this.initialize.apply(this, arguments);
+ });
+}
+constructor_wrapper_1();
+
+var runonce_lazy_1 = function (){}();
+
+var runonce_lazy_2 = function* (){}();
diff --git a/js/src/jit-test/tests/parser/lazy-parse-bad-offset.js b/js/src/jit-test/tests/parser/lazy-parse-bad-offset.js
new file mode 100644
index 0000000000..676fcd75cb
--- /dev/null
+++ b/js/src/jit-test/tests/parser/lazy-parse-bad-offset.js
@@ -0,0 +1,4 @@
+// Bug 1098132: Shouldn't assert.
+
+function eval() {};
+eval();
diff --git a/js/src/jit-test/tests/parser/let-after-directive.js b/js/src/jit-test/tests/parser/let-after-directive.js
new file mode 100644
index 0000000000..58864ab341
--- /dev/null
+++ b/js/src/jit-test/tests/parser/let-after-directive.js
@@ -0,0 +1,6 @@
+// 'let' after "use strict" directive without semicolon is lexed as TOK_NAME
+// before parsing the directive. 'let' with TOK_NAME should be handled
+// correctly in strict mode.
+
+"use strict"
+let a = 1;
diff --git a/js/src/jit-test/tests/parser/letContextualKeyword.js b/js/src/jit-test/tests/parser/letContextualKeyword.js
new file mode 100644
index 0000000000..8bccfacf0f
--- /dev/null
+++ b/js/src/jit-test/tests/parser/letContextualKeyword.js
@@ -0,0 +1,110 @@
+function expectError(str) {
+ var log = "";
+ try {
+ eval(str);
+ } catch (e) {
+ log += "e";
+ assertEq(e instanceof SyntaxError, true);
+ }
+ assertEq(log, "e");
+}
+
+eval(`let x = 42; assertEq(x, 42);`);
+eval(`var let = 42; assertEq(let, 42);`);
+eval(`let;`);
+eval(`[...let] = [];`);
+eval(`function let() { return 42; } assertEq(let(), 42);`)
+eval(`let {x:x} = {x:42}; assertEq(x, 42);`);
+eval(`let [x] = [42]; assertEq(x, 42);`);
+
+eval(`for (let x in [1]) { assertEq(x, "0"); }`);
+eval(`for (const x in [1]) { assertEq(x, "0"); }`);
+
+eval(`for (let x of [1]) { assertEq(x, 1); }`);
+eval(`for (const x of [1]) { assertEq(x, 1); }`);
+
+eval(`for (let i = 0; i < 1; i++) { assertEq(i, 0); }`);
+eval(`var done = false; for (const i = 0; !done; done = true) { assertEq(i, 0); }`);
+
+eval(`for (let of of [1]) { assertEq(of, 1); }`);
+eval(`for (const of of [1]) { assertEq(of, 1); }`);
+
+eval(`try { throw 17; } catch (let) { assertEq(let, 17); }`);
+eval(`try { throw [17]; } catch ([let]) { assertEq(let, 17); }`);
+eval(`try { throw { x: 17 }; } catch ({ x: let }) { assertEq(let, 17); }`);
+eval(`try { throw {}; } catch ({ x: let = 17 }) { assertEq(let, 17); }`);
+
+expectError(`try { throw [17, 42]; } catch ([let, let]) {}`);
+
+eval(`for (let in [1]) { assertEq(let, "0"); }`);
+eval(`for (let / 1; ; ) { break; }`);
+expectError(`let = {}; for (let.x of;;);`);
+expectError(`for (let of [1]) { }`);
+
+expectError(`for (let let in [1]) { }`);
+expectError(`for (const let in [1]) { }`);
+
+expectError(`for (let let of [1]) { }`);
+expectError(`for (const let of [1]) { }`);
+
+expectError(`for (let let = 17; false; ) { }`);
+expectError(`for (const let = 17; false; ) { }`);
+
+expectError(`for (let [let] = 17; false; ) { }`);
+expectError(`for (const [let] = 17; false; ) { }`);
+
+expectError(`for (let [let = 42] = 17; false; ) { }`);
+expectError(`for (const [let = 42] = 17; false; ) { }`);
+
+expectError(`for (let { x: let } = 17; false; ) { }`);
+expectError(`for (const { x: let } = 17; false; ) { }`);
+
+expectError(`for (let { x: let = 42 } = 17; false; ) { }`);
+expectError(`for (const { x: let = 42 } = 17; false; ) { }`);
+
+expectError("let\nlet;");
+expectError("const\nlet;");
+
+expectError(`let let = 17;`);
+expectError(`const let = 17;`);
+
+expectError(`let [let] = 17;`);
+expectError(`const [let] = 17;`);
+
+expectError(`let [let = 42] = 17;`);
+expectError(`const [let = 42] = 17;`);
+
+expectError(`let {let} = 17;`);
+expectError(`const {let} = 17;`);
+
+expectError(`let { let = 42 } = 17;`);
+expectError(`const { let = 42 } = 17;`);
+
+expectError(`let { x: let } = 17;`);
+expectError(`const { x: let } = 17;`);
+
+expectError(`let { x: let = 42 } = 17;`);
+expectError(`const { x: let = 42 } = 17;`);
+
+expectError(`let { ['y']: let } = 17;`);
+expectError(`const { ['y']: let } = 17;`);
+
+expectError(`let { ['y']: let = 42 } = 17;`);
+expectError(`const { ['y']: let = 42 } = 17;`);
+
+expectError(`let { x: [let] } = { x: 17 };`);
+expectError(`const { x: [let] } = { x: 17 };`);
+
+expectError(`let { x: [let = 42] } = { x: 17 };`);
+expectError(`const { x: [let = 42] } = { x: 17 };`);
+
+expectError(`let [foo, let] = 42;`);
+expectError(`const [foo, let] = 42;`);
+
+expectError(`let [foo, { let }] = [17, {}];`);
+expectError(`const [foo, { let }] = [17, {}];`);
+
+expectError(`"use strict"; var let = 42;`);
+expectError(`"use strict"; function let() {}`);
+expectError(`"use strict"; for (let of [1]) {}`);
+expectError(`"use strict"; try {} catch (let) {}`);
diff --git a/js/src/jit-test/tests/parser/lineNumber.js b/js/src/jit-test/tests/parser/lineNumber.js
new file mode 100644
index 0000000000..f86efbc03e
--- /dev/null
+++ b/js/src/jit-test/tests/parser/lineNumber.js
@@ -0,0 +1,37 @@
+
+// Simple tests for evaluate's "lineNumber" option.
+
+load(libdir + 'asserts.js');
+
+const maxLine = Math.pow(2,32) - 1;
+
+assertEq(evaluate("saveStack().line"), 1);
+assertEq(evaluate("saveStack().line", { lineNumber: maxLine }), maxLine);
+assertEq(evaluate("\nsaveStack().line"), 2);
+assertEq(evaluate("\nsaveStack().line", { lineNumber: 1000 }), 1001);
+assertThrowsInstanceOf(() => evaluate("\nsaveStack().line", { lineNumber: maxLine }),
+ RangeError);
+
+if (helperThreadCount() > 0) {
+ offThreadCompileToStencil("saveStack().line");
+ var stencil = finishOffThreadStencil();
+ assertEq(evalStencil(stencil), 1);
+
+ offThreadCompileToStencil("saveStack().line", { lineNumber: maxLine });
+ stencil = finishOffThreadStencil();
+ assertEq(evalStencil(stencil), maxLine);
+
+ offThreadCompileToStencil("\nsaveStack().line");
+ stencil = finishOffThreadStencil();
+ assertEq(evalStencil(stencil), 2);
+
+ offThreadCompileToStencil("\nsaveStack().line", { lineNumber: 1000 });
+ stencil = finishOffThreadStencil();
+ assertEq(evalStencil(stencil), 1001);
+
+ offThreadCompileToStencil("\nsaveStack().line", { lineNumber: maxLine });
+ assertThrowsInstanceOf(() => {
+ stencil = finishOffThreadStencil();
+ evalStencil(stencil);
+ }, RangeError);
+}
diff --git a/js/src/jit-test/tests/parser/missing-closing-brace.js b/js/src/jit-test/tests/parser/missing-closing-brace.js
new file mode 100644
index 0000000000..53fede80af
--- /dev/null
+++ b/js/src/jit-test/tests/parser/missing-closing-brace.js
@@ -0,0 +1,90 @@
+function test(source, [lineNumber, columnNumber], openType = "{", closeType = "}") {
+ let caught = false;
+ try {
+ Reflect.parse(source, { source: "foo.js" });
+ } catch (e) {
+ assertEq(e.message.includes("missing " + closeType + " "), true);
+ let notes = getErrorNotes(e);
+ assertEq(notes.length, 1);
+ let note = notes[0];
+ assertEq(note.message, openType + " opened at line " + lineNumber + ", column " + columnNumber);
+ assertEq(note.fileName, "foo.js");
+ assertEq(note.lineNumber, lineNumber);
+ assertEq(note.columnNumber, columnNumber);
+ caught = true;
+ }
+ assertEq(caught, true);
+}
+
+// Function
+
+test(`
+function test1() {
+}
+function test2() {
+ if (true) {
+ //}
+}
+function test3() {
+}
+`, [4, 18]);
+
+// Block statement.
+test(`
+{
+ if (true) {
+}
+`, [2, 1]);
+test(`
+if (true) {
+ if (true) {
+}
+`, [2, 11]);
+test(`
+for (;;) {
+ if (true) {
+}
+`, [2, 10]);
+test(`
+while (true) {
+ if (true) {
+}
+`, [2, 14]);
+test(`
+do {
+ do {
+} while(true);
+`, [2, 4]);
+
+// try-catch-finally.
+test(`
+try {
+ if (true) {
+}
+`, [2, 5]);
+test(`
+try {
+} catch (e) {
+ if (true) {
+}
+`, [3, 13]);
+test(`
+try {
+} finally {
+ if (true) {
+}
+`, [3, 11]);
+
+// Object literal.
+test(`
+var x = {
+ foo: {
+};
+`, [2, 9]);
+
+// Array literal.
+test(`
+var x = [
+ [
+];
+`, [2, 9], "[", "]");
diff --git a/js/src/jit-test/tests/parser/modifier-arrow-rest.js b/js/src/jit-test/tests/parser/modifier-arrow-rest.js
new file mode 100644
index 0000000000..e66aa5c37d
--- /dev/null
+++ b/js/src/jit-test/tests/parser/modifier-arrow-rest.js
@@ -0,0 +1,11 @@
+load(libdir + "syntax.js");
+
+var postfixes = [
+ "...foo) => 1 @",
+];
+
+function check_syntax_error(e, code) {
+ assertEq(e instanceof SyntaxError, true);
+}
+
+test_syntax(postfixes, check_syntax_error, true);
diff --git a/js/src/jit-test/tests/parser/modifier-do-while.js b/js/src/jit-test/tests/parser/modifier-do-while.js
new file mode 100644
index 0000000000..9fa9b06dfe
--- /dev/null
+++ b/js/src/jit-test/tests/parser/modifier-do-while.js
@@ -0,0 +1,12 @@
+do 1
+while(false);
+
+do if (1) {
+} while(false);
+
+do if (1) 1
+while(false);
+
+do try {
+} catch(ex) {
+} while(false);
diff --git a/js/src/jit-test/tests/parser/modifier-regexp-vs-div.js b/js/src/jit-test/tests/parser/modifier-regexp-vs-div.js
new file mode 100644
index 0000000000..7754bcb191
--- /dev/null
+++ b/js/src/jit-test/tests/parser/modifier-regexp-vs-div.js
@@ -0,0 +1,12 @@
+load(libdir + "syntax.js");
+
+var postfixes = [
+ "/bar/g; @",
+ "\n/bar/g; @",
+];
+
+function check_syntax_error(e, code) {
+ assertEq(e instanceof SyntaxError, true);
+}
+
+test_syntax(postfixes, check_syntax_error, true);
diff --git a/js/src/jit-test/tests/parser/modifier-semicolon-insertion.js b/js/src/jit-test/tests/parser/modifier-semicolon-insertion.js
new file mode 100644
index 0000000000..5a5dfee0f2
--- /dev/null
+++ b/js/src/jit-test/tests/parser/modifier-semicolon-insertion.js
@@ -0,0 +1,48 @@
+Reflect.parse(`
+let a
+f2()
+`);
+Reflect.parse(`
+let a=1
+f2()
+`);
+Reflect.parse(`
+import 'a'
+f2()
+`, {target: "module"});
+Reflect.parse(`
+export { a } from 'a'
+f2()
+`, {target: "module"});
+Reflect.parse(`
+var a
+f2()
+`);
+Reflect.parse(`
+var a=1
+f2()
+`);
+Reflect.parse(`
+f1()
+f2()
+`);
+Reflect.parse(`
+while(false) { continue
+f2() }
+`);
+Reflect.parse(`
+while(false) { break
+f2() }
+`);
+Reflect.parse(`
+function a() { return
+f2() }
+`);
+Reflect.parse(`
+throw 1
+f2()
+`);
+Reflect.parse(`
+debugger
+f2()
+`);
diff --git a/js/src/jit-test/tests/parser/modifier-yield-without-operand-1.js b/js/src/jit-test/tests/parser/modifier-yield-without-operand-1.js
new file mode 100644
index 0000000000..635acbe323
--- /dev/null
+++ b/js/src/jit-test/tests/parser/modifier-yield-without-operand-1.js
@@ -0,0 +1,12 @@
+load(libdir + "syntax.js");
+
+var postfixes = [
+ "yield, @",
+ "yield; @",
+];
+
+function check_syntax_error(e, code) {
+ // No need to check exception type
+}
+
+test_syntax(postfixes, check_syntax_error, true);
diff --git a/js/src/jit-test/tests/parser/modifier-yield-without-operand-2.js b/js/src/jit-test/tests/parser/modifier-yield-without-operand-2.js
new file mode 100644
index 0000000000..2b7a8ddedb
--- /dev/null
+++ b/js/src/jit-test/tests/parser/modifier-yield-without-operand-2.js
@@ -0,0 +1,13 @@
+load(libdir + "syntax.js");
+
+var postfixes = [
+ "yield) @",
+ "yield} @",
+ "yield] @",
+];
+
+function check_syntax_error(e, code) {
+ // No need to check exception type
+}
+
+test_syntax(postfixes, check_syntax_error, true);
diff --git a/js/src/jit-test/tests/parser/module-line-0.js b/js/src/jit-test/tests/parser/module-line-0.js
new file mode 100644
index 0000000000..6f905a1070
--- /dev/null
+++ b/js/src/jit-test/tests/parser/module-line-0.js
@@ -0,0 +1,18 @@
+load(libdir + "asserts.js");
+
+compileToStencil("", { lineNumber: 1, module: true });
+assertThrowsInstanceOf(() => {
+ compileToStencil("", { lineNumber: 0, module: true });
+}, Error);
+
+compileToStencilXDR("", { lineNumber: 1, module: true });
+assertThrowsInstanceOf(() => {
+ compileToStencilXDR("", { lineNumber: 0, module: true });
+}, Error);
+
+if (helperThreadCount() > 0) {
+ offThreadCompileModuleToStencil("", { lineNumber: 1, module: true });
+ assertThrowsInstanceOf(() => {
+ offThreadCompileModuleToStencil("", { lineNumber: 0, module: true });
+ }, Error);
+}
diff --git a/js/src/jit-test/tests/parser/off_thread_compile_oom.js b/js/src/jit-test/tests/parser/off_thread_compile_oom.js
new file mode 100644
index 0000000000..5a8e32eb37
--- /dev/null
+++ b/js/src/jit-test/tests/parser/off_thread_compile_oom.js
@@ -0,0 +1,4 @@
+// |jit-test| skip-if: !('oomTest' in this) || helperThreadCount() === 0
+
+// OOM during off-thread initialization shouldn't leak memory.
+eval('oomTest(function(){offThreadCompileToStencil("")})');
diff --git a/js/src/jit-test/tests/parser/off_thread_compile_throws_error.js b/js/src/jit-test/tests/parser/off_thread_compile_throws_error.js
new file mode 100644
index 0000000000..7b4323f908
--- /dev/null
+++ b/js/src/jit-test/tests/parser/off_thread_compile_throws_error.js
@@ -0,0 +1,7 @@
+// |jit-test| skip-if: helperThreadCount() === 0
+
+load(libdir + "asserts.js");
+
+offThreadCompileToStencil("var shouldFailToParse =");
+
+assertThrowsInstanceOf(() => finishOffThreadStencil(), SyntaxError);
diff --git a/js/src/jit-test/tests/parser/oom-tracking-line-starts-in-tokenizer.js b/js/src/jit-test/tests/parser/oom-tracking-line-starts-in-tokenizer.js
new file mode 100644
index 0000000000..46aa1dbd04
--- /dev/null
+++ b/js/src/jit-test/tests/parser/oom-tracking-line-starts-in-tokenizer.js
@@ -0,0 +1,143 @@
+// Constraints on this test's appearance:
+//
+// * |TokenStream::SourceCoords::add| must try to allocate memory. (This test
+// ensures this happens by making the function below >=128 lines long so
+// that |SourceCoords::lineStartOffsets_| must convert to heap storage. The
+// precise approach doesn't matter.)
+// * That allocation attempt must fail (by forced simulated OOM, here).
+//
+// It'd be nice to build up the function programmatically, but it appears that
+// the above only happens if the provided function has a lazy script. Cursory
+// attempts to relazify |Function("...")| didn't work, so this fuzzer-like
+// version had to be used instead.
+if ("oomTest" in this) {
+ oomTest(function() {
+ try {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ } catch(e) {
+ ;
+ }
+ })
+}
diff --git a/js/src/jit-test/tests/parser/optimized-out-functions.js b/js/src/jit-test/tests/parser/optimized-out-functions.js
new file mode 100644
index 0000000000..10c225d548
--- /dev/null
+++ b/js/src/jit-test/tests/parser/optimized-out-functions.js
@@ -0,0 +1,7 @@
+// Functions optimized out by constant-folding should have correct
+// stencil data.
+// This shouldn't hit any assertion while iterating stencil while instantiation.
+(function() {
+ (function() {
+ });
+});
diff --git a/js/src/jit-test/tests/parser/parse-module.js b/js/src/jit-test/tests/parser/parse-module.js
new file mode 100644
index 0000000000..3303be2253
--- /dev/null
+++ b/js/src/jit-test/tests/parser/parse-module.js
@@ -0,0 +1 @@
+parse("1", {module: true});
diff --git a/js/src/jit-test/tests/parser/parse-non-ascii-latin1.js b/js/src/jit-test/tests/parser/parse-non-ascii-latin1.js
new file mode 100644
index 0000000000..91d0c8bd20
--- /dev/null
+++ b/js/src/jit-test/tests/parser/parse-non-ascii-latin1.js
@@ -0,0 +1,5 @@
+load(libdir + "asserts.js");
+
+parse("10");
+assertThrowsInstanceOf(() => parse("10_"), SyntaxError);
+assertThrowsInstanceOf(() => parse("10_\xff"), SyntaxError);
diff --git a/js/src/jit-test/tests/parser/redeclaration-message.js b/js/src/jit-test/tests/parser/redeclaration-message.js
new file mode 100644
index 0000000000..29de3cf7ba
--- /dev/null
+++ b/js/src/jit-test/tests/parser/redeclaration-message.js
@@ -0,0 +1,10 @@
+var aVar = 56;
+try {
+ console.log(aLet);
+ let aLet = 56;
+ // We cannot add `caught` variable on the toplevel for this testcase.
+ // We use assertEq here to catch non-throwing case.
+ assertEq(true, false);
+} catch (e) {
+ assertEq(e.message, "can't access lexical declaration 'aLet' before initialization");
+}
diff --git a/js/src/jit-test/tests/parser/redeclaration.js b/js/src/jit-test/tests/parser/redeclaration.js
new file mode 100644
index 0000000000..6f019edb07
--- /dev/null
+++ b/js/src/jit-test/tests/parser/redeclaration.js
@@ -0,0 +1,229 @@
+// Error message for redeclaration should show the position where the variable
+// was declared.
+
+const npos = -1;
+
+function test_one(fun, filename, name,
+ [prevLineNumber, prevColumnNumber],
+ [lineNumber, columnNumber]) {
+ let caught = false;
+ try {
+ fun();
+ } catch (e) {
+ assertEq(e.message.includes("redeclaration"), true);
+ assertEq(e.lineNumber, lineNumber);
+ assertEq(e.columnNumber, columnNumber);
+ let notes = getErrorNotes(e);
+ if (prevLineNumber == npos) {
+ assertEq(notes.length, 0);
+ } else {
+ assertEq(notes.length, 1);
+ let note = notes[0];
+ assertEq(note.message,
+ `Previously declared at line ${prevLineNumber}, column ${prevColumnNumber}`);
+ assertEq(note.lineNumber, prevLineNumber);
+ assertEq(note.columnNumber, prevColumnNumber);
+ if (filename)
+ assertEq(note.fileName, filename);
+ }
+ caught = true;
+ }
+ assertEq(caught, true);
+}
+
+function test_parse(source, ...args) {
+ test_one(() => {
+ Reflect.parse(source, { source: "foo.js" });
+ }, "foo.js", ...args);
+}
+
+function test_eval(source, ...args) {
+ test_one(() => {
+ eval(source);
+ }, undefined, ...args);
+}
+
+function test(...args) {
+ test_parse(...args);
+ test_eval(...args);
+}
+
+// let
+
+test(`
+let a, a;
+`, "a", [2, 5], [2, 8]);
+
+test(`
+let a;
+let a;
+`, "a", [2, 5], [3, 5]);
+
+test(`
+let a;
+const a = 1;
+`, "a", [2, 5], [3, 7]);
+
+test(`
+let a;
+var a;
+`, "a", [2, 5], [3, 5]);
+
+test(`
+let a;
+function a() {
+}
+`, "a", [2, 5], [3, 10]);
+
+test(`
+{
+ let a;
+ function a() {
+ }
+}
+`, "a", [3, 7], [4, 12]);
+
+// const
+
+test(`
+const a = 1, a = 2;
+`, "a", [2, 7], [2, 14]);
+
+test(`
+const a = 1;
+const a = 2;
+`, "a", [2, 7], [3, 7]);
+
+test(`
+const a = 1;
+let a;
+`, "a", [2, 7], [3, 5]);
+
+test(`
+const a = 1;
+var a;
+`, "a", [2, 7], [3, 5]);
+
+test(`
+const a = 1;
+function a() {
+}
+`, "a", [2, 7], [3, 10]);
+
+test(`
+{
+ const a = 1;
+ function a() {
+ }
+}
+`, "a", [3, 9], [4, 12]);
+
+// var
+
+test(`
+var a;
+let a;
+`, "a", [2, 5], [3, 5]);
+
+test(`
+var a;
+const a = 1;
+`, "a", [2, 5], [3, 7]);
+
+// function
+
+test(`
+function a() {};
+let a;
+`, "a", [2, 10], [3, 5]);
+
+test(`
+function a() {};
+const a = 1;
+`, "a", [2, 10], [3, 7]);
+
+// Annex B lexical function
+
+test(`
+{
+ function a() {};
+ let a;
+}
+`, "a", [3, 12], [4, 7]);
+
+test(`
+{
+ function a() {};
+ const a = 1;
+}
+`, "a", [3, 12], [4, 9]);
+
+// catch parameter
+
+test(`
+try {
+} catch (a) {
+ let a;
+}
+`, "a", [3, 10], [4, 7]);
+test(`
+try {
+} catch (a) {
+ const a = 1;
+}
+`, "a", [3, 10], [4, 9]);
+
+test(`
+try {
+} catch (a) {
+ function a() {
+ }
+}
+`, "a", [3, 10], [4, 12]);
+
+// parameter
+
+test(`
+function f(a) {
+ let a;
+}
+`, "a", [2, 12], [3, 7]);
+
+test(`
+function f(a) {
+ const a = 1;
+}
+`, "a", [2, 12], [3, 9]);
+
+test(`
+function f([a]) {
+ let a;
+}
+`, "a", [2, 13], [3, 7]);
+
+test(`
+function f({a}) {
+ let a;
+}
+`, "a", [2, 13], [3, 7]);
+
+test(`
+function f(...a) {
+ let a;
+}
+`, "a", [2, 15], [3, 7]);
+
+test(`
+function f(a=1) {
+ let a;
+}
+`, "a", [2, 12], [3, 7]);
+
+// eval
+// We don't have position information at runtime.
+// No note should be shown.
+
+test_eval(`
+let a;
+eval("var a");
+`, "a", [npos, npos], [1, 5]);
diff --git a/js/src/jit-test/tests/parser/regexp-after-do-while.js b/js/src/jit-test/tests/parser/regexp-after-do-while.js
new file mode 100644
index 0000000000..e94f8ac24d
--- /dev/null
+++ b/js/src/jit-test/tests/parser/regexp-after-do-while.js
@@ -0,0 +1,8 @@
+// RegExp after do-while get parsed.
+
+load(libdir + "asserts.js");
+
+assertNoWarning(() => Function("do {} while (true) \n /bar/g"), SyntaxError,
+ "RegExp in next line should be parsed");
+assertNoWarning(() => Function("do {} while (true) /bar/g"), SyntaxError,
+ "RegExp in same line should be parsed");
diff --git a/js/src/jit-test/tests/parser/regexp-after-variable.js b/js/src/jit-test/tests/parser/regexp-after-variable.js
new file mode 100644
index 0000000000..3ba2206c1f
--- /dev/null
+++ b/js/src/jit-test/tests/parser/regexp-after-variable.js
@@ -0,0 +1,8 @@
+// RegExp after variable name get parsed or throws error correctly.
+
+load(libdir + "asserts.js");
+
+assertNoWarning(() => Function("var foo \n /bar/g"), SyntaxError,
+ "RegExp in next line should be parsed");
+assertThrowsInstanceOf(() => Function("var foo /bar/g"), SyntaxError,
+ "RegExp in same line should be error");
diff --git a/js/src/jit-test/tests/parser/regexp-error-location.js b/js/src/jit-test/tests/parser/regexp-error-location.js
new file mode 100644
index 0000000000..0d94cf72ee
--- /dev/null
+++ b/js/src/jit-test/tests/parser/regexp-error-location.js
@@ -0,0 +1,16 @@
+// Check that error location for RegExp points to the actual line/column inside
+// the script instead of inside the pattern.
+var line, column;
+try {
+ eval(`
+
+ /aaa(/;
+123456789;
+`);
+} catch (e) {
+ line = e.lineNumber;
+ column = e.columnNumber;
+}
+
+assertEq(line, 3);
+assertEq(column, 7);
diff --git a/js/src/jit-test/tests/parser/script-source-extent.js b/js/src/jit-test/tests/parser/script-source-extent.js
new file mode 100644
index 0000000000..01624ed143
--- /dev/null
+++ b/js/src/jit-test/tests/parser/script-source-extent.js
@@ -0,0 +1,337 @@
+// |jit-test|
+
+// Test that the sourceStart/sourceEnd values of scripts match the current
+// expectations. These values are internal details and slightly arbitrary so
+// these tests expectations can be updated as needed.
+//
+// We don't check lineno/column here since they are reasonably robustly
+// determined from source start offset.
+
+// We use the Debugger API to introspect locate (possibly hidden) scripts and
+// inspect their internal source coordinates. While we want new globals for each
+// test case, they can share the same debuggee compartment.
+let dbg = new Debugger();
+let debuggeeCompartment = newGlobal({newCompartment: true});
+
+// Some static class field initializer lambdas may be thrown away by GC.
+gczeal(0);
+
+function getScriptSourceExtent(source) {
+ // NOTE: We will _evaluate_ the source below which may introduce dynamic
+ // scripts which are also reported. This is intended so that we may test
+ // those cases too.
+
+ let g = newGlobal({sameCompartmentAs: debuggeeCompartment});
+ dbg.addDebuggee(g);
+
+ g.evaluate(source);
+
+ // Use Debugger.findScripts to locate scripts, including hidden ones that
+ // are implementation details.
+ let scripts = dbg.findScripts();
+
+ // Ignore the top-level script since it may or may not be GC'd and is
+ // otherwise uninteresting to us here.
+ scripts = scripts.filter(script => (script.sourceStart > 0) || script.isFunction);
+
+ // Sanity-check that line/column are consistent with sourceStart. If we need
+ // to test multi-line sources, this will need to be updated.
+ for (let script of scripts) {
+ assertEq(script.startLine, 1);
+ assertEq(script.startColumn, script.sourceStart + 1);
+ }
+
+ // Map each found script to a source extent string.
+ function getExtentString(script) {
+ let start = script.sourceStart;
+ let end = script.sourceStart + script.sourceLength;
+ let length = script.sourceLength;
+
+ let resultLength = source.length;
+ assertEq(start < resultLength, true);
+ assertEq(end <= resultLength, true);
+
+ // The result string takes one of following forms:
+ // ` ^ `, when start == end.
+ // ` ^--^ `, typical case.
+ // ` ^----`, when end == resultLength.
+ let result = " ".repeat(start) + "^";
+ if (end > start) {
+ result += "^".padStart(length, "-");
+ }
+ return result.padEnd(resultLength)
+ .substring(0, resultLength);
+ }
+ let results = scripts.map(getExtentString);
+
+ // Sort results since `findScripts` does not have deterministic ordering.
+ results.sort();
+
+ dbg.removeDebuggee(g);
+
+ return results;
+}
+
+function testSourceExtent(source, ...expectations) {
+ let actual = getScriptSourceExtent(source);
+
+ // Check that strings of each array match. These should have been presorted.
+ assertEq(actual.length, expectations.length);
+ for (let i = 0; i < expectations.length; ++i) {
+ assertEq(actual[i], expectations[i]);
+ }
+}
+
+////////////////////
+
+// Function statements.
+testSourceExtent(`function foo () { }`,
+ ` ^-----`);
+testSourceExtent(`function foo (a) { }`,
+ ` ^------`);
+testSourceExtent(`function foo (a, b) { }`,
+ ` ^---------`);
+
+// Function expressions.
+testSourceExtent(`let foo = function () { }`,
+ ` ^-----`);
+testSourceExtent(`let foo = function (a) { }`,
+ ` ^------`);
+testSourceExtent(`let foo = function (a, b) { }`,
+ ` ^---------`);
+
+// Named function expressions.
+testSourceExtent(`let foo = function bar () { }`,
+ ` ^-----`);
+testSourceExtent(`let foo = function bar (a) { }`,
+ ` ^------`);
+testSourceExtent(`let foo = function bar (a, b) { }`,
+ ` ^---------`);
+
+// Arrow functions.
+testSourceExtent(`let foo = x => { }`,
+ ` ^-------`);
+testSourceExtent(`let foo = x => { };`,
+ ` ^-------^`);
+testSourceExtent(`let foo = () => { }`,
+ ` ^--------`);
+testSourceExtent(`let foo = (a, b) => { }`,
+ ` ^------------`);
+testSourceExtent(`let foo = x => x`,
+ ` ^-----`);
+testSourceExtent(`let foo = () => 0`,
+ ` ^------`);
+
+// Async / Generator functions.
+testSourceExtent(`function * foo () { }`,
+ ` ^-----`);
+testSourceExtent(`async function foo () { }`,
+ ` ^-----`);
+testSourceExtent(`async function * foo () { }`,
+ ` ^-----`);
+
+// Async arrow functions.
+testSourceExtent(`let foo = async x => { }`,
+ ` ^-------`);
+testSourceExtent(`let foo = async () => { }`,
+ ` ^--------`);
+
+// Basic inner functions.
+testSourceExtent(`function foo() { function bar () {} }`,
+ ` ^----^ `,
+ ` ^------------------------`);
+
+// Default parameter expressions.
+// NOTE: Arrow function parser back-tracking may generate multiple scripts for
+// the same source text. Delazification expects these copies to have correct
+// range information for `skipInnerLazyFunction` to work. If syntax parsing is
+// disabled (such as for coverage builds), these extra functions are not
+// generated.
+if (!isLcovEnabled()) {
+ testSourceExtent(`function foo(a = b => c) {}`,
+ ` ^-----^ `,
+ ` ^--------------`);
+ testSourceExtent(`let foo = (a = (b = c => 1) => 2) => 3;`,
+ ` ^-----^ `,
+ ` ^----------------^ `,
+ ` ^---------------------------^`);
+}
+
+// Object methods, getters, setters.
+testSourceExtent(`let obj = { x () {} };`,
+ ` ^----^ `);
+testSourceExtent(`let obj = { * x () {} };`,
+ ` ^----^ `);
+testSourceExtent(`let obj = { async x () {} };`,
+ ` ^----^ `);
+testSourceExtent(`let obj = { async * x () {} };`,
+ ` ^----^ `);
+testSourceExtent(`let obj = { get x () {} };`,
+ ` ^----^ `);
+testSourceExtent(`let obj = { set x (v) {} };`,
+ ` ^-----^ `);
+testSourceExtent(`let obj = { x: function () {} };`,
+ ` ^----^ `);
+testSourceExtent(`let obj = { x: y => z };`,
+ ` ^-----^ `);
+
+// Classes without user-defined constructors.
+testSourceExtent(` class C { } `,
+ ` ^----------^`);
+testSourceExtent(` let C = class { } `,
+ ` ^--------^`);
+testSourceExtent(` class C { }; class D extends C { } `,
+ ` ^--------------------^`,
+ ` ^----------^ `);
+testSourceExtent(` class C { }; let D = class extends C { } `,
+ ` ^------------------^`,
+ ` ^----------^ `);
+testSourceExtent(`let C = class extends class { } { }`,
+ ` ^--------^ `,
+ ` ^--------------------------`);
+
+// Classes with user-defined constructors.
+testSourceExtent(` class C { constructor() { } } `,
+ ` ^-----^ `);
+testSourceExtent(` let C = class { constructor() { } } `,
+ ` ^-----^ `);
+testSourceExtent(` class C { }; class D extends C { constructor() { } } `,
+ ` ^-----^ `,
+ ` ^----------^ `);
+testSourceExtent(` class C { }; let D = class extends C { constructor() { } } `,
+ ` ^-----^ `,
+ ` ^----------^ `);
+testSourceExtent(`let C = class extends class { } { constructor() { } }`,
+ ` ^-----^ `,
+ ` ^--------^ `);
+
+// Class field initializers lambdas.
+// NOTE: These are an implementation detail and may be optimized away in future.
+testSourceExtent(`class C { field }`,
+ ` ^----^ `,
+ `^----------------`);
+testSourceExtent(`class C { field; }`,
+ ` ^----^ `,
+ `^-----------------`);
+testSourceExtent(`class C { "field" }`,
+ ` ^------^ `,
+ `^------------------`);
+testSourceExtent(`class C { 0 }`,
+ ` ^^ `,
+ `^------------`);
+testSourceExtent(`class C { [1n] }`,
+ ` ^---^ `,
+ `^---------------`);
+testSourceExtent(`class C { field = 1 }`,
+ ` ^--------^ `,
+ `^--------------------`);
+testSourceExtent(`class C { "field" = 1 }`,
+ ` ^----------^ `,
+ `^----------------------`);
+testSourceExtent(`class C { 0 = 1 }`,
+ ` ^----^ `,
+ `^----------------`);
+testSourceExtent(`class C { [1n] = 1}`,
+ ` ^-------^`,
+ `^------------------`);
+
+// Static class field initializer lambdas.
+// NOTE: These are an implementation detail and may be optimized away in future.
+testSourceExtent(`class C { static field }`,
+ ` ^----^ `,
+ `^-----------------------`);
+testSourceExtent(`class C { static field; }`,
+ ` ^----^ `,
+ `^------------------------`);
+testSourceExtent(`class C { static field = 1 }`,
+ ` ^--------^ `,
+ `^---------------------------`);
+testSourceExtent(`class C { static [0] = 1 }`,
+ ` ^------^ `,
+ `^-------------------------`);
+
+// Static class methods, getters, setters.
+testSourceExtent(`class C { static mtd() {} }`,
+ ` ^----^ `,
+ `^--------------------------`);
+testSourceExtent(`class C { static * mtd() {} }`,
+ ` ^----^ `,
+ `^----------------------------`);
+testSourceExtent(`class C { static async mtd() {} }`,
+ ` ^----^ `,
+ `^--------------------------------`);
+testSourceExtent(`class C { static async * mtd() {} }`,
+ ` ^----^ `,
+ `^----------------------------------`);
+testSourceExtent(`class C { static get prop() {} }`,
+ ` ^----^ `,
+ `^-------------------------------`);
+testSourceExtent(`class C { static get [0]() {} }`,
+ ` ^----^ `,
+ `^------------------------------`);
+testSourceExtent(`class C { static set prop(v) {} }`,
+ ` ^-----^ `,
+ `^--------------------------------`);
+
+// Private class field initializer lambdas.
+// NOTE: These are an implementation detail and may be optimized away in future.
+testSourceExtent(`class C { #field }`,
+ ` ^-----^ `,
+ `^-----------------`);
+testSourceExtent(`class C { #field = 1 }`,
+ ` ^---------^ `,
+ `^---------------------`);
+testSourceExtent(`class C { static #field }`,
+ ` ^-----^ `,
+ `^------------------------`);
+testSourceExtent(`class C { static #field = 1 }`,
+ ` ^---------^ `,
+ `^----------------------------`);
+
+// Private class methods, getters, setters.
+// NOTE: These generate both a field initializer lambda and a method script.
+testSourceExtent(` class C { #field() { } }`,
+ ` ^-----^ `,
+ ` ^-----------------------`);
+testSourceExtent(` class C { get #field() { } }`,
+ ` ^-----^ `,
+ ` ^---------------^ `,
+ ` ^---------------------------`);
+testSourceExtent(` class C { set #field(v) { } }`,
+ ` ^------^ `,
+ ` ^----------------^ `,
+ ` ^----------------------------`);
+testSourceExtent(` class C { * #field() { } }`,
+ ` ^-----^ `,
+ ` ^-------------------------`);
+testSourceExtent(` class C { async #field() { } }`,
+ ` ^-----^ `,
+ ` ^-----------------------------`);
+testSourceExtent(` class C { async * #field() { } }`,
+ ` ^-----^ `,
+ ` ^-------------------------------`);
+
+// Private static class methods.
+testSourceExtent(` class C { static #mtd() { } }`,
+ ` ^-----^ `,
+ ` ^----------------------------`);
+testSourceExtent(` class C { static * #mtd() { } }`,
+ ` ^-----^ `,
+ ` ^------------------------------`);
+testSourceExtent(` class C { static async #mtd() { } }`,
+ ` ^-----^ `,
+ ` ^----------------------------------`);
+testSourceExtent(` class C { static async * #mtd() { } }`,
+ ` ^-----^ `,
+ ` ^------------------------------------`);
+testSourceExtent(` class C { static get #prop() { } }`,
+ ` ^-----^ `,
+ ` ^---------------------------------`);
+testSourceExtent(` class C { static set #prop(v) { } }`,
+ ` ^------^ `,
+ ` ^----------------------------------`);
+
+// Static Class Blocks
+testSourceExtent(` class C { static { 10; } }`,
+ ` ^-------------^ `,
+ ` ^-------------------------`);
diff --git a/js/src/jit-test/tests/parser/standalone-function-name.js b/js/src/jit-test/tests/parser/standalone-function-name.js
new file mode 100644
index 0000000000..e676d7cb9c
--- /dev/null
+++ b/js/src/jit-test/tests/parser/standalone-function-name.js
@@ -0,0 +1,22 @@
+function test(name) {
+ eval(`
+function ${name}(stdlib, foreign, heap) {
+ "use asm";
+ var ffi = foreign.t;
+ return {};
+}
+${name}(15, 10);
+`);
+}
+
+test("as");
+test("async");
+test("await");
+test("each");
+test("from");
+test("get");
+test("let");
+test("of");
+test("set");
+test("static");
+test("target");
diff --git a/js/src/jit-test/tests/parser/stencil-asmjs.js b/js/src/jit-test/tests/parser/stencil-asmjs.js
new file mode 100644
index 0000000000..0379fa05eb
--- /dev/null
+++ b/js/src/jit-test/tests/parser/stencil-asmjs.js
@@ -0,0 +1,28 @@
+// |jit-test| skip-if: isLcovEnabled()
+
+let source = `
+ var m = function() {
+ "use asm"
+ function g(){}
+ return g;
+ }
+
+ function check() {
+ var objM = new m;
+ var g = m();
+ // g is a ctor returning an primitive value, thus an empty object
+ assertEq(Object.getOwnPropertyNames(new g).length, 0);
+ }
+
+ check()
+`;
+
+// Check that on-demand delazification and concurrent delazification are not
+// attempting to parse "use asm" functions.
+const options = {
+ fileName: "tests/asm.js/testBug999790.js",
+ lineNumber: 1,
+ eagerDelazificationStrategy: "CheckConcurrentWithOnDemand",
+ newContext: true,
+};
+evaluate(source, options);
diff --git a/js/src/jit-test/tests/parser/stencil-compile-invalid-argument.js b/js/src/jit-test/tests/parser/stencil-compile-invalid-argument.js
new file mode 100644
index 0000000000..26ed7b9eb4
--- /dev/null
+++ b/js/src/jit-test/tests/parser/stencil-compile-invalid-argument.js
@@ -0,0 +1,14 @@
+// Passing non-object to `options` argument of stencil testing functions should
+// throw.
+
+load(libdir + "asserts.js");
+
+const stencil = compileToStencil("");
+const xdr = compileToStencilXDR("");
+
+for (const arg of [0, 1.1, "foo", true, false, null, Symbol.iterator]) {
+ assertThrowsInstanceOf(() => compileToStencil("", arg), Error);
+ assertThrowsInstanceOf(() => evalStencil(stencil, arg), Error);
+ assertThrowsInstanceOf(() => compileToStencilXDR("", arg), Error);
+ assertThrowsInstanceOf(() => evalStencilXDR(xdr, arg), Error);
+}
diff --git a/js/src/jit-test/tests/parser/stencil-eager-delazify-certviewer.js b/js/src/jit-test/tests/parser/stencil-eager-delazify-certviewer.js
new file mode 100644
index 0000000000..ddd7f32ed4
--- /dev/null
+++ b/js/src/jit-test/tests/parser/stencil-eager-delazify-certviewer.js
@@ -0,0 +1,35 @@
+// |jit-test| skip-if: helperThreadCount() === 0 || isLcovEnabled()
+
+const eagerOptions = {
+ fileName: "certViewer.js",
+ lineNumber: 1,
+ eagerDelazificationStrategy: "OnDemandOnly",
+};
+
+const concurrentOptions = {
+ fileName: "certViewer.js",
+ lineNumber: 1,
+ eagerDelazificationStrategy: "ConcurrentDepthFirst",
+};
+
+// Check that `undefined` is properly resolved to the global scope.
+let script = `
+function certDecoderInitializer() {
+ return undefined;
+}
+
+let result = certDecoderInitializer();
+export { result };
+`;
+
+function evalModule(source, opts) {
+ let job = offThreadCompileModuleToStencil(source, opts);
+ let stencil = finishOffThreadStencil(job);
+ let m = instantiateModuleStencil(stencil);
+ moduleLink(m);
+ moduleEvaluate(m)
+ return m.result;
+}
+
+assertEq(evalModule(script, eagerOptions), undefined);
+assertEq(evalModule(script, concurrentOptions), undefined);
diff --git a/js/src/jit-test/tests/parser/stencil-eager-delazify-empty.js b/js/src/jit-test/tests/parser/stencil-eager-delazify-empty.js
new file mode 100644
index 0000000000..3121f5491b
--- /dev/null
+++ b/js/src/jit-test/tests/parser/stencil-eager-delazify-empty.js
@@ -0,0 +1,22 @@
+// |jit-test| skip-if: helperThreadCount() === 0 || isLcovEnabled()
+
+// Extra GCs can empty the StencilCache to reclaim memory. This lines
+// re-configure the gc-zeal setting to prevent this from happening in this test
+// case which waits for the cache to contain some entry.
+if ('gczeal' in this)
+ gczeal(0);
+
+// Generate a source code with no inner functions.
+function justVariables(n) {
+ let text = "";
+ for (let i = 0; i < n; i++) {
+ text += `let v${i} = ${i};`;
+ }
+ return text;
+};
+
+// Create an extra task to test the case where there is nothing to delazify.
+let job = offThreadCompileToStencil(justVariables(10000), options);
+
+const stencil = finishOffThreadStencil(job);
+evalStencil(stencil, options);
diff --git a/js/src/jit-test/tests/parser/stencil-eager-delazify.js b/js/src/jit-test/tests/parser/stencil-eager-delazify.js
new file mode 100644
index 0000000000..d638b16e78
--- /dev/null
+++ b/js/src/jit-test/tests/parser/stencil-eager-delazify.js
@@ -0,0 +1,75 @@
+// |jit-test| skip-if: helperThreadCount() === 0 || isLcovEnabled()
+
+// Extra GCs can empty the StencilCache to reclaim memory. This lines
+// re-configure the gc-zeal setting to prevent this from happening in this test
+// case which waits for the cache to contain some entry.
+if ('gczeal' in this)
+ gczeal(0);
+
+let u = 0;
+
+// At each function, create `width` inner functions.
+let width = 2;
+// Depth of inner functions.
+let depth = 4;
+// Number of additional parser & delazification workload running concurrently
+// with the one we are attempting to measure, such that we can see differences
+// in the report of `isInStencilCache`.
+let load = 14;
+
+// Return the number of function generated by a to `depthFirstExec` given the
+// same parameters.
+function count(w, d) {
+ return (Math.pow(w, d + 1) - 1) / (w - 1);
+}
+
+// Generate a source code with a large number of inner functions, such that
+// eager delazification can be observe while running JS code concurrently.
+function depthFirstExec(indent, name, w, d) {
+ let fun = `${indent}function ${name} (arg) {\n`;
+ let inner = "";
+ let val = `arg + isInStencilCache(${name})`;
+ if (d > 0) {
+ for (let i = 0; i < w; i++) {
+ inner += depthFirstExec(`${indent} `, `${name}_${i}`, w, d - 1);
+ val = `${name}_${i}(${val})`;
+ }
+ }
+ fun += inner;
+ fun += `${indent} return ${u} + ${val} - ${u};\n`;
+ fun += `${indent}}\n`;
+ u += 1;
+ return fun;
+};
+
+const options = {
+ fileName: "depthFirstExec.js",
+ lineNumber: 1,
+ eagerDelazificationStrategy: "ConcurrentDepthFirst",
+};
+let script = depthFirstExec("", "raceMe", width, depth);
+
+let jobs = [];
+for (let i = 0; i < load; i++) {
+ // Spin up extra compilation workload...
+ jobs.push(offThreadCompileToStencil(script, options));
+}
+
+const stencil = finishOffThreadStencil(jobs[0]);
+evalStencil(stencil, options);
+
+waitForStencilCache(raceMe);
+let start = raceMe(0);
+let mid = raceMe(0);
+let end = raceMe(0);
+
+// The garbage collector should clear the cache and suppress all delazification
+// tasks.
+gc();
+let afterGc = raceMe(0);
+
+assertEq(1 <= start, true);
+assertEq(start <= mid, true);
+assertEq(mid <= end, true);
+assertEq(end <= count(width, depth), true);
+assertEq(afterGc, 0);
diff --git a/js/src/jit-test/tests/parser/stencil-laziness-validate.js b/js/src/jit-test/tests/parser/stencil-laziness-validate.js
new file mode 100644
index 0000000000..78bcb80910
--- /dev/null
+++ b/js/src/jit-test/tests/parser/stencil-laziness-validate.js
@@ -0,0 +1,29 @@
+// |jit-test| skip-if: isLcovEnabled()
+
+load(libdir + "asserts.js");
+
+const gWithSource = newGlobal({discardSource: false});
+const gWithoutSource = newGlobal({discardSource: true});
+
+const stencil = compileToStencil("");
+
+gWithSource.evalStencil(stencil);
+assertThrowsInstanceOf(() => gWithoutSource.evalStencil(stencil), gWithoutSource.Error);
+
+const xdr = compileToStencilXDR("");
+gWithSource.evalStencilXDR(xdr);
+assertThrowsInstanceOf(() => gWithoutSource.evalStencilXDR(xdr), gWithoutSource.Error);
+
+const code = cacheEntry("");
+
+evaluate(code, { global: gWithSource, saveIncrementalBytecode: true});
+evaluate(code, { global: gWithSource, loadBytecode: true});
+assertThrowsInstanceOf(() => evaluate(code, { global: gWithoutSource, loadBytecode: true}), gWithoutSource.Error);
+
+const moduleStencil = compileToStencil("", { module: true });
+gWithSource.instantiateModuleStencil(moduleStencil);
+assertThrowsInstanceOf(() => gWithoutSource.instantiateModuleStencil(moduleStencil), gWithoutSource.Error);
+
+const moduleXDR = compileToStencilXDR("", { module: true });
+gWithSource.instantiateModuleStencilXDR(moduleXDR);
+assertThrowsInstanceOf(() => gWithoutSource.instantiateModuleStencilXDR(moduleXDR), gWithoutSource.Error);
diff --git a/js/src/jit-test/tests/parser/stencil-scope.js b/js/src/jit-test/tests/parser/stencil-scope.js
new file mode 100644
index 0000000000..0dc562147a
--- /dev/null
+++ b/js/src/jit-test/tests/parser/stencil-scope.js
@@ -0,0 +1,134 @@
+const optionsFull = {
+ fileName: "compileToStencil-DATA.js",
+ lineNumber: 1,
+ eagerDelazificationStrategy: "ParseEverythingEagerly",
+};
+
+const optionsLazy = {
+ fileName: "compileToStencil-DATA.js",
+ lineNumber: 1,
+ eagerDelazificationStrategy: "OnDemandOnly",
+};
+
+const optionsLazyCache = {
+ fileName: "compileToStencil-DATA.js",
+ lineNumber: 1,
+ eagerDelazificationStrategy: "ConcurrentDepthFirst",
+};
+
+const optionsLazyCache2 = {
+ fileName: "compileToStencil-DATA.js",
+ lineNumber: 1,
+ eagerDelazificationStrategy: "ConcurrentLargeFirst",
+};
+
+let result = 0;
+
+function testMainThread(script_str) {
+ const stencil = compileToStencil(script_str, optionsFull);
+ result = evalStencil(stencil, optionsFull);
+ assertEq(result, 1);
+}
+
+function testMainThreadDelazifyAll(script_str) {
+ if (isLcovEnabled()) {
+ // Code-coverage implies forceFullParse = true, and as such it cannot be
+ // used while testing to incrementally delazify.
+ return;
+ }
+ const stencil = compileToStencil(script_str, optionsLazy);
+ result = evalStencil(stencil, optionsLazy);
+ assertEq(result, 1);
+}
+
+function testMainThreadCacheAll(script_str) {
+ if (isLcovEnabled() || helperThreadCount() === 0) {
+ // Code-coverage implies forceFullParse = true, and as such it cannot be
+ // used while testing to incrementally delazify.
+ // Similarly, concurrent delazification requires off-threads processing.
+ return;
+ }
+ const stencil = compileToStencil(script_str, optionsLazyCache);
+ result = evalStencil(stencil, optionsLazyCache);
+ assertEq(result, 1);
+}
+
+function testMainThreadCacheAll2(script_str) {
+ if (isLcovEnabled() || helperThreadCount() === 0) {
+ // Code-coverage implies forceFullParse = true, and as such it cannot be
+ // used while testing to incrementally delazify.
+ // Similarly, concurrent delazification requires off-threads processing.
+ return;
+ }
+ const stencil = compileToStencil(script_str, optionsLazyCache2);
+ result = evalStencil(stencil, optionsLazyCache2);
+ assertEq(result, 1);
+}
+
+function testOffThread(script_str) {
+ const job = offThreadCompileToStencil(script_str, optionsFull);
+ const stencil = finishOffThreadStencil(job);
+ result = evalStencil(stencil, optionsFull);
+ assertEq(result, 1);
+}
+
+// These patches are meant to wrap the inner code given as argument into one
+// kind of scope. The freeVars specify one way to retrieve the variable name
+// added in this process if any.
+const scopeCases = [
+ { code: inner => `{ ${inner} }`, freeVars: [] },
+ { code: inner => `{ var v = 1; ${inner} }`, freeVars: ["v"] },
+ { code: inner => `{ let l = 1; ${inner} }`, freeVars: ["l"] },
+ { code: inner => `{ const c = 1; ${inner} }`, freeVars: ["c"] },
+ { code: inner => `with ({ p: 1 }) { ${inner} }`, freeVars: ["p"],
+ inClass: false },
+ { code: inner => `(a => { ${inner} })(1)`, freeVars: ["a"] },
+ { code: inner => `function fun(a) { ${inner} }; fun(1)`, freeVars: ["a"],
+ inClass: false},
+ { code: inner => `try { ${inner} } catch(unused) { }`, freeVars: [] },
+ { code: inner => `try { throw 1; } catch(t) { ${inner} }`, freeVars: ["t"] },
+ { code: inner => `{ class C { #m = 1; constructor() { ${inner} }}; new C() }`,
+ freeVars: ["this.#m"], isClass: true },
+];
+
+// This function is used to generate code which mostly exercise the various kind
+// of scopes to cover ScopeContext class in CompilationStencil.h
+function generateCode(seed) {
+ let start = inner => `
+ ${inner};
+ result
+ `;
+
+ let prog = [start];
+ let freeVars = ["1"];
+ let inClass = false;
+
+ while (seed >= freeVars.length) {
+ let index = seed % scopeCases.length;
+ seed = (seed / scopeCases.length) | 0;
+ let scope = scopeCases[index];
+ if (inClass && !(scope.inClass ?? false)) {
+ // Skip illegal code (non-strict) or code which might not accept
+ // this to work.
+ continue;
+ }
+ inClass ||= scope.isClass ?? false;
+ prog.push(scope.code);
+ freeVars = freeVars.concat(scope.freeVars);
+ }
+
+ let name = freeVars[seed];
+ return prog.reduceRight((inner, f) => f(inner), `result = ${name}`);
+}
+
+for (let s = 0; s < 3000; s++) {
+ let code = generateCode(s);
+ // console.log(s, ":", code);
+ testMainThread(code);
+ testMainThreadDelazifyAll(code);
+ testMainThreadCacheAll(code);
+ testMainThreadCacheAll2(code);
+ if (helperThreadCount() > 0) {
+ testOffThread(code);
+ }
+}
diff --git a/js/src/jit-test/tests/parser/stencil.js b/js/src/jit-test/tests/parser/stencil.js
new file mode 100644
index 0000000000..0001ebaca1
--- /dev/null
+++ b/js/src/jit-test/tests/parser/stencil.js
@@ -0,0 +1,111 @@
+const optionsFull = {
+ fileName: "compileToStencil-DATA.js",
+ lineNumber: 1,
+ eagerDelazificationStrategy: "ParseEverythingEagerly",
+};
+
+const optionsLazy = {
+ fileName: "compileToStencil-DATA.js",
+ lineNumber: 1,
+ eagerDelazificationStrategy: "OnDemandOnly",
+};
+
+const optionsLazyCache = {
+ fileName: "compileToStencil-DATA.js",
+ lineNumber: 1,
+ eagerDelazificationStrategy: "ConcurrentDepthFirst",
+};
+
+function testMainThread(script_str) {
+ const eval_f = eval;
+ const stencil = compileToStencil(script_str, optionsFull);
+ const result = evalStencil(stencil, optionsFull);
+ assertEq(result, eval_f(script_str));
+}
+
+function testMainThreadDelazifyAll(script_str) {
+ if (isLcovEnabled()) {
+ // Code-coverage implies forceFullParse = true, and as such it cannot be
+ // used while testing to incrementally delazify.
+ return;
+ }
+ const eval_f = eval;
+ const stencil = compileToStencil(script_str, optionsLazy);
+ const result = evalStencil(stencil, optionsLazy);
+ assertEq(result, eval_f(script_str));
+}
+
+function testMainThreadCacheAll(script_str) {
+ if (isLcovEnabled() || helperThreadCount() === 0) {
+ // Code-coverage implies forceFullParse = true, and as such it cannot be
+ // used while testing to incrementally delazify.
+ // Similarly, concurrent delazification requires off-threads processing.
+ return;
+ }
+ const eval_f = eval;
+ const stencil = compileToStencil(script_str, optionsLazyCache);
+ const result = evalStencil(stencil, optionsLazyCache);
+ assertEq(result, eval_f(script_str));
+}
+
+function testOffThread(script_str) {
+ const eval_f = eval;
+ const job = offThreadCompileToStencil(script_str, optionsFull);
+ const stencil = finishOffThreadStencil(job);
+ const result = evalStencil(stencil, optionsFull);
+ assertEq(result, eval_f(script_str));
+}
+
+testMainThread(`
+var a = 10;
+let b = 20, c = 30;
+const d = 40;
+function f() {
+ return a + b + c + d;
+}
+f();
+`);
+
+testMainThreadDelazifyAll(`
+var a1 = 10;
+let b1 = 20, c1 = 30;
+const d1 = 40;
+function g1() {
+ function h1() {
+ return a1 + b1;
+ }
+ return h1() + c1;
+}
+function f1() {
+ return a1 + b1 + c1 + d1;
+}
+f1();
+`);
+
+testMainThreadCacheAll(`
+var a3 = 10;
+let b3 = 20, c3 = 30;
+const d3 = 40;
+function g3() {
+ function h3() {
+ return a3 + b3;
+ }
+ return h3() + c3;
+}
+function f3() {
+ return a3 + b3 + c3 + d3;
+}
+f3();
+`);
+
+if (helperThreadCount() > 0) {
+ testOffThread(`
+var a2 = 10;
+let b2 = 20, c2 = 30;
+const d2 = 40;
+function f2() {
+ return a2 + b2 + c2 + d2;
+}
+f2();
+`);
+}
diff --git a/js/src/jit-test/tests/parser/strict-with-asi-and-deprecated-octal.js b/js/src/jit-test/tests/parser/strict-with-asi-and-deprecated-octal.js
new file mode 100644
index 0000000000..cb09ac5849
--- /dev/null
+++ b/js/src/jit-test/tests/parser/strict-with-asi-and-deprecated-octal.js
@@ -0,0 +1,4 @@
+// |jit-test| error: SyntaxError
+"use strict"
+010
+
diff --git a/js/src/jit-test/tests/parser/syntax-error-illegal-character.js b/js/src/jit-test/tests/parser/syntax-error-illegal-character.js
new file mode 100644
index 0000000000..03a98122ef
--- /dev/null
+++ b/js/src/jit-test/tests/parser/syntax-error-illegal-character.js
@@ -0,0 +1,22 @@
+load(libdir + "syntax.js");
+
+if (!getBuildConfiguration("decorators")) {
+ function check_syntax_error_at(e, code, name) {
+ assertEq(e instanceof SyntaxError, true, name + ": " + code);
+ assertEq(e.message, "illegal character U+0040", name + ": " + code);
+ }
+ test_syntax(["@"], check_syntax_error_at, false);
+}
+
+function check_syntax_error_ellipsis(e, code, name) {
+ assertEq(e instanceof SyntaxError, true, name + ": " + code);
+ assertEq(e.message, "illegal character U+2026", name + ": " + code);
+}
+test_syntax(["…"], check_syntax_error_ellipsis, false);
+
+function check_syntax_error_clown(e, code, name) {
+ assertEq(e instanceof SyntaxError, true, name + ": " + code);
+ assertEq(e.message, "illegal character U+1F921", name + ": " + code);
+}
+test_syntax(["🤡"], check_syntax_error_clown, false);
+
diff --git a/js/src/jit-test/tests/parser/syntax-parse-error.js b/js/src/jit-test/tests/parser/syntax-parse-error.js
new file mode 100644
index 0000000000..4d13989a1e
--- /dev/null
+++ b/js/src/jit-test/tests/parser/syntax-parse-error.js
@@ -0,0 +1,4 @@
+load(libdir + "asserts.js");
+
+assertThrowsInstanceOf(() => syntaxParse(">"), SyntaxError);
+
diff --git a/js/src/jit-test/tests/parser/truncation.js b/js/src/jit-test/tests/parser/truncation.js
new file mode 100644
index 0000000000..3cfc6e37f6
--- /dev/null
+++ b/js/src/jit-test/tests/parser/truncation.js
@@ -0,0 +1,73 @@
+load(libdir + "asserts.js");
+
+var cases = [
+ "{",
+ "{ ;",
+ "var",
+ "var x,",
+ "var x =",
+ "let x,",
+ "let x =",
+ "const",
+ "const x =",
+ "const x = 1,",
+ "if",
+ "if (",
+ "if (0) ; else",
+ "do",
+ "do ;",
+ "do ; while",
+ "do ; while (",
+ "do ; while (1",
+ "while",
+ "while (",
+ "while (1",
+ "while (1)",
+ "for",
+ "for (",
+ "for (;",
+ "for (;;",
+ "for (;;)",
+ "for (var",
+ "for (x",
+ "for (x in",
+ "for (x in y",
+ "for (x in y)",
+ "for (x of",
+ "for (x of y",
+ "for (x of y)",
+ "switch",
+ "switch (",
+ "switch (x",
+ "switch (x)",
+ "with",
+ "with (",
+ "with (x",
+ "with (x)",
+ "a:",
+ "throw",
+ "try",
+ "try {",
+ "try {} catch",
+ "try {} catch (",
+ "try {} catch (exc",
+ "try {} catch (exc if",
+ "try {} catch (exc if 1",
+ "try {} finally",
+ "try {} finally {",
+
+ "function",
+ "function f",
+ "function f(",
+ "function f()",
+ "function f() {",
+ "(function",
+ "(function f",
+ "(function f(",
+ "(function f()",
+
+];
+
+for (var s of cases)
+ assertThrowsInstanceOf(() => Function(s), SyntaxError);
+
diff --git a/js/src/jit-test/tests/parser/warning-oom.js b/js/src/jit-test/tests/parser/warning-oom.js
new file mode 100644
index 0000000000..baf91cb9c9
--- /dev/null
+++ b/js/src/jit-test/tests/parser/warning-oom.js
@@ -0,0 +1,7 @@
+// |jit-test| skip-if: !('oomTest' in this)
+
+// OOM during reporting warning should be handled.
+
+oomTest(function(){
+ new Function("return; 0;");
+});
diff --git a/js/src/jit-test/tests/parser/yield-in-formal-destructuring.js b/js/src/jit-test/tests/parser/yield-in-formal-destructuring.js
new file mode 100644
index 0000000000..08e4ed5fd8
--- /dev/null
+++ b/js/src/jit-test/tests/parser/yield-in-formal-destructuring.js
@@ -0,0 +1 @@
+function d([{ [yield]: {} } ]) { f }