From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../non262/destructuring/array-default-class.js | 25 + .../non262/destructuring/array-iterator-close.js | 93 +++ js/src/tests/non262/destructuring/browser.js | 0 js/src/tests/non262/destructuring/bug1396261.js | 44 ++ .../tests/non262/destructuring/constant-folding.js | 16 + .../non262/destructuring/cover-init-name-syntax.js | 72 +++ .../non262/destructuring/duplicate-__proto__.js | 54 ++ .../non262/destructuring/iterator-primitive.js | 36 ++ js/src/tests/non262/destructuring/order-super.js | 701 ++++++++++++++++++++ js/src/tests/non262/destructuring/order.js | 719 +++++++++++++++++++++ .../destructuring/rest-parameter-aray-iterator.js | 40 ++ .../destructuring/rest-parameter-arguments.js | 101 +++ .../rest-parameter-function-length.js | 41 ++ .../rest-parameter-spread-call-optimization.js | 29 + .../non262/destructuring/rest-parameter-syntax.js | 87 +++ .../tests/non262/destructuring/rest-parameter.js | 54 ++ .../destructuring/rest-with-trailing-comma.js | 45 ++ js/src/tests/non262/destructuring/shell.js | 0 .../yield-in-object-destr-function.js | 182 ++++++ .../yield-in-object-destr-generator.js | 200 ++++++ .../destructuring/yield-in-object-destr-script.js | 123 ++++ .../yield-with-escape-in-object-destr-function.js | 182 ++++++ .../yield-with-escape-in-object-destr-generator.js | 200 ++++++ .../yield-with-escape-in-object-destr-script.js | 123 ++++ 24 files changed, 3167 insertions(+) create mode 100644 js/src/tests/non262/destructuring/array-default-class.js create mode 100644 js/src/tests/non262/destructuring/array-iterator-close.js create mode 100644 js/src/tests/non262/destructuring/browser.js create mode 100644 js/src/tests/non262/destructuring/bug1396261.js create mode 100644 js/src/tests/non262/destructuring/constant-folding.js create mode 100644 js/src/tests/non262/destructuring/cover-init-name-syntax.js create mode 100644 js/src/tests/non262/destructuring/duplicate-__proto__.js create mode 100644 js/src/tests/non262/destructuring/iterator-primitive.js create mode 100644 js/src/tests/non262/destructuring/order-super.js create mode 100644 js/src/tests/non262/destructuring/order.js create mode 100644 js/src/tests/non262/destructuring/rest-parameter-aray-iterator.js create mode 100644 js/src/tests/non262/destructuring/rest-parameter-arguments.js create mode 100644 js/src/tests/non262/destructuring/rest-parameter-function-length.js create mode 100644 js/src/tests/non262/destructuring/rest-parameter-spread-call-optimization.js create mode 100644 js/src/tests/non262/destructuring/rest-parameter-syntax.js create mode 100644 js/src/tests/non262/destructuring/rest-parameter.js create mode 100644 js/src/tests/non262/destructuring/rest-with-trailing-comma.js create mode 100644 js/src/tests/non262/destructuring/shell.js create mode 100644 js/src/tests/non262/destructuring/yield-in-object-destr-function.js create mode 100644 js/src/tests/non262/destructuring/yield-in-object-destr-generator.js create mode 100644 js/src/tests/non262/destructuring/yield-in-object-destr-script.js create mode 100644 js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-function.js create mode 100644 js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-generator.js create mode 100644 js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-script.js (limited to 'js/src/tests/non262/destructuring') diff --git a/js/src/tests/non262/destructuring/array-default-class.js b/js/src/tests/non262/destructuring/array-default-class.js new file mode 100644 index 0000000000..5aa9c579b1 --- /dev/null +++ b/js/src/tests/non262/destructuring/array-default-class.js @@ -0,0 +1,25 @@ +var BUGNUMBER = 1322314; +var summary = "Function in computed property in class expression in array destructuring default"; + +print(BUGNUMBER + ": " + summary); + +function* g([ + a = class E { + [ (function() { return "foo"; })() ]() { + return 10; + } + } +]) { + yield a; +} + +let C = [...g([])][0]; +let x = new C(); +assertEq(x.foo(), 10); + +C = [...g([undefined])][0]; +x = new C(); +assertEq(x.foo(), 10); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/destructuring/array-iterator-close.js b/js/src/tests/non262/destructuring/array-iterator-close.js new file mode 100644 index 0000000000..ed35135dba --- /dev/null +++ b/js/src/tests/non262/destructuring/array-iterator-close.js @@ -0,0 +1,93 @@ +// Tests that IteratorClose is called in array destructuring patterns. + +function test() { + var returnCalled = 0; + var returnCalledExpected = 0; + var iterable = {}; + + // empty [] calls IteratorClose regardless of "done" on the result. + iterable[Symbol.iterator] = makeIterator({ + next: function() { + return { done: true }; + }, + ret: function() { + returnCalled++; + return {}; + } + }); + var [] = iterable; + assertEq(returnCalled, ++returnCalledExpected); + + iterable[Symbol.iterator] = makeIterator({ + ret: function() { + returnCalled++; + return {}; + } + }); + var [] = iterable; + assertEq(returnCalled, ++returnCalledExpected); + + // Non-empty destructuring calls IteratorClose if iterator is not done by + // the end of destructuring. + var [a,b] = iterable; + assertEq(returnCalled, ++returnCalledExpected); + var [c,] = iterable; + assertEq(returnCalled, ++returnCalledExpected); + + // throw in lhs ref calls IteratorClose + function throwlhs() { + throw "in lhs"; + } + assertThrowsValue(function() { + 0, [...{}[throwlhs()]] = iterable; + }, "in lhs"); + assertEq(returnCalled, ++returnCalledExpected); + + // throw in lhs ref calls IteratorClose with falsy "done". + iterable[Symbol.iterator] = makeIterator({ + next: function() { + // "done" is undefined. + return {}; + }, + ret: function() { + returnCalled++; + return {}; + } + }); + assertThrowsValue(function() { + 0, [...{}[throwlhs()]] = iterable; + }, "in lhs"); + assertEq(returnCalled, ++returnCalledExpected); + + // throw in iter.next doesn't call IteratorClose + iterable[Symbol.iterator] = makeIterator({ + next: function() { + throw "in next"; + }, + ret: function() { + returnCalled++; + return {}; + } + }); + assertThrowsValue(function() { + var [d] = iterable; + }, "in next"); + assertEq(returnCalled, returnCalledExpected); + + // "return" must return an Object. + iterable[Symbol.iterator] = makeIterator({ + ret: function() { + returnCalled++; + return 42; + } + }); + assertThrowsInstanceOf(function() { + var [] = iterable; + }, TypeError); + assertEq(returnCalled, ++returnCalledExpected); +} + +test(); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/destructuring/browser.js b/js/src/tests/non262/destructuring/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/destructuring/bug1396261.js b/js/src/tests/non262/destructuring/bug1396261.js new file mode 100644 index 0000000000..5d16b09323 --- /dev/null +++ b/js/src/tests/non262/destructuring/bug1396261.js @@ -0,0 +1,44 @@ +// Ensure array or object literals with trailing property accessors are not +// treated as nested destructuring patterns in assignment destructuring +// contexts. + +// Array destructuring with normal element. +[{a: 0}.x] = []; +[[0].x] = []; + +// Array destructuring with spread element. +[...{a: 0}.x] = []; +[...[0].x] = []; + +// Object destructuring with normal property. +({a: {b: 0}.x} = {}); +({a: [0].x} = {}); + +// Object destructuring with spread property. +({...{b: 0}.x} = {}); +({...[0].x} = {}); + +// Object literal with initializer shorthand in destructuring context. +assertThrowsInstanceOf(() => Function(`[{a = 0}.x] = [];`), SyntaxError); +assertThrowsInstanceOf(() => Function(`[...{a = 0}.x] = [];`), SyntaxError); +assertThrowsInstanceOf(() => Function(`({a: {b = 0}.x} = {});`), SyntaxError); +assertThrowsInstanceOf(() => Function(`({...{b = 0}.x} = {});`), SyntaxError); + +// Object destructuring with "eval" or "arguments" shorthand in strict mode. +(function() { + "use strict"; + + // Ensure "eval" resp. "arguments" is not treated as an assignment. + [{eval}.x] = []; + [...{eval}.x] = []; + ({a: {eval}.x} = {}); + ({...{eval}.x} = {}); + + [{arguments}.x] = []; + [...{arguments}.x] = []; + ({a: {arguments}.x} = {}); + ({...{arguments}.x} = {}); +})(); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/destructuring/constant-folding.js b/js/src/tests/non262/destructuring/constant-folding.js new file mode 100644 index 0000000000..b5aa893215 --- /dev/null +++ b/js/src/tests/non262/destructuring/constant-folding.js @@ -0,0 +1,16 @@ +function assertSyntaxError(code) { + assertThrowsInstanceOf(function () { Function(code); }, SyntaxError, "Function:" + code); + assertThrowsInstanceOf(function () { eval(code); }, SyntaxError, "eval:" + code); + var ieval = eval; + assertThrowsInstanceOf(function () { ieval(code); }, SyntaxError, "indirect eval:" + code); +} + +// |true && a| is constant-folded to |a|, ensure the destructuring assignment +// validation takes place before constant-folding. +for (let prefix of ["null,", "var", "let", "const"]) { + assertSyntaxError(`${prefix} [true && a] = [];`); + assertSyntaxError(`${prefix} {p: true && a} = {};`); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/destructuring/cover-init-name-syntax.js b/js/src/tests/non262/destructuring/cover-init-name-syntax.js new file mode 100644 index 0000000000..b37d8c2904 --- /dev/null +++ b/js/src/tests/non262/destructuring/cover-init-name-syntax.js @@ -0,0 +1,72 @@ +/* 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/. */ + + +// CoverInitName in arrow parameters. +({a = 1}, {b = 2}, {c = 3}) => {}; +({a = 1} = {}, {b = 2}, {c = 3}) => {}; +({a = 1} = {}, {b = 2} = {}, {c = 3}) => {}; +({a = 1} = {}, {b = 2} = {}, {c = 3} = {}) => {}; + + +// CoverInitName in CoverParenthesizedExpressionAndArrowParameterList, +// but not ArrowParameters. +assertThrowsInstanceOf(() => eval(` + ({a = 1}, {b = 2}, {c = 3}); +`), SyntaxError); +assertThrowsInstanceOf(() => eval(` + ({a = 1}, {b = 2}, {c = 3} = {}); +`), SyntaxError); +assertThrowsInstanceOf(() => eval(` + ({a = 1}, {b = 2} = {}, {c = 3} = {}); +`), SyntaxError); + + +// CoverInitName nested in array destructuring. +[{a = 0}] = [{}]; +var [{a = 0}] = [{}]; +{ let [{a = 0}] = [{}]; } +{ const [{a = 0}] = [{}]; } + +for ([{a = 0}] of []); +for (var [{a = 0}] of []); +for (let [{a = 0}] of []); +for (const [{a = 0}] of []); + +function f([{a = 0}]) {} +var h = ([{a = 0}]) => {}; + + +// CoverInitName nested in rest pattern. +[...[{a = 0}]] = [{}]; +var [...[{a = 0}]] = [{}]; +{ let [...[{a = 0}]] = [{}]; } +{ const [...[{a = 0}]] = [{}]; } + +for ([...[{a = 0}]] of []); +for (var [...[{a = 0}]] of []); +for (let [...[{a = 0}]] of []); +for (const [...[{a = 0}]] of []); + +function f([...[{a = 0}]]) {} +var h = ([...[{a = 0}]]) => {}; + + +// CoverInitName nested in object destructuring. +({p: {a = 0}} = {p: {}}); +var {p: {a = 0}} = {p: {}}; +{ let {p: {a = 0}} = {p: {}}; } +{ const {p: {a = 0}} = {p: {}}; } + +for ({p: {a = 0}} of []); +for (var {p: {a = 0}} of []); +for (let {p: {a = 0}} of []); +for (const {p: {a = 0}} of []); + +function f({p: {a = 0}}) {} +var h = ({p: {a = 0}}) => {}; + + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/destructuring/duplicate-__proto__.js b/js/src/tests/non262/destructuring/duplicate-__proto__.js new file mode 100644 index 0000000000..a8f76014e9 --- /dev/null +++ b/js/src/tests/non262/destructuring/duplicate-__proto__.js @@ -0,0 +1,54 @@ +/* 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/. */ + + +// Destructuring assignment. +var a, b; +({__proto__: a, __proto__: b} = {}); +assertEq(a, Object.prototype); +assertEq(b, Object.prototype); + +// Destructuring binding with "var". +var {__proto__: a, __proto__: b} = {}; +assertEq(a, Object.prototype); +assertEq(b, Object.prototype); + +// Destructuring binding with "let". +{ + let {__proto__: a, __proto__: b} = {}; + assertEq(a, Object.prototype); + assertEq(b, Object.prototype); +} + +// Destructuring binding with "const". +{ + const {__proto__: a, __proto__: b} = {}; + assertEq(a, Object.prototype); + assertEq(b, Object.prototype); +} + +// Function parameters. +function f1({__proto__: a, __proto__: b}) { + assertEq(a, Object.prototype); + assertEq(b, Object.prototype); +} +f1({}); + +// Arrow function parameters. +var f2 = ({__proto__: a, __proto__: b}) => { + assertEq(a, Object.prototype); + assertEq(b, Object.prototype); +}; +f2({}); + +// Arrow function parameters with defaults (initially parsed as destructuring assignment). +var f3 = ({__proto__: a, __proto__: b} = {}) => { + assertEq(a, Object.prototype); + assertEq(b, Object.prototype); +}; +f3({}); + + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/destructuring/iterator-primitive.js b/js/src/tests/non262/destructuring/iterator-primitive.js new file mode 100644 index 0000000000..17d100367c --- /dev/null +++ b/js/src/tests/non262/destructuring/iterator-primitive.js @@ -0,0 +1,36 @@ +var BUGNUMBER = 1021835; +var summary = "Returning non-object from @@iterator should throw"; + +print(BUGNUMBER + ": " + summary); + +let primitives = [ + 1, + true, + undefined, + null, + "foo", + Symbol.iterator +]; + +function f([]) { +} + +for (let primitive of primitives) { + let obj = { + [Symbol.iterator]() { + return primitive; + } + }; + assertThrowsInstanceOf(() => { + let [] = obj; + }, TypeError); + assertThrowsInstanceOf(() => { + [] = obj; + }, TypeError); + assertThrowsInstanceOf(() => { + f(obj); + }, TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/destructuring/order-super.js b/js/src/tests/non262/destructuring/order-super.js new file mode 100644 index 0000000000..2bc534e23f --- /dev/null +++ b/js/src/tests/non262/destructuring/order-super.js @@ -0,0 +1,701 @@ +var BUGNUMBER = 1204028; +var summary = "Destructuring should evaluate lhs reference before rhs in super property"; + +if (typeof assertEq === "undefined") { + assertEq = function(a, b) { + if (a !== b) + throw new Error(`expected ${b}, got ${a}\n${new Error().stack}`); + }; +} + +print(BUGNUMBER + ": " + summary); + +let logs = []; +function log(x) { + logs.push(x); +} + +let unwrapMap = new Map(); +function unwrap(maybeWrapped) { + if (unwrapMap.has(maybeWrapped)) + return unwrapMap.get(maybeWrapped); + return maybeWrapped; +} +function ToString(name) { + if (name == Symbol.iterator) + return "@@iterator"; + return String(name); +} +function logger(obj, prefix=[]) { + let wrapped = new Proxy(obj, { + get(that, name) { + if (name == "return") { + // FIXME: Bug 1147371. + // We ignore IteratorClose for now. + return obj[name]; + } + + let names = prefix.concat(ToString(name)); + log("rhs get " + names.join("::")); + let v = obj[name]; + if (typeof v === "object" || typeof v === "function") + return logger(v, names); + return v; + }, + apply(that, thisArg, args) { + let names = prefix.slice(); + log("rhs call " + names.join("::")); + let v = obj.apply(unwrap(thisArg), args); + if (typeof v === "object" || typeof v === "function") { + names[names.length - 1] += "()"; + return logger(v, names); + } + return v; + } + }); + unwrapMap.set(wrapped, obj); + return wrapped; +} + +class C1 { + constructor() { + this.clear(); + } + clear() { + this.values = {}; + } +} +for (let name of [ + "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", + "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", + "0", "1", "length" +]) { + Object.defineProperty(C1.prototype, name, { + set: function(value) { + log("lhs set " + name); + this.values[name] = value; + } + }); +} +class C2 extends C1 { + constructor() { + super(); + + let clear = () => { + logs = []; + this.clear(); + }; + + // Array. + + clear(); + [ + super.a + ] = logger(["A"]); + assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "lhs set a", + ].join(",")); + assertEq(this.values.a, "A"); + + clear(); + [ + super[ (log("lhs before name a"), "a") ] + ] = logger(["A"]); + assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "lhs before name a", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "lhs set a", + ].join(",")); + assertEq(this.values.a, "A"); + + // Array rest. + + clear(); + [ + ...super.a + ] = logger(["A", "B", "C"]); + assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "lhs set a", + ].join(",")); + assertEq(this.values.a.join(","), "A,B,C"); + + clear(); + [ + ...super[ (log("lhs before name a"), "a") ] + ] = logger(["A", "B", "C"]);; + assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "lhs before name a", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "lhs set a", + ].join(",")); + assertEq(this.values.a.join(","), "A,B,C"); + + // Array combined. + + clear(); + [ + super.a, + super[ (log("lhs before name b"), "b") ], + ...super[ (log("lhs before name c"), "c") ] + ] = logger(["A", "B", "C"]); + assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "lhs set a", + + "lhs before name b", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "lhs set b", + + "lhs before name c", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "lhs set c", + ].join(",")); + assertEq(this.values.a, "A"); + assertEq(this.values.b, "B"); + assertEq(this.values.c.join(","), "C"); + + // Object. + + clear(); + ({ + a: super.a + } = logger({a: "A"})); + assertEq(logs.join(","), + [ + "rhs get a", + "lhs set a", + ].join(",")); + assertEq(this.values.a, "A"); + + clear(); + ({ + a: super[ (log("lhs before name a"), "a") ] + } = logger({a: "A"})); + assertEq(logs.join(","), + [ + "lhs before name a", + "rhs get a", + "lhs set a", + ].join(",")); + assertEq(this.values.a, "A"); + + // Object combined. + + clear(); + ({ + a: super.a, + b: super[ (log("lhs before name b"), "b") ] + } = logger({a: "A", b: "B"})); + assertEq(logs.join(","), + [ + "rhs get a", + "lhs set a", + + "lhs before name b", + "rhs get b", + "lhs set b", + ].join(",")); + assertEq(this.values.a, "A"); + assertEq(this.values.b, "B"); + + // == Nested == + + // Array -> Array + + clear(); + [ + [ + super[ (log("lhs before name a"), "a") ], + ...super[ (log("lhs before name b"), "b") ] + ] + ] = logger([["A", "B"]]); + assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs get @@iterator()::next()::value::@@iterator", + "rhs call @@iterator()::next()::value::@@iterator", + "rhs get @@iterator()::next()::value::@@iterator()::next", + + "lhs before name a", + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + "lhs set a", + + "lhs before name b", + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "lhs set b", + ].join(",")); + assertEq(this.values.a, "A"); + assertEq(this.values.b.length, 1); + assertEq(this.values.b[0], "B"); + + // Array rest -> Array + + clear(); + [ + ...[ + super[ (log("lhs before name a"), "a") ], + ...super[ (log("lhs before name b"), "b") ] + ] + ] = logger(["A", "B"]); + assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + + "lhs before name a", + "lhs set a", + + "lhs before name b", + "lhs set b", + ].join(",")); + assertEq(this.values.a, "A"); + assertEq(this.values.b.join(","), "B"); + + // Array -> Object + clear(); + [ + { + a: super[ (log("lhs before name a"), "a") ] + } + ] = logger([{a: "A"}]); + assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + + "lhs before name a", + "rhs get @@iterator()::next()::value::a", + "lhs set a", + ].join(",")); + assertEq(this.values.a, "A"); + + // Array rest -> Object + clear(); + [ + ...{ + 0: super[ (log("lhs before name 0"), "0") ], + 1: super[ (log("lhs before name 1"), "1") ], + length: super[ (log("lhs before name length"), "length") ], + } + ] = logger(["A", "B"]); + assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + + "lhs before name 0", + "lhs set 0", + + "lhs before name 1", + "lhs set 1", + + "lhs before name length", + "lhs set length", + ].join(",")); + assertEq(this.values["0"], "A"); + assertEq(this.values["1"], "B"); + assertEq(this.values.length, 2); + + // Object -> Array + clear(); + ({ + a: [ + super[ (log("lhs before name b"), "b") ] + ] + } = logger({a: ["B"]})); + assertEq(logs.join(","), + [ + "rhs get a", + "rhs get a::@@iterator", + "rhs call a::@@iterator", + "rhs get a::@@iterator()::next", + + "lhs before name b", + "rhs call a::@@iterator()::next", + "rhs get a::@@iterator()::next()::done", + "rhs get a::@@iterator()::next()::value", + "lhs set b", + ].join(",")); + assertEq(this.values.b, "B"); + + // Object -> Object + clear(); + ({ + a: { + b: super[ (log("lhs before name b"), "b") ] + } + } = logger({a: {b: "B"}})); + assertEq(logs.join(","), + [ + "rhs get a", + "lhs before name b", + "rhs get a::b", + "lhs set b", + ].join(",")); + assertEq(this.values.b, "B"); + + // All combined + + clear(); + [ + super[ (log("lhs before name a"), "a") ], + [ + super[ (log("lhs before name b"), "b") ], + { + c: super[ (log("lhs before name c"), "c") ], + d: { + e: super[ (log("lhs before name e"), "e") ], + f: [ + super[ (log("lhs before name g"), "g") ] + ] + } + } + ], + { + h: super[ (log("lhs before name h"), "h") ], + i: [ + super[ (log("lhs before name j"), "j") ], + { + k: [ + super[ (log("lhs before name l"), "l") ] + ] + } + ] + }, + ...[ + super[ (log("lhs before name m"), "m") ], + [ + super[ (log("lhs before name n"), "n") ], + { + o: super[ (log("lhs before name o"), "o") ], + p: { + q: super[ (log("lhs before name q"), "q") ], + r: [ + super[ (log("lhs before name s"), "s") ] + ] + } + } + ], + ...{ + 0: super[ (log("lhs before name t"), "t") ], + 1: [ + super[ (log("lhs before name u"), "u") ], + { + v: super[ (log("lhs before name v"), "v") ], + w: { + x: super[ (log("lhs before name x"), "x") ], + y: [ + super[ (log("lhs before name z"), "z") ] + ] + } + } + ], + length: super[ (log("lhs before name length"), "length") ], + } + ] + ] = logger(["A", + ["B", {c: "C", d: {e: "E", f: ["G"]}}], + {h: "H", i: ["J", {k: ["L"]}]}, + "M", + ["N", {o: "O", p: {q: "Q", r: ["S"]}}], + "T", ["U", {v: "V", w: {x: "X", y: ["Z"]}}]]); + assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "lhs before name a", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "lhs set a", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs get @@iterator()::next()::value::@@iterator", + "rhs call @@iterator()::next()::value::@@iterator", + "rhs get @@iterator()::next()::value::@@iterator()::next", + + "lhs before name b", + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + "lhs set b", + + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + + "lhs before name c", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::c", + "lhs set c", + + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::d", + + "lhs before name e", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::e", + "lhs set e", + + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator", + "rhs call @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator()::next", + + "lhs before name g", + "rhs call @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator()::next()::value", + "lhs set g", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + + "lhs before name h", + "rhs get @@iterator()::next()::value::h", + "lhs set h", + + "rhs get @@iterator()::next()::value::i", + "rhs get @@iterator()::next()::value::i::@@iterator", + "rhs call @@iterator()::next()::value::i::@@iterator", + "rhs get @@iterator()::next()::value::i::@@iterator()::next", + + "lhs before name j", + "rhs call @@iterator()::next()::value::i::@@iterator()::next", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::value", + "lhs set j", + + "rhs call @@iterator()::next()::value::i::@@iterator()::next", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::value", + + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator", + "rhs call @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator()::next", + + "lhs before name l", + "rhs call @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator()::next", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator()::next()::value", + "lhs set l", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + + "lhs before name m", + "lhs set m", + + "rhs get @@iterator()::next()::value::@@iterator", + "rhs call @@iterator()::next()::value::@@iterator", + "rhs get @@iterator()::next()::value::@@iterator()::next", + + "lhs before name n", + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + "lhs set n", + + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + + "lhs before name o", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::o", + "lhs set o", + + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::p", + + "lhs before name q", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::q", + "lhs set q", + + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator", + "rhs call @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator()::next", + + "lhs before name s", + "rhs call @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator()::next()::value", + "lhs set s", + + "lhs before name t", + "lhs set t", + + "rhs get @@iterator()::next()::value::@@iterator", + "rhs call @@iterator()::next()::value::@@iterator", + "rhs get @@iterator()::next()::value::@@iterator()::next", + + "lhs before name u", + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + "lhs set u", + + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + + "lhs before name v", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::v", + "lhs set v", + + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::w", + + "lhs before name x", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::x", + "lhs set x", + + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator", + "rhs call @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator()::next", + + "lhs before name z", + "rhs call @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator()::next()::value", + "lhs set z", + + "lhs before name length", + "lhs set length", + ].join(",")); + assertEq(this.values.a, "A"); + assertEq(this.values.b, "B"); + assertEq(this.values.c, "C"); + assertEq(this.values.e, "E"); + assertEq(this.values.g, "G"); + assertEq(this.values.h, "H"); + assertEq(this.values.j, "J"); + assertEq(this.values.l, "L"); + assertEq(this.values.m, "M"); + assertEq(this.values.n, "N"); + assertEq(this.values.o, "O"); + assertEq(this.values.q, "Q"); + assertEq(this.values.s, "S"); + assertEq(this.values.t, "T"); + assertEq(this.values.u, "U"); + assertEq(this.values.v, "V"); + assertEq(this.values.x, "X"); + assertEq(this.values.z, "Z"); + assertEq(this.values.length, 2); + } +} + +new C2(); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/destructuring/order.js b/js/src/tests/non262/destructuring/order.js new file mode 100644 index 0000000000..4da0a58512 --- /dev/null +++ b/js/src/tests/non262/destructuring/order.js @@ -0,0 +1,719 @@ +var BUGNUMBER = 1204028; +var summary = "Destructuring should evaluate lhs reference before rhs"; + +print(BUGNUMBER + ": " + summary); + +let storage = { + clear() { + this.values = {}; + } +}; +storage.clear(); +let obj = new Proxy(storage, { + set(that, name, value) { + log("lhs set " + name); + storage.values[name] = value; + } +}); + +let logs = []; +function log(x) { + logs.push(x); +} + +function clear() { + logs = []; + storage.clear(); +} + +let unwrapMap = new Map(); +function unwrap(maybeWrapped) { + if (unwrapMap.has(maybeWrapped)) + return unwrapMap.get(maybeWrapped); + return maybeWrapped; +} +function ToString(name) { + if (name == Symbol.iterator) + return "@@iterator"; + return String(name); +} +function logger(obj, prefix=[]) { + let wrapped = new Proxy(obj, { + get(that, name) { + if (name == "return") { + // FIXME: Bug 1147371. + // We ignore IteratorClose for now. + return obj[name]; + } + + let names = prefix.concat(ToString(name)); + log("rhs get " + names.join("::")); + let v = obj[name]; + if (typeof v === "object" || typeof v === "function") + return logger(v, names); + return v; + }, + apply(that, thisArg, args) { + let names = prefix.slice(); + log("rhs call " + names.join("::")); + let v = obj.apply(unwrap(thisArg), args); + if (typeof v === "object" || typeof v === "function") { + names[names.length - 1] += "()"; + return logger(v, names); + } + return v; + } + }); + unwrapMap.set(wrapped, obj); + return wrapped; +} + +// Array. + +clear(); +[ + ( log("lhs before obj a"), obj ).a +] = logger(["A"]); +assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "lhs before obj a", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "lhs set a", + ].join(",")); +assertEq(storage.values.a, "A"); + +clear(); +[ + ( log("lhs before obj a"), obj )[ (log("lhs before name a"), "a") ] +] = logger(["A"]); +assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "lhs before obj a", + "lhs before name a", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "lhs set a", + ].join(",")); +assertEq(storage.values.a, "A"); + +// Array rest. + +clear(); +[ + ...( log("lhs before obj a"), obj ).a +] = logger(["A", "B", "C"]); +assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "lhs before obj a", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "lhs set a", + ].join(",")); +assertEq(storage.values.a.join(","), "A,B,C"); + +clear(); +[ + ...( log("lhs before obj a"), obj )[ (log("lhs before name a"), "a") ] +] = logger(["A", "B", "C"]);; +assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "lhs before obj a", + "lhs before name a", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "lhs set a", + ].join(",")); +assertEq(storage.values.a.join(","), "A,B,C"); + +// Array combined. + +clear(); +[ + ( log("lhs before obj a"), obj ).a, + ( log("lhs before obj b"), obj )[ (log("lhs before name b"), "b") ], + ...( log("lhs before obj c"), obj )[ (log("lhs before name c"), "c") ] +] = logger(["A", "B", "C"]); +assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "lhs before obj a", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "lhs set a", + + "lhs before obj b", + "lhs before name b", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "lhs set b", + + "lhs before obj c", + "lhs before name c", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "lhs set c", + ].join(",")); +assertEq(storage.values.a, "A"); +assertEq(storage.values.b, "B"); +assertEq(storage.values.c.join(","), "C"); + +// Object. + +clear(); +({ + a: ( log("lhs before obj a"), obj ).a +} = logger({a: "A"})); +assertEq(logs.join(","), + [ + "lhs before obj a", + "rhs get a", + "lhs set a", + ].join(",")); +assertEq(storage.values.a, "A"); + +clear(); +({ + a: ( log("lhs before obj a"), obj )[ (log("lhs before name a"), "a") ] +} = logger({a: "A"})); +assertEq(logs.join(","), + [ + "lhs before obj a", + "lhs before name a", + "rhs get a", + "lhs set a", + ].join(",")); +assertEq(storage.values.a, "A"); + +// Object combined. + +clear(); +({ + a: ( log("lhs before obj a"), obj ).a, + b: ( log("lhs before obj b"), obj )[ (log("lhs before name b"), "b") ] +} = logger({a: "A", b: "B"})); +assertEq(logs.join(","), + [ + "lhs before obj a", + "rhs get a", + "lhs set a", + + "lhs before obj b", + "lhs before name b", + "rhs get b", + "lhs set b", + ].join(",")); +assertEq(storage.values.a, "A"); +assertEq(storage.values.b, "B"); + +// == Nested == + +// Array -> Array + +clear(); +[ + [ + ( log("lhs before obj a"), obj )[ (log("lhs before name a"), "a") ], + ...( log("lhs before obj b"), obj )[ (log("lhs before name b"), "b") ] + ] +] = logger([["A", "B"]]); +assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs get @@iterator()::next()::value::@@iterator", + "rhs call @@iterator()::next()::value::@@iterator", + "rhs get @@iterator()::next()::value::@@iterator()::next", + + "lhs before obj a", + "lhs before name a", + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + "lhs set a", + + "lhs before obj b", + "lhs before name b", + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "lhs set b", + ].join(",")); +assertEq(storage.values.a, "A"); +assertEq(storage.values.b.length, 1); +assertEq(storage.values.b[0], "B"); + +// Array rest -> Array + +clear(); +[ + ...[ + ( log("lhs before obj a"), obj )[ (log("lhs before name a"), "a") ], + ...( log("lhs before obj b"), obj )[ (log("lhs before name b"), "b") ] + ] +] = logger(["A", "B"]); +assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + + "lhs before obj a", + "lhs before name a", + "lhs set a", + + "lhs before obj b", + "lhs before name b", + "lhs set b", + ].join(",")); +assertEq(storage.values.a, "A"); +assertEq(storage.values.b.join(","), "B"); + +// Array -> Object +clear(); +[ + { + a: ( log("lhs before obj a"), obj )[ (log("lhs before name a"), "a") ] + } +] = logger([{a: "A"}]); +assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + + "lhs before obj a", + "lhs before name a", + "rhs get @@iterator()::next()::value::a", + "lhs set a", + ].join(",")); +assertEq(storage.values.a, "A"); + +// Array rest -> Object +clear(); +[ + ...{ + 0: ( log("lhs before obj 0"), obj )[ (log("lhs before name 0"), "0") ], + 1: ( log("lhs before obj 1"), obj )[ (log("lhs before name 1"), "1") ], + length: ( log("lhs before obj length"), obj )[ (log("lhs before name length"), "length") ], + } +] = logger(["A", "B"]); +assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + + "lhs before obj 0", + "lhs before name 0", + "lhs set 0", + + "lhs before obj 1", + "lhs before name 1", + "lhs set 1", + + "lhs before obj length", + "lhs before name length", + "lhs set length", + ].join(",")); +assertEq(storage.values["0"], "A"); +assertEq(storage.values["1"], "B"); +assertEq(storage.values.length, 2); + +// Object -> Array +clear(); +({ + a: [ + ( log("lhs before obj b"), obj )[ (log("lhs before name b"), "b") ] + ] +} = logger({a: ["B"]})); +assertEq(logs.join(","), + [ + "rhs get a", + "rhs get a::@@iterator", + "rhs call a::@@iterator", + "rhs get a::@@iterator()::next", + + "lhs before obj b", + "lhs before name b", + "rhs call a::@@iterator()::next", + "rhs get a::@@iterator()::next()::done", + "rhs get a::@@iterator()::next()::value", + "lhs set b", + ].join(",")); +assertEq(storage.values.b, "B"); + +// Object -> Object +clear(); +({ + a: { + b: ( log("lhs before obj b"), obj )[ (log("lhs before name b"), "b") ] + } +} = logger({a: {b: "B"}})); +assertEq(logs.join(","), + [ + "rhs get a", + "lhs before obj b", + "lhs before name b", + "rhs get a::b", + "lhs set b", + ].join(",")); +assertEq(storage.values.b, "B"); + +// All combined + +clear(); +[ + ( log("lhs before obj a"), obj )[ (log("lhs before name a"), "a") ], + [ + ( log("lhs before obj b"), obj )[ (log("lhs before name b"), "b") ], + { + c: ( log("lhs before obj c"), obj )[ (log("lhs before name c"), "c") ], + d: { + e: ( log("lhs before obj e"), obj )[ (log("lhs before name e"), "e") ], + f: [ + ( log("lhs before obj g"), obj )[ (log("lhs before name g"), "g") ] + ] + } + } + ], + { + h: ( log("lhs before obj h"), obj )[ (log("lhs before name h"), "h") ], + i: [ + ( log("lhs before obj j"), obj )[ (log("lhs before name j"), "j") ], + { + k: [ + ( log("lhs before obj l"), obj )[ (log("lhs before name l"), "l") ] + ] + } + ] + }, + ...[ + ( log("lhs before obj m"), obj )[ (log("lhs before name m"), "m") ], + [ + ( log("lhs before obj n"), obj )[ (log("lhs before name n"), "n") ], + { + o: ( log("lhs before obj o"), obj )[ (log("lhs before name o"), "o") ], + p: { + q: ( log("lhs before obj q"), obj )[ (log("lhs before name q"), "q") ], + r: [ + ( log("lhs before obj s"), obj )[ (log("lhs before name s"), "s") ] + ] + } + } + ], + ...{ + 0: ( log("lhs before obj t"), obj )[ (log("lhs before name t"), "t") ], + 1: [ + ( log("lhs before obj u"), obj )[ (log("lhs before name u"), "u") ], + { + v: ( log("lhs before obj v"), obj )[ (log("lhs before name v"), "v") ], + w: { + x: ( log("lhs before obj x"), obj )[ (log("lhs before name x"), "x") ], + y: [ + ( log("lhs before obj z"), obj )[ (log("lhs before name z"), "z") ] + ] + } + } + ], + length: ( log("lhs before obj length"), obj )[ (log("lhs before name length"), "length") ], + } + ] +] = logger(["A", + ["B", {c: "C", d: {e: "E", f: ["G"]}}], + {h: "H", i: ["J", {k: ["L"]}]}, + "M", + ["N", {o: "O", p: {q: "Q", r: ["S"]}}], + "T", ["U", {v: "V", w: {x: "X", y: ["Z"]}}]]); +assertEq(logs.join(","), + [ + "rhs get @@iterator", + "rhs call @@iterator", + "rhs get @@iterator()::next", + + "lhs before obj a", + "lhs before name a", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "lhs set a", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs get @@iterator()::next()::value::@@iterator", + "rhs call @@iterator()::next()::value::@@iterator", + "rhs get @@iterator()::next()::value::@@iterator()::next", + + "lhs before obj b", + "lhs before name b", + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + "lhs set b", + + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + + "lhs before obj c", + "lhs before name c", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::c", + "lhs set c", + + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::d", + + "lhs before obj e", + "lhs before name e", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::e", + "lhs set e", + + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator", + "rhs call @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator()::next", + + "lhs before obj g", + "lhs before name g", + "rhs call @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::d::f::@@iterator()::next()::value", + "lhs set g", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + + "lhs before obj h", + "lhs before name h", + "rhs get @@iterator()::next()::value::h", + "lhs set h", + + "rhs get @@iterator()::next()::value::i", + "rhs get @@iterator()::next()::value::i::@@iterator", + "rhs call @@iterator()::next()::value::i::@@iterator", + "rhs get @@iterator()::next()::value::i::@@iterator()::next", + + "lhs before obj j", + "lhs before name j", + "rhs call @@iterator()::next()::value::i::@@iterator()::next", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::value", + "lhs set j", + + "rhs call @@iterator()::next()::value::i::@@iterator()::next", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::value", + + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator", + "rhs call @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator()::next", + + "lhs before obj l", + "lhs before name l", + "rhs call @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator()::next", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::i::@@iterator()::next()::value::k::@@iterator()::next()::value", + "lhs set l", + + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + "rhs get @@iterator()::next()::value", + "rhs call @@iterator()::next", + "rhs get @@iterator()::next()::done", + + "lhs before obj m", + "lhs before name m", + "lhs set m", + + "rhs get @@iterator()::next()::value::@@iterator", + "rhs call @@iterator()::next()::value::@@iterator", + "rhs get @@iterator()::next()::value::@@iterator()::next", + + "lhs before obj n", + "lhs before name n", + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + "lhs set n", + + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + + "lhs before obj o", + "lhs before name o", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::o", + "lhs set o", + + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::p", + + "lhs before obj q", + "lhs before name q", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::q", + "lhs set q", + + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator", + "rhs call @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator()::next", + + "lhs before obj s", + "lhs before name s", + "rhs call @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::p::r::@@iterator()::next()::value", + "lhs set s", + + "lhs before obj t", + "lhs before name t", + "lhs set t", + + "rhs get @@iterator()::next()::value::@@iterator", + "rhs call @@iterator()::next()::value::@@iterator", + "rhs get @@iterator()::next()::value::@@iterator()::next", + + "lhs before obj u", + "lhs before name u", + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + "lhs set u", + + "rhs call @@iterator()::next()::value::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value", + + "lhs before obj v", + "lhs before name v", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::v", + "lhs set v", + + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::w", + + "lhs before obj x", + "lhs before name x", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::x", + "lhs set x", + + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator", + "rhs call @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator()::next", + + "lhs before obj z", + "lhs before name z", + "rhs call @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator()::next", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator()::next()::done", + "rhs get @@iterator()::next()::value::@@iterator()::next()::value::w::y::@@iterator()::next()::value", + "lhs set z", + + "lhs before obj length", + "lhs before name length", + "lhs set length", + ].join(",")); +assertEq(storage.values.a, "A"); +assertEq(storage.values.b, "B"); +assertEq(storage.values.c, "C"); +assertEq(storage.values.e, "E"); +assertEq(storage.values.g, "G"); +assertEq(storage.values.h, "H"); +assertEq(storage.values.j, "J"); +assertEq(storage.values.l, "L"); +assertEq(storage.values.m, "M"); +assertEq(storage.values.n, "N"); +assertEq(storage.values.o, "O"); +assertEq(storage.values.q, "Q"); +assertEq(storage.values.s, "S"); +assertEq(storage.values.t, "T"); +assertEq(storage.values.u, "U"); +assertEq(storage.values.v, "V"); +assertEq(storage.values.x, "X"); +assertEq(storage.values.z, "Z"); +assertEq(storage.values.length, 2); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/destructuring/rest-parameter-aray-iterator.js b/js/src/tests/non262/destructuring/rest-parameter-aray-iterator.js new file mode 100644 index 0000000000..bf9643fd78 --- /dev/null +++ b/js/src/tests/non262/destructuring/rest-parameter-aray-iterator.js @@ -0,0 +1,40 @@ +/* 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/. */ + +// Destructuring rest arrays call the array iterator. This behaviour is +// observable when Array.prototype[Symbol.iterator] is overridden. + +const oldArrayIterator = Array.prototype[Symbol.iterator]; +try { + let callCount = 0; + Array.prototype[Symbol.iterator] = function() { + callCount += 1; + return oldArrayIterator.call(this); + }; + + // Array iterator called exactly once. + function arrayIterCalledOnce(...[]) { } + assertEq(callCount, 0); + arrayIterCalledOnce(); + assertEq(callCount, 1); + + // Array iterator not called before rest parameter. + callCount = 0; + function arrayIterNotCalledBeforeRest(t = assertEq(callCount, 0), ...[]) { } + assertEq(callCount, 0); + arrayIterNotCalledBeforeRest(); + assertEq(callCount, 1); + + // Array iterator called when rest parameter is processed. + callCount = 0; + function arrayIterCalledWhenDestructuring(...[t = assertEq(callCount, 1)]) { } + assertEq(callCount, 0); + arrayIterCalledWhenDestructuring(); + assertEq(callCount, 1); +} finally { + Array.prototype[Symbol.iterator] = oldArrayIterator; +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/destructuring/rest-parameter-arguments.js b/js/src/tests/non262/destructuring/rest-parameter-arguments.js new file mode 100644 index 0000000000..e87cdff339 --- /dev/null +++ b/js/src/tests/non262/destructuring/rest-parameter-arguments.js @@ -0,0 +1,101 @@ +/* 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/. */ + +// Ensure the |arguments| object works as expected when a destructuring rest +// parameter is present. + +// |arguments.length| with destructuring rest array. +function argsLengthEmptyRestArray(...[]) { + return arguments.length; +} +assertEq(argsLengthEmptyRestArray(), 0); +assertEq(argsLengthEmptyRestArray(10), 1); +assertEq(argsLengthEmptyRestArray(10, 20), 2); + +function argsLengthRestArray(...[a]) { + return arguments.length; +} +assertEq(argsLengthRestArray(), 0); +assertEq(argsLengthRestArray(10), 1); +assertEq(argsLengthRestArray(10, 20), 2); + +function argsLengthRestArrayWithDefault(...[a = 0]) { + return arguments.length; +} +assertEq(argsLengthRestArrayWithDefault(), 0); +assertEq(argsLengthRestArrayWithDefault(10), 1); +assertEq(argsLengthRestArrayWithDefault(10, 20), 2); + + +// |arguments.length| with destructuring rest object. +function argsLengthEmptyRestObject(...{}) { + return arguments.length; +} +assertEq(argsLengthEmptyRestObject(), 0); +assertEq(argsLengthEmptyRestObject(10), 1); +assertEq(argsLengthEmptyRestObject(10, 20), 2); + +function argsLengthRestObject(...{a}) { + return arguments.length; +} +assertEq(argsLengthRestObject(), 0); +assertEq(argsLengthRestObject(10), 1); +assertEq(argsLengthRestObject(10, 20), 2); + +function argsLengthRestObjectWithDefault(...{a = 0}) { + return arguments.length; +} +assertEq(argsLengthRestObjectWithDefault(), 0); +assertEq(argsLengthRestObjectWithDefault(10), 1); +assertEq(argsLengthRestObjectWithDefault(10, 20), 2); + + +// |arguments| access with destructuring rest array. +function argsAccessEmptyRestArray(...[]) { + return arguments[0]; +} +assertEq(argsAccessEmptyRestArray(), undefined); +assertEq(argsAccessEmptyRestArray(10), 10); +assertEq(argsAccessEmptyRestArray(10, 20), 10); + +function argsAccessRestArray(...[a]) { + return arguments[0]; +} +assertEq(argsAccessRestArray(), undefined); +assertEq(argsAccessRestArray(10), 10); +assertEq(argsAccessRestArray(10, 20), 10); + +function argsAccessRestArrayWithDefault(...[a = 0]) { + return arguments[0]; +} +assertEq(argsAccessRestArrayWithDefault(), undefined); +assertEq(argsAccessRestArrayWithDefault(10), 10); +assertEq(argsAccessRestArrayWithDefault(10, 20), 10); + + +// |arguments| access with destructuring rest object. +function argsAccessEmptyRestObject(...{}) { + return arguments[0]; +} +assertEq(argsAccessEmptyRestObject(), undefined); +assertEq(argsAccessEmptyRestObject(10), 10); +assertEq(argsAccessEmptyRestObject(10, 20), 10); + +function argsAccessRestObject(...{a}) { + return arguments[0]; +} +assertEq(argsAccessRestObject(), undefined); +assertEq(argsAccessRestObject(10), 10); +assertEq(argsAccessRestObject(10, 20), 10); + +function argsAccessRestObjectWithDefault(...{a = 0}) { + return arguments[0]; +} +assertEq(argsAccessRestObjectWithDefault(), undefined); +assertEq(argsAccessRestObjectWithDefault(10), 10); +assertEq(argsAccessRestObjectWithDefault(10, 20), 10); + + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/destructuring/rest-parameter-function-length.js b/js/src/tests/non262/destructuring/rest-parameter-function-length.js new file mode 100644 index 0000000000..5924e799ad --- /dev/null +++ b/js/src/tests/non262/destructuring/rest-parameter-function-length.js @@ -0,0 +1,41 @@ +/* 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/. */ + +// Ensure function length is set correctly when a destructuring rest parameter +// is present. + +assertEq(function(...[]) {}.length, 0); +assertEq(function(...[a]) {}.length, 0); +assertEq(function(...[a = 0]) {}.length, 0); +assertEq(function(...{}) {}.length, 0); +assertEq(function(...{p: a}) {}.length, 0); +assertEq(function(...{p: a = 0}) {}.length, 0); +assertEq(function(...{a = 0}) {}.length, 0); + +assertEq(function(x, ...[]) {}.length, 1); +assertEq(function(x, ...[a]) {}.length, 1); +assertEq(function(x, ...[a = 0]) {}.length, 1); +assertEq(function(x, ...{}) {}.length, 1); +assertEq(function(x, ...{p: a}) {}.length, 1); +assertEq(function(x, ...{p: a = 0}) {}.length, 1); +assertEq(function(x, ...{a = 0}) {}.length, 1); + +assertEq(function(x, y, ...[]) {}.length, 2); +assertEq(function(x, y, ...[a]) {}.length, 2); +assertEq(function(x, y, ...[a = 0]) {}.length, 2); +assertEq(function(x, y, ...{}) {}.length, 2); +assertEq(function(x, y, ...{p: a}) {}.length, 2); +assertEq(function(x, y, ...{p: a = 0}) {}.length, 2); +assertEq(function(x, y, ...{a = 0}) {}.length, 2); + +assertEq(function(x, y = 0, ...[]) {}.length, 1); +assertEq(function(x, y = 0, ...[a]) {}.length, 1); +assertEq(function(x, y = 0, ...[a = 0]) {}.length, 1); +assertEq(function(x, y = 0, ...{}) {}.length, 1); +assertEq(function(x, y = 0, ...{p: a}) {}.length, 1); +assertEq(function(x, y = 0, ...{p: a = 0}) {}.length, 1); +assertEq(function(x, y = 0, ...{a = 0}) {}.length, 1); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/destructuring/rest-parameter-spread-call-optimization.js b/js/src/tests/non262/destructuring/rest-parameter-spread-call-optimization.js new file mode 100644 index 0000000000..20f6a529dc --- /dev/null +++ b/js/src/tests/non262/destructuring/rest-parameter-spread-call-optimization.js @@ -0,0 +1,29 @@ +/* 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/. */ + +// Ensure the spread-call optimization doesn't break when a destructuring rest +// parameter is used. + +function spreadTarget() { return arguments.length; } + +function spreadOpt(...[r]){ return spreadTarget(...r); } +assertEq(spreadOpt([]), 0); +assertEq(spreadOpt([10]), 1); +assertEq(spreadOpt([10, 20]), 2); +assertEq(spreadOpt([10, 20, 30]), 3); + +function spreadOpt2(...[...r]){ return spreadTarget(...r); } +assertEq(spreadOpt2(), 0); +assertEq(spreadOpt2(10), 1); +assertEq(spreadOpt2(10, 20), 2); +assertEq(spreadOpt2(10, 20, 30), 3); + +function spreadOpt3(r, ...[]){ return spreadTarget(...r); } +assertEq(spreadOpt3([]), 0); +assertEq(spreadOpt3([10]), 1); +assertEq(spreadOpt3([10, 20]), 2); +assertEq(spreadOpt3([10, 20, 30]), 3); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/destructuring/rest-parameter-syntax.js b/js/src/tests/non262/destructuring/rest-parameter-syntax.js new file mode 100644 index 0000000000..a145d1a2df --- /dev/null +++ b/js/src/tests/non262/destructuring/rest-parameter-syntax.js @@ -0,0 +1,87 @@ +/* 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 bindingPatterns = [ + "[]", + "[a]", + "[a, b]", + "[a, ...b]", + "[...a]", + "[...[]]", + + "{}", + "{p: a}", + "{p: a = 0}", + "{p: {}}", + "{p: a, q: b}", + "{a}", + "{a, b}", + "{a = 0}", +]; + +const functions = [ + p => `function f(${p}) {}`, + p => `function* g(${p}) {}`, + p => `({m(${p}) {}});`, + p => `(class {m(${p}) {}});`, + p => `(${p}) => {};`, +]; + +for (let pattern of bindingPatterns) { + for (let fn of functions) { + // No leading parameters. + eval(fn(`...${pattern}`)); + + // Leading normal parameters. + eval(fn(`x, ...${pattern}`)); + eval(fn(`x, y, ...${pattern}`)); + + // Leading parameters with defaults. + eval(fn(`x = 0, ...${pattern}`)); + eval(fn(`x = 0, y = 0, ...${pattern}`)); + + // Leading array destructuring parameters. + eval(fn(`[], ...${pattern}`)); + eval(fn(`[x], ...${pattern}`)); + eval(fn(`[x = 0], ...${pattern}`)); + eval(fn(`[...x], ...${pattern}`)); + + // Leading object destructuring parameters. + eval(fn(`{}, ...${pattern}`)); + eval(fn(`{p: x}, ...${pattern}`)); + eval(fn(`{x}, ...${pattern}`)); + eval(fn(`{x = 0}, ...${pattern}`)); + + // Trailing parameters after rest parameter. + assertThrowsInstanceOf(() => eval(fn(`...${pattern},`)), SyntaxError); + assertThrowsInstanceOf(() => eval(fn(`...${pattern}, x`)), SyntaxError); + assertThrowsInstanceOf(() => eval(fn(`...${pattern}, x = 0`)), SyntaxError); + assertThrowsInstanceOf(() => eval(fn(`...${pattern}, ...x`)), SyntaxError); + assertThrowsInstanceOf(() => eval(fn(`...${pattern}, []`)), SyntaxError); + assertThrowsInstanceOf(() => eval(fn(`...${pattern}, {}`)), SyntaxError); + + // Rest parameter with defaults. + assertThrowsInstanceOf(() => eval(fn(`...${pattern} = 0`)), SyntaxError); + } +} + +for (let fn of functions) { + // Missing name, incomplete patterns. + assertThrowsInstanceOf(() => eval(fn(`...`)), SyntaxError); + assertThrowsInstanceOf(() => eval(fn(`...[`)), SyntaxError); + assertThrowsInstanceOf(() => eval(fn(`...{`)), SyntaxError); + + // Invalid binding name. + assertThrowsInstanceOf(() => eval(fn(`...[0]`)), SyntaxError); + assertThrowsInstanceOf(() => eval(fn(`...[p.q]`)), SyntaxError); +} + +// Rest parameters aren't valid in getter/setter methods. +assertThrowsInstanceOf(() => eval(`({get p(...[]) {}})`), SyntaxError); +assertThrowsInstanceOf(() => eval(`({set p(...[]) {}})`), SyntaxError); + + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/destructuring/rest-parameter.js b/js/src/tests/non262/destructuring/rest-parameter.js new file mode 100644 index 0000000000..50d77f3cc5 --- /dev/null +++ b/js/src/tests/non262/destructuring/rest-parameter.js @@ -0,0 +1,54 @@ +/* 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/. */ + +// Simple functional test for destructuring rest parameters. + +function arrayRest(...[a, b]) { + return a + b; +} +assertEq(arrayRest(3, 7), 10); + + +function arrayRestWithDefault(...[a, b = 1]) { + return a + b; +} +assertEq(arrayRestWithDefault(3, 7), 10); +assertEq(arrayRestWithDefault(4), 5); +assertEq(arrayRestWithDefault(4, undefined), 5); + + +function objectRest(...{length: len}) { + return len; +} +assertEq(objectRest(), 0); +assertEq(objectRest(10), 1); +assertEq(objectRest(10, 20), 2); + + +function objectRestWithDefault(...{0: a, 1: b = 1}) { + return a + b; +} +assertEq(objectRestWithDefault(3, 7), 10); +assertEq(objectRestWithDefault(4), 5); +assertEq(objectRestWithDefault(4, undefined), 5); + + +function arrayRestWithNestedRest(...[...r]) { + return r.length; +} +assertEq(arrayRestWithNestedRest(), 0); +assertEq(arrayRestWithNestedRest(10), 1); +assertEq(arrayRestWithNestedRest(10, 20), 2); + + +function arrayRestTDZ(...[a = a]) { } +assertThrowsInstanceOf(() => arrayRestTDZ(), ReferenceError); + + +function objectRestTDZ(...{a = a}) { } +assertThrowsInstanceOf(() => objectRestTDZ(), ReferenceError); + + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/destructuring/rest-with-trailing-comma.js b/js/src/tests/non262/destructuring/rest-with-trailing-comma.js new file mode 100644 index 0000000000..310180e14b --- /dev/null +++ b/js/src/tests/non262/destructuring/rest-with-trailing-comma.js @@ -0,0 +1,45 @@ +/* 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 invalidSyntax = [ + "[...r, ]", + "[a, ...r, ]", + "[a = 0, ...r, ]", + "[[], ...r, ]", + "[[...r,]]", + "[[...r,], ]", + "[[...r,], a]", +]; + +const validSyntax = [ + "[, ]", + "[a, ]", + "[[], ]", +]; + +const destructuringForms = [ + a => `${a} = [];`, + a => `var ${a} = [];`, + a => `let ${a} = [];`, + a => `const ${a} = [];`, + a => `(${a}) => {};`, + a => `(${a} = []) => {};`, + a => `function f(${a}) {}`, +]; + +for (let invalid of invalidSyntax) { + for (let fn of destructuringForms) { + assertThrowsInstanceOf(() => Function(fn(invalid)), SyntaxError); + } +} + +for (let invalid of validSyntax) { + for (let fn of destructuringForms) { + Function(fn(invalid)); + } +} + + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/destructuring/shell.js b/js/src/tests/non262/destructuring/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/destructuring/yield-in-object-destr-function.js b/js/src/tests/non262/destructuring/yield-in-object-destr-function.js new file mode 100644 index 0000000000..9f5eed8345 --- /dev/null +++ b/js/src/tests/non262/destructuring/yield-in-object-destr-function.js @@ -0,0 +1,182 @@ +/* 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/. */ + + +// Destructuring binding patterns with var. +(function() { + var {a: yield} = {a: "yield-with-name"}; + assertEq(yield, "yield-with-name"); + + var {yield} = {yield: "yield-with-shorthand"}; + assertEq(yield, "yield-with-shorthand"); + + var {yield = 0} = {yield: "yield-with-coverinitname"}; + assertEq(yield, "yield-with-coverinitname"); +})(); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f() { + var {a: yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f() { + var {yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f() { + var {yield = 0} = {}; + } +`), SyntaxError); + + +// Destructuring binding patterns with let. +(function(){ + let {a: yield} = {a: "yield-with-name"}; + assertEq(yield, "yield-with-name"); +})(); + +(function() { + let {yield} = {yield: "yield-with-shorthand"}; + assertEq(yield, "yield-with-shorthand"); +})(); + +(function() { + let {yield = 0} = {yield: "yield-with-coverinitname"}; + assertEq(yield, "yield-with-coverinitname"); +})(); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f() { + let {a: yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f() { + let {yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f() { + let {yield = 0} = {}; + } +`), SyntaxError); + + +// Destructuring binding patterns with const. +(function() { + const {a: yield} = {a: "yield-with-name"}; + assertEq(yield, "yield-with-name"); +})(); + +(function() { + const {yield} = {yield: "yield-with-shorthand"}; + assertEq(yield, "yield-with-shorthand"); +})(); + +(function() { + const {yield = 0} = {yield: "yield-with-coverinitname"}; + assertEq(yield, "yield-with-coverinitname"); +})(); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f() { + const {a: yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f() { + const {yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f() { + const {yield = 0} = {}; + } +`), SyntaxError); + + +// Destructuring binding patterns in parameters. +(function({a: yield} = {a: "yield-with-name"}) { + assertEq(yield, "yield-with-name"); +})(); + +(function({yield} = {yield: "yield-with-shorthand"}) { + assertEq(yield, "yield-with-shorthand"); +})(); + +(function({yield = 0} = {yield: "yield-with-coverinitname"}) { + assertEq(yield, "yield-with-coverinitname"); +})(); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f({a: yield} = {}) { } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f({yield} = {}) { } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f({yield = 0} = {}) { } +`), SyntaxError); + + +// Destructuring assignment pattern. +(function() { + var a, yield; + + ({a: yield} = {a: "yield-with-name"}); + assertEq(yield, "yield-with-name"); + + ({yield} = {yield: "yield-with-shorthand"}); + assertEq(yield, "yield-with-shorthand"); + + ({yield = 0} = {yield: "yield-with-coverinitname"}); + assertEq(yield, "yield-with-coverinitname"); +})(); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f() { + ({a: yield} = {}); + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f() { + ({yield} = {}); + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function f() { + ({yield = 0} = {}); + } +`), SyntaxError); + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/destructuring/yield-in-object-destr-generator.js b/js/src/tests/non262/destructuring/yield-in-object-destr-generator.js new file mode 100644 index 0000000000..4423f8190f --- /dev/null +++ b/js/src/tests/non262/destructuring/yield-in-object-destr-generator.js @@ -0,0 +1,200 @@ +/* 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/. */ + + +// Destructuring binding patterns with var. +assertThrowsInstanceOf(() => eval(` + function* g() { + var {a: yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + function* g() { + var {yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + function* g() { + var {yield = 0} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g() { + var {a: yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g() { + var {yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g() { + var {yield = 0} = {}; + } +`), SyntaxError); + + +// Destructuring binding patterns with let. +assertThrowsInstanceOf(() => eval(` + function* g() { + let {a: yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + function* g() { + let {yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + function* g() { + let {yield = 0} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g() { + let {a: yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g() { + let {yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g() { + let {yield = 0} = {}; + } +`), SyntaxError); + + +// Destructuring binding patterns with const. +assertThrowsInstanceOf(() => eval(` + function* g() { + const {a: yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + function* g() { + const {yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + function* g() { + const {yield = 0} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g() { + const {a: yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g() { + const {yield} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g() { + const {yield = 0} = {}; + } +`), SyntaxError); + + +// Destructuring binding patterns in parameters. +assertThrowsInstanceOf(() => eval(` + function* g({a: yield} = {}) { } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + function* g({yield} = {}) { } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + function* g({yield = 0} = {}) { } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g({a: yield} = {}) { } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g({yield} = {}) { } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g({yield = 0} = {}) { } +`), SyntaxError); + + +// Destructuring assignment pattern. +assertThrowsInstanceOf(() => eval(` + function* g() { + ({a: yield} = {}); + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + function* g() { + ({yield} = {}); + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + function* g() { + ({yield = 0} = {}); + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g() { + ({a: yield} = {}); + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g() { + ({yield} = {}); + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + function* g() { + ({yield = 0} = {}); + } +`), SyntaxError); + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/destructuring/yield-in-object-destr-script.js b/js/src/tests/non262/destructuring/yield-in-object-destr-script.js new file mode 100644 index 0000000000..99b48dd417 --- /dev/null +++ b/js/src/tests/non262/destructuring/yield-in-object-destr-script.js @@ -0,0 +1,123 @@ +/* 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/. */ + + +// Destructuring binding patterns with var. +var {a: yield} = {a: "yield-with-name"}; +assertEq(yield, "yield-with-name"); + +var {yield} = {yield: "yield-with-shorthand"}; +assertEq(yield, "yield-with-shorthand"); + +var {yield = 0} = {yield: "yield-with-coverinitname"}; +assertEq(yield, "yield-with-coverinitname"); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + var {a: yield} = {}; +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + var {yield} = {}; +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + var {yield = 0} = {}; +`), SyntaxError); + + +// Destructuring binding patterns with let. +{ + let {a: yield} = {a: "yield-with-name"}; + assertEq(yield, "yield-with-name"); +} + +{ + let {yield} = {yield: "yield-with-shorthand"}; + assertEq(yield, "yield-with-shorthand"); +} + +{ + let {yield = 0} = {yield: "yield-with-coverinitname"}; + assertEq(yield, "yield-with-coverinitname"); +} + +assertThrowsInstanceOf(() => eval(` + "use strict"; + let {a: yield} = {}; +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + let {yield} = {}; +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + let {yield = 0} = {}; +`), SyntaxError); + + +// Destructuring binding patterns with const. +{ + const {a: yield} = {a: "yield-with-name"}; + assertEq(yield, "yield-with-name"); +} + +{ + const {yield} = {yield: "yield-with-shorthand"}; + assertEq(yield, "yield-with-shorthand"); +} + +{ + const {yield = 0} = {yield: "yield-with-coverinitname"}; + assertEq(yield, "yield-with-coverinitname"); +} + +assertThrowsInstanceOf(() => eval(` + "use strict"; + const {a: yield} = {}; +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + const {yield} = {}; +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + const {yield = 0} = {}; +`), SyntaxError); + + +// Destructuring assignment pattern. +({a: yield} = {a: "yield-with-name"}); +assertEq(yield, "yield-with-name"); + +({yield} = {yield: "yield-with-shorthand"}); +assertEq(yield, "yield-with-shorthand"); + +({yield = 0} = {yield: "yield-with-coverinitname"}); +assertEq(yield, "yield-with-coverinitname"); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + ({a: yield} = {}); +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + ({yield} = {}); +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(` + "use strict"; + ({yield = 0} = {}); +`), SyntaxError); + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-function.js b/js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-function.js new file mode 100644 index 0000000000..349badeaf7 --- /dev/null +++ b/js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-function.js @@ -0,0 +1,182 @@ +/* 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/. */ + + +// Destructuring binding patterns with var. +(function() { + var {a: yi\u0065ld} = {a: "yield-with-name"}; + assertEq(yield, "yield-with-name"); + + var {yi\u0065ld} = {yield: "yield-with-shorthand"}; + assertEq(yield, "yield-with-shorthand"); + + var {yi\u0065ld = 0} = {yield: "yield-with-coverinitname"}; + assertEq(yield, "yield-with-coverinitname"); +})(); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f() { + var {a: yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f() { + var {yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f() { + var {yi\u0065ld = 0} = {}; + } +`), SyntaxError); + + +// Destructuring binding patterns with let. +(function(){ + let {a: yi\u0065ld} = {a: "yield-with-name"}; + assertEq(yield, "yield-with-name"); +})(); + +(function() { + let {yi\u0065ld} = {yield: "yield-with-shorthand"}; + assertEq(yield, "yield-with-shorthand"); +})(); + +(function() { + let {yi\u0065ld = 0} = {yield: "yield-with-coverinitname"}; + assertEq(yield, "yield-with-coverinitname"); +})(); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f() { + let {a: yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f() { + let {yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f() { + let {yi\u0065ld = 0} = {}; + } +`), SyntaxError); + + +// Destructuring binding patterns with const. +(function() { + const {a: yi\u0065ld} = {a: "yield-with-name"}; + assertEq(yield, "yield-with-name"); +})(); + +(function() { + const {yi\u0065ld} = {yield: "yield-with-shorthand"}; + assertEq(yield, "yield-with-shorthand"); +})(); + +(function() { + const {yi\u0065ld = 0} = {yield: "yield-with-coverinitname"}; + assertEq(yield, "yield-with-coverinitname"); +})(); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f() { + const {a: yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f() { + const {yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f() { + const {yi\u0065ld = 0} = {}; + } +`), SyntaxError); + + +// Destructuring binding patterns in parameters. +(function({a: yi\u0065ld} = {a: "yield-with-name"}) { + assertEq(yield, "yield-with-name"); +})(); + +(function({yi\u0065ld} = {yield: "yield-with-shorthand"}) { + assertEq(yield, "yield-with-shorthand"); +})(); + +(function({yi\u0065ld = 0} = {yield: "yield-with-coverinitname"}) { + assertEq(yield, "yield-with-coverinitname"); +})(); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f({a: yi\u0065ld} = {}) { } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f({yi\u0065ld} = {}) { } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f({yi\u0065ld = 0} = {}) { } +`), SyntaxError); + + +// Destructuring assignment pattern. +(function() { + var a, yield; + + ({a: yi\u0065ld} = {a: "yield-with-name"}); + assertEq(yield, "yield-with-name"); + + ({yi\u0065ld} = {yield: "yield-with-shorthand"}); + assertEq(yield, "yield-with-shorthand"); + + ({yi\u0065ld = 0} = {yield: "yield-with-coverinitname"}); + assertEq(yield, "yield-with-coverinitname"); +})(); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f() { + ({a: yi\u0065ld} = {}); + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f() { + ({yi\u0065ld} = {}); + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function f() { + ({yi\u0065ld = 0} = {}); + } +`), SyntaxError); + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-generator.js b/js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-generator.js new file mode 100644 index 0000000000..faa3563914 --- /dev/null +++ b/js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-generator.js @@ -0,0 +1,200 @@ +/* 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/. */ + + +// Destructuring binding patterns with var. +assertThrowsInstanceOf(() => eval(String.raw` + function* g() { + var {a: yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + function* g() { + var {yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + function* g() { + var {yi\u0065ld = 0} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g() { + var {a: yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g() { + var {yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g() { + var {yi\u0065ld = 0} = {}; + } +`), SyntaxError); + + +// Destructuring binding patterns with let. +assertThrowsInstanceOf(() => eval(String.raw` + function* g() { + let {a: yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + function* g() { + let {yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + function* g() { + let {yi\u0065ld = 0} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g() { + let {a: yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g() { + let {yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g() { + let {yi\u0065ld = 0} = {}; + } +`), SyntaxError); + + +// Destructuring binding patterns with const. +assertThrowsInstanceOf(() => eval(String.raw` + function* g() { + const {a: yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + function* g() { + const {yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + function* g() { + const {yi\u0065ld = 0} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g() { + const {a: yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g() { + const {yi\u0065ld} = {}; + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g() { + const {yi\u0065ld = 0} = {}; + } +`), SyntaxError); + + +// Destructuring binding patterns in parameters. +assertThrowsInstanceOf(() => eval(String.raw` + function* g({a: yi\u0065ld} = {}) { } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + function* g({yi\u0065ld} = {}) { } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + function* g({yi\u0065ld = 0} = {}) { } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g({a: yi\u0065ld} = {}) { } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g({yi\u0065ld} = {}) { } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g({yi\u0065ld = 0} = {}) { } +`), SyntaxError); + + +// Destructuring assignment pattern. +assertThrowsInstanceOf(() => eval(String.raw` + function* g() { + ({a: yi\u0065ld} = {}); + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + function* g() { + ({yi\u0065ld} = {}); + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + function* g() { + ({yi\u0065ld = 0} = {}); + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g() { + ({a: yi\u0065ld} = {}); + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g() { + ({yi\u0065ld} = {}); + } +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + function* g() { + ({yi\u0065ld = 0} = {}); + } +`), SyntaxError); + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-script.js b/js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-script.js new file mode 100644 index 0000000000..65352a66cf --- /dev/null +++ b/js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-script.js @@ -0,0 +1,123 @@ +/* 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/. */ + + +// Destructuring binding patterns with var. +var {a: yi\u0065ld} = {a: "yield-with-name"}; +assertEq(yield, "yield-with-name"); + +var {yi\u0065ld} = {yield: "yield-with-shorthand"}; +assertEq(yield, "yield-with-shorthand"); + +var {yi\u0065ld = 0} = {yield: "yield-with-coverinitname"}; +assertEq(yield, "yield-with-coverinitname"); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + var {a: yi\u0065ld} = {}; +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + var {yi\u0065ld} = {}; +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + var {yi\u0065ld = 0} = {}; +`), SyntaxError); + + +// Destructuring binding patterns with let. +{ + let {a: yi\u0065ld} = {a: "yield-with-name"}; + assertEq(yield, "yield-with-name"); +} + +{ + let {yi\u0065ld} = {yield: "yield-with-shorthand"}; + assertEq(yield, "yield-with-shorthand"); +} + +{ + let {yi\u0065ld = 0} = {yield: "yield-with-coverinitname"}; + assertEq(yield, "yield-with-coverinitname"); +} + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + let {a: yi\u0065ld} = {}; +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + let {yi\u0065ld} = {}; +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + let {yi\u0065ld = 0} = {}; +`), SyntaxError); + + +// Destructuring binding patterns with const. +{ + const {a: yi\u0065ld} = {a: "yield-with-name"}; + assertEq(yield, "yield-with-name"); +} + +{ + const {yi\u0065ld} = {yield: "yield-with-shorthand"}; + assertEq(yield, "yield-with-shorthand"); +} + +{ + const {yi\u0065ld = 0} = {yield: "yield-with-coverinitname"}; + assertEq(yield, "yield-with-coverinitname"); +} + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + const {a: yi\u0065ld} = {}; +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + const {yi\u0065ld} = {}; +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + const {yi\u0065ld = 0} = {}; +`), SyntaxError); + + +// Destructuring assignment pattern. +({a: yi\u0065ld} = {a: "yield-with-name"}); +assertEq(yield, "yield-with-name"); + +({yi\u0065ld} = {yield: "yield-with-shorthand"}); +assertEq(yield, "yield-with-shorthand"); + +({yi\u0065ld = 0} = {yield: "yield-with-coverinitname"}); +assertEq(yield, "yield-with-coverinitname"); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + ({a: yi\u0065ld} = {}); +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + ({yi\u0065ld} = {}); +`), SyntaxError); + +assertThrowsInstanceOf(() => eval(String.raw` + "use strict"; + ({yi\u0065ld = 0} = {}); +`), SyntaxError); + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); -- cgit v1.2.3