diff options
Diffstat (limited to 'js/src/tests/ecma_6/Expressions/destructuring-pattern-parenthesized.js')
-rw-r--r-- | js/src/tests/ecma_6/Expressions/destructuring-pattern-parenthesized.js | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/js/src/tests/ecma_6/Expressions/destructuring-pattern-parenthesized.js b/js/src/tests/ecma_6/Expressions/destructuring-pattern-parenthesized.js new file mode 100644 index 000000000..ca495c886 --- /dev/null +++ b/js/src/tests/ecma_6/Expressions/destructuring-pattern-parenthesized.js @@ -0,0 +1,140 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 1146136; +var summary = + 'Parenthesized "destructuring patterns" are not usable as destructuring ' + + 'patterns'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// Don't pollute the top-level script with eval references. +var savedEval = this[String.fromCharCode(101, 118, 97, 108)]; + +function checkError(code, nonstrictErr, strictErr) +{ + function helper(exec, prefix, err) + { + var fullCode = prefix + code; + try + { + var f = exec(fullCode); + + var error = + "no early error, parsed code <" + fullCode + "> using " + exec.name; + if (typeof f === "function") + { + try + { + f(); + error += ", and the function can be called without error"; + } + catch (e) + { + error +=", and calling the function throws " + e; + } + } + + throw new Error(error); + } + catch (e) + { + assertEq(e instanceof err, true, + "expected " + err.name + ", got " + e + " " + + "for code <" + fullCode + "> when parsed using " + exec.name); + } + } + + helper(Function, "", nonstrictErr); + helper(Function, "'use strict'; ", strictErr); + helper(savedEval, "", nonstrictErr); + helper(savedEval, "'use strict'; ", strictErr); +} + +// Parenthesized destructuring patterns don't trigger grammar refinement, so we +// get the currently-usual ReferenceError for an invalid assignment target, per +// 12.14.1 second bullet. +checkError("var a, b; ([a, b]) = [1, 2];", ReferenceError, ReferenceError); +checkError("var a, b; ({a, b}) = { a: 1, b: 2 };", ReferenceError, ReferenceError); + +// *Nested* parenthesized destructuring patterns, on the other hand, do trigger +// grammar refinement. But subtargets in a destructuring pattern must be +// either object/array literals that match the destructuring pattern refinement +// *or* valid simple assignment targets (or such things with a default, with the +// entire subtarget unparenthesized: |a = 3| is fine, |(a) = 3| is fine for +// destructuring in an expression, |(a = 3)| is forbidden). Parenthesized +// object/array patterns are neither. And so 12.14.5.1 third bullet requires an +// early SyntaxError. +checkError("var a, b; ({ a: ({ b: b }) } = { a: { b: 42 } });", SyntaxError, SyntaxError); +checkError("var a, b; ({ a: { b: (b = 7) } } = { a: {} });", SyntaxError, SyntaxError); +checkError("var a, b; ({ a: ([b]) } = { a: [42] });", SyntaxError, SyntaxError); +checkError("var a, b; [(a = 5)] = [1];", SyntaxError, SyntaxError); +checkError("var a, b; ({ a: (b = 7)} = { b: 1 });", SyntaxError, SyntaxError); + +Function("var a, b; [(a), b] = [1, 2];")(); +Function("var a, b; [(a) = 5, b] = [1, 2];")(); +Function("var a, b; [(arguments), b] = [1, 2];")(); +Function("var a, b; [(arguments) = 5, b] = [1, 2];")(); +Function("var a, b; [(eval), b] = [1, 2];")(); +Function("var a, b; [(eval) = 5, b] = [1, 2];")(); + +var repair = {}, demolition = {}; + +Function("var a, b; [(repair.man), b] = [1, 2];")(); +Function("var a, b; [(demolition['man']) = 'motel', b] = [1, 2];")(); +Function("var a, b; [(demolition['man' + {}]) = 'motel', b] = [1, 2];")(); // evade constant-folding + +function classesEnabled() +{ + try + { + new Function("class B { constructor() { } }; class D extends B { constructor() { super(); } }"); + return true; + } + catch (e if e instanceof SyntaxError) + { + return false; + } +} + +if (classesEnabled()) +{ + Function("var a, b; var obj = { x() { [(super.man), b] = [1, 2]; } };")(); + Function("var a, b; var obj = { x() { [(super[8]) = 'motel', b] = [1, 2]; } };")(); + Function("var a, b; var obj = { x() { [(super[8 + {}]) = 'motel', b] = [1, 2]; } };")(); // evade constant-folding +} + +// As noted above, when the assignment element has an initializer, the +// assignment element must not be parenthesized. +checkError("var a, b; [(repair.man = 17)] = [1];", SyntaxError, SyntaxError); +checkError("var a, b; [(demolition['man'] = 'motel')] = [1, 2];", SyntaxError, SyntaxError); +checkError("var a, b; [(demolition['man' + {}] = 'motel')] = [1];", SyntaxError, SyntaxError); // evade constant-folding +if (classesEnabled()) +{ + checkError("var a, b; var obj = { x() { [(super.man = 5)] = [1]; } };", SyntaxError, SyntaxError); + checkError("var a, b; var obj = { x() { [(super[8] = 'motel')] = [1]; } };", SyntaxError, SyntaxError); + checkError("var a, b; var obj = { x() { [(super[8 + {}] = 'motel')] = [1]; } };", SyntaxError, SyntaxError); // evade constant-folding +} + +// In strict mode, assignment to funcall *immediately* triggers ReferenceError +// before we can recognize this doesn't even match the destructuring grammar to +// begin with. Bleh. :-( Probably they should all be made SyntaxError in the +// specs; see <https://bugs.ecmascript.org/show_bug.cgi?id=4375>. +checkError("var a, b; [f() = 'ohai', b] = [1, 2];", SyntaxError, ReferenceError); +checkError("var a, b; [(f()) = 'kthxbai', b] = [1, 2];", SyntaxError, ReferenceError); + +Function("var a, b; ({ a: (a), b} = { a: 1, b: 2 });")(); +Function("var a, b; ({ a: (a) = 5, b} = { a: 1, b: 2 });")(); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); |