mirror of
https://github.com/classilla/tenfourfox.git
synced 2025-01-12 20:30:18 +00:00
#485: mostly working destructuring nested rest assignment
This commit is contained in:
parent
c3b712f863
commit
6c2488e150
@ -3761,7 +3761,6 @@ BytecodeEmitter::emitDestructuringDeclsWithEmitter(JSOp prologueOp, ParseNode* p
|
||||
continue;
|
||||
ParseNode* target = element;
|
||||
if (element->isKind(PNK_SPREAD)) {
|
||||
MOZ_ASSERT(element->pn_kid->isKind(PNK_NAME));
|
||||
target = element->pn_kid;
|
||||
}
|
||||
if (target->isKind(PNK_ASSIGN))
|
||||
|
@ -4276,11 +4276,6 @@ Parser<FullParseHandler>::checkDestructuringArray(BindData<FullParseHandler>* da
|
||||
return false;
|
||||
}
|
||||
target = element->pn_kid;
|
||||
|
||||
if (handler.isUnparenthesizedDestructuringPattern(target)) {
|
||||
report(ParseError, false, target, JSMSG_BAD_DESTRUCT_TARGET);
|
||||
return false;
|
||||
}
|
||||
} else if (handler.isUnparenthesizedAssignment(element)) {
|
||||
target = element->pn_left;
|
||||
} else {
|
||||
|
@ -49,6 +49,23 @@ assertIterable([5,5,4,4],
|
||||
it => { var [,,...rest] = it; return rest; },
|
||||
[3,4]);
|
||||
|
||||
// the iterator should be exhausted before any error is thrown
|
||||
if(0) {
|
||||
// XXX: this doesn't throw right now. just test syntax below.
|
||||
// plan to reenable this for issue 485
|
||||
assertIterable([5,5,4,4],
|
||||
it => {
|
||||
assertThrowsInstanceOf(function () {
|
||||
"use strict";
|
||||
[...{0: "".x}] = it;
|
||||
}, TypeError);
|
||||
return [];
|
||||
},
|
||||
[]);
|
||||
} else {
|
||||
assertIterable([5,5,4,4], it => { [...{0: "".x}] = it; return []; }, []);
|
||||
}
|
||||
|
||||
var arraycalls = 0;
|
||||
var ArrayIterator = Array.prototype[Symbol.iterator];
|
||||
Array.prototype[Symbol.iterator] = function () {
|
||||
@ -58,7 +75,11 @@ Array.prototype[Symbol.iterator] = function () {
|
||||
// [...rest] should not call Array#@@iterator for the LHS
|
||||
var [...rest] = iterable;
|
||||
assertEq(arraycalls, 0, 'calls to Array#@@iterator');
|
||||
|
||||
// [...[...rest]] should do so, since it creates an implicit array for the
|
||||
// first rest pattern, then destructures that again using @@iterator() for the
|
||||
// second rest pattern.
|
||||
var [...[...rest]] = iterable;
|
||||
assertEq(arraycalls, 1, 'calls to Array#@@iterator');
|
||||
|
||||
// loop `fn` a few times, to get it JIT-compiled
|
||||
function loop(fn) {
|
||||
@ -67,7 +88,7 @@ function loop(fn) {
|
||||
}
|
||||
|
||||
loop(() => { doneafter = 4; var [a] = iterable; return a; });
|
||||
loop(() => { doneafter = 4; var [a,b,...rest] = iterable; return rest; });
|
||||
loop(() => { doneafter = 4; var [a,b,...[...rest]] = iterable; return rest; });
|
||||
|
||||
|
||||
// destructuring assignment should always use iterators and not optimize
|
||||
|
@ -4,8 +4,6 @@ load(libdir + 'eqArrayHelper.js');
|
||||
|
||||
assertThrowsInstanceOf(() => new Function('[...a, ,] = []'), SyntaxError, 'trailing elision');
|
||||
assertThrowsInstanceOf(() => new Function('[a, ...b, c] = []'), SyntaxError, 'trailing param');
|
||||
assertThrowsInstanceOf(() => new Function('[...[a]] = []'), SyntaxError, 'nested arraypattern');
|
||||
assertThrowsInstanceOf(() => new Function('[...{a}] = []'), SyntaxError, 'nested objectpattern');
|
||||
assertThrowsInstanceOf(() => new Function('[...a=b] = []'), SyntaxError, 'assignment expression');
|
||||
assertThrowsInstanceOf(() => new Function('[...a()] = []'), SyntaxError, 'call expression');
|
||||
assertThrowsInstanceOf(() => new Function('[...(a,b)] = []'), SyntaxError, 'comma expression');
|
||||
@ -22,6 +20,14 @@ assertThrowsInstanceOf(() =>
|
||||
assertThrowsInstanceOf(() => new Function('[...b,] = []'), SyntaxError)
|
||||
, Error);
|
||||
|
||||
assertThrowsInstanceOf(() => {
|
||||
try {
|
||||
eval('let [...[...x]] = (() => { throw "foo"; } )();');
|
||||
} catch(e) {
|
||||
assertEq(e, "foo");
|
||||
}
|
||||
x;
|
||||
}, ReferenceError);
|
||||
|
||||
var inputArray = [1, 2, 3];
|
||||
var inputDeep = [1, inputArray];
|
||||
@ -45,6 +51,11 @@ function testAll(fn) {
|
||||
assertEqArray(fn('[, ...(o.prop)]', inputArray, 'o.prop'), expected);
|
||||
o.prop = null;
|
||||
assertEqArray(fn('[, ...(o.call().prop)]', inputArray, 'o.prop'), expected);
|
||||
|
||||
o.prop = null;
|
||||
assertEqArray(fn('[, ...[...(o.prop)]]', inputArray, 'o.prop'), expected);
|
||||
o.prop = null;
|
||||
assertEqArray(fn('[, ...[...(o.call().prop)]]', inputArray, 'o.prop'), expected);
|
||||
}
|
||||
function testDeclaration(fn) {
|
||||
testStr(fn);
|
||||
@ -53,10 +64,24 @@ function testDeclaration(fn) {
|
||||
assertEqArray(fn('[, ...rest]', inputGenerator()), expected);
|
||||
assertEqArray(fn('[, [, ...rest]]', inputDeep), expected);
|
||||
assertEqArray(fn('{a: [, ...rest]}', inputObject), expected);
|
||||
|
||||
assertEqArray(fn('[, ...[...rest]]', inputArray), expected);
|
||||
assertEqArray(fn('[, ...[...rest]]', inputGenerator()), expected);
|
||||
assertEqArray(fn('[, [, ...[...rest]]]', inputDeep), expected);
|
||||
assertEqArray(fn('{a: [, ...[...rest]]}', inputObject), expected);
|
||||
|
||||
assertEqArray(fn('[, ...{0: a, 1: b}]', inputArray, '[a, b]'), expected);
|
||||
assertEqArray(fn('[, ...{0: a, 1: b}]', inputGenerator(), '[a, b]'), expected);
|
||||
assertEqArray(fn('[, [, ...{0: a, 1: b}]]', inputDeep, '[a, b]'), expected);
|
||||
assertEqArray(fn('{a: [, ...{0: a, 1: b}]}', inputObject, '[a, b]'), expected);
|
||||
}
|
||||
|
||||
function testStr(fn) {
|
||||
assertEqArray(fn('[, ...rest]', inputStr), expectedStr);
|
||||
|
||||
assertEqArray(fn('[, ...[...rest]]', inputStr), expectedStr);
|
||||
|
||||
assertEqArray(fn('[, ...{0: a, 1: b}]', inputStr, '[a, b]'), expectedStr);
|
||||
}
|
||||
|
||||
function testForIn(pattern, input, binding) {
|
||||
@ -88,8 +113,9 @@ testAll(testGlobal);
|
||||
|
||||
function testClosure(pattern, input, binding) {
|
||||
binding = binding || 'rest';
|
||||
const decl = binding.replace('[', '').replace(']', '');
|
||||
return new Function('input',
|
||||
'var ' + binding + '; (function () {' +
|
||||
'var ' + decl + '; (function () {' +
|
||||
'(' + pattern + ' = input);' +
|
||||
'})();' +
|
||||
'return ' + binding
|
||||
|
Loading…
x
Reference in New Issue
Block a user