Bug 742612 - Reflect.parse: separate guarded/unguarded catch clauses. r=jorendorff

This commit is contained in:
Dave Herman 2012-08-24 08:30:44 -07:00
Родитель f1d99acd96
Коммит a3853b3e79
2 изменённых файлов: 42 добавлений и 24 удалений

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

@ -509,7 +509,7 @@ class NodeBuilder
bool switchStatement(Value disc, NodeVector &elts, bool lexical, TokenPos *pos, Value *dst);
bool tryStatement(Value body, NodeVector &catches, Value finally, TokenPos *pos, Value *dst);
bool tryStatement(Value body, NodeVector &guarded, Value unguarded, Value finally, TokenPos *pos, Value *dst);
bool debuggerStatement(TokenPos *pos, Value *dst);
@ -916,23 +916,24 @@ NodeBuilder::switchStatement(Value disc, NodeVector &elts, bool lexical, TokenPo
}
bool
NodeBuilder::tryStatement(Value body, NodeVector &catches, Value finally,
NodeBuilder::tryStatement(Value body, NodeVector &guarded, Value unguarded, Value finally,
TokenPos *pos, Value *dst)
{
Value handlers;
Value guardedHandlers;
Value cb = callbacks[AST_TRY_STMT];
if (!cb.isNull()) {
return newArray(catches, &handlers) &&
callback(cb, body, handlers, opt(finally), pos, dst);
return newArray(guarded, &guardedHandlers) &&
callback(cb, body, guardedHandlers, unguarded, opt(finally), pos, dst);
}
if (!newArray(catches, &handlers))
if (!newArray(guarded, &guardedHandlers))
return false;
return newNode(AST_TRY_STMT, pos,
"block", body,
"handlers", handlers,
"guardedHandlers", guardedHandlers,
"handler", unguarded,
"finalizer", finally,
dst);
}
@ -1637,7 +1638,7 @@ class ASTSerializer
bool switchStatement(ParseNode *pn, Value *dst);
bool switchCase(ParseNode *pn, Value *dst);
bool tryStatement(ParseNode *pn, Value *dst);
bool catchClause(ParseNode *pn, Value *dst);
bool catchClause(ParseNode *pn, bool *isGuarded, Value *dst);
bool optExpression(ParseNode *pn, Value *dst) {
if (!pn) {
@ -2066,7 +2067,7 @@ ASTSerializer::switchStatement(ParseNode *pn, Value *dst)
}
bool
ASTSerializer::catchClause(ParseNode *pn, Value *dst)
ASTSerializer::catchClause(ParseNode *pn, bool *isGuarded, Value *dst)
{
JS_ASSERT(pn->pn_pos.encloses(pn->pn_kid1->pn_pos));
JS_ASSERT_IF(pn->pn_kid2, pn->pn_pos.encloses(pn->pn_kid2->pn_pos));
@ -2074,9 +2075,14 @@ ASTSerializer::catchClause(ParseNode *pn, Value *dst)
Value var, guard, body;
return pattern(pn->pn_kid1, NULL, &var) &&
optExpression(pn->pn_kid2, &guard) &&
statement(pn->pn_kid3, &body) &&
if (!pattern(pn->pn_kid1, NULL, &var) ||
!optExpression(pn->pn_kid2, &guard)) {
return false;
}
*isGuarded = !guard.isMagic(JS_SERIALIZE_NO_NODE);
return statement(pn->pn_kid3, &body) &&
builder.catchClause(var, guard, body, &pn->pn_pos, dst);
}
@ -2091,22 +2097,28 @@ ASTSerializer::tryStatement(ParseNode *pn, Value *dst)
if (!statement(pn->pn_kid1, &body))
return false;
NodeVector clauses(cx);
NodeVector guarded(cx);
Value unguarded = NullValue();
if (pn->pn_kid2) {
if (!clauses.reserve(pn->pn_kid2->pn_count))
if (!guarded.reserve(pn->pn_kid2->pn_count))
return false;
for (ParseNode *next = pn->pn_kid2->pn_head; next; next = next->pn_next) {
Value clause;
if (!catchClause(next->pn_expr, &clause))
bool isGuarded;
if (!catchClause(next->pn_expr, &isGuarded, &clause))
return false;
clauses.infallibleAppend(clause);
if (isGuarded)
guarded.infallibleAppend(clause);
else
unguarded = clause;
}
}
Value finally;
return optStatement(pn->pn_kid3, &finally) &&
builder.tryStatement(body, clauses, finally, &pn->pn_pos, dst);
builder.tryStatement(body, guarded, unguarded, finally, &pn->pn_pos, dst);
}
bool

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

@ -63,7 +63,7 @@ function switchStmt(disc, cases) Pattern({ type: "SwitchStatement", discriminant
function caseClause(test, stmts) Pattern({ type: "SwitchCase", test: test, consequent: stmts })
function defaultClause(stmts) Pattern({ type: "SwitchCase", test: null, consequent: stmts })
function catchClause(id, guard, body) Pattern({ type: "CatchClause", param: id, guard: guard, body: body })
function tryStmt(body, catches, fin) Pattern({ type: "TryStatement", block: body, handlers: catches, finalizer: fin })
function tryStmt(body, guarded, unguarded, fin) Pattern({ type: "TryStatement", block: body, guardedHandlers: guarded, handler: unguarded, finalizer: fin })
function letStmt(head, body) Pattern({ type: "LetStatement", head: head, body: body })
function funExpr(id, args, body, gen) Pattern({ type: "FunctionExpression",
id: id,
@ -414,26 +414,30 @@ assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; case
caseClause(lit(42), [ exprStmt(lit(42)) ]) ]));
assertStmt("try { } catch (e) { }",
tryStmt(blockStmt([]),
[ catchClause(ident("e"), null, blockStmt([])) ],
[],
catchClause(ident("e"), null, blockStmt([])),
null));
assertStmt("try { } catch (e) { } finally { }",
tryStmt(blockStmt([]),
[ catchClause(ident("e"), null, blockStmt([])) ],
[],
catchClause(ident("e"), null, blockStmt([])),
blockStmt([])));
assertStmt("try { } finally { }",
tryStmt(blockStmt([]),
[],
null,
blockStmt([])));
assertStmt("try { } catch (e if foo) { } catch (e if bar) { } finally { }",
tryStmt(blockStmt([]),
[ catchClause(ident("e"), ident("foo"), blockStmt([])),
catchClause(ident("e"), ident("bar"), blockStmt([])) ],
null,
blockStmt([])));
assertStmt("try { } catch (e if foo) { } catch (e if bar) { } catch (e) { } finally { }",
tryStmt(blockStmt([]),
[ catchClause(ident("e"), ident("foo"), blockStmt([])),
catchClause(ident("e"), ident("bar"), blockStmt([])),
catchClause(ident("e"), null, blockStmt([])) ],
catchClause(ident("e"), ident("bar"), blockStmt([])) ],
catchClause(ident("e"), null, blockStmt([])),
blockStmt([])));
// Bug 632028: yield outside of a function should throw
@ -1037,9 +1041,11 @@ assertGlobalExpr("(function() { yield 42 })", genFunExpr(null, [], blockStmt([ex
assertGlobalExpr("(let (x) x)", 20, { letExpression: function() 20 });
assertGlobalStmt("switch (x) { case y: }", switchStmt(ident("x"), [1]), { switchCase: function() 1 });
assertGlobalStmt("try { } catch (e) { }", tryStmt(blockStmt([]), [2], null), { catchClause: function() 2 });
assertGlobalStmt("try { } catch (e) { }", 2, { tryStatement: (function(b, g, u, f) u), catchClause: function() 2 });
assertGlobalStmt("try { } catch (e if e instanceof A) { } catch (e if e instanceof B) { }", [2, 2], { tryStatement: (function(b, g, u, f) g), catchClause: function() 2 });
assertGlobalStmt("try { } catch (e) { }", tryStmt(blockStmt([]), [], 2, null), { catchClause: function() 2 });
assertGlobalStmt("try { } catch (e if e instanceof A) { } catch (e if e instanceof B) { }",
tryStmt(blockStmt([]), [2, 2], null),
tryStmt(blockStmt([]), [2, 2], null, null),
{ catchClause: function() 2 });
assertGlobalExpr("[x for (y in z) for (x in y)]", compExpr(ident("x"), [3, 3], null), { comprehensionBlock: function() 3 });