From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../arrow-function-at-end-of-for-statement-head.js | 64 + .../arrow-function-in-for-statement-head.js | 33 + js/src/tests/non262/statements/browser.js | 0 .../statements/for-in-with-assignment-semantics.js | 46 + .../statements/for-in-with-assignment-syntax.js | 66 + .../non262/statements/for-in-with-assignments.js | 87 + .../non262/statements/for-in-with-declaration.js | 31 + .../for-in-with-destructuring-assignments.js | 130 + .../for-in-with-gc-and-unvisited-deletion.js | 76 + .../for-in-with-gc-during-iterator-init.js | 30 + .../for-inof-coverinitname-destr-assign.js | 55 + js/src/tests/non262/statements/for-inof-finally.js | 78 + .../statements/for-inof-loop-const-declaration.js | 94 + ...e-iteration-expression-contains-index-string.js | 43 + .../for-loop-declaration-contains-computed-name.js | 48 + .../for-loop-declaration-contains-initializer.js | 50 + .../statements/for-of-async-of-starting-lhs.js | 115 + .../statements/for-of-iterator-close-throw.js | 35 + .../non262/statements/for-of-iterator-close.js | 102 + .../non262/statements/for-of-iterator-primitive.js | 28 + .../statements/for-of-var-with-initializer.js | 32 + .../tests/non262/statements/if-constant-folding.js | 35 + .../property-reference-self-assignment.js | 38 + js/src/tests/non262/statements/regress-131348.js | 147 + js/src/tests/non262/statements/regress-157509.js | 74 + js/src/tests/non262/statements/regress-194364.js | 115 + js/src/tests/non262/statements/regress-226517.js | 75 + js/src/tests/non262/statements/regress-302439.js | 1335 +++ js/src/tests/non262/statements/regress-324650.js | 5427 ++++++++++++ js/src/tests/non262/statements/regress-444979.js | 40 + js/src/tests/non262/statements/regress-642975.js | 30 + .../tests/non262/statements/regress-74474-001.js | 102 + .../tests/non262/statements/regress-74474-002.js | 9060 +++++++++++++++++++ .../tests/non262/statements/regress-74474-003.js | 9062 ++++++++++++++++++++ .../tests/non262/statements/regress-83532-001.js | 34 + .../tests/non262/statements/regress-83532-002.js | 37 + js/src/tests/non262/statements/shell.js | 0 .../non262/statements/trailing_comma_parameters.js | 92 + js/src/tests/non262/statements/try-completion.js | 482 ++ 39 files changed, 27428 insertions(+) create mode 100644 js/src/tests/non262/statements/arrow-function-at-end-of-for-statement-head.js create mode 100644 js/src/tests/non262/statements/arrow-function-in-for-statement-head.js create mode 100644 js/src/tests/non262/statements/browser.js create mode 100644 js/src/tests/non262/statements/for-in-with-assignment-semantics.js create mode 100644 js/src/tests/non262/statements/for-in-with-assignment-syntax.js create mode 100644 js/src/tests/non262/statements/for-in-with-assignments.js create mode 100644 js/src/tests/non262/statements/for-in-with-declaration.js create mode 100644 js/src/tests/non262/statements/for-in-with-destructuring-assignments.js create mode 100644 js/src/tests/non262/statements/for-in-with-gc-and-unvisited-deletion.js create mode 100644 js/src/tests/non262/statements/for-in-with-gc-during-iterator-init.js create mode 100644 js/src/tests/non262/statements/for-inof-coverinitname-destr-assign.js create mode 100644 js/src/tests/non262/statements/for-inof-finally.js create mode 100644 js/src/tests/non262/statements/for-inof-loop-const-declaration.js create mode 100644 js/src/tests/non262/statements/for-inof-name-iteration-expression-contains-index-string.js create mode 100644 js/src/tests/non262/statements/for-loop-declaration-contains-computed-name.js create mode 100644 js/src/tests/non262/statements/for-loop-declaration-contains-initializer.js create mode 100644 js/src/tests/non262/statements/for-of-async-of-starting-lhs.js create mode 100644 js/src/tests/non262/statements/for-of-iterator-close-throw.js create mode 100644 js/src/tests/non262/statements/for-of-iterator-close.js create mode 100644 js/src/tests/non262/statements/for-of-iterator-primitive.js create mode 100644 js/src/tests/non262/statements/for-of-var-with-initializer.js create mode 100644 js/src/tests/non262/statements/if-constant-folding.js create mode 100644 js/src/tests/non262/statements/property-reference-self-assignment.js create mode 100644 js/src/tests/non262/statements/regress-131348.js create mode 100644 js/src/tests/non262/statements/regress-157509.js create mode 100644 js/src/tests/non262/statements/regress-194364.js create mode 100644 js/src/tests/non262/statements/regress-226517.js create mode 100644 js/src/tests/non262/statements/regress-302439.js create mode 100644 js/src/tests/non262/statements/regress-324650.js create mode 100644 js/src/tests/non262/statements/regress-444979.js create mode 100644 js/src/tests/non262/statements/regress-642975.js create mode 100644 js/src/tests/non262/statements/regress-74474-001.js create mode 100644 js/src/tests/non262/statements/regress-74474-002.js create mode 100644 js/src/tests/non262/statements/regress-74474-003.js create mode 100644 js/src/tests/non262/statements/regress-83532-001.js create mode 100644 js/src/tests/non262/statements/regress-83532-002.js create mode 100644 js/src/tests/non262/statements/shell.js create mode 100644 js/src/tests/non262/statements/trailing_comma_parameters.js create mode 100644 js/src/tests/non262/statements/try-completion.js (limited to 'js/src/tests/non262/statements') diff --git a/js/src/tests/non262/statements/arrow-function-at-end-of-for-statement-head.js b/js/src/tests/non262/statements/arrow-function-at-end-of-for-statement-head.js new file mode 100644 index 0000000000..9043b818c6 --- /dev/null +++ b/js/src/tests/non262/statements/arrow-function-at-end-of-for-statement-head.js @@ -0,0 +1,64 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var gTestfile = "arrow-function-in-for-statement-head.js"; +var BUGNUMBER = 1302994; +var summary = + "Don't assert when an arrow function occurs at the end of a declaration " + + "init-component of a for(;;) loop head"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function f1() +{ + for (var x = a => b; false; false) + {} +} +f1(); + +function f2() +{ + for (var x = a => b, y = c => d; false; false) + {} +} +f2(); + +function f3() +{ + for (var x = a => {}; false; false) + {} +} +f3(); + +function f4() +{ + for (var x = a => {}, y = b => {}; false; false) + {} +} +f4(); + +function g1() +{ + for (a => b; false; false) + {} +} +g1(); + +function g2() +{ + for (a => {}; false; false) + {} +} +g2(); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/statements/arrow-function-in-for-statement-head.js b/js/src/tests/non262/statements/arrow-function-in-for-statement-head.js new file mode 100644 index 0000000000..4b636d3acf --- /dev/null +++ b/js/src/tests/non262/statements/arrow-function-in-for-statement-head.js @@ -0,0 +1,33 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var gTestfile = "arrow-function-in-for-statement-head.js"; +var BUGNUMBER = 1163851; +var summary = + "|for (x => 0 in 1;;) break;| must be a syntax error per ES6, not an " + + "elaborate nop"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +try +{ + Function("for (x => 0 in 1;;) break;"); + throw new Error("didn't throw"); +} +catch (e) +{ + assertEq(e instanceof SyntaxError, true, + "expected syntax error, got " + e); +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/statements/browser.js b/js/src/tests/non262/statements/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/statements/for-in-with-assignment-semantics.js b/js/src/tests/non262/statements/for-in-with-assignment-semantics.js new file mode 100644 index 0000000000..f1dbb3438f --- /dev/null +++ b/js/src/tests/non262/statements/for-in-with-assignment-semantics.js @@ -0,0 +1,46 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const unreachable = () => { throw "unreachable"; }; + +// var-initializer expression is executed before for-in expression. +var log = ""; +for (var x = (log += "head") in (log += "|expr", null)) unreachable(); +assertEq(log, "head|expr"); + +log = ""; +for (var x = (log += "head") in (log += "|expr", {})) unreachable(); +assertEq(log, "head|expr"); + + +// for-in expression isn't executed when var-initializer throws exception. +function ExpectedError() {} +assertThrowsInstanceOf(() => { + var throwErr = () => { throw new ExpectedError(); }; + for (var x = throwErr() in unreachable()) unreachable(); +}, ExpectedError); + + +// Ensure environment operations are performed correctly. +var scope = new Proxy({x: 0}, new Proxy({}, { + get(t, pk, r) { + log += pk + "|"; + } +})); + +log = ""; +with (scope) { + for (var x = 0 in {}) ; +} +assertEq(log, "has|get|set|getOwnPropertyDescriptor|defineProperty|"); + +log = ""; +with (scope) { + for (var x = 0 in {p: 0}) ; +} +assertEq(log, "has|get|set|getOwnPropertyDescriptor|defineProperty|".repeat(2)); + + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/statements/for-in-with-assignment-syntax.js b/js/src/tests/non262/statements/for-in-with-assignment-syntax.js new file mode 100644 index 0000000000..7540b4bd1b --- /dev/null +++ b/js/src/tests/non262/statements/for-in-with-assignment-syntax.js @@ -0,0 +1,66 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const validSyntax = [ + "var x", +]; + +const destructuring = [ + "[]", + "[,]", + "[a]", + "[a = 0]", + "[...a]", + "[...[]]", + "[...[a]]", + "{}", + "{p: x}", + "{p: x = 0}", + "{x}", + "{x = 0}", +]; + +const invalidSyntax = [ + ...destructuring.map(binding => `var ${binding}`), + "let x", + ...destructuring.map(binding => `let ${binding}`), + "const x", + ...destructuring.map(binding => `const ${binding}`), + "x", + ...destructuring.map(binding => `${binding}`), + "o.p", + "o[0]", + "f()", +]; + +for (let valid of validSyntax) { + Function(`for (${valid} = 0 in {});`); + assertThrowsInstanceOf(() => Function(`"use strict"; for (${valid} = 0 in {});`), + SyntaxError); +} + +for (let invalid of invalidSyntax) { + assertThrowsInstanceOf(() => Function(`for (${invalid} = 0 in {});`), SyntaxError); +} + +// Invalid syntax, needs method context to parse. +assertThrowsInstanceOf(() => Function(`({ m() { for (super.p = 0 in {}); } })`), SyntaxError); +assertThrowsInstanceOf(() => Function(`({ m() { for (super[0] = 0 in {}); } })`), SyntaxError); + +assertThrowsInstanceOf(() => Function(`for (0 = 0 in {});`), SyntaxError); +assertThrowsInstanceOf(() => Function(`for (i++ = 0 in {});`), SyntaxError); +assertThrowsInstanceOf(() => Function(`for (new F() = 0 in {});`), SyntaxError); +assertThrowsInstanceOf(() => Function(`function f() { for (new.target = 0 in {}); }`), SyntaxError); +assertThrowsInstanceOf(() => Function(`class C extends D { constructor() { for (super() = 0 in {}); } }`), SyntaxError); + +// Same as above, only this time don't make it look like we actually parse a for-in statement. +assertThrowsInstanceOf(() => Function(`for (0 = 0 #####`), SyntaxError); +assertThrowsInstanceOf(() => Function(`for (i++ = 0 #####`), SyntaxError); +assertThrowsInstanceOf(() => Function(`for (new F() = 0 #####`), SyntaxError); +assertThrowsInstanceOf(() => Function(`function f() { for (new.target = 0 #####`), SyntaxError); +assertThrowsInstanceOf(() => Function(`class C extends D { constructor() { for (super() = 0 #####`), SyntaxError); + + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/statements/for-in-with-assignments.js b/js/src/tests/non262/statements/for-in-with-assignments.js new file mode 100644 index 0000000000..302be2b42d --- /dev/null +++ b/js/src/tests/non262/statements/for-in-with-assignments.js @@ -0,0 +1,87 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = "for-in-with-assignments.js"; +var BUGNUMBER = 1164741; +var summary = "Parse |for (var ... = ... in ...)|." + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// This is a total grab-bag of junk originally in tests changed when this +// syntax was removed. Leaving it all in one file will make it easier to +// eventually remove. Avert your eyes! +// TC39 has revived this syntax for ES2017 - "What is dead may never die." + +if (typeof Reflect !== "undefined" && Reflect.parse) + Reflect.parse("for (var x = 3 in []) { }"); + +/******************************************************************************/ + +function testQ() { + try { + for (var i = 0 in this) throw p; + } catch (e) { + if (i !== 94) + return "what"; + } +} +testQ(); + +/******************************************************************************/ + +function f3(i,o){for(var x=i in o)parseInt(o[x]); return x} +function f4(i,o){with(this)for(var x=i in o)parseInt(o[x]); return x} + +assertEq(f3(42, []), 42); +assertEq(f3(42, ['first']), "0"); +assertEq(f4(42, []), 42); +assertEq(f4(42, ['first']), "0"); + +/******************************************************************************/ + +function SetLangHead(l){ + with(p){ + for(var i=0 in x) + if(getElementById("TxtH"+i)!=undefined) + parseInt('huh'); + } +} +x=[0,1,2,3]; +p={getElementById: function (id){ + if (typeof dis === "function") { + dis(SetLangHead); + } + return undefined; +}}; +SetLangHead(1); + +/******************************************************************************/ + +(function(){for(var x = arguments in []){} function x(){}})(); + +/******************************************************************************/ + +with (0) + for (var b = 0 in 0); // don't assert in parser + +/******************************************************************************/ + +function* g1() { + for (var x = yield in {}) ; +} +var it = g1(); +assertEq(it.next().done, false); +assertEq(it.next().done, true); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/statements/for-in-with-declaration.js b/js/src/tests/non262/statements/for-in-with-declaration.js new file mode 100644 index 0000000000..13c71b19c8 --- /dev/null +++ b/js/src/tests/non262/statements/for-in-with-declaration.js @@ -0,0 +1,31 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var gTestfile = "for-in-with-declaration.js"; +var BUGNUMBER = 1163851; +var summary = + "Declarations in for-in loop heads must not contain |in|-expression " + + "initializers"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +assertThrowsInstanceOf(() => Function("for (var x = 3 in {}; ; ) break;"), SyntaxError); +assertThrowsInstanceOf(() => Function("for (var x, y = 3 in {}; ; ) break;"), SyntaxError); +assertThrowsInstanceOf(() => Function("for (var x = 5, y = 3 in {}; ; ) break;"), SyntaxError); +assertThrowsInstanceOf(() => Function("for (const x = 3 in {}; ; ) break;"), SyntaxError); +assertThrowsInstanceOf(() => Function("for (const x = 5, y = 3 in {}; ; ) break;"), SyntaxError); +assertThrowsInstanceOf(() => Function("for (let x = 3 in {}; ; ) break;"), SyntaxError); +assertThrowsInstanceOf(() => Function("for (let x, y = 3 in {}; ; ) break;"), SyntaxError); +assertThrowsInstanceOf(() => Function("for (let x = 2, y = 3 in {}; ; ) break;"), SyntaxError); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/statements/for-in-with-destructuring-assignments.js b/js/src/tests/non262/statements/for-in-with-destructuring-assignments.js new file mode 100644 index 0000000000..6741c885e5 --- /dev/null +++ b/js/src/tests/non262/statements/for-in-with-destructuring-assignments.js @@ -0,0 +1,130 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = "for-in-with-destructuring-assignments.js"; +var BUGNUMBER = 1164741; +var summary = "|for (var = ... in ...)| is invalid syntax"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// This is a total grab-bag of junk originally in tests changed when this +// syntax was removed. Avert your eyes! + +assertThrowsInstanceOf(() => eval(` + for (var [x] = x>>x in [[]<[]]) + { + []; + }`), + SyntaxError); + +/******************************************************************************/ + +assertThrowsInstanceOf(function() { + // Abandon all hope, ye who try to read this. + eval(` + (function () { + for + (var [x] = function(){} + in + (function m(a) { + if (a < 1) { + x; + return; + } + return m(a - 1) + m(a - 2); + })(7)(eval("")) + ) + { + []; + } + }) + `)(); +}, SyntaxError); + +/******************************************************************************/ + +assertThrowsInstanceOf(() => eval(` + for (var [e] = [] in (eval("for (b = 0; b < 6; ++b) gc()"))) {} +`), SyntaxError); + +/******************************************************************************/ + +assertThrowsInstanceOf(() => eval("for (var [ v , c ] = 0 in undefined) { }"), + SyntaxError); + +/******************************************************************************/ + +assertThrowsInstanceOf(() => eval("var b = e; for (var [e] = b in w) c"), + SyntaxError); + +/******************************************************************************/ + +assertThrowsInstanceOf(() => eval("for (var {a: []} = 2 in []) { }"), + SyntaxError); + +/******************************************************************************/ + +assertThrowsInstanceOf(() => eval(`try + { + for (var [,{y}] = 1 in []) {} + } + catch(ex) + { + }`), +SyntaxError); + +/******************************************************************************/ + +assertThrowsInstanceOf(() => eval("for (var [x] = [] in null);"), + SyntaxError); + +/******************************************************************************/ + +assertThrowsInstanceOf(() => eval("for (var [x] = x in y) var x;"), + SyntaxError); + +/******************************************************************************/ + +assertThrowsInstanceOf(() => eval(` + for (var [arguments] = ({ get y(){} }) in y ) (x); +`), +SyntaxError); + +/******************************************************************************/ + +if (typeof evalcx == 'function') { + var src = 'try {\n' + + ' for (var [e] = /x/ in d) {\n' + + ' (function () {});\n' + + ' }\n' + + '} catch (e) {}\n' + + 'try {\n' + + ' let(x = Object.freeze(this, /x/))\n' + + ' e = {}.toString\n' + + ' function y() {}\n' + + '} catch (e) {}'; + + try + { + evalcx(src); + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e.name === "SyntaxError", true, + "expected invalid syntax, got " + e); + } +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/statements/for-in-with-gc-and-unvisited-deletion.js b/js/src/tests/non262/statements/for-in-with-gc-and-unvisited-deletion.js new file mode 100644 index 0000000000..34e1eba1ec --- /dev/null +++ b/js/src/tests/non262/statements/for-in-with-gc-and-unvisited-deletion.js @@ -0,0 +1,76 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var gTestfile = "for-in-with-gc-and-unvisited-deletion.js"; +var BUGNUMBER = 1462939; +var summary = + "Don't mishandle deletion of a property from the internal iterator " + + "created for a for-in loop, when a gc occurs just after it"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function testOneDeletion() +{ + var o = { + p: 1, + r: 3, + s: 4, + }; + + for (var i in o) + { + gc(); + delete o.s; + } +} +testOneDeletion(); + +function testTwoDeletions() +{ + var o = { + p: 1, + r: 3, + s: 4, + t: 5, + }; + + for (var i in o) + { + gc(); + delete o.t; + delete o.s; + } +} +testTwoDeletions(); + +function testThreeDeletions() +{ + var o = { + p: 1, + r: 3, + s: 4, + t: 5, + x: 7, + }; + + for (var i in o) + { + gc(); + delete o.x; + delete o.t; + delete o.s; + } +} +testThreeDeletions(); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/statements/for-in-with-gc-during-iterator-init.js b/js/src/tests/non262/statements/for-in-with-gc-during-iterator-init.js new file mode 100644 index 0000000000..d36322878f --- /dev/null +++ b/js/src/tests/non262/statements/for-in-with-gc-during-iterator-init.js @@ -0,0 +1,30 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var gTestfile = "for-in-with-gc-during-iterator-init.js"; +var BUGNUMBER = 1464472; +var summary = + "Properly trace NativeIterator when a GC occurs during its initialization"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +gczeal(17, 1); +for (var i = 0; i < 100; ++i) +{ + Object.prototype[1012] = "value"; + imports = {}; + for (dmod in imports) + continue; // gc occurs here converting 1012 to string +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/statements/for-inof-coverinitname-destr-assign.js b/js/src/tests/non262/statements/for-inof-coverinitname-destr-assign.js new file mode 100644 index 0000000000..ba9e409599 --- /dev/null +++ b/js/src/tests/non262/statements/for-inof-coverinitname-destr-assign.js @@ -0,0 +1,55 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const defaultValue = "default-value"; +const unreachable = () => { throw "unreachable"; }; + +// for-in statement, object destructuring. +var forIn; +for ({forIn = defaultValue} in {"": null}); +assertEq(forIn, defaultValue); + +forIn = undefined; +String.prototype.forIn = defaultValue; +for ({forIn = unreachable()} in {"": null}); +delete String.prototype.forIn; +assertEq(forIn, defaultValue); + +// for-in statement, array destructuring. +forIn = undefined; +for ([forIn = defaultValue] in {"": null}); +assertEq(forIn, defaultValue); + +forIn = undefined; +for ([forIn = unreachable()] in {"ABC": null}); +assertEq(forIn, "A"); + + +// for-of statement, object destructuring. +var forOf; +for ({forOf = defaultValue} of [{}]); +assertEq(forOf, defaultValue); + +forOf = undefined; +for ({forOf = unreachable()} of [{forOf: defaultValue}]); +assertEq(forOf, defaultValue); + +// for-of statement, array destructuring. +forOf = undefined; +for ([forOf = defaultValue] of [[]]); +assertEq(forOf, defaultValue); + +forOf = undefined; +for ([forOf = unreachable()] of [[defaultValue]]); +assertEq(forOf, defaultValue); + + +// for-statement, object destructuring. +assertThrowsInstanceOf(() => eval(` + for ({invalid = 0};;); +`), SyntaxError); + + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/statements/for-inof-finally.js b/js/src/tests/non262/statements/for-inof-finally.js new file mode 100644 index 0000000000..e1f0c77e12 --- /dev/null +++ b/js/src/tests/non262/statements/for-inof-finally.js @@ -0,0 +1,78 @@ +var BUGNUMBER = 1332881; +var summary = + "Leaving for-in and try should handle stack value in correct order"; + +print(BUGNUMBER + ": " + summary); + +var called = 0; +function reset() { + called = 0; +} +var obj = { + [Symbol.iterator]() { + return { + next() { + return { value: 10, done: false }; + }, + return() { + called++; + return {}; + } + }; + } +}; + +var a = (function () { + for (var x in [0]) { + try {} finally { + return 11; + } + } +})(); +assertEq(a, 11); + +reset(); +var b = (function () { + for (var x of obj) { + try {} finally { + return 12; + } + } +})(); +assertEq(called, 1); +assertEq(b, 12); + +reset(); +var c = (function () { + for (var x in [0]) { + for (var y of obj) { + try {} finally { + return 13; + } + } + } +})(); +assertEq(called, 1); +assertEq(c, 13); + +reset(); +var d = (function () { + for (var x in [0]) { + for (var y of obj) { + try {} finally { + for (var z in [0]) { + for (var w of obj) { + try {} finally { + return 14; + } + } + } + } + } + } +})(); +assertEq(called, 2); +assertEq(d, 14); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/statements/for-inof-loop-const-declaration.js b/js/src/tests/non262/statements/for-inof-loop-const-declaration.js new file mode 100644 index 0000000000..e8daa343b9 --- /dev/null +++ b/js/src/tests/non262/statements/for-inof-loop-const-declaration.js @@ -0,0 +1,94 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = "for-inof-loop-const-declaration.js"; +var BUGNUMBER = 1278150; +var summary = "Support const declarations in for-of loop heads"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var count; + +count = 0; +for (const x in "abcdef") +{ + assertEq(x, "" + count++); + + try + { + x = 3; + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "didn't get a TypeError, instead got: " + e); + } +} + +count = 0; +for (const x of "012345") +{ + assertEq(x, "" + count++); + + try + { + x = 3; + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "didn't get a TypeError, instead got: " + e); + } +} + +count = 0; +for (const { length, 0: c } in "abcdef") +{ + assertEq(length, 1); + assertEq(c, "" + count++); + + + try + { + length = 1; + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "didn't get a TypeError, instead got: " + e); + } +} + +count = 0; +for (const { length, 0: c } of "012345") +{ + assertEq(length, 1); + assertEq(c, "" + count++); + + try + { + c = 42; + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "didn't get a TypeError, instead got: " + e); + } +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/statements/for-inof-name-iteration-expression-contains-index-string.js b/js/src/tests/non262/statements/for-inof-name-iteration-expression-contains-index-string.js new file mode 100644 index 0000000000..212b34db97 --- /dev/null +++ b/js/src/tests/non262/statements/for-inof-name-iteration-expression-contains-index-string.js @@ -0,0 +1,43 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var gTestfile = "for-inof-name-iteration-expression-contains-index-string.js"; +var BUGNUMBER = 1235640; +var summary = + "Don't assert parsing a for-in/of loop whose target is a name, where the " + + "expression being iterated over contains a string containing an index"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function f() +{ + var x; + for (x in "9") + continue; + assertEq(x, "0"); +} + +f(); + +function g() +{ + "use strict"; + var x = "unset"; + for (x in arguments) + continue; + assertEq(x, "unset"); +} + +g(); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/statements/for-loop-declaration-contains-computed-name.js b/js/src/tests/non262/statements/for-loop-declaration-contains-computed-name.js new file mode 100644 index 0000000000..7928d049dc --- /dev/null +++ b/js/src/tests/non262/statements/for-loop-declaration-contains-computed-name.js @@ -0,0 +1,48 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = "for-loop-declaration-contains-computed-name.js"; +var BUGNUMBER = 1233767; +var summary = + "Support computed property names in destructuring declarations in " + + "for-in/of loop heads"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var count; + +count = 0; +for (var { [5]: x, [x]: y } of [{ 5: 42, 42: "hi" }, { 5: 17, 17: 'fnord' }]) +{ + if (count === 0) { + assertEq(x, 42); + assertEq(y, "hi"); + } else { + assertEq(x, 17); + assertEq(y, "fnord"); + } + + count++; +} + +count = 0; +for (var { length: x, [x - 1]: y } in "foo") +{ + assertEq(x, 1); + assertEq("" + count, y); + + count++; +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/statements/for-loop-declaration-contains-initializer.js b/js/src/tests/non262/statements/for-loop-declaration-contains-initializer.js new file mode 100644 index 0000000000..7010c9eba9 --- /dev/null +++ b/js/src/tests/non262/statements/for-loop-declaration-contains-initializer.js @@ -0,0 +1,50 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = "for-loop-declaration-contains-computed-name.js"; +var BUGNUMBER = 1233767; +var summary = + "Support initializer defaults in destructuring declarations in for-in/of " + + "loop heads"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var count; +var expr; + +expr = [{ z: 42, 42: "hi" }, { 7: 'fnord' }]; +count = 0; +for (var { z: x = 7, [x]: y = 3 } of expr) +{ + if (count === 0) { + assertEq(x, 42); + assertEq(y, "hi"); + } else { + assertEq(x, 7); + assertEq(y, "fnord"); + } + + count++; +} + +count = 0; +for (var { length: x, [x - 1 + count]: y = "psych" } in "foo") +{ + assertEq(x, 1); + assertEq(y, count === 0 ? "0" : "psych"); + + count++; +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/statements/for-of-async-of-starting-lhs.js b/js/src/tests/non262/statements/for-of-async-of-starting-lhs.js new file mode 100644 index 0000000000..74c81e2a06 --- /dev/null +++ b/js/src/tests/non262/statements/for-of-async-of-starting-lhs.js @@ -0,0 +1,115 @@ +if (typeof getRealmConfiguration === "undefined") { + var getRealmConfiguration = SpecialPowers.Cu.getJSTestingFunctions().getRealmConfiguration; +} + + +const AsyncFunction = async function(){}.constructor; + +function assertNoError(f, msg) { + try { + f(); + } catch (e) { + assertEq(true, false, `${msg}: ${e}`); + } +} + +function assertSyntaxError(code) { + assertThrowsInstanceOf(function () { Function(code); }, SyntaxError, "Function:" + code); + assertThrowsInstanceOf(function () { AsyncFunction(code); }, SyntaxError, "AsyncFunction:" + code); + + if (typeof parseModule === "function") { + assertThrowsInstanceOf(function () { parseModule(code); }, SyntaxError, "Module:" + code); + } +} + +function assertNoSyntaxError(code) { + assertNoError(function () { Function(code); }, "Function:" + code); + assertNoError(function () { AsyncFunction(code); }, "AsyncFunction:" + code); + + if (typeof parseModule === "function") { + assertNoError(function () { parseModule(code); }, "Module:" + code); + } +} + +function assertNoSyntaxErrorAsyncContext(code) { + assertNoError(function () { AsyncFunction(code); }, "AsyncFunction:" + code); + + if (typeof parseModule === "function") { + assertNoError(function () { parseModule(code); }, "Module:" + code); + } +} + +const invalidTestCases = [ + // for-in loop: LHS can't start with an async arrow function. + "for ( async of => {} in [] ) ;", + "for ( async o\\u0066 => {} in [] ) ;", + + // for-of loop: LHS can't start with an async arrow function. + "for ( async of => {} of [] ) ;", + "for ( async o\\u0066 => {} of [] ) ;", + + // for-of loop: LHS can't start with an identifier named "async". + "for ( async of [] ) ;", + + // for-await-of loop: LHS can't start with an async arrow function. + "for await ( async of => {} of [] ) ;", + "for await ( async o\\u0066 => {} of [] ) ;", +]; + +for (let source of invalidTestCases) { + assertSyntaxError(source); + + // Also test when the tokens are separated by newline characters. + assertSyntaxError(source.split(" ").join("\n")); +} + +// for-loop: async arrow functions are allowed in C-style for-loops. +assertNoSyntaxError("for ( async of => {} ; ; ) ;") + +const validTestCases = [ + // for-loop: LHS can start with an identifier named "async". + "for ( async ; ; ) ;", + "for ( \\u0061sync ; ; ) ;", + + // for-in loop: LHS can start with an identifier named "async". + "for ( async in [] ) ;", + "for ( \\u0061sync in [] ) ;", + + // for-in loop: LHS can start with an property assignment starting with "async". + "for ( async . prop in [] ) ;", + "for ( async [ 0 ] in [] ) ;", + + // for-of loop: LHS can start with an identifier named "async" when escape characters are used. + "for ( \\u0061sync of [] ) ;", + + // for-of loop: LHS can start with an property assignment starting with "async". + "for ( async . prop of [] ) ;", + "for ( async [ 0 ] of [] ) ;", +]; + +for (let source of validTestCases) { + assertNoSyntaxError(source); + + // Also test when the tokens are separated by newline characters. + assertNoSyntaxError(source.split(" ").join("\n")); +} + +const validTestCasesAsync = [ + // for-await-of loop: LHS can start with an identifier named "async". + "for await ( async of [] ) ;", + "for await ( \\u0061sync of [] ) ;", + + // for-await-of loop: LHS can start with an property assignment starting with "async". + "for await ( async . prop of [] ) ;", + "for await ( async [ 0 ] of [] ) ;", +]; + +for (let source of validTestCasesAsync) { + assertNoSyntaxErrorAsyncContext(source); + + // Also test when the tokens are separated by newline characters. + assertNoSyntaxErrorAsyncContext(source.split(" ").join("\n")); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/statements/for-of-iterator-close-throw.js b/js/src/tests/non262/statements/for-of-iterator-close-throw.js new file mode 100644 index 0000000000..1974e416be --- /dev/null +++ b/js/src/tests/non262/statements/for-of-iterator-close-throw.js @@ -0,0 +1,35 @@ +function test() { + var returnCalled = 0; + var returnCalledExpected = 0; + var catchEntered = 0; + var finallyEntered = 0; + var finallyEnteredExpected = 0; + var iterable = {}; + iterable[Symbol.iterator] = makeIterator({ + ret: function() { + returnCalled++; + throw 42; + } + }); + + // inner try cannot catch IteratorClose throwing + assertThrowsValue(function() { + for (var x of iterable) { + try { + return; + } catch (e) { + catchEntered++; + } finally { + finallyEntered++; + } + } + }, 42); + assertEq(returnCalled, ++returnCalledExpected); + assertEq(catchEntered, 0); + assertEq(finallyEntered, ++finallyEnteredExpected); +} + +test(); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/statements/for-of-iterator-close.js b/js/src/tests/non262/statements/for-of-iterator-close.js new file mode 100644 index 0000000000..b28895d8fe --- /dev/null +++ b/js/src/tests/non262/statements/for-of-iterator-close.js @@ -0,0 +1,102 @@ +// Tests that IteratorReturn is called when a for-of loop has an abrupt +// completion value during non-iterator code. + +function test() { + var returnCalled = 0; + var returnCalledExpected = 0; + var iterable = {}; + iterable[Symbol.iterator] = makeIterator({ + ret: function() { + returnCalled++; + return {}; + } + }); + + // break calls iter.return + for (var x of iterable) + break; + assertEq(returnCalled, ++returnCalledExpected); + + // throw in body calls iter.return + assertThrowsValue(function() { + for (var x of iterable) + throw "in body"; + }, "in body"); + assertEq(returnCalled, ++returnCalledExpected); + + // throw in lhs ref calls iter.return + function throwlhs() { + throw "in lhs"; + } + assertThrowsValue(function() { + for ((throwlhs()) of iterable) + continue; + }, "in lhs"); + assertEq(returnCalled, ++returnCalledExpected); + + // throw in iter.return doesn't re-call iter.return + iterable[Symbol.iterator] = makeIterator({ + ret: function() { + returnCalled++; + throw "in iter.return"; + } + }); + assertThrowsValue(function() { + for (var x of iterable) + break; + }, "in iter.return"); + assertEq(returnCalled, ++returnCalledExpected); + + // throw in iter.next doesn't call IteratorClose + iterable[Symbol.iterator] = makeIterator({ + next: function() { + throw "in next"; + } + }); + assertThrowsValue(function() { + for (var x of iterable) + break; + }, "in next"); + assertEq(returnCalled, returnCalledExpected); + + // "return" must return an Object. + iterable[Symbol.iterator] = makeIterator({ + ret: function() { + returnCalled++; + return 42; + } + }); + assertThrowsInstanceOf(function() { + for (var x of iterable) + break; + }, TypeError); + assertEq(returnCalled, ++returnCalledExpected); + + // continue doesn't call iter.return for the loop it's continuing + var i = 0; + iterable[Symbol.iterator] = makeIterator({ + next: function() { + return { done: i++ > 5 }; + }, + ret: function() { + returnCalled++; + return {}; + } + }); + for (var x of iterable) + continue; + assertEq(returnCalled, returnCalledExpected); + + // continue does call iter.return for loops it skips + i = 0; + L: do { + for (var x of iterable) + continue L; + } while (false); + assertEq(returnCalled, ++returnCalledExpected); +} + +test(); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/statements/for-of-iterator-primitive.js b/js/src/tests/non262/statements/for-of-iterator-primitive.js new file mode 100644 index 0000000000..6d69a1282f --- /dev/null +++ b/js/src/tests/non262/statements/for-of-iterator-primitive.js @@ -0,0 +1,28 @@ +var BUGNUMBER = 1021835; +var summary = "Returning non-object from @@iterator should throw"; + +print(BUGNUMBER + ": " + summary); + +let primitives = [ + 1, + true, + undefined, + null, + "foo", + Symbol.iterator +]; + +for (let primitive of primitives) { + let obj = { + [Symbol.iterator]() { + return primitive; + } + }; + assertThrowsInstanceOf(() => { + for (let x of obj) { + } + }, TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/statements/for-of-var-with-initializer.js b/js/src/tests/non262/statements/for-of-var-with-initializer.js new file mode 100644 index 0000000000..ae42e153b3 --- /dev/null +++ b/js/src/tests/non262/statements/for-of-var-with-initializer.js @@ -0,0 +1,32 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = "for-of-var-with-initializer.js"; +var BUGNUMBER = 1164741; +var summary = "Don't assert parsing |for (var x = 3 of 42);|"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +try +{ + Function("for (var x = 3 of 42);"); + throw new Error("didn't throw"); +} +catch (e) +{ + assertEq(e instanceof SyntaxError, true, + "expected syntax error, got: " + e); +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/statements/if-constant-folding.js b/js/src/tests/non262/statements/if-constant-folding.js new file mode 100644 index 0000000000..0486ad56f6 --- /dev/null +++ b/js/src/tests/non262/statements/if-constant-folding.js @@ -0,0 +1,35 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var gTestfile = "if-constant-folding.js"; +var BUGNUMBER = 1183400; +var summary = + "Don't crash constant-folding an |if| governed by a truthy constant, whose " + + "alternative statement is another |if|"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// Perform |if| constant folding correctly when the condition is constantly +// truthy and the alternative statement is another |if|. +if (true) +{ + assertEq(true, true, "sanity"); +} +else if (42) +{ + assertEq(false, true, "not reached"); + assertEq(true, false, "also not reached"); +} + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/statements/property-reference-self-assignment.js b/js/src/tests/non262/statements/property-reference-self-assignment.js new file mode 100644 index 0000000000..81c95b9cfb --- /dev/null +++ b/js/src/tests/non262/statements/property-reference-self-assignment.js @@ -0,0 +1,38 @@ +var hits = 0; + +var p = { toString() { hits++; return "prop" } }; +var obj = { foo: 1 }; + + +var ops = [["obj[p]++", 2], + ["++obj[p]", 2], + ["--obj[p]", 0], + ["obj[p]--", 0], + ["obj[p] += 2", 3], + ["obj[p] -= 2", -1], + ["obj[p] *= 2", 2], + ["obj[p] /= 2", 0.5], + ["obj[p] %= 2", 1], + ["obj[p] >>>= 2", 0], + ["obj[p] >>= 2", 0], + ["obj[p] <<= 2", 4], + ["obj[p] |= 2", 3], + ["obj[p] ^= 2", 3], + ["obj[p] &= 2", 0]]; + +var testHits = 0; +for (let op of ops) { + // Seed the value for each test. + obj.prop = 1; + + // Do the operation. + eval(op[0]); + assertEq(obj.prop, op[1]); + + // We should always call toString once, for each operation. + testHits++; + assertEq(hits, testHits); +} + +if (typeof reportCompare === 'function') + reportCompare(0,0,"OK"); diff --git a/js/src/tests/non262/statements/regress-131348.js b/js/src/tests/non262/statements/regress-131348.js new file mode 100644 index 0000000000..f21b7dc3cf --- /dev/null +++ b/js/src/tests/non262/statements/regress-131348.js @@ -0,0 +1,147 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * + * Date: 10 Apr 2002 + * Revised: 14 July 2002 + * + * SUMMARY: JS should NOT error on |for(i in undefined)|, |for(i in null)| + * + * ECMA-262 3rd Edition Final spec says such statements SHOULD error. See: + * + * Section 12.6.4 The for-in Statement + * Section 9.9 ToObject + * + * + * But SpiderMonkey has decided NOT to follow this; it's a bug in the spec. + * See http://bugzilla.mozilla.org/show_bug.cgi?id=131348 + * + * Update: Rhino has also decided not to follow the spec on this + * See http://bugzilla.mozilla.org/show_bug.cgi?id=136893 + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 131348; +var summary = 'JS should not error on |for(i in undefined)|, |for(i in null)|'; +var TEST_PASSED = 'No error'; +var TEST_FAILED = 'An error was generated!!!'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; + + + +status = inSection(1); +expect = TEST_PASSED; +actual = TEST_PASSED; +try +{ + for (var i in undefined) + { + print(i); + } +} +catch(e) +{ + actual = TEST_FAILED; +} +addThis(); + + + +status = inSection(2); +expect = TEST_PASSED; +actual = TEST_PASSED; +try +{ + for (var i in null) + { + print(i); + } +} +catch(e) +{ + actual = TEST_FAILED; +} +addThis(); + + + +status = inSection(3); +expect = TEST_PASSED; +actual = TEST_PASSED; +/* + * Variable names that cannot be looked up generate ReferenceErrors; however, + * property names like obj.ZZZ that cannot be looked up are set to |undefined| + * + * Therefore, this should indirectly test | for (var i in undefined) | + */ +try +{ + for (var i in this.ZZZ) + { + print(i); + } +} +catch(e) +{ + actual = TEST_FAILED; +} +addThis(); + + + +status = inSection(4); +expect = TEST_PASSED; +actual = TEST_PASSED; +/* + * The result of an unsuccessful regexp match is the null value + * Therefore, this should indirectly test | for (var i in null) | + */ +try +{ + for (var i in 'bbb'.match(/aaa/)) + { + print(i); + } +} +catch(e) +{ + actual = TEST_FAILED; +} +addThis(); + + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i test(","), SyntaxError); + + // Leading comma. + assertThrowsInstanceOf(() => test(", a"), SyntaxError); + assertThrowsInstanceOf(() => test(", ...a"), SyntaxError); + + // Multiple trailing comma. + assertThrowsInstanceOf(() => test("a, , "), SyntaxError); + assertThrowsInstanceOf(() => test("a..., , "), SyntaxError); + + // Trailing comma after rest parameter. + assertThrowsInstanceOf(() => test("...a, "), SyntaxError); + assertThrowsInstanceOf(() => test("a, ...b, "), SyntaxError); + + // Elision. + assertThrowsInstanceOf(() => test("a, , b"), SyntaxError); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/statements/try-completion.js b/js/src/tests/non262/statements/try-completion.js new file mode 100644 index 0000000000..f9bd1e1496 --- /dev/null +++ b/js/src/tests/non262/statements/try-completion.js @@ -0,0 +1,482 @@ +var BUGNUMBER = 819125; +var summary = "try block should return try value if finally returned normally"; + +print(BUGNUMBER + ": " + summary); + +function expectTryValue(code, isUndefined) { + assertEq(eval(code), isUndefined ? undefined : 'try'); +} + +function expectCatchValue(code, isUndefined) { + assertEq(eval(code), isUndefined ? undefined : 'catch'); +} + +function expectFinallyValue(code, isUndefined) { + assertEq(eval(code), isUndefined ? undefined : 'finally'); +} + +// ==== finally: normal ==== + +// try: normal +// finally: normal +expectTryValue(` +try { + 'try'; +} finally { + 'finally'; +} +`); + +// try: normal without value +// finally: normal +expectTryValue(` +try { +} finally { + 'finally'; +} +`, true); + +// try: break +// finally: normal +expectTryValue(` +while (true) { + try { + 'try'; + break; + } finally { + 'finally'; + } +} +`); + +// try: break without value +// finally: normal +expectTryValue(` +while (true) { + try { + break; + } finally { + 'finally'; + } +} +`, true); + +// try: continue +// finally: normal +expectTryValue(` +do { + try { + 'try'; + continue; + } finally { + 'finally'; + } +} while (false); +`); + +// try: continue without value +// finally: normal +expectTryValue(` +do { + try { + continue; + } finally { + 'finally'; + } +} while (false); +`, true); + +// try: throw +// catch: normal +// finally: normal +expectCatchValue(` +try { + 'try'; + throw 'exception'; +} catch (e) { + 'catch'; +} finally { + 'finally'; +} +`); + +// try: throw +// catch: normal +// finally: normal +expectCatchValue(` +try { + 'try'; + throw 'exception'; +} catch (e) { + 'catch'; +} finally { + 'finally'; +} +`); + +// try: throw +// catch: normal without value +// finally: normal +expectCatchValue(` +try { + 'try'; + throw 'exception'; +} catch (e) { +} finally { + 'finally'; +} +`, true); + +// try: throw +// catch: normal without value +// finally: normal +expectCatchValue(` +try { + 'try'; + throw 'exception'; +} catch (e) { +} finally { + 'finally'; +} +`, true); + +// try: throw +// catch: break +// finally: normal +expectCatchValue(` +while (true) { + try { + 'try'; + throw 'exception'; + } catch (e) { + 'catch'; + break; + } finally { + 'finally'; + } +} +`); + +// try: throw +// catch: break without value +// finally: normal +expectCatchValue(` +while (true) { + try { + 'try'; + throw 'exception'; + } catch (e) { + break; + } finally { + 'finally'; + } +} +`, true); + +// try: throw +// catch: continue +// finally: normal +expectCatchValue(` +do { + try { + 'try'; + throw 'exception'; + } catch (e) { + 'catch'; + continue; + } finally { + 'finally'; + } +} while (false); +`); + +// try: throw +// catch: continue without value +// finally: normal +expectCatchValue(` +do { + try { + 'try'; + throw 'exception'; + } catch (e) { + continue; + } finally { + 'finally'; + } +} while (false); +`, true); + +// ==== finally: break ==== + +// try: normal +// finally: break +expectFinallyValue(` +while (true) { + try { + 'try'; + } finally { + 'finally'; + break; + } +} +`); + +// try: normal +// finally: break without value +expectFinallyValue(` +while (true) { + try { + 'try'; + } finally { + break; + } +} +`, true); + +// try: break +// finally: break +expectFinallyValue(` +while (true) { + try { + 'try'; + break; + } finally { + 'finally'; + break; + } +} +`); + +// try: break +// finally: break without value +expectFinallyValue(` +while (true) { + try { + 'try'; + break; + } finally { + break; + } +} +`, true); + +// try: continue +// finally: break +expectFinallyValue(` +do { + try { + 'try'; + continue; + } finally { + 'finally'; + break; + } +} while (false); +`); + +// try: continue +// finally: break without value +expectFinallyValue(` +do { + try { + 'try'; + continue; + } finally { + break; + } +} while (false); +`, true); + +// try: throw +// catch: normal +// finally: break +expectFinallyValue(` +while (true) { + try { + 'try'; + throw 'exception'; + } catch (e) { + 'catch'; + } finally { + 'finally'; + break; + } +} +`, false); + +// try: throw +// catch: normal +// finally: break without value +expectFinallyValue(` +while (true) { + try { + 'try'; + throw 'exception'; + } catch (e) { + 'catch'; + } finally { + break; + } +} +`, true); + +// ==== finally: continue ==== + +// try: normal +// finally: continue +expectFinallyValue(` +do { + try { + 'try'; + } finally { + 'finally'; + continue; + } +} while (false); +`); + +// try: normal +// finally: continue without value +expectFinallyValue(` +do { + try { + 'try'; + } finally { + continue; + } +} while (false); +`, true); + +// try: break +// finally: continue +expectFinallyValue(` +do { + try { + 'try'; + break; + } finally { + 'finally'; + continue; + } +} while (false); +`); + +// try: break +// finally: continue without value +expectFinallyValue(` +do { + try { + 'try'; + break; + } finally { + continue; + } +} while (false); +`, true); + +// try: continue +// finally: continue +expectFinallyValue(` +do { + try { + 'try'; + continue; + } finally { + 'finally'; + continue; + } +} while (false); +`); + +// try: continue +// finally: continue without value +expectFinallyValue(` +do { + try { + 'try'; + continue; + } finally { + continue; + } +} while (false); +`, true); + +// ==== without finally ==== + +// try: throw +// catch: normal +expectCatchValue(` +try { + 'try'; + throw 'exception'; +} catch (e) { + 'catch'; +} +`); + +// try: throw +// catch: normal without value +expectCatchValue(` +try { + 'try'; + throw 'exception'; +} catch (e) { +} +`, true); + +// try: throw +// catch: break +expectCatchValue(` +while (true) { + try { + 'try'; + throw 'exception'; + } catch (e) { + 'catch'; + break; + } +} +`); + +// try: throw +// catch: break without value +expectCatchValue(` +while (true) { + try { + 'try'; + throw 'exception'; + } catch (e) { + break; + } +} +`, true); + +// try: throw +// catch: continue +expectCatchValue(` +do { + try { + 'try'; + throw 'exception'; + } catch (e) { + 'catch'; + continue; + } +} while (false); +`); + +// try: throw +// catch: continue without value +expectCatchValue(` +do { + try { + 'try'; + throw 'exception'; + } catch (e) { + continue; + } +} while (false); +`, true); + +if (typeof reportCompare === "function") + reportCompare(true, true); -- cgit v1.2.3