зеркало из https://github.com/mozilla/gecko-dev.git
Bug 742612 - Reflect.parse: separate guarded/unguarded catch clauses. r=jorendorff
This commit is contained in:
Родитель
f1d99acd96
Коммит
a3853b3e79
|
@ -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 });
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче