Bug 1124480: fix destructuring defaults inside for-in loops; r=jorendorff

--HG--
extra : rebase_source : ed77c5ff4ff7859c15e6d099706c35f9acbfe628
This commit is contained in:
Arpad Borsos 2015-01-22 10:55:51 +01:00
Родитель ba5bfc9e79
Коммит 628c7a579f
3 изменённых файлов: 51 добавлений и 1 удалений

Просмотреть файл

@ -423,6 +423,31 @@ Parser<FullParseHandler>::cloneParseTree(ParseNode *opn)
return pn;
}
template <>
ParseNode *
Parser<FullParseHandler>::cloneLeftHandSide(ParseNode *opn);
/*
* Used by Parser::cloneLeftHandSide to clone a default expression
* in the form of
* [a = default] or {a: b = default}
*/
template <>
ParseNode *
Parser<FullParseHandler>::cloneDestructuringDefault(ParseNode *opn)
{
MOZ_ASSERT(opn->isKind(PNK_ASSIGN));
ParseNode *target = cloneLeftHandSide(opn->pn_left);
if (!target)
return nullptr;
ParseNode *defaultNode = cloneParseTree(opn->pn_right);
if (!defaultNode)
return nullptr;
return handler.new_<BinaryNode>(opn->getKind(), JSOP_NOP, opn->pn_pos, target, defaultNode);
}
/*
* Used by Parser::forStatement and comprehensionTail to clone the TARGET in
* for (var/const/let TARGET in EXPR)
@ -463,7 +488,12 @@ Parser<FullParseHandler>::cloneLeftHandSide(ParseNode *opn)
ParseNode *tag = cloneParseTree(opn2->pn_left);
if (!tag)
return nullptr;
ParseNode *target = cloneLeftHandSide(opn2->pn_right);
ParseNode *target;
if (opn2->pn_right->isKind(PNK_ASSIGN)) {
target = cloneDestructuringDefault(opn2->pn_right);
} else {
target = cloneLeftHandSide(opn2->pn_right);
}
if (!target)
return nullptr;
@ -477,6 +507,8 @@ Parser<FullParseHandler>::cloneLeftHandSide(ParseNode *opn)
if (!target)
return nullptr;
pn2 = handler.new_<UnaryNode>(PNK_SPREAD, JSOP_NOP, opn2->pn_pos, target);
} else if (opn2->isKind(PNK_ASSIGN)) {
pn2 = cloneDestructuringDefault(opn2);
} else {
pn2 = cloneLeftHandSide(opn2);
}

Просмотреть файл

@ -672,6 +672,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
bool bindDestructuringVar(BindData<ParseHandler> *data, Node pn);
bool bindDestructuringLHS(Node pn);
bool makeSetCall(Node pn, unsigned msg);
Node cloneDestructuringDefault(Node opn);
Node cloneLeftHandSide(Node opn);
Node cloneParseTree(Node opn);

Просмотреть файл

@ -164,3 +164,20 @@ assertThrowsInstanceOf(() => { [[] = (evaled = true, 2)] = [] }, TypeError);
assertEq(evaled, true);
assertThrowsInstanceOf(() => new Function('var [...rest = defaults] = [];'), SyntaxError);
// bug 1124480: destructuring defaults should work correctly as part of for-in
b = undefined;
for (var [a, b = 10] in " ") {}
assertEq(b, 10);
b = undefined;
for (let [a, c = 10] in " ") { b = c; }
assertEq(b, 10);
b = undefined;
for (var {1: b = 10} in " ") {}
assertEq(b, 10);
b = undefined;
for (let {1: c = 10} in " ") { b = c; }
assertEq(b, 10);