mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-18 13:17:29 +09:00
parent
9c17ec0533
commit
4726d96fd2
12 changed files with 560 additions and 475 deletions
|
|
@ -1806,7 +1806,7 @@ class ASTSerializer
|
|||
bool importSpecifier(ParseNode* pn, MutableHandleValue dst);
|
||||
bool exportDeclaration(ParseNode* pn, MutableHandleValue dst);
|
||||
bool exportSpecifier(ParseNode* pn, MutableHandleValue dst);
|
||||
bool classDefinition(ParseNode* pn, bool expr, MutableHandleValue dst);
|
||||
bool classDefinition(ClassNode* pn, bool expr, MutableHandleValue dst);
|
||||
|
||||
bool optStatement(ParseNode* pn, MutableHandleValue dst) {
|
||||
if (!pn) {
|
||||
|
|
@ -1817,16 +1817,16 @@ class ASTSerializer
|
|||
}
|
||||
|
||||
bool forInit(ParseNode* pn, MutableHandleValue dst);
|
||||
bool forIn(ParseNode* loop, ParseNode* head, HandleValue var, HandleValue stmt,
|
||||
bool forIn(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt,
|
||||
MutableHandleValue dst);
|
||||
bool forOf(ParseNode* loop, ParseNode* head, HandleValue var, HandleValue stmt,
|
||||
bool forOf(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt,
|
||||
MutableHandleValue dst);
|
||||
bool statement(ParseNode* pn, MutableHandleValue dst);
|
||||
bool blockStatement(ListNode* node, MutableHandleValue dst);
|
||||
bool switchStatement(ParseNode* pn, MutableHandleValue dst);
|
||||
bool switchCase(ParseNode* pn, MutableHandleValue dst);
|
||||
bool tryStatement(ParseNode* pn, MutableHandleValue dst);
|
||||
bool catchClause(ParseNode* pn, bool* isGuarded, MutableHandleValue dst);
|
||||
bool tryStatement(TernaryNode* tryNode, MutableHandleValue dst);
|
||||
bool catchClause(TernaryNode* clauseNode, bool* isGuarded, MutableHandleValue dst);
|
||||
|
||||
bool optExpression(ParseNode* pn, MutableHandleValue dst) {
|
||||
if (!pn) {
|
||||
|
|
@ -1874,7 +1874,7 @@ class ASTSerializer
|
|||
bool functionBody(ParseNode* pn, TokenPos* pos, MutableHandleValue dst);
|
||||
|
||||
bool comprehensionBlock(ParseNode* pn, MutableHandleValue dst);
|
||||
bool comprehensionIf(ParseNode* pn, MutableHandleValue dst);
|
||||
bool comprehensionIf(TernaryNode* ifNode, MutableHandleValue dst);
|
||||
bool comprehension(ParseNode* pn, MutableHandleValue dst);
|
||||
bool generatorExpression(ParseNode* pn, MutableHandleValue dst);
|
||||
|
||||
|
|
@ -2236,7 +2236,7 @@ ASTSerializer::exportDeclaration(ParseNode* pn, MutableHandleValue dst)
|
|||
break;
|
||||
|
||||
case PNK_CLASS:
|
||||
if (!classDefinition(kid, false, &decl))
|
||||
if (!classDefinition(&kid->as<ClassNode>(), false, &decl))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
|
@ -2321,47 +2321,58 @@ ASTSerializer::switchStatement(ParseNode* pn, MutableHandleValue dst)
|
|||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::catchClause(ParseNode* pn, bool* isGuarded, MutableHandleValue dst)
|
||||
ASTSerializer::catchClause(TernaryNode* clauseNode, bool* isGuarded, MutableHandleValue dst)
|
||||
{
|
||||
MOZ_ASSERT_IF(pn->pn_kid1, pn->pn_pos.encloses(pn->pn_kid1->pn_pos));
|
||||
MOZ_ASSERT_IF(pn->pn_kid2, pn->pn_pos.encloses(pn->pn_kid2->pn_pos));
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid3->pn_pos));
|
||||
ParseNode* patNode = clauseNode->kid1();
|
||||
MOZ_ASSERT_IF(patNode, clauseNode->pn_pos.encloses(patNode->pn_pos));
|
||||
|
||||
ParseNode* condNode = clauseNode->kid2();
|
||||
MOZ_ASSERT_IF(condNode, clauseNode->pn_pos.encloses(condNode->pn_pos));
|
||||
|
||||
ParseNode* bodyNode = clauseNode->kid3();
|
||||
MOZ_ASSERT(clauseNode->pn_pos.encloses(bodyNode->pn_pos));
|
||||
|
||||
RootedValue var(cx), guard(cx), body(cx);
|
||||
|
||||
if (!optPattern(pn->pn_kid1, &var) ||
|
||||
!optExpression(pn->pn_kid2, &guard)) {
|
||||
if (!optPattern(patNode, &var) ||
|
||||
!optExpression(condNode, &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);
|
||||
return statement(bodyNode, &body) &&
|
||||
builder.catchClause(var, guard, body, &clauseNode->pn_pos, dst);
|
||||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::tryStatement(ParseNode* pn, MutableHandleValue dst)
|
||||
ASTSerializer::tryStatement(TernaryNode* tryNode, MutableHandleValue dst)
|
||||
{
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid1->pn_pos));
|
||||
MOZ_ASSERT_IF(pn->pn_kid2, pn->pn_pos.encloses(pn->pn_kid2->pn_pos));
|
||||
MOZ_ASSERT_IF(pn->pn_kid3, pn->pn_pos.encloses(pn->pn_kid3->pn_pos));
|
||||
ParseNode* bodyNode = tryNode->kid1();
|
||||
MOZ_ASSERT(tryNode->pn_pos.encloses(bodyNode->pn_pos));
|
||||
|
||||
ParseNode* catchNode = tryNode->kid2();
|
||||
MOZ_ASSERT_IF(catchNode, tryNode->pn_pos.encloses(catchNode->pn_pos));
|
||||
|
||||
ParseNode* finallyNode = tryNode->kid3();
|
||||
MOZ_ASSERT_IF(finallyNode, tryNode->pn_pos.encloses(finallyNode->pn_pos));
|
||||
|
||||
RootedValue body(cx);
|
||||
if (!statement(pn->pn_kid1, &body))
|
||||
if (!statement(bodyNode, &body))
|
||||
return false;
|
||||
|
||||
NodeVector guarded(cx);
|
||||
RootedValue unguarded(cx, NullValue());
|
||||
|
||||
if (ListNode* catchList = &pn->pn_kid2->as<ListNode>()) {
|
||||
if (ListNode* catchList = &catchNode->as<ListNode>()) {
|
||||
if (!guarded.reserve(catchList->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* next : catchList->contents()) {
|
||||
for (ParseNode* catchScope : catchList->contents()) {
|
||||
MOZ_ASSERT(catchScope->isKind(PNK_LEXICALSCOPE));
|
||||
RootedValue clause(cx);
|
||||
bool isGuarded;
|
||||
if (!catchClause(next->pn_expr, &isGuarded, &clause))
|
||||
if (!catchClause(&catchScope->scopeBody()->as<TernaryNode>(), &isGuarded, &clause))
|
||||
return false;
|
||||
if (isGuarded)
|
||||
guarded.infallibleAppend(clause);
|
||||
|
|
@ -2371,8 +2382,8 @@ ASTSerializer::tryStatement(ParseNode* pn, MutableHandleValue dst)
|
|||
}
|
||||
|
||||
RootedValue finally(cx);
|
||||
return optStatement(pn->pn_kid3, &finally) &&
|
||||
builder.tryStatement(body, guarded, unguarded, finally, &pn->pn_pos, dst);
|
||||
return optStatement(finallyNode, &finally) &&
|
||||
builder.tryStatement(body, guarded, unguarded, finally, &tryNode->pn_pos, dst);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -2390,40 +2401,40 @@ ASTSerializer::forInit(ParseNode* pn, MutableHandleValue dst)
|
|||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::forOf(ParseNode* loop, ParseNode* head, HandleValue var, HandleValue stmt,
|
||||
ASTSerializer::forOf(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt,
|
||||
MutableHandleValue dst)
|
||||
{
|
||||
RootedValue expr(cx);
|
||||
|
||||
return expression(head->pn_kid3, &expr) &&
|
||||
return expression(iterExpr, &expr) &&
|
||||
builder.forOfStatement(var, expr, stmt, &loop->pn_pos, dst);
|
||||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::forIn(ParseNode* loop, ParseNode* head, HandleValue var, HandleValue stmt,
|
||||
ASTSerializer::forIn(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt,
|
||||
MutableHandleValue dst)
|
||||
{
|
||||
RootedValue expr(cx);
|
||||
bool isForEach = loop->pn_iflags & JSITER_FOREACH;
|
||||
|
||||
return expression(head->pn_kid3, &expr) &&
|
||||
return expression(iterExpr, &expr) &&
|
||||
builder.forInStatement(var, expr, stmt, isForEach, &loop->pn_pos, dst);
|
||||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::classDefinition(ParseNode* pn, bool expr, MutableHandleValue dst)
|
||||
ASTSerializer::classDefinition(ClassNode* pn, bool expr, MutableHandleValue dst)
|
||||
{
|
||||
RootedValue className(cx, MagicValue(JS_SERIALIZE_NO_NODE));
|
||||
RootedValue heritage(cx);
|
||||
RootedValue classBody(cx);
|
||||
|
||||
if (pn->pn_kid1) {
|
||||
if (!identifier(pn->pn_kid1->as<ClassNames>().innerBinding(), &className))
|
||||
if (ClassNames* names = pn->names()) {
|
||||
if (!identifier(names->innerBinding(), &className))
|
||||
return false;
|
||||
}
|
||||
|
||||
return optExpression(pn->pn_kid2, &heritage) &&
|
||||
statement(pn->pn_kid3, &classBody) &&
|
||||
return optExpression(pn->heritage(), &heritage) &&
|
||||
statement(pn->methodList(), &classBody) &&
|
||||
builder.classDefinition(expr, className, heritage, classBody, &pn->pn_pos, dst);
|
||||
}
|
||||
|
||||
|
|
@ -2467,23 +2478,30 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
|||
|
||||
case PNK_IF:
|
||||
{
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid1->pn_pos));
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid2->pn_pos));
|
||||
MOZ_ASSERT_IF(pn->pn_kid3, pn->pn_pos.encloses(pn->pn_kid3->pn_pos));
|
||||
TernaryNode* ifNode = &pn->as<TernaryNode>();
|
||||
|
||||
ParseNode* testNode = ifNode->kid1();
|
||||
MOZ_ASSERT(ifNode->pn_pos.encloses(testNode->pn_pos));
|
||||
|
||||
ParseNode* consNode = ifNode->kid2();
|
||||
MOZ_ASSERT(ifNode->pn_pos.encloses(consNode->pn_pos));
|
||||
|
||||
ParseNode* altNode = ifNode->kid3();
|
||||
MOZ_ASSERT_IF(altNode, ifNode->pn_pos.encloses(altNode->pn_pos));
|
||||
|
||||
RootedValue test(cx), cons(cx), alt(cx);
|
||||
|
||||
return expression(pn->pn_kid1, &test) &&
|
||||
statement(pn->pn_kid2, &cons) &&
|
||||
optStatement(pn->pn_kid3, &alt) &&
|
||||
builder.ifStatement(test, cons, alt, &pn->pn_pos, dst);
|
||||
return expression(testNode, &test) &&
|
||||
statement(consNode, &cons) &&
|
||||
optStatement(altNode, &alt) &&
|
||||
builder.ifStatement(test, cons, alt, &ifNode->pn_pos, dst);
|
||||
}
|
||||
|
||||
case PNK_SWITCH:
|
||||
return switchStatement(pn, dst);
|
||||
|
||||
case PNK_TRY:
|
||||
return tryStatement(pn, dst);
|
||||
return tryStatement(&pn->as<TernaryNode>(), dst);
|
||||
|
||||
case PNK_WITH:
|
||||
case PNK_WHILE:
|
||||
|
|
@ -2518,11 +2536,16 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
|||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
|
||||
|
||||
ParseNode* head = pn->pn_left;
|
||||
TernaryNode* head = &pn->pn_left->as<TernaryNode>();
|
||||
|
||||
MOZ_ASSERT_IF(head->pn_kid1, head->pn_pos.encloses(head->pn_kid1->pn_pos));
|
||||
MOZ_ASSERT_IF(head->pn_kid2, head->pn_pos.encloses(head->pn_kid2->pn_pos));
|
||||
MOZ_ASSERT_IF(head->pn_kid3, head->pn_pos.encloses(head->pn_kid3->pn_pos));
|
||||
ParseNode* initNode = head->kid1();
|
||||
MOZ_ASSERT_IF(initNode, head->pn_pos.encloses(initNode->pn_pos));
|
||||
|
||||
ParseNode* maybeTest = head->kid2();
|
||||
MOZ_ASSERT_IF(maybeTest, head->pn_pos.encloses(maybeTest->pn_pos));
|
||||
|
||||
ParseNode* updateOrIter = head->kid3();
|
||||
MOZ_ASSERT_IF(updateOrIter, head->pn_pos.encloses(updateOrIter->pn_pos));
|
||||
|
||||
RootedValue stmt(cx);
|
||||
if (!statement(pn->pn_right, &stmt))
|
||||
|
|
@ -2530,34 +2553,34 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
|||
|
||||
if (head->isKind(PNK_FORIN) || head->isKind(PNK_FOROF)) {
|
||||
RootedValue var(cx);
|
||||
if (head->pn_kid1->isKind(PNK_LEXICALSCOPE)) {
|
||||
if (!variableDeclaration(&head->pn_kid1->scopeBody()->as<ListNode>(), true, &var))
|
||||
if (initNode->isKind(PNK_LEXICALSCOPE)) {
|
||||
if (!variableDeclaration(&initNode->scopeBody()->as<ListNode>(), true, &var))
|
||||
return false;
|
||||
} else if (!head->pn_kid1->isKind(PNK_VAR) &&
|
||||
!head->pn_kid1->isKind(PNK_LET) &&
|
||||
!head->pn_kid1->isKind(PNK_CONST))
|
||||
} else if (!initNode->isKind(PNK_VAR) &&
|
||||
!initNode->isKind(PNK_LET) &&
|
||||
!initNode->isKind(PNK_CONST))
|
||||
{
|
||||
if (!pattern(head->pn_kid1, &var))
|
||||
if (!pattern(initNode, &var))
|
||||
return false;
|
||||
} else {
|
||||
if (!variableDeclaration(&head->pn_kid1->as<ListNode>(),
|
||||
head->pn_kid1->isKind(PNK_LET) ||
|
||||
head->pn_kid1->isKind(PNK_CONST),
|
||||
if (!variableDeclaration(&initNode->as<ListNode>(),
|
||||
initNode->isKind(PNK_LET) ||
|
||||
initNode->isKind(PNK_CONST),
|
||||
&var))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (head->isKind(PNK_FORIN))
|
||||
return forIn(pn, head, var, stmt, dst);
|
||||
return forOf(pn, head, var, stmt, dst);
|
||||
return forIn(pn, updateOrIter, var, stmt, dst);
|
||||
return forOf(pn, updateOrIter, var, stmt, dst);
|
||||
}
|
||||
|
||||
RootedValue init(cx), test(cx), update(cx);
|
||||
|
||||
return forInit(head->pn_kid1, &init) &&
|
||||
optExpression(head->pn_kid2, &test) &&
|
||||
optExpression(head->pn_kid3, &update) &&
|
||||
return forInit(initNode, &init) &&
|
||||
optExpression(maybeTest, &test) &&
|
||||
optExpression(updateOrIter, &update) &&
|
||||
builder.forStatement(init, test, update, stmt, &pn->pn_pos, dst);
|
||||
}
|
||||
|
||||
|
|
@ -2607,7 +2630,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
|||
return builder.debuggerStatement(&pn->pn_pos, dst);
|
||||
|
||||
case PNK_CLASS:
|
||||
return classDefinition(pn, false, dst);
|
||||
return classDefinition(&pn->as<ClassNode>(), false, dst);
|
||||
|
||||
case PNK_CLASSMETHODLIST:
|
||||
{
|
||||
|
|
@ -2748,7 +2771,7 @@ ASTSerializer::comprehensionBlock(ParseNode* pn, MutableHandleValue dst)
|
|||
{
|
||||
LOCAL_ASSERT(pn->isArity(PN_BINARY));
|
||||
|
||||
ParseNode* in = pn->pn_left;
|
||||
TernaryNode* in = &pn->pn_left->as<TernaryNode>();
|
||||
|
||||
LOCAL_ASSERT(in && (in->isKind(PNK_FORIN) || in->isKind(PNK_FOROF)));
|
||||
|
||||
|
|
@ -2756,27 +2779,27 @@ ASTSerializer::comprehensionBlock(ParseNode* pn, MutableHandleValue dst)
|
|||
bool isForOf = in->isKind(PNK_FOROF);
|
||||
|
||||
ListNode* decl;
|
||||
if (in->pn_kid1->isKind(PNK_LEXICALSCOPE))
|
||||
decl = &in->pn_kid1->pn_expr->as<ListNode>();
|
||||
if (in->kid1()->isKind(PNK_LEXICALSCOPE))
|
||||
decl = &in->kid1()->pn_expr->as<ListNode>();
|
||||
else
|
||||
decl = &in->pn_kid1->as<ListNode>();
|
||||
decl = &in->kid1()->as<ListNode>();
|
||||
MOZ_ASSERT(decl->count() == 1);
|
||||
|
||||
RootedValue patt(cx), src(cx);
|
||||
return pattern(decl->head(), &patt) &&
|
||||
expression(in->pn_kid3, &src) &&
|
||||
expression(in->kid3(), &src) &&
|
||||
builder.comprehensionBlock(patt, src, isForEach, isForOf, &in->pn_pos, dst);
|
||||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::comprehensionIf(ParseNode* pn, MutableHandleValue dst)
|
||||
ASTSerializer::comprehensionIf(TernaryNode* ifNode, MutableHandleValue dst)
|
||||
{
|
||||
LOCAL_ASSERT(pn->isKind(PNK_IF));
|
||||
LOCAL_ASSERT(!pn->pn_kid3);
|
||||
LOCAL_ASSERT(ifNode->isKind(PNK_IF));
|
||||
LOCAL_ASSERT(!ifNode->kid3());
|
||||
|
||||
RootedValue patt(cx);
|
||||
return pattern(pn->pn_kid1, &patt) &&
|
||||
builder.comprehensionIf(patt, &pn->pn_pos, dst);
|
||||
return pattern(ifNode->kid1(), &patt) &&
|
||||
builder.comprehensionIf(patt, &ifNode->pn_pos, dst);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -2799,17 +2822,19 @@ ASTSerializer::comprehension(ParseNode* pn, MutableHandleValue dst)
|
|||
return false;
|
||||
next = next->pn_right;
|
||||
} else if (next->isKind(PNK_IF)) {
|
||||
TernaryNode* tn = &next->as<TernaryNode>();
|
||||
if (isLegacy) {
|
||||
MOZ_ASSERT(filter.isMagic(JS_SERIALIZE_NO_NODE));
|
||||
if (!optExpression(next->pn_kid1, &filter))
|
||||
if (!optExpression(tn->kid1(), &filter))
|
||||
return false;
|
||||
} else {
|
||||
// ES7 comprehension can contain multiple ComprehensionIfs.
|
||||
RootedValue compif(cx);
|
||||
if (!comprehensionIf(next, &compif) || !blocks.append(compif))
|
||||
if (!comprehensionIf(tn, &compif) ||
|
||||
!blocks.append(compif))
|
||||
return false;
|
||||
}
|
||||
next = next->pn_kid2;
|
||||
next = tn->kid2();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
|
@ -2842,17 +2867,19 @@ ASTSerializer::generatorExpression(ParseNode* pn, MutableHandleValue dst)
|
|||
return false;
|
||||
next = next->pn_right;
|
||||
} else if (next->isKind(PNK_IF)) {
|
||||
TernaryNode* tn = &next->as<TernaryNode>();
|
||||
if (isLegacy) {
|
||||
MOZ_ASSERT(filter.isMagic(JS_SERIALIZE_NO_NODE));
|
||||
if (!optExpression(next->pn_kid1, &filter))
|
||||
if (!optExpression(tn->kid1(), &filter))
|
||||
return false;
|
||||
} else {
|
||||
// ES7 comprehension can contain multiple ComprehensionIfs.
|
||||
RootedValue compif(cx);
|
||||
if (!comprehensionIf(next, &compif) || !blocks.append(compif))
|
||||
if (!comprehensionIf(tn, &compif) ||
|
||||
!blocks.append(compif))
|
||||
return false;
|
||||
}
|
||||
next = next->pn_kid2;
|
||||
next = tn->kid2();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
|
@ -2888,16 +2915,20 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
|
||||
case PNK_CONDITIONAL:
|
||||
{
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid1->pn_pos));
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid2->pn_pos));
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid3->pn_pos));
|
||||
ConditionalExpression* condNode = &pn->as<ConditionalExpression>();
|
||||
ParseNode* testNode = condNode->kid1();
|
||||
ParseNode* consNode = condNode->kid2();
|
||||
ParseNode* altNode = condNode->kid3();
|
||||
MOZ_ASSERT(condNode->pn_pos.encloses(testNode->pn_pos));
|
||||
MOZ_ASSERT(condNode->pn_pos.encloses(consNode->pn_pos));
|
||||
MOZ_ASSERT(condNode->pn_pos.encloses(altNode->pn_pos));
|
||||
|
||||
RootedValue test(cx), cons(cx), alt(cx);
|
||||
|
||||
return expression(pn->pn_kid1, &test) &&
|
||||
expression(pn->pn_kid2, &cons) &&
|
||||
expression(pn->pn_kid3, &alt) &&
|
||||
builder.conditionalExpression(test, cons, alt, &pn->pn_pos, dst);
|
||||
return expression(testNode, &test) &&
|
||||
expression(consNode, &cons) &&
|
||||
expression(altNode, &alt) &&
|
||||
builder.conditionalExpression(test, cons, alt, &condNode->pn_pos, dst);
|
||||
}
|
||||
|
||||
case PNK_COALESCE:
|
||||
|
|
@ -3281,7 +3312,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
}
|
||||
|
||||
case PNK_CLASS:
|
||||
return classDefinition(pn, true, dst);
|
||||
return classDefinition(&pn->as<ClassNode>(), true, dst);
|
||||
|
||||
case PNK_NEWTARGET:
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1322,18 +1322,20 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||
|
||||
case PNK_IF:
|
||||
case PNK_CONDITIONAL:
|
||||
MOZ_ASSERT(pn->isArity(PN_TERNARY));
|
||||
if (!checkSideEffects(pn->pn_kid1, answer))
|
||||
{
|
||||
TernaryNode* node = &pn->as<TernaryNode>();
|
||||
if (!checkSideEffects(node->kid1(), answer))
|
||||
return false;
|
||||
if (*answer)
|
||||
return true;
|
||||
if (!checkSideEffects(pn->pn_kid2, answer))
|
||||
if (!checkSideEffects(node->kid2(), answer))
|
||||
return false;
|
||||
if (*answer)
|
||||
return true;
|
||||
if ((pn = pn->pn_kid3))
|
||||
if ((pn = node->kid3()))
|
||||
goto restart;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Function calls can invoke non-local code.
|
||||
case PNK_NEW:
|
||||
|
|
@ -1362,7 +1364,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||
// the heritage and/or class body (through computed property names)
|
||||
// usually have effects.
|
||||
case PNK_CLASS:
|
||||
MOZ_ASSERT(pn->isArity(PN_TERNARY));
|
||||
MOZ_ASSERT(pn->is<ClassNode>());
|
||||
*answer = true;
|
||||
return true;
|
||||
|
||||
|
|
@ -1415,39 +1417,43 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||
return true;
|
||||
|
||||
case PNK_TRY:
|
||||
MOZ_ASSERT(pn->isArity(PN_TERNARY));
|
||||
if (!checkSideEffects(pn->pn_kid1, answer))
|
||||
{
|
||||
TernaryNode* tryNode = &pn->as<TernaryNode>();
|
||||
if (!checkSideEffects(tryNode->kid1(), answer))
|
||||
return false;
|
||||
if (*answer)
|
||||
return true;
|
||||
if (ParseNode* catchList = pn->pn_kid2) {
|
||||
if (ParseNode* catchList = tryNode->kid2()) {
|
||||
MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
|
||||
if (!checkSideEffects(catchList, answer))
|
||||
return false;
|
||||
if (*answer)
|
||||
return true;
|
||||
}
|
||||
if (ParseNode* finallyBlock = pn->pn_kid3) {
|
||||
if (ParseNode* finallyBlock = tryNode->kid3()) {
|
||||
if (!checkSideEffects(finallyBlock, answer))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case PNK_CATCH:
|
||||
MOZ_ASSERT(pn->isArity(PN_TERNARY));
|
||||
if (ParseNode* name = pn->pn_kid1) {
|
||||
if (!checkSideEffects(name, answer))
|
||||
{
|
||||
TernaryNode* catchNode = &pn->as<TernaryNode>();
|
||||
if (ParseNode* binding = catchNode->kid1()) {
|
||||
if (!checkSideEffects(binding, answer))
|
||||
return false;
|
||||
if (*answer)
|
||||
return true;
|
||||
}
|
||||
if (ParseNode* cond = pn->pn_kid2) {
|
||||
if (ParseNode* cond = catchNode->kid2()) {
|
||||
if (!checkSideEffects(cond, answer))
|
||||
return false;
|
||||
if (*answer)
|
||||
return true;
|
||||
}
|
||||
return checkSideEffects(pn->pn_kid3, answer);
|
||||
return checkSideEffects(catchNode->kid3(), answer);
|
||||
}
|
||||
|
||||
case PNK_SWITCH:
|
||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||
|
|
@ -4087,7 +4093,7 @@ class EmitLevelManager
|
|||
} /* anonymous namespace */
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitCatch(ParseNode* pn)
|
||||
BytecodeEmitter::emitCatch(TernaryNode* catchNode)
|
||||
{
|
||||
// We must be nested under a try-finally statement.
|
||||
TryFinallyControl& controlInfo = innermostNestableControl->as<TryFinallyControl>();
|
||||
|
|
@ -4100,10 +4106,10 @@ BytecodeEmitter::emitCatch(ParseNode* pn)
|
|||
* Dup the exception object if there is a guard for rethrowing to use
|
||||
* it later when rethrowing or in other catches.
|
||||
*/
|
||||
if (pn->pn_kid2 && !emit1(JSOP_DUP))
|
||||
if (catchNode->kid2() && !emit1(JSOP_DUP))
|
||||
return false;
|
||||
|
||||
ParseNode* pn2 = pn->pn_kid1;
|
||||
ParseNode* pn2 = catchNode->kid1();
|
||||
if (!pn2) {
|
||||
// See ES2019 13.15.7 Runtime Semantics: CatchClauseEvaluation
|
||||
// Catch variable was omitted: discard the exception.
|
||||
|
|
@ -4133,8 +4139,8 @@ BytecodeEmitter::emitCatch(ParseNode* pn)
|
|||
|
||||
// If there is a guard expression, emit it and arrange to jump to the next
|
||||
// catch block if the guard expression is false.
|
||||
if (pn->pn_kid2) {
|
||||
if (!emitTree(pn->pn_kid2))
|
||||
if (catchNode->kid2()) {
|
||||
if (!emitTree(catchNode->kid2()))
|
||||
return false;
|
||||
|
||||
// If the guard expression is false, fall through, pop the block scope,
|
||||
|
|
@ -4171,16 +4177,16 @@ BytecodeEmitter::emitCatch(ParseNode* pn)
|
|||
}
|
||||
|
||||
/* Emit the catch body. */
|
||||
return emitTree(pn->pn_kid3);
|
||||
return emitTree(catchNode->kid3());
|
||||
}
|
||||
|
||||
// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the
|
||||
// comment on EmitSwitch.
|
||||
MOZ_NEVER_INLINE bool
|
||||
BytecodeEmitter::emitTry(ParseNode* pn)
|
||||
BytecodeEmitter::emitTry(TernaryNode* tryNode)
|
||||
{
|
||||
ParseNode* catchList = pn->pn_kid2;
|
||||
ParseNode* finallyNode = pn->pn_kid3;
|
||||
ParseNode* catchList = tryNode->kid2();
|
||||
ParseNode* finallyNode = tryNode->kid3();
|
||||
|
||||
TryEmitter::Kind kind;
|
||||
if (catchList) {
|
||||
|
|
@ -4197,7 +4203,7 @@ BytecodeEmitter::emitTry(ParseNode* pn)
|
|||
if (!tryCatch.emitTry())
|
||||
return false;
|
||||
|
||||
if (!emitTree(pn->pn_kid1))
|
||||
if (!emitTree(tryNode->kid1()))
|
||||
return false;
|
||||
|
||||
// If this try has a catch block, emit it.
|
||||
|
|
@ -4256,16 +4262,16 @@ BytecodeEmitter::emitTry(ParseNode* pn)
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitIf(ParseNode* pn)
|
||||
BytecodeEmitter::emitIf(TernaryNode* ifNode)
|
||||
{
|
||||
IfEmitter ifThenElse(this);
|
||||
|
||||
if_again:
|
||||
/* Emit code for the condition before pushing stmtInfo. */
|
||||
if (!emitTreeInBranch(pn->pn_kid1))
|
||||
if (!emitTreeInBranch(ifNode->kid1()))
|
||||
return false;
|
||||
|
||||
ParseNode* elseNode = pn->pn_kid3;
|
||||
ParseNode* elseNode = ifNode->kid3();
|
||||
if (elseNode) {
|
||||
if (!ifThenElse.emitThenElse())
|
||||
return false;
|
||||
|
|
@ -4275,12 +4281,12 @@ BytecodeEmitter::emitIf(ParseNode* pn)
|
|||
}
|
||||
|
||||
/* Emit code for the then part. */
|
||||
if (!emitTreeInBranch(pn->pn_kid2))
|
||||
if (!emitTreeInBranch(ifNode->kid2()))
|
||||
return false;
|
||||
|
||||
if (elseNode) {
|
||||
if (elseNode->isKind(PNK_IF)) {
|
||||
pn = elseNode;
|
||||
ifNode = &elseNode->as<TernaryNode>();
|
||||
|
||||
if (!ifThenElse.emitElseIf())
|
||||
return false;
|
||||
|
|
@ -4380,11 +4386,12 @@ BytecodeEmitter::emitLexicalScope(ParseNode* pn)
|
|||
|
||||
EmitterScope emitterScope(this);
|
||||
ScopeKind kind;
|
||||
if (body->isKind(PNK_CATCH))
|
||||
kind = (!body->pn_kid1 || body->pn_kid1->isKind(PNK_NAME)) ?
|
||||
if (body->isKind(PNK_CATCH)) {
|
||||
TernaryNode* catchNode = &body->as<TernaryNode>();
|
||||
kind = (!catchNode->kid1() || catchNode->kid1()->isKind(PNK_NAME)) ?
|
||||
ScopeKind::SimpleCatch :
|
||||
ScopeKind::Catch;
|
||||
else
|
||||
} else
|
||||
kind = ScopeKind::Lexical;
|
||||
|
||||
if (!emitterScope.enterLexical(this, kind, pn->scopeBindings()))
|
||||
|
|
@ -4664,16 +4671,15 @@ BytecodeEmitter::emitSpread(bool allowSelfHosted)
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitInitializeForInOrOfTarget(ParseNode* forHead)
|
||||
BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead)
|
||||
{
|
||||
MOZ_ASSERT(forHead->isKind(PNK_FORIN) || forHead->isKind(PNK_FOROF));
|
||||
MOZ_ASSERT(forHead->isArity(PN_TERNARY));
|
||||
|
||||
MOZ_ASSERT(this->stackDepth >= 1,
|
||||
"must have a per-iteration value for initializing");
|
||||
|
||||
ParseNode* target = forHead->pn_kid1;
|
||||
MOZ_ASSERT(!forHead->pn_kid2);
|
||||
ParseNode* target = forHead->kid1();
|
||||
MOZ_ASSERT(!forHead->kid2());
|
||||
|
||||
// If the for-in/of loop didn't have a variable declaration, per-loop
|
||||
// initialization is just assigning the iteration value to a target
|
||||
|
|
@ -4733,9 +4739,8 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
|
|||
MOZ_ASSERT(forOfLoop->isKind(PNK_FOR));
|
||||
MOZ_ASSERT(forOfLoop->isArity(PN_BINARY));
|
||||
|
||||
ParseNode* forOfHead = forOfLoop->pn_left;
|
||||
TernaryNode* forOfHead = &forOfLoop->pn_left->as<TernaryNode>();
|
||||
MOZ_ASSERT(forOfHead->isKind(PNK_FOROF));
|
||||
MOZ_ASSERT(forOfHead->isArity(PN_TERNARY));
|
||||
|
||||
unsigned iflags = forOfLoop->pn_iflags;
|
||||
IteratorKind iterKind = (iflags & JSITER_FORAWAITOF)
|
||||
|
|
@ -4744,7 +4749,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
|
|||
MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->asFunctionBox());
|
||||
MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->asFunctionBox()->isAsync());
|
||||
|
||||
ParseNode* forHeadExpr = forOfHead->pn_kid3;
|
||||
ParseNode* forHeadExpr = forOfHead->kid3();
|
||||
|
||||
// Certain builtins (e.g. Array.from) are implemented in self-hosting
|
||||
// as for-of loops.
|
||||
|
|
@ -4799,7 +4804,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
|
|||
// recreation each iteration. If a lexical scope exists for the head,
|
||||
// it must be the innermost one. If that scope has closed-over
|
||||
// bindings inducing an environment, recreate the current environment.
|
||||
DebugOnly<ParseNode*> forOfTarget = forOfHead->pn_kid1;
|
||||
DebugOnly<ParseNode*> forOfTarget = forOfHead->kid1();
|
||||
MOZ_ASSERT(forOfTarget->isKind(PNK_LET) || forOfTarget->isKind(PNK_CONST));
|
||||
MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope());
|
||||
MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical);
|
||||
|
|
@ -4909,13 +4914,12 @@ BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitte
|
|||
MOZ_ASSERT(forInLoop->isArity(PN_BINARY));
|
||||
MOZ_ASSERT(forInLoop->isOp(JSOP_ITER));
|
||||
|
||||
ParseNode* forInHead = forInLoop->pn_left;
|
||||
TernaryNode* forInHead = &forInLoop->pn_left->as<TernaryNode>();
|
||||
MOZ_ASSERT(forInHead->isKind(PNK_FORIN));
|
||||
MOZ_ASSERT(forInHead->isArity(PN_TERNARY));
|
||||
|
||||
// Annex B: Evaluate the var-initializer expression if present.
|
||||
// |for (var i = initializer in expr) { ... }|
|
||||
ParseNode* forInTarget = forInHead->pn_kid1;
|
||||
ParseNode* forInTarget = forInHead->kid1();
|
||||
if (parser->handler.isDeclarationList(forInTarget)) {
|
||||
ParseNode* decl = parser->handler.singleBindingFromDeclaration(&forInTarget->as<ListNode>());
|
||||
if (decl->isKind(PNK_NAME)) {
|
||||
|
|
@ -4945,7 +4949,7 @@ BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitte
|
|||
}
|
||||
|
||||
// Evaluate the expression being iterated.
|
||||
ParseNode* expr = forInHead->pn_kid3;
|
||||
ParseNode* expr = forInHead->kid3();
|
||||
if (!emitTree(expr)) // EXPR
|
||||
return false;
|
||||
|
||||
|
|
@ -5058,7 +5062,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc
|
|||
{
|
||||
LoopControl loopInfo(this, StatementKind::ForLoop);
|
||||
|
||||
ParseNode* forHead = pn->pn_left;
|
||||
TernaryNode* forHead = &pn->pn_left->as<TernaryNode>();
|
||||
ParseNode* forBody = pn->pn_right;
|
||||
|
||||
// If the head of this for-loop declared any lexical variables, the parser
|
||||
|
|
@ -5085,7 +5089,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc
|
|||
// can't reassign consts. This is observable through the Debugger API. (The
|
||||
// ES6 spec also skips cloning the environment in this case.)
|
||||
bool forLoopRequiresFreshening = false;
|
||||
if (ParseNode* init = forHead->pn_kid1) {
|
||||
if (ParseNode* init = forHead->kid1()) {
|
||||
// Emit the `init` clause, whether it's an expression or a variable
|
||||
// declaration. (The loop variables were hoisted into an enclosing
|
||||
// scope, but we still need to emit code for the initializers.)
|
||||
|
|
@ -5140,7 +5144,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc
|
|||
ptrdiff_t tmp = offset();
|
||||
|
||||
JumpList jmp;
|
||||
if (forHead->pn_kid2) {
|
||||
if (forHead->kid2()) {
|
||||
/* Goto the loop condition, which branches back to iterate. */
|
||||
if (!emitJump(JSOP_GOTO, &jmp))
|
||||
return false;
|
||||
|
|
@ -5175,7 +5179,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc
|
|||
|
||||
// Check for update code to do before the condition (if any).
|
||||
// The update code may not be executed at all; it needs its own TDZ cache.
|
||||
if (ParseNode* update = forHead->pn_kid3) {
|
||||
if (ParseNode* update = forHead->kid3()) {
|
||||
TDZCheckCache tdzCache(this);
|
||||
|
||||
if (!updateSourceCoordNotes(update->pn_pos.begin))
|
||||
|
|
@ -5197,15 +5201,15 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc
|
|||
|
||||
ptrdiff_t tmp3 = offset();
|
||||
|
||||
if (forHead->pn_kid2) {
|
||||
if (forHead->kid2()) {
|
||||
/* Fix up the goto from top to target the loop condition. */
|
||||
MOZ_ASSERT(jmp.offset >= 0);
|
||||
if (!emitLoopEntry(forHead->pn_kid2, jmp))
|
||||
if (!emitLoopEntry(forHead->kid2(), jmp))
|
||||
return false;
|
||||
|
||||
if (!emitTree(forHead->pn_kid2))
|
||||
if (!emitTree(forHead->kid2()))
|
||||
return false;
|
||||
} else if (!forHead->pn_kid3) {
|
||||
} else if (!forHead->kid3()) {
|
||||
// If there is no condition clause and no update clause, mark
|
||||
// the loop-ending "goto" with the location of the "for".
|
||||
// This ensures that the debugger will stop on each loop
|
||||
|
|
@ -5223,7 +5227,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc
|
|||
/* If no loop condition, just emit a loop-closing jump. */
|
||||
JumpList beq;
|
||||
JumpTarget breakTarget{ -1 };
|
||||
if (!emitBackwardJump(forHead->pn_kid2 ? JSOP_IFNE : JSOP_GOTO, top, &beq, &breakTarget))
|
||||
if (!emitBackwardJump(forHead->kid2() ? JSOP_IFNE : JSOP_GOTO, top, &beq, &breakTarget))
|
||||
return false;
|
||||
|
||||
/* The third note offset helps us find the loop-closing jump. */
|
||||
|
|
@ -5292,13 +5296,13 @@ BytecodeEmitter::emitComprehensionForOf(ParseNode* pn)
|
|||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_COMPREHENSIONFOR));
|
||||
|
||||
ParseNode* forHead = pn->pn_left;
|
||||
TernaryNode* forHead = &pn->pn_left->as<TernaryNode>();
|
||||
MOZ_ASSERT(forHead->isKind(PNK_FOROF));
|
||||
|
||||
ParseNode* forHeadExpr = forHead->pn_kid3;
|
||||
ParseNode* forHeadExpr = forHead->kid3();
|
||||
ParseNode* forBody = pn->pn_right;
|
||||
|
||||
ParseNode* loopDecl = forHead->pn_kid1;
|
||||
ParseNode* loopDecl = forHead->kid1();
|
||||
bool lexicalScope = false;
|
||||
if (!emitComprehensionForInOrOfVariables(loopDecl, &lexicalScope))
|
||||
return false;
|
||||
|
|
@ -5436,18 +5440,18 @@ BytecodeEmitter::emitComprehensionForIn(ParseNode* pn)
|
|||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_COMPREHENSIONFOR));
|
||||
|
||||
ParseNode* forHead = pn->pn_left;
|
||||
TernaryNode* forHead = &pn->pn_left->as<TernaryNode>();
|
||||
MOZ_ASSERT(forHead->isKind(PNK_FORIN));
|
||||
|
||||
ParseNode* forBody = pn->pn_right;
|
||||
|
||||
ParseNode* loopDecl = forHead->pn_kid1;
|
||||
ParseNode* loopDecl = forHead->kid1();
|
||||
bool lexicalScope = false;
|
||||
if (loopDecl && !emitComprehensionForInOrOfVariables(loopDecl, &lexicalScope))
|
||||
return false;
|
||||
|
||||
// Evaluate the expression to the right of 'in'.
|
||||
if (!emitTree(forHead->pn_kid3))
|
||||
if (!emitTree(forHead->kid3()))
|
||||
return false;
|
||||
|
||||
/*
|
||||
|
|
@ -5500,7 +5504,7 @@ BytecodeEmitter::emitComprehensionForIn(ParseNode* pn)
|
|||
|
||||
// Emit code to assign the enumeration value to the left hand side, but
|
||||
// also leave it on the stack.
|
||||
if (!emitAssignment(forHead->pn_kid2, JSOP_NOP, nullptr))
|
||||
if (!emitAssignment(forHead->kid2(), JSOP_NOP, nullptr))
|
||||
return false;
|
||||
|
||||
/* The stack should be balanced around the assignment opcode sequence. */
|
||||
|
|
@ -8458,15 +8462,12 @@ BytecodeEmitter::emitLexicalInitialization(ParseNode* pn)
|
|||
// This follows ES6 14.5.14 (ClassDefinitionEvaluation) and ES6 14.5.15
|
||||
// (BindingClassDeclarationEvaluation).
|
||||
bool
|
||||
BytecodeEmitter::emitClass(ParseNode* pn)
|
||||
BytecodeEmitter::emitClass(ClassNode* classNode)
|
||||
{
|
||||
ClassNode& classNode = pn->as<ClassNode>();
|
||||
ClassNames* names = classNode->names();
|
||||
ParseNode* heritageExpression = classNode->heritage();
|
||||
ListNode* classMethods = classNode->methodList();
|
||||
|
||||
ClassNames* names = classNode.names();
|
||||
|
||||
ParseNode* heritageExpression = classNode.heritage();
|
||||
|
||||
ListNode* classMethods = classNode.methodList();
|
||||
ParseNode* constructor = nullptr;
|
||||
for (ParseNode* mn : classMethods->contents()) {
|
||||
ClassMethod& method = mn->as<ClassMethod>();
|
||||
|
|
@ -8487,7 +8488,7 @@ BytecodeEmitter::emitClass(ParseNode* pn)
|
|||
if (names) {
|
||||
tdzCache.emplace(this);
|
||||
emitterScope.emplace(this);
|
||||
if (!emitterScope->enterLexical(this, ScopeKind::Lexical, classNode.scopeBindings()))
|
||||
if (!emitterScope->enterLexical(this, ScopeKind::Lexical, classNode->scopeBindings()))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -8525,7 +8526,9 @@ BytecodeEmitter::emitClass(ParseNode* pn)
|
|||
// offsets in the source buffer as source notes so that when we
|
||||
// actually make the constructor during execution, we can give it the
|
||||
// correct toString output.
|
||||
if (!newSrcNote3(SRC_CLASS_SPAN, ptrdiff_t(pn->pn_pos.begin), ptrdiff_t(pn->pn_pos.end)))
|
||||
ptrdiff_t classStart = ptrdiff_t(classNode->pn_pos.begin);
|
||||
ptrdiff_t classEnd = ptrdiff_t(classNode->pn_pos.end);
|
||||
if (!newSrcNote3(SRC_CLASS_SPAN, classStart, classEnd))
|
||||
return false;
|
||||
|
||||
JSAtom *name = names ? names->innerBinding()->pn_atom : cx->names().empty;
|
||||
|
|
@ -8609,7 +8612,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
|
|||
break;
|
||||
|
||||
case PNK_IF:
|
||||
if (!emitIf(pn))
|
||||
if (!emitIf(&pn->as<TernaryNode>()))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
|
@ -8654,12 +8657,12 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
|
|||
break;
|
||||
|
||||
case PNK_TRY:
|
||||
if (!emitTry(pn))
|
||||
if (!emitTry(&pn->as<TernaryNode>()))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case PNK_CATCH:
|
||||
if (!emitCatch(pn))
|
||||
if (!emitCatch(&pn->as<TernaryNode>()))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
|
@ -9017,7 +9020,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
|
|||
break;
|
||||
|
||||
case PNK_CLASS:
|
||||
if (!emitClass(pn))
|
||||
if (!emitClass(&pn->as<ClassNode>()))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -583,8 +583,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitElemOpBase(JSOp op);
|
||||
MOZ_MUST_USE bool emitElemIncDec(ParseNode* pn);
|
||||
|
||||
MOZ_MUST_USE bool emitCatch(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitIf(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitCatch(TernaryNode* catchNode);
|
||||
MOZ_MUST_USE bool emitIf(TernaryNode* ifNode);
|
||||
MOZ_MUST_USE bool emitWith(ParseNode* pn);
|
||||
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLabeledStatement(const LabeledStatement* pn);
|
||||
|
|
@ -592,7 +592,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitLexicalScopeBody(ParseNode* body,
|
||||
EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitSwitch(SwitchStatement* pn);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitTry(ParseNode* pn);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitTry(TernaryNode* tryNode);
|
||||
|
||||
enum DestructuringFlavor {
|
||||
// Destructuring into a declaration.
|
||||
|
|
@ -778,7 +778,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitForIn(ParseNode* pn, EmitterScope* headLexicalEmitterScope);
|
||||
MOZ_MUST_USE bool emitForOf(ParseNode* pn, EmitterScope* headLexicalEmitterScope);
|
||||
|
||||
MOZ_MUST_USE bool emitInitializeForInOrOfTarget(ParseNode* forHead);
|
||||
MOZ_MUST_USE bool emitInitializeForInOrOfTarget(TernaryNode* forHead);
|
||||
|
||||
MOZ_MUST_USE bool emitBreak(PropertyName* label);
|
||||
MOZ_MUST_USE bool emitContinue(PropertyName* label);
|
||||
|
|
@ -799,7 +799,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
// iteration count). The stack after iteration will look like |ARRAY INDEX|.
|
||||
MOZ_MUST_USE bool emitSpread(bool allowSelfHosted = false);
|
||||
|
||||
MOZ_MUST_USE bool emitClass(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitClass(ClassNode* classNode);
|
||||
};
|
||||
|
||||
class MOZ_RAII AutoCheckUnstableEmitterScope {
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
// Similarly to the lexical declarations above, classes cannot add hoisted
|
||||
// declarations
|
||||
case PNK_CLASS:
|
||||
MOZ_ASSERT(node->isArity(PN_TERNARY));
|
||||
MOZ_ASSERT(node->is<ClassNode>());
|
||||
*result = false;
|
||||
return true;
|
||||
|
||||
|
|
@ -158,15 +158,14 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
// if-statement nodes may have hoisted declarations in their consequent
|
||||
// and alternative components.
|
||||
case PNK_IF: {
|
||||
MOZ_ASSERT(node->isArity(PN_TERNARY));
|
||||
|
||||
ParseNode* consequent = node->pn_kid2;
|
||||
TernaryNode* ifNode = &node->as<TernaryNode>();
|
||||
ParseNode* consequent = ifNode->kid2();
|
||||
if (!ContainsHoistedDeclaration(cx, consequent, result))
|
||||
return false;
|
||||
if (*result)
|
||||
return true;
|
||||
|
||||
if ((node = node->pn_kid3))
|
||||
if ((node = ifNode->kid3()))
|
||||
goto restart;
|
||||
|
||||
*result = false;
|
||||
|
|
@ -192,25 +191,25 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
// try-statements have statements to execute, and one or both of a
|
||||
// catch-list and a finally-block.
|
||||
case PNK_TRY: {
|
||||
MOZ_ASSERT(node->isArity(PN_TERNARY));
|
||||
MOZ_ASSERT(node->pn_kid2 || node->pn_kid3,
|
||||
TernaryNode* tryNode = &node->as<TernaryNode>();
|
||||
MOZ_ASSERT(tryNode->kid2() || tryNode->kid3(),
|
||||
"must have either catch(es) or finally");
|
||||
|
||||
ParseNode* tryBlock = node->pn_kid1;
|
||||
ParseNode* tryBlock = tryNode->kid1();
|
||||
if (!ContainsHoistedDeclaration(cx, tryBlock, result))
|
||||
return false;
|
||||
if (*result)
|
||||
return true;
|
||||
|
||||
if (node->pn_kid2) {
|
||||
if (ListNode* catchList = &node->pn_kid2->as<ListNode>()) {
|
||||
if (tryNode->kid2()) {
|
||||
if (ListNode* catchList = &tryNode->kid2()->as<ListNode>()) {
|
||||
for (ParseNode* lexicalScope : catchList->contents()) {
|
||||
MOZ_ASSERT(lexicalScope->isKind(PNK_LEXICALSCOPE));
|
||||
|
||||
ParseNode* catchNode = lexicalScope->scopeBody();
|
||||
TernaryNode* catchNode = &lexicalScope->scopeBody()->as<TernaryNode>();
|
||||
MOZ_ASSERT(catchNode->isKind(PNK_CATCH));
|
||||
|
||||
ParseNode* catchStatements = catchNode->pn_kid3;
|
||||
ParseNode* catchStatements = catchNode->kid3();
|
||||
if (!ContainsHoistedDeclaration(cx, catchStatements, result))
|
||||
return false;
|
||||
if (*result)
|
||||
|
|
@ -219,7 +218,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
}
|
||||
}
|
||||
|
||||
if (ParseNode* finallyBlock = node->pn_kid3)
|
||||
if (ParseNode* finallyBlock = tryNode->kid3())
|
||||
return ContainsHoistedDeclaration(cx, finallyBlock, result);
|
||||
|
||||
*result = false;
|
||||
|
|
@ -240,7 +239,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
case PNK_COMPREHENSIONFOR: {
|
||||
MOZ_ASSERT(node->isArity(PN_BINARY));
|
||||
|
||||
ParseNode* loopHead = node->pn_left;
|
||||
TernaryNode* loopHead = &node->pn_left->as<TernaryNode>();
|
||||
MOZ_ASSERT(loopHead->isKind(PNK_FORHEAD) ||
|
||||
loopHead->isKind(PNK_FORIN) ||
|
||||
loopHead->isKind(PNK_FOROF));
|
||||
|
|
@ -251,9 +250,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
// (at present) hoisted in SpiderMonkey parlance -- but such
|
||||
// hoisting doesn't extend outside of this statement, so it is not
|
||||
// hoisting in the sense meant by ContainsHoistedDeclaration.)
|
||||
MOZ_ASSERT(loopHead->isArity(PN_TERNARY));
|
||||
|
||||
ParseNode* init = loopHead->pn_kid1;
|
||||
ParseNode* init = loopHead->kid1();
|
||||
if (init && init->isKind(PNK_VAR)) {
|
||||
*result = true;
|
||||
return true;
|
||||
|
|
@ -271,9 +268,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
//
|
||||
// Either way, if |target| contains a declaration, it's |loopHead|'s
|
||||
// first kid.
|
||||
MOZ_ASSERT(loopHead->isArity(PN_TERNARY));
|
||||
|
||||
ParseNode* decl = loopHead->pn_kid1;
|
||||
ParseNode* decl = loopHead->kid1();
|
||||
if (decl && decl->isKind(PNK_VAR)) {
|
||||
*result = true;
|
||||
return true;
|
||||
|
|
@ -856,19 +851,17 @@ FoldConditional(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandl
|
|||
nodePtr = nextNode;
|
||||
nextNode = nullptr;
|
||||
|
||||
ParseNode* node = *nodePtr;
|
||||
TernaryNode* node = &(*nodePtr)->as<TernaryNode>();
|
||||
MOZ_ASSERT(node->isKind(PNK_CONDITIONAL));
|
||||
MOZ_ASSERT(node->isArity(PN_TERNARY));
|
||||
|
||||
ParseNode*& expr = node->pn_kid1;
|
||||
if (!FoldCondition(cx, &expr, parser, inGenexpLambda))
|
||||
ParseNode** expr = node->unsafeKid1Reference();
|
||||
if (!FoldCondition(cx, expr, parser, inGenexpLambda))
|
||||
return false;
|
||||
|
||||
ParseNode*& ifTruthy = node->pn_kid2;
|
||||
if (!Fold(cx, &ifTruthy, parser, inGenexpLambda))
|
||||
ParseNode** ifTruthy = node->unsafeKid2Reference();
|
||||
if (!Fold(cx, ifTruthy, parser, inGenexpLambda))
|
||||
return false;
|
||||
|
||||
ParseNode*& ifFalsy = node->pn_kid3;
|
||||
ParseNode** ifFalsy = node->unsafeKid3Reference();
|
||||
|
||||
// If our C?T:F node has F as another ?: node, *iteratively* constant-
|
||||
// fold F *after* folding C and T (and possibly eliminating C and one
|
||||
|
|
@ -877,15 +870,16 @@ FoldConditional(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandl
|
|||
//
|
||||
// Conceivably we could instead/also iteratively constant-fold T, if T
|
||||
// were more complex than F. Such an optimization is unimplemented.
|
||||
if (ifFalsy->isKind(PNK_CONDITIONAL)) {
|
||||
nextNode = &ifFalsy;
|
||||
if ((*ifFalsy)->isKind(PNK_CONDITIONAL)) {
|
||||
MOZ_ASSERT((*ifFalsy)->is<TernaryNode>());
|
||||
nextNode = ifFalsy;
|
||||
} else {
|
||||
if (!Fold(cx, &ifFalsy, parser, inGenexpLambda))
|
||||
if (!Fold(cx, ifFalsy, parser, inGenexpLambda))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to constant-fold based on the condition expression.
|
||||
Truthiness t = Boolish(expr);
|
||||
Truthiness t = Boolish(*expr);
|
||||
if (t == Unknown)
|
||||
continue;
|
||||
|
||||
|
|
@ -893,11 +887,11 @@ FoldConditional(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandl
|
|||
ParseNode* replacement;
|
||||
ParseNode* discarded;
|
||||
if (t == Truthy) {
|
||||
replacement = ifTruthy;
|
||||
discarded = ifFalsy;
|
||||
replacement = *ifTruthy;
|
||||
discarded = *ifFalsy;
|
||||
} else {
|
||||
replacement = ifFalsy;
|
||||
discarded = ifTruthy;
|
||||
replacement = *ifFalsy;
|
||||
discarded = *ifTruthy;
|
||||
}
|
||||
|
||||
// Otherwise perform a replacement. This invalidates |nextNode|, so
|
||||
|
|
@ -925,29 +919,28 @@ FoldIf(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& pars
|
|||
nodePtr = nextNode;
|
||||
nextNode = nullptr;
|
||||
|
||||
ParseNode* node = *nodePtr;
|
||||
TernaryNode* node = &(*nodePtr)->as<TernaryNode>();
|
||||
MOZ_ASSERT(node->isKind(PNK_IF));
|
||||
MOZ_ASSERT(node->isArity(PN_TERNARY));
|
||||
|
||||
ParseNode*& expr = node->pn_kid1;
|
||||
if (!FoldCondition(cx, &expr, parser, inGenexpLambda))
|
||||
ParseNode** expr = node->unsafeKid1Reference();
|
||||
if (!FoldCondition(cx, expr, parser, inGenexpLambda))
|
||||
return false;
|
||||
|
||||
ParseNode*& consequent = node->pn_kid2;
|
||||
if (!Fold(cx, &consequent, parser, inGenexpLambda))
|
||||
ParseNode** consequent = node->unsafeKid2Reference();
|
||||
if (!Fold(cx, consequent, parser, inGenexpLambda))
|
||||
return false;
|
||||
|
||||
ParseNode*& alternative = node->pn_kid3;
|
||||
if (alternative) {
|
||||
ParseNode** alternative = node->unsafeKid3Reference();
|
||||
if (*alternative) {
|
||||
// If in |if (C) T; else F;| we have |F| as another |if|,
|
||||
// *iteratively* constant-fold |F| *after* folding |C| and |T| (and
|
||||
// possibly completely replacing the whole thing with |T| or |F|);
|
||||
// otherwise fold F normally. Making |nextNode| non-null causes
|
||||
// this loop to run again to fold F.
|
||||
if (alternative->isKind(PNK_IF)) {
|
||||
nextNode = &alternative;
|
||||
if ((*alternative)->isKind(PNK_IF)) {
|
||||
MOZ_ASSERT((*alternative)->is<TernaryNode>());
|
||||
nextNode = alternative;
|
||||
} else {
|
||||
if (!Fold(cx, &alternative, parser, inGenexpLambda))
|
||||
if (!Fold(cx, alternative, parser, inGenexpLambda))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -956,7 +949,7 @@ FoldIf(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& pars
|
|||
// constant truthiness. Don't eliminate if we have an |if (0)| in
|
||||
// trailing position in a generator expression, as this is a special
|
||||
// form we can't fold away.
|
||||
Truthiness t = Boolish(expr);
|
||||
Truthiness t = Boolish(*expr);
|
||||
if (t == Unknown || inGenexpLambda)
|
||||
continue;
|
||||
|
||||
|
|
@ -965,11 +958,11 @@ FoldIf(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& pars
|
|||
ParseNode* replacement;
|
||||
ParseNode* discarded;
|
||||
if (t == Truthy) {
|
||||
replacement = consequent;
|
||||
discarded = alternative;
|
||||
replacement = *consequent;
|
||||
discarded = *alternative;
|
||||
} else {
|
||||
replacement = alternative;
|
||||
discarded = consequent;
|
||||
replacement = *alternative;
|
||||
discarded = *consequent;
|
||||
}
|
||||
|
||||
bool performReplacement = true;
|
||||
|
|
@ -1234,23 +1227,23 @@ FoldReturn(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& pars
|
|||
}
|
||||
|
||||
static bool
|
||||
FoldTry(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
|
||||
FoldTry(ExclusiveContext* cx, TernaryNode* node, Parser<FullParseHandler>& parser,
|
||||
bool inGenexpLambda)
|
||||
{
|
||||
MOZ_ASSERT(node->isKind(PNK_TRY));
|
||||
MOZ_ASSERT(node->isArity(PN_TERNARY));
|
||||
|
||||
ParseNode*& statements = node->pn_kid1;
|
||||
if (!Fold(cx, &statements, parser, inGenexpLambda))
|
||||
ParseNode** statements = node->unsafeKid1Reference();
|
||||
if (!Fold(cx, statements, parser, inGenexpLambda))
|
||||
return false;
|
||||
|
||||
if (ParseNode*& catchList = node->pn_kid2) {
|
||||
if (!Fold(cx, &catchList, parser, inGenexpLambda))
|
||||
ParseNode** catchList = node->unsafeKid2Reference();
|
||||
if (*catchList) {
|
||||
if (!Fold(cx, catchList, parser, inGenexpLambda))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ParseNode*& finally = node->pn_kid3) {
|
||||
if (!Fold(cx, &finally, parser, inGenexpLambda))
|
||||
ParseNode** finally = node->unsafeKid3Reference();
|
||||
if (*finally) {
|
||||
if (!Fold(cx, finally, parser, inGenexpLambda))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1258,24 +1251,25 @@ FoldTry(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
|
|||
}
|
||||
|
||||
static bool
|
||||
FoldCatch(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
|
||||
FoldCatch(ExclusiveContext* cx, TernaryNode* node, Parser<FullParseHandler>& parser,
|
||||
bool inGenexpLambda)
|
||||
{
|
||||
MOZ_ASSERT(node->isKind(PNK_CATCH));
|
||||
MOZ_ASSERT(node->isArity(PN_TERNARY));
|
||||
|
||||
if (ParseNode*& declPattern = node->pn_kid1) {
|
||||
if (!Fold(cx, &declPattern, parser, inGenexpLambda))
|
||||
ParseNode** binding = node->unsafeKid1Reference();
|
||||
if (*binding) {
|
||||
if (!Fold(cx, binding, parser, inGenexpLambda))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ParseNode*& cond = node->pn_kid2) {
|
||||
if (!FoldCondition(cx, &cond, parser, inGenexpLambda))
|
||||
ParseNode** cond = node->unsafeKid2Reference();
|
||||
if (*cond) {
|
||||
if (!FoldCondition(cx, cond, parser, inGenexpLambda))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ParseNode*& statements = node->pn_kid3) {
|
||||
if (!Fold(cx, &statements, parser, inGenexpLambda))
|
||||
if (ParseNode** statements = node->unsafeKid3Reference()) {
|
||||
if (!Fold(cx, statements, parser, inGenexpLambda))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1283,24 +1277,24 @@ FoldCatch(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parse
|
|||
}
|
||||
|
||||
static bool
|
||||
FoldClass(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
|
||||
FoldClass(ExclusiveContext* cx, ClassNode* node, Parser<FullParseHandler>& parser,
|
||||
bool inGenexpLambda)
|
||||
{
|
||||
MOZ_ASSERT(node->isKind(PNK_CLASS));
|
||||
MOZ_ASSERT(node->isArity(PN_TERNARY));
|
||||
|
||||
if (ParseNode*& classNames = node->pn_kid1) {
|
||||
if (!Fold(cx, &classNames, parser, inGenexpLambda))
|
||||
ParseNode** classNames = node->unsafeKid1Reference();
|
||||
if (*classNames) {
|
||||
if (!Fold(cx, classNames, parser, inGenexpLambda))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ParseNode*& heritage = node->pn_kid2) {
|
||||
if (!Fold(cx, &heritage, parser, inGenexpLambda))
|
||||
ParseNode** heritage = node->unsafeKid2Reference();
|
||||
if (*heritage) {
|
||||
if (!Fold(cx, heritage, parser, inGenexpLambda))
|
||||
return false;
|
||||
}
|
||||
|
||||
ParseNode*& body = node->pn_kid3;
|
||||
return Fold(cx, &body, parser, inGenexpLambda);
|
||||
ParseNode** body = node->unsafeKid3Reference();
|
||||
return Fold(cx, body, parser, inGenexpLambda);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -1580,41 +1574,41 @@ FoldArguments(ExclusiveContext* cx, ListNode* node, Parser<FullParseHandler>& pa
|
|||
}
|
||||
|
||||
static bool
|
||||
FoldForInOrOf(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
|
||||
FoldForInOrOf(ExclusiveContext* cx, TernaryNode* node, Parser<FullParseHandler>& parser,
|
||||
bool inGenexpLambda)
|
||||
{
|
||||
MOZ_ASSERT(node->isKind(PNK_FORIN) || node->isKind(PNK_FOROF));
|
||||
MOZ_ASSERT(node->isArity(PN_TERNARY));
|
||||
MOZ_ASSERT(!node->pn_kid2);
|
||||
MOZ_ASSERT(!node->kid2());
|
||||
|
||||
return Fold(cx, &node->pn_kid1, parser, inGenexpLambda) &&
|
||||
Fold(cx, &node->pn_kid3, parser, inGenexpLambda);
|
||||
return Fold(cx, node->unsafeKid1Reference(), parser, inGenexpLambda) &&
|
||||
Fold(cx, node->unsafeKid3Reference(), parser, inGenexpLambda);
|
||||
}
|
||||
|
||||
static bool
|
||||
FoldForHead(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
|
||||
FoldForHead(ExclusiveContext* cx, TernaryNode* node, Parser<FullParseHandler>& parser,
|
||||
bool inGenexpLambda)
|
||||
{
|
||||
MOZ_ASSERT(node->isKind(PNK_FORHEAD));
|
||||
MOZ_ASSERT(node->isArity(PN_TERNARY));
|
||||
|
||||
if (ParseNode*& init = node->pn_kid1) {
|
||||
if (!Fold(cx, &init, parser, inGenexpLambda))
|
||||
ParseNode** init = node->unsafeKid1Reference();
|
||||
if (*init) {
|
||||
if (!Fold(cx, init, parser, inGenexpLambda))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ParseNode*& test = node->pn_kid2) {
|
||||
if (!FoldCondition(cx, &test, parser, inGenexpLambda))
|
||||
ParseNode** test = node->unsafeKid2Reference();
|
||||
if (*test) {
|
||||
if (!FoldCondition(cx, test, parser, inGenexpLambda))
|
||||
return false;
|
||||
|
||||
if (test->isKind(PNK_TRUE)) {
|
||||
parser.freeTree(test);
|
||||
test = nullptr;
|
||||
if ((*test)->isKind(PNK_TRUE)) {
|
||||
parser.freeTree(*test);
|
||||
*test = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (ParseNode*& update = node->pn_kid3) {
|
||||
if (!Fold(cx, &update, parser, inGenexpLambda))
|
||||
ParseNode** update = node->unsafeKid3Reference();
|
||||
if (*update) {
|
||||
if (!Fold(cx, update, parser, inGenexpLambda))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1709,9 +1703,11 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
return FoldDeleteProperty(cx, pn, parser, inGenexpLambda);
|
||||
|
||||
case PNK_CONDITIONAL:
|
||||
MOZ_ASSERT((*pnp)->is<TernaryNode>());
|
||||
return FoldConditional(cx, pnp, parser, inGenexpLambda);
|
||||
|
||||
case PNK_IF:
|
||||
MOZ_ASSERT((*pnp)->is<TernaryNode>());
|
||||
return FoldIf(cx, pnp, parser, inGenexpLambda);
|
||||
|
||||
case PNK_NOT:
|
||||
|
|
@ -1830,13 +1826,13 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
return FoldReturn(cx, pn, parser, inGenexpLambda);
|
||||
|
||||
case PNK_TRY:
|
||||
return FoldTry(cx, pn, parser, inGenexpLambda);
|
||||
return FoldTry(cx, &pn->as<TernaryNode>(), parser, inGenexpLambda);
|
||||
|
||||
case PNK_CATCH:
|
||||
return FoldCatch(cx, pn, parser, inGenexpLambda);
|
||||
return FoldCatch(cx, &pn->as<TernaryNode>(), parser, inGenexpLambda);
|
||||
|
||||
case PNK_CLASS:
|
||||
return FoldClass(cx, pn, parser, inGenexpLambda);
|
||||
return FoldClass(cx, &pn->as<ClassNode>(), parser, inGenexpLambda);
|
||||
|
||||
case PNK_OPTELEM:
|
||||
case PNK_ELEM:
|
||||
|
|
@ -1926,10 +1922,10 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
|
||||
case PNK_FORIN:
|
||||
case PNK_FOROF:
|
||||
return FoldForInOrOf(cx, pn, parser, inGenexpLambda);
|
||||
return FoldForInOrOf(cx, &pn->as<TernaryNode>(), parser, inGenexpLambda);
|
||||
|
||||
case PNK_FORHEAD:
|
||||
return FoldForHead(cx, pn, parser, inGenexpLambda);
|
||||
return FoldForHead(cx, &pn->as<TernaryNode>(), parser, inGenexpLambda);
|
||||
|
||||
case PNK_LABEL:
|
||||
MOZ_ASSERT(pn->isArity(PN_NAME));
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
return new_<RegExpLiteral>(objbox, pos);
|
||||
}
|
||||
|
||||
ParseNode* newConditional(ParseNode* cond, ParseNode* thenExpr, ParseNode* elseExpr) {
|
||||
ConditionalExpressionType newConditional(Node cond, Node thenExpr, Node elseExpr) {
|
||||
return new_<ConditionalExpression>(cond, thenExpr, elseExpr);
|
||||
}
|
||||
|
||||
|
|
@ -372,9 +372,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
return literal;
|
||||
}
|
||||
|
||||
ParseNode* newClass(ParseNode* name, ParseNode* heritage, ParseNode* methodBlock,
|
||||
const TokenPos& pos)
|
||||
{
|
||||
ClassNodeType newClass(Node name, Node heritage, Node methodBlock, const TokenPos& pos) {
|
||||
return new_<ClassNode>(name, heritage, methodBlock, pos);
|
||||
}
|
||||
ListNodeType newClassMethodList(uint32_t begin) {
|
||||
|
|
@ -606,14 +604,12 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, TokenPos(expr->pn_pos.begin, end), expr);
|
||||
}
|
||||
|
||||
ParseNode* newIfStatement(uint32_t begin, ParseNode* cond, ParseNode* thenBranch,
|
||||
ParseNode* elseBranch)
|
||||
{
|
||||
ParseNode* pn = new_<TernaryNode>(PNK_IF, JSOP_NOP, cond, thenBranch, elseBranch);
|
||||
if (!pn)
|
||||
TernaryNodeType newIfStatement(uint32_t begin, Node cond, Node thenBranch, Node elseBranch) {
|
||||
TernaryNode* node = new_<TernaryNode>(PNK_IF, JSOP_NOP, cond, thenBranch, elseBranch);
|
||||
if (!node)
|
||||
return null();
|
||||
pn->pn_pos.begin = begin;
|
||||
return pn;
|
||||
node->pn_pos.begin = begin;
|
||||
return node;
|
||||
}
|
||||
|
||||
ParseNode* newDoWhileStatement(ParseNode* body, ParseNode* cond, const TokenPos& pos) {
|
||||
|
|
@ -625,9 +621,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
return new_<BinaryNode>(PNK_WHILE, JSOP_NOP, pos, cond, body);
|
||||
}
|
||||
|
||||
ParseNode* newForStatement(uint32_t begin, ParseNode* forHead, ParseNode* body,
|
||||
unsigned iflags)
|
||||
{
|
||||
Node newForStatement(uint32_t begin, TernaryNodeType forHead, Node body, unsigned iflags) {
|
||||
/* A FOR node is binary, left is loop control and right is the body. */
|
||||
JSOp op = forHead->isKind(PNK_FORIN) ? JSOP_ITER : JSOP_NOP;
|
||||
BinaryNode* pn = new_<BinaryNode>(PNK_FOR, op, TokenPos(begin, body->pn_pos.end),
|
||||
|
|
@ -638,7 +632,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
return pn;
|
||||
}
|
||||
|
||||
ParseNode* newComprehensionFor(uint32_t begin, ParseNode* forHead, ParseNode* body) {
|
||||
Node newComprehensionFor(uint32_t begin, TernaryNodeType forHead, Node body) {
|
||||
// A PNK_COMPREHENSIONFOR node is binary: left is loop control, right
|
||||
// is the body.
|
||||
MOZ_ASSERT(forHead->isKind(PNK_FORIN) || forHead->isKind(PNK_FOROF));
|
||||
|
|
@ -656,14 +650,12 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
return new_<ListNode>(PNK_LET, JSOP_NOP, kid);
|
||||
}
|
||||
|
||||
ParseNode* newForHead(ParseNode* init, ParseNode* test, ParseNode* update,
|
||||
const TokenPos& pos)
|
||||
{
|
||||
TernaryNodeType newForHead(Node init, Node test, Node update, const TokenPos& pos) {
|
||||
return new_<TernaryNode>(PNK_FORHEAD, JSOP_NOP, init, test, update, pos);
|
||||
}
|
||||
|
||||
ParseNode* newForInOrOfHead(ParseNodeKind kind, ParseNode* target, ParseNode* iteratedExpr,
|
||||
const TokenPos& pos)
|
||||
TernaryNodeType newForInOrOfHead(ParseNodeKind kind, Node target, Node iteratedExpr,
|
||||
const TokenPos& pos)
|
||||
{
|
||||
MOZ_ASSERT(kind == PNK_FORIN || kind == PNK_FOROF);
|
||||
return new_<TernaryNode>(kind, JSOP_NOP, target, nullptr, iteratedExpr, pos);
|
||||
|
|
@ -707,8 +699,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
return new_<UnaryNode>(PNK_THROW, JSOP_THROW, pos, expr);
|
||||
}
|
||||
|
||||
ParseNode* newTryStatement(uint32_t begin, ParseNode* body, ListNodeType catchList,
|
||||
ParseNode* finallyBlock) {
|
||||
TernaryNodeType newTryStatement(uint32_t begin, Node body, ListNodeType catchList,
|
||||
Node finallyBlock) {
|
||||
TokenPos pos(begin, (finallyBlock ? finallyBlock : catchList)->pn_pos.end);
|
||||
return new_<TernaryNode>(PNK_TRY, JSOP_NOP, body, catchList, finallyBlock, pos);
|
||||
}
|
||||
|
|
@ -738,7 +730,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
}
|
||||
|
||||
inline MOZ_MUST_USE bool addCatchBlock(ListNodeType catchList, ParseNode* lexicalScope,
|
||||
ParseNode* catchName, ParseNode* catchGuard,
|
||||
ParseNode* catchBinding, ParseNode* catchGuard,
|
||||
ParseNode* catchBody);
|
||||
|
||||
inline MOZ_MUST_USE bool setLastFunctionFormalParameterDefault(ParseNode* funcpn,
|
||||
|
|
@ -1023,9 +1015,9 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
|
||||
inline bool
|
||||
FullParseHandler::addCatchBlock(ListNodeType catchList, ParseNode* lexicalScope,
|
||||
ParseNode* catchName, ParseNode* catchGuard, ParseNode* catchBody)
|
||||
ParseNode* catchBinding, ParseNode* catchGuard, ParseNode* catchBody)
|
||||
{
|
||||
ParseNode* catchpn = newTernary(PNK_CATCH, catchName, catchGuard, catchBody);
|
||||
ParseNode* catchpn = newTernary(PNK_CATCH, catchBinding, catchGuard, catchBody);
|
||||
if (!catchpn)
|
||||
return false;
|
||||
catchList->append(lexicalScope);
|
||||
|
|
|
|||
|
|
@ -545,15 +545,16 @@ class NameResolver
|
|||
break;
|
||||
|
||||
// Ternary nodes with three expression children.
|
||||
case PNK_CONDITIONAL:
|
||||
MOZ_ASSERT(cur->isArity(PN_TERNARY));
|
||||
if (!resolve(cur->pn_kid1, prefix))
|
||||
case PNK_CONDITIONAL: {
|
||||
TernaryNode* condNode = &cur->as<TernaryNode>();
|
||||
if (!resolve(condNode->kid1(), prefix))
|
||||
return false;
|
||||
if (!resolve(cur->pn_kid2, prefix))
|
||||
if (!resolve(condNode->kid2(), prefix))
|
||||
return false;
|
||||
if (!resolve(cur->pn_kid3, prefix))
|
||||
if (!resolve(condNode->kid3(), prefix))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
// The first part of a for-in/of is the declaration in the loop (or
|
||||
// null if no declaration). The latter two parts are the location
|
||||
|
|
@ -562,107 +563,115 @@ class NameResolver
|
|||
// computed property names, and possibly through [deprecated!]
|
||||
// initializers) also contain functions to name.
|
||||
case PNK_FORIN:
|
||||
case PNK_FOROF:
|
||||
MOZ_ASSERT(cur->isArity(PN_TERNARY));
|
||||
if (ParseNode* decl = cur->pn_kid1) {
|
||||
case PNK_FOROF: {
|
||||
TernaryNode* forHead = &cur->as<TernaryNode>();
|
||||
if (ParseNode* decl = forHead->kid1()) {
|
||||
if (!resolve(decl, prefix))
|
||||
return false;
|
||||
}
|
||||
if (!resolve(cur->pn_kid2, prefix))
|
||||
return false;
|
||||
if (!resolve(cur->pn_kid3, prefix))
|
||||
MOZ_ASSERT(!forHead->kid2());
|
||||
if (!resolve(forHead->kid3(), prefix))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Every part of a for(;;) head may contain a function needing name
|
||||
// resolution.
|
||||
case PNK_FORHEAD:
|
||||
MOZ_ASSERT(cur->isArity(PN_TERNARY));
|
||||
if (ParseNode* init = cur->pn_kid1) {
|
||||
case PNK_FORHEAD: {
|
||||
TernaryNode* forHead = &cur->as<TernaryNode>();
|
||||
if (ParseNode* init = forHead->kid1()) {
|
||||
if (!resolve(init, prefix))
|
||||
return false;
|
||||
}
|
||||
if (ParseNode* cond = cur->pn_kid2) {
|
||||
if (ParseNode* cond = forHead->kid2()) {
|
||||
if (!resolve(cond, prefix))
|
||||
return false;
|
||||
}
|
||||
if (ParseNode* step = cur->pn_kid3) {
|
||||
if (!resolve(step, prefix))
|
||||
if (ParseNode* update = forHead->kid3()) {
|
||||
if (!resolve(update, prefix))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// The first child of a class is a pair of names referring to it,
|
||||
// inside and outside the class. The second is the class's heritage,
|
||||
// if any. The third is the class body.
|
||||
case PNK_CLASS:
|
||||
MOZ_ASSERT(cur->isArity(PN_TERNARY));
|
||||
MOZ_ASSERT_IF(cur->pn_kid1, cur->pn_kid1->isKind(PNK_CLASSNAMES));
|
||||
MOZ_ASSERT_IF(cur->pn_kid1, cur->pn_kid1->isArity(PN_BINARY));
|
||||
MOZ_ASSERT_IF(cur->pn_kid1 && cur->pn_kid1->pn_left,
|
||||
cur->pn_kid1->pn_left->isKind(PNK_NAME));
|
||||
MOZ_ASSERT_IF(cur->pn_kid1 && cur->pn_kid1->pn_left,
|
||||
!cur->pn_kid1->pn_left->expr());
|
||||
MOZ_ASSERT_IF(cur->pn_kid1, cur->pn_kid1->pn_right->isKind(PNK_NAME));
|
||||
MOZ_ASSERT_IF(cur->pn_kid1, !cur->pn_kid1->pn_right->expr());
|
||||
if (cur->pn_kid2) {
|
||||
if (!resolve(cur->pn_kid2, prefix))
|
||||
case PNK_CLASS: {
|
||||
ClassNode* classNode = &cur->as<ClassNode>();
|
||||
#ifdef DEBUG
|
||||
if (classNode->names()) {
|
||||
ParseNode* name = classNode->names();
|
||||
MOZ_ASSERT(name->isKind(PNK_CLASSNAMES));
|
||||
MOZ_ASSERT(name->isArity(PN_BINARY));
|
||||
MOZ_ASSERT_IF(name->pn_left, name->pn_left->isKind(PNK_NAME));
|
||||
MOZ_ASSERT_IF(name->pn_left, !name->pn_left->expr());
|
||||
MOZ_ASSERT(name->pn_right->isKind(PNK_NAME));
|
||||
MOZ_ASSERT(!name->pn_right->expr());
|
||||
}
|
||||
#endif
|
||||
if (ParseNode* heritage = classNode->heritage()) {
|
||||
if (!resolve(heritage, prefix))
|
||||
return false;
|
||||
}
|
||||
if (!resolve(cur->pn_kid3, prefix))
|
||||
if (!resolve(classNode->methodList(), prefix))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
// The condition and consequent are non-optional, but the alternative
|
||||
// might be omitted.
|
||||
case PNK_IF:
|
||||
MOZ_ASSERT(cur->isArity(PN_TERNARY));
|
||||
if (!resolve(cur->pn_kid1, prefix))
|
||||
case PNK_IF: {
|
||||
TernaryNode* ifNode = &cur->as<TernaryNode>();
|
||||
if (!resolve(ifNode->kid1(), prefix))
|
||||
return false;
|
||||
if (!resolve(cur->pn_kid2, prefix))
|
||||
if (!resolve(ifNode->kid2(), prefix))
|
||||
return false;
|
||||
if (cur->pn_kid3) {
|
||||
if (!resolve(cur->pn_kid3, prefix))
|
||||
if (ParseNode* alternative = ifNode->kid3()) {
|
||||
if (!resolve(alternative, prefix))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// The statements in the try-block are mandatory. The catch-blocks
|
||||
// and finally block are optional (but at least one or the other must
|
||||
// be present).
|
||||
case PNK_TRY:
|
||||
MOZ_ASSERT(cur->isArity(PN_TERNARY));
|
||||
if (!resolve(cur->pn_kid1, prefix))
|
||||
case PNK_TRY: {
|
||||
TernaryNode* tryNode = &cur->as<TernaryNode>();
|
||||
if (!resolve(tryNode->kid1(), prefix))
|
||||
return false;
|
||||
MOZ_ASSERT(cur->pn_kid2 || cur->pn_kid3);
|
||||
if (ParseNode* catchList = cur->pn_kid2) {
|
||||
MOZ_ASSERT(tryNode->kid2() || tryNode->kid3());
|
||||
if (ParseNode* catchList = tryNode->kid2()) {
|
||||
MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
|
||||
if (!resolve(catchList, prefix))
|
||||
return false;
|
||||
}
|
||||
if (ParseNode* finallyBlock = cur->pn_kid3) {
|
||||
if (ParseNode* finallyBlock = tryNode->kid3()) {
|
||||
if (!resolve(finallyBlock, prefix))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// The first child, the catch-pattern, may contain functions via
|
||||
// computed property names. The optional catch-conditions may
|
||||
// contain any expression. The catch statements, of course, may
|
||||
// contain arbitrary expressions.
|
||||
case PNK_CATCH:
|
||||
MOZ_ASSERT(cur->isArity(PN_TERNARY));
|
||||
if (cur->pn_kid1) {
|
||||
if (!resolve(cur->pn_kid1, prefix))
|
||||
case PNK_CATCH: {
|
||||
TernaryNode* catchNode = &cur->as<TernaryNode>();
|
||||
if (ParseNode* patNode = catchNode->kid1()) {
|
||||
if (!resolve(patNode, prefix))
|
||||
return false;
|
||||
}
|
||||
if (cur->pn_kid2) {
|
||||
if (!resolve(cur->pn_kid2, prefix))
|
||||
if (ParseNode* condNode = catchNode->kid2()) {
|
||||
if (!resolve(condNode, prefix))
|
||||
return false;
|
||||
}
|
||||
if (!resolve(cur->pn_kid3, prefix))
|
||||
if (!resolve(catchNode->kid3(), prefix))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Nodes with arbitrary-expression children.
|
||||
case PNK_COALESCE:
|
||||
|
|
|
|||
|
|
@ -349,10 +349,10 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
|||
|
||||
// Ternary nodes with all children non-null.
|
||||
case PNK_CONDITIONAL: {
|
||||
MOZ_ASSERT(pn->isArity(PN_TERNARY));
|
||||
stack->push(pn->pn_kid1);
|
||||
stack->push(pn->pn_kid2);
|
||||
stack->push(pn->pn_kid3);
|
||||
TernaryNode* tn = &pn->as<TernaryNode>();
|
||||
stack->push(tn->kid1());
|
||||
stack->push(tn->kid2());
|
||||
stack->push(tn->kid3());
|
||||
return PushResult::Recyclable;
|
||||
}
|
||||
|
||||
|
|
@ -363,57 +363,57 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
|||
// p|, the second child is null, and the third child is |obj|.
|
||||
case PNK_FORIN:
|
||||
case PNK_FOROF: {
|
||||
MOZ_ASSERT(pn->isArity(PN_TERNARY));
|
||||
MOZ_ASSERT(!pn->pn_kid2);
|
||||
stack->push(pn->pn_kid1);
|
||||
stack->push(pn->pn_kid3);
|
||||
TernaryNode* tn = &pn->as<TernaryNode>();
|
||||
MOZ_ASSERT(!tn->kid2());
|
||||
stack->push(tn->kid1());
|
||||
stack->push(tn->kid3());
|
||||
return PushResult::Recyclable;
|
||||
}
|
||||
|
||||
// for (;;) nodes have one child per optional component of the loop head.
|
||||
case PNK_FORHEAD: {
|
||||
MOZ_ASSERT(pn->isArity(PN_TERNARY));
|
||||
if (pn->pn_kid1)
|
||||
stack->push(pn->pn_kid1);
|
||||
if (pn->pn_kid2)
|
||||
stack->push(pn->pn_kid2);
|
||||
if (pn->pn_kid3)
|
||||
stack->push(pn->pn_kid3);
|
||||
TernaryNode* tn = &pn->as<TernaryNode>();
|
||||
if (tn->kid1())
|
||||
stack->push(tn->kid1());
|
||||
if (tn->kid2())
|
||||
stack->push(tn->kid2());
|
||||
if (tn->kid3())
|
||||
stack->push(tn->kid3());
|
||||
return PushResult::Recyclable;
|
||||
}
|
||||
|
||||
// classes might have an optional node for the heritage, as well as the names
|
||||
case PNK_CLASS: {
|
||||
MOZ_ASSERT(pn->isArity(PN_TERNARY));
|
||||
if (pn->pn_kid1)
|
||||
stack->push(pn->pn_kid1);
|
||||
if (pn->pn_kid2)
|
||||
stack->push(pn->pn_kid2);
|
||||
stack->push(pn->pn_kid3);
|
||||
TernaryNode* tn = &pn->as<TernaryNode>();
|
||||
if (tn->kid1())
|
||||
stack->push(tn->kid1());
|
||||
if (tn->kid2())
|
||||
stack->push(tn->kid2());
|
||||
stack->push(tn->kid3());
|
||||
return PushResult::Recyclable;
|
||||
}
|
||||
|
||||
// if-statement nodes have condition and consequent children and a
|
||||
// possibly-null alternative.
|
||||
case PNK_IF: {
|
||||
MOZ_ASSERT(pn->isArity(PN_TERNARY));
|
||||
stack->push(pn->pn_kid1);
|
||||
stack->push(pn->pn_kid2);
|
||||
if (pn->pn_kid3)
|
||||
stack->push(pn->pn_kid3);
|
||||
TernaryNode* tn = &pn->as<TernaryNode>();
|
||||
stack->push(tn->kid1());
|
||||
stack->push(tn->kid2());
|
||||
if (tn->kid3())
|
||||
stack->push(tn->kid3());
|
||||
return PushResult::Recyclable;
|
||||
}
|
||||
|
||||
// try-statements have statements to execute, and one or both of a
|
||||
// catch-list and a finally-block.
|
||||
case PNK_TRY: {
|
||||
MOZ_ASSERT(pn->isArity(PN_TERNARY));
|
||||
MOZ_ASSERT(pn->pn_kid2 || pn->pn_kid3);
|
||||
stack->push(pn->pn_kid1);
|
||||
if (pn->pn_kid2)
|
||||
stack->push(pn->pn_kid2);
|
||||
if (pn->pn_kid3)
|
||||
stack->push(pn->pn_kid3);
|
||||
TernaryNode* tn = &pn->as<TernaryNode>();
|
||||
MOZ_ASSERT(tn->kid2() || tn->kid3());
|
||||
stack->push(tn->kid1());
|
||||
if (tn->kid2())
|
||||
stack->push(tn->kid2());
|
||||
if (tn->kid3())
|
||||
stack->push(tn->kid3());
|
||||
return PushResult::Recyclable;
|
||||
}
|
||||
|
||||
|
|
@ -422,12 +422,12 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
|||
// |<cond>| in SpiderMonkey's |catch (e if <cond>)| extension), and
|
||||
// third kid as the statements in the catch block.
|
||||
case PNK_CATCH: {
|
||||
MOZ_ASSERT(pn->isArity(PN_TERNARY));
|
||||
if (pn->pn_kid1)
|
||||
stack->push(pn->pn_kid1);
|
||||
if (pn->pn_kid2)
|
||||
stack->push(pn->pn_kid2);
|
||||
stack->push(pn->pn_kid3);
|
||||
TernaryNode* tn = &pn->as<TernaryNode>();
|
||||
if (tn->kid1())
|
||||
stack->push(tn->kid1());
|
||||
if (tn->kid2())
|
||||
stack->push(tn->kid2());
|
||||
stack->push(tn->kid3());
|
||||
return PushResult::Recyclable;
|
||||
}
|
||||
|
||||
|
|
@ -663,7 +663,7 @@ ParseNode::dump(int indent)
|
|||
((BinaryNode*) this)->dump(indent);
|
||||
break;
|
||||
case PN_TERNARY:
|
||||
((TernaryNode*) this)->dump(indent);
|
||||
as<TernaryNode>().dump(indent);
|
||||
break;
|
||||
case PN_CODE:
|
||||
((CodeNode*) this)->dump(indent);
|
||||
|
|
@ -757,11 +757,11 @@ TernaryNode::dump(int indent)
|
|||
const char* name = parseNodeNames[getKind()];
|
||||
fprintf(stderr, "(%s ", name);
|
||||
indent += strlen(name) + 2;
|
||||
DumpParseTree(pn_kid1, indent);
|
||||
DumpParseTree(kid1(), indent);
|
||||
IndentNewLine(indent);
|
||||
DumpParseTree(pn_kid2, indent);
|
||||
DumpParseTree(kid2(), indent);
|
||||
IndentNewLine(indent);
|
||||
DumpParseTree(pn_kid3, indent);
|
||||
DumpParseTree(kid3(), indent);
|
||||
fprintf(stderr, ")");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -241,16 +241,31 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* * Return for expression closure
|
||||
* count: number of formal parameters + 1
|
||||
* PNK_SPREAD unary pn_kid: expression being spread
|
||||
* PNK_CLASS (ClassNode)
|
||||
* kid1: PNK_CLASSNAMES for class name. can be null for anonymous class.
|
||||
* kid2: expression after `extends`. null if no expression
|
||||
* kid3: either of
|
||||
* * PNK_CLASSMETHODLIST, if anonymous class
|
||||
* * PNK_LEXICALSCOPE which contains PNK_CLASSMETHODLIST as scopeBody,
|
||||
* if named class
|
||||
* PNK_CLASSNAMES (ClassNames)
|
||||
* pn_left: Name node for outer binding. can be null
|
||||
* pn_right: Name node for inner binding
|
||||
* PNK_CLASSMETHODLIST (ListNode)
|
||||
* head: list of N PNK_CLASSMETHOD nodes
|
||||
* count: N >= 0
|
||||
* PNK_CLASSMETHOD (ClassMethod)
|
||||
* name: propertyName
|
||||
* method: methodDefinition
|
||||
*
|
||||
* <Statements>
|
||||
* PNK_STATEMENTLIST (ListNode)
|
||||
* head: list of N statements
|
||||
* count: N >= 0
|
||||
* PNK_IF ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else or null.
|
||||
* In body of a comprehension or desugared generator
|
||||
* expression, pn_kid2 is PNK_YIELD, PNK_ARRAYPUSH,
|
||||
* or (if the push was optimized away) empty
|
||||
* PNK_STATEMENTLIST.
|
||||
* PNK_IF (TernaryNode) In body of a comprehension or desugared PNK_GENEXP:
|
||||
* kid1: cond
|
||||
* kid2: then = PNK_YIELD, PNK_ARRAYPUSH, (empty) PNK_STATEMENTLIST
|
||||
* kid3: else or null
|
||||
* PNK_SWITCH binary pn_left: discriminant
|
||||
* pn_right: PNK_LEXICALSCOPE node that contains the list
|
||||
* of PNK_CASE nodes, with at most one default node.
|
||||
|
|
@ -266,26 +281,30 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* pn_right: body
|
||||
* PNK_COMPREHENSIONFOR pn_left: either PNK_FORIN or PNK_FOROF
|
||||
* binary pn_right: body
|
||||
* PNK_FORIN ternary pn_kid1: declaration or expression to left of 'in'
|
||||
* pn_kid2: null
|
||||
* pn_kid3: object expr to right of 'in'
|
||||
* PNK_FOROF ternary pn_kid1: declaration or expression to left of 'of'
|
||||
* pn_kid2: null
|
||||
* pn_kid3: expr to right of 'of'
|
||||
* PNK_FORHEAD ternary pn_kid1: init expr before first ';' or nullptr
|
||||
* pn_kid2: cond expr before second ';' or nullptr
|
||||
* pn_kid3: update expr after second ';' or nullptr
|
||||
* PNK_THROW unary pn_op: JSOP_THROW, pn_kid: exception
|
||||
* PNK_TRY ternary pn_kid1: try block
|
||||
* pn_kid2: null or PNK_CATCHLIST list
|
||||
* pn_kid3: null or finally block
|
||||
* PNK_FORIN (TernaryNode)
|
||||
* kid1: declaration or expression to left of 'in'
|
||||
* kid2: null
|
||||
* kid3: object expr to right of 'in'
|
||||
* PNK_FOROF (TernaryNode)
|
||||
* kid1: declaration or expression to left of 'of'
|
||||
* kid2: null
|
||||
* kid3: expr to right of 'of'
|
||||
* PNK_FORHEAD (TernaryNode)
|
||||
* kid1: init expr before first ';' or nullptr
|
||||
* kid2: cond expr before second ';' or nullptr
|
||||
* kid3: update expr after second ';' or nullptr
|
||||
* PNK_TRY (TernaryNode)
|
||||
* kid1: try block
|
||||
* kid2: null or PNK_CATCHLIST list
|
||||
* kid3: null or finally block
|
||||
* PNK_CATCHLIST list pn_head: list of PNK_LEXICALSCOPE nodes, one per
|
||||
* catch-block, each with pn_expr pointing
|
||||
* to a PNK_CATCH node
|
||||
* PNK_CATCH ternary pn_kid1: PNK_NAME, PNK_ARRAY, or PNK_OBJECT catch var node
|
||||
* (PNK_ARRAY or PNK_OBJECT if destructuring)
|
||||
* pn_kid2: null or the catch guard expression
|
||||
* pn_kid3: catch block statements
|
||||
* PNK_CATCH (TernaryNode)
|
||||
* kid1: PNK_NAME, PNK_ARRAY, or PNK_OBJECT catch binding node (PNK_ARRAY or PNK_OBJECT if destructuring)
|
||||
or null if optional catch binding
|
||||
* kid2: null or the catch guard expression
|
||||
* kid3: catch block statements
|
||||
* PNK_BREAK name pn_atom: label or null
|
||||
* PNK_CONTINUE name pn_atom: label or null
|
||||
* PNK_WITH binary pn_left: head expr; pn_right: body;
|
||||
|
|
@ -342,8 +361,11 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* PNK_DIVASSIGN,
|
||||
* PNK_MODASSIGN,
|
||||
* PNK_POWASSIGN
|
||||
* PNK_CONDITIONAL ternary (cond ? trueExpr : falseExpr)
|
||||
* pn_kid1: cond, pn_kid2: then, pn_kid3: else
|
||||
* PNK_CONDITIONAL (ConditionalExpression)
|
||||
* (cond ? thenExpr : elseExpr)
|
||||
* kid1: cond
|
||||
* kid2: thenExpr
|
||||
* kid3: elseExpr
|
||||
* PNK_COALESCE, list pn_head; list of pn_count subexpressions
|
||||
* PNK_OR, PNK_AND, PNK_BITOR,
|
||||
* PNK_BITXOR, PNK_BITAND, PNK_EQ,
|
||||
|
|
@ -498,12 +520,15 @@ enum ParseNodeArity
|
|||
|
||||
#define FOR_EACH_PARSENODE_SUBCLASS(macro) \
|
||||
macro(ListNode, ListNodeType, asList) \
|
||||
macro(CallSiteNode, CallSiteNodeType, asCallSite)
|
||||
macro(CallSiteNode, CallSiteNodeType, asCallSite) \
|
||||
\
|
||||
macro(TernaryNode, TernaryNodeType, asTernary) \
|
||||
macro(ClassNode, ClassNodeType, asClass) \
|
||||
macro(ConditionalExpression, ConditionalExpressionType, asConditionalExpression)
|
||||
|
||||
class LoopControlStatement;
|
||||
class BreakStatement;
|
||||
class ContinueStatement;
|
||||
class ConditionalExpression;
|
||||
class PropertyAccess;
|
||||
|
||||
#define DECLARE_CLASS(typeName, longTypeName, asMethodName) \
|
||||
|
|
@ -604,6 +629,8 @@ class ParseNode
|
|||
uint32_t xflags; /* see ListNode class */
|
||||
} list;
|
||||
struct { /* ternary: if, for(;;), ?: */
|
||||
private:
|
||||
friend class TernaryNode;
|
||||
ParseNode* kid1; /* condition, discriminant, etc. */
|
||||
ParseNode* kid2; /* then-part, case list, etc. */
|
||||
ParseNode* kid3; /* else-part, default case, etc. */
|
||||
|
|
@ -648,9 +675,6 @@ class ParseNode
|
|||
#define pn_objbox pn_u.name.objbox
|
||||
#define pn_funbox pn_u.name.funbox
|
||||
#define pn_body pn_u.name.expr
|
||||
#define pn_kid1 pn_u.ternary.kid1
|
||||
#define pn_kid2 pn_u.ternary.kid2
|
||||
#define pn_kid3 pn_u.ternary.kid3
|
||||
#define pn_left pn_u.binary.left
|
||||
#define pn_right pn_u.binary.right
|
||||
#define pn_pval pn_u.binary.pval
|
||||
|
|
@ -854,30 +878,56 @@ struct BinaryNode : public ParseNode
|
|||
#endif
|
||||
};
|
||||
|
||||
struct TernaryNode : public ParseNode
|
||||
class TernaryNode : public ParseNode
|
||||
{
|
||||
public:
|
||||
TernaryNode(ParseNodeKind kind, JSOp op, ParseNode* kid1, ParseNode* kid2, ParseNode* kid3)
|
||||
: ParseNode(kind, op, PN_TERNARY,
|
||||
TokenPos((kid1 ? kid1 : kid2 ? kid2 : kid3)->pn_pos.begin,
|
||||
(kid3 ? kid3 : kid2 ? kid2 : kid1)->pn_pos.end))
|
||||
{
|
||||
pn_kid1 = kid1;
|
||||
pn_kid2 = kid2;
|
||||
pn_kid3 = kid3;
|
||||
}
|
||||
: TernaryNode(kind, op, kid1, kid2, kid3,
|
||||
TokenPos((kid1 ? kid1 : kid2 ? kid2 : kid3)->pn_pos.begin,
|
||||
(kid3 ? kid3 : kid2 ? kid2 : kid1)->pn_pos.end))
|
||||
{}
|
||||
|
||||
TernaryNode(ParseNodeKind kind, JSOp op, ParseNode* kid1, ParseNode* kid2, ParseNode* kid3,
|
||||
const TokenPos& pos)
|
||||
: ParseNode(kind, op, PN_TERNARY, pos)
|
||||
{
|
||||
pn_kid1 = kid1;
|
||||
pn_kid2 = kid2;
|
||||
pn_kid3 = kid3;
|
||||
pn_u.ternary.kid1 = kid1;
|
||||
pn_u.ternary.kid2 = kid2;
|
||||
pn_u.ternary.kid3 = kid3;
|
||||
}
|
||||
|
||||
static bool test(const ParseNode& node) {
|
||||
return node.isArity(PN_TERNARY);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void dump(int indent);
|
||||
#endif
|
||||
|
||||
ParseNode* kid1() const {
|
||||
return pn_u.ternary.kid1;
|
||||
}
|
||||
|
||||
ParseNode* kid2() const {
|
||||
return pn_u.ternary.kid2;
|
||||
}
|
||||
|
||||
ParseNode* kid3() const {
|
||||
return pn_u.ternary.kid3;
|
||||
}
|
||||
|
||||
// Methods used by FoldConstants.cpp.
|
||||
ParseNode** unsafeKid1Reference() {
|
||||
return &pn_u.ternary.kid1;
|
||||
}
|
||||
|
||||
ParseNode** unsafeKid2Reference() {
|
||||
return &pn_u.ternary.kid2;
|
||||
}
|
||||
|
||||
ParseNode** unsafeKid3Reference() {
|
||||
return &pn_u.ternary.kid3;
|
||||
}
|
||||
};
|
||||
|
||||
class ListNode : public ParseNode
|
||||
|
|
@ -1377,36 +1427,33 @@ class DebuggerStatement : public ParseNode
|
|||
{ }
|
||||
};
|
||||
|
||||
class ConditionalExpression : public ParseNode
|
||||
class ConditionalExpression : public TernaryNode
|
||||
{
|
||||
public:
|
||||
ConditionalExpression(ParseNode* condition, ParseNode* thenExpr, ParseNode* elseExpr)
|
||||
: ParseNode(PNK_CONDITIONAL, JSOP_NOP, PN_TERNARY,
|
||||
TokenPos(condition->pn_pos.begin, elseExpr->pn_pos.end))
|
||||
: TernaryNode(PNK_CONDITIONAL, JSOP_NOP, condition, thenExpr, elseExpr,
|
||||
TokenPos(condition->pn_pos.begin, elseExpr->pn_pos.end))
|
||||
{
|
||||
MOZ_ASSERT(condition);
|
||||
MOZ_ASSERT(thenExpr);
|
||||
MOZ_ASSERT(elseExpr);
|
||||
pn_u.ternary.kid1 = condition;
|
||||
pn_u.ternary.kid2 = thenExpr;
|
||||
pn_u.ternary.kid3 = elseExpr;
|
||||
}
|
||||
|
||||
ParseNode& condition() const {
|
||||
return *pn_u.ternary.kid1;
|
||||
return *kid1();
|
||||
}
|
||||
|
||||
ParseNode& thenExpression() const {
|
||||
return *pn_u.ternary.kid2;
|
||||
return *kid2();
|
||||
}
|
||||
|
||||
ParseNode& elseExpression() const {
|
||||
return *pn_u.ternary.kid3;
|
||||
return *kid3();
|
||||
}
|
||||
|
||||
static bool test(const ParseNode& node) {
|
||||
bool match = node.isKind(PNK_CONDITIONAL);
|
||||
MOZ_ASSERT_IF(match, node.isArity(PN_TERNARY));
|
||||
MOZ_ASSERT_IF(match, node.is<TernaryNode>());
|
||||
MOZ_ASSERT_IF(match, node.isOp(JSOP_NOP));
|
||||
return match;
|
||||
}
|
||||
|
|
@ -1721,7 +1768,9 @@ struct ClassNames : public BinaryNode {
|
|||
}
|
||||
};
|
||||
|
||||
struct ClassNode : public TernaryNode {
|
||||
class ClassNode : public TernaryNode
|
||||
{
|
||||
public:
|
||||
ClassNode(ParseNode* names, ParseNode* heritage, ParseNode* methodsOrBlock,
|
||||
const TokenPos& pos)
|
||||
: TernaryNode(PNK_CLASS, JSOP_NOP, names, heritage, methodsOrBlock, pos)
|
||||
|
|
@ -1733,28 +1782,30 @@ struct ClassNode : public TernaryNode {
|
|||
|
||||
static bool test(const ParseNode& node) {
|
||||
bool match = node.isKind(PNK_CLASS);
|
||||
MOZ_ASSERT_IF(match, node.isArity(PN_TERNARY));
|
||||
MOZ_ASSERT_IF(match, node.is<TernaryNode>());
|
||||
return match;
|
||||
}
|
||||
|
||||
ClassNames* names() const {
|
||||
return pn_kid1 ? &pn_kid1->as<ClassNames>() : nullptr;
|
||||
return kid1() ? &kid1()->as<ClassNames>() : nullptr;
|
||||
}
|
||||
ParseNode* heritage() const {
|
||||
return pn_kid2;
|
||||
return kid2();
|
||||
}
|
||||
ListNode* methodList() const {
|
||||
if (pn_kid3->isKind(PNK_CLASSMETHODLIST))
|
||||
return &pn_kid3->as<ListNode>();
|
||||
ParseNode* methodsOrBlock = kid3();
|
||||
if (methodsOrBlock->isKind(PNK_CLASSMETHODLIST))
|
||||
return &methodsOrBlock->as<ListNode>();
|
||||
|
||||
MOZ_ASSERT(pn_kid3->is<LexicalScopeNode>());
|
||||
ListNode* list = &pn_kid3->scopeBody()->as<ListNode>();
|
||||
MOZ_ASSERT(methodsOrBlock->is<LexicalScopeNode>());
|
||||
ListNode* list = &methodsOrBlock->scopeBody()->as<ListNode>();
|
||||
MOZ_ASSERT(list->isKind(PNK_CLASSMETHODLIST));
|
||||
return list;
|
||||
}
|
||||
Handle<LexicalScope::Data*> scopeBindings() const {
|
||||
MOZ_ASSERT(pn_kid3->is<LexicalScopeNode>());
|
||||
return pn_kid3->scopeBindings();
|
||||
ParseNode* scope = kid3();
|
||||
MOZ_ASSERT(scope->is<LexicalScopeNode>());
|
||||
return scope->scopeBindings();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5369,16 +5369,15 @@ Parser<SyntaxParseHandler>::checkExportedNameForFunction(Node node)
|
|||
|
||||
template<>
|
||||
bool
|
||||
Parser<FullParseHandler>::checkExportedNameForClass(ParseNode* node)
|
||||
Parser<FullParseHandler>::checkExportedNameForClass(ClassNode* classNode)
|
||||
{
|
||||
const ClassNode& cls = node->as<ClassNode>();
|
||||
MOZ_ASSERT(cls.names());
|
||||
return checkExportedName(cls.names()->innerBinding()->pn_atom);
|
||||
MOZ_ASSERT(classNode->names());
|
||||
return checkExportedName(classNode->names()->innerBinding()->pn_atom);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
Parser<SyntaxParseHandler>::checkExportedNameForClass(Node node)
|
||||
Parser<SyntaxParseHandler>::checkExportedNameForClass(ClassNodeType classNode)
|
||||
{
|
||||
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return false;
|
||||
|
|
@ -5658,7 +5657,7 @@ Parser<ParseHandler>::exportClassDeclaration(uint32_t begin)
|
|||
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_CLASS));
|
||||
|
||||
Node kid = classDefinition(YieldIsKeyword, ClassStatement, NameRequired);
|
||||
ClassNodeType kid = classDefinition(YieldIsName, ClassStatement, NameRequired);
|
||||
if (!kid)
|
||||
return null();
|
||||
|
||||
|
|
@ -5736,7 +5735,7 @@ Parser<ParseHandler>::exportDefaultClassDeclaration(uint32_t begin)
|
|||
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_CLASS));
|
||||
|
||||
Node kid = classDefinition(YieldIsKeyword, ClassStatement, AllowDefaultName);
|
||||
ClassNodeType kid = classDefinition(YieldIsName, ClassStatement, AllowDefaultName);
|
||||
if (!kid)
|
||||
return null();
|
||||
|
||||
|
|
@ -5966,7 +5965,7 @@ Parser<ParseHandler>::consequentOrAlternative(YieldHandling yieldHandling)
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::TernaryNodeType
|
||||
Parser<ParseHandler>::ifStatement(YieldHandling yieldHandling)
|
||||
{
|
||||
Vector<Node, 4> condList(context), thenList(context);
|
||||
|
|
@ -6015,13 +6014,16 @@ Parser<ParseHandler>::ifStatement(YieldHandling yieldHandling)
|
|||
break;
|
||||
}
|
||||
|
||||
TernaryNodeType ifNode;
|
||||
for (int i = condList.length() - 1; i >= 0; i--) {
|
||||
elseBranch = handler.newIfStatement(posList[i], condList[i], thenList[i], elseBranch);
|
||||
if (!elseBranch)
|
||||
ifNode = handler.newIfStatement(posList[i], condList[i], thenList[i], elseBranch);
|
||||
if (!ifNode) {
|
||||
return null();
|
||||
}
|
||||
elseBranch = ifNode;
|
||||
}
|
||||
|
||||
return elseBranch;
|
||||
return ifNode;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
|
|
@ -6325,7 +6327,7 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
|
|||
|
||||
MOZ_ASSERT(headKind == PNK_FORIN || headKind == PNK_FOROF || headKind == PNK_FORHEAD);
|
||||
|
||||
Node forHead;
|
||||
TernaryNodeType forHead;
|
||||
if (headKind == PNK_FORHEAD) {
|
||||
Node init = startNode;
|
||||
|
||||
|
|
@ -6947,7 +6949,7 @@ Parser<ParseHandler>::throwStatement(YieldHandling yieldHandling)
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::TernaryNodeType
|
||||
Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_TRY));
|
||||
|
|
@ -7219,7 +7221,7 @@ JSOpFromPropertyType(PropertyType propType)
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::ClassNodeType
|
||||
Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling,
|
||||
ClassContext classContext,
|
||||
DefaultHandling defaultHandling)
|
||||
|
|
@ -8929,7 +8931,7 @@ Parser<ParseHandler>::comprehensionFor(GeneratorKind comprehensionKind)
|
|||
if (!lexicalScope)
|
||||
return null();
|
||||
|
||||
Node head = handler.newForInOrOfHead(PNK_FOROF, lexicalScope, rhs, headPos);
|
||||
TernaryNodeType head = handler.newForInOrOfHead(PNK_FOROF, lexicalScope, rhs, headPos);
|
||||
if (!head)
|
||||
return null();
|
||||
|
||||
|
|
|
|||
|
|
@ -1216,7 +1216,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
|||
Node returnStatement(YieldHandling yieldHandling);
|
||||
Node withStatement(YieldHandling yieldHandling);
|
||||
Node throwStatement(YieldHandling yieldHandling);
|
||||
Node tryStatement(YieldHandling yieldHandling);
|
||||
TernaryNodeType tryStatement(YieldHandling yieldHandling);
|
||||
Node catchBlockStatement(YieldHandling yieldHandling, ParseContext::Scope& catchParamScope);
|
||||
Node debuggerStatement();
|
||||
|
||||
|
|
@ -1225,7 +1225,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
|||
Node labeledStatement(YieldHandling yieldHandling);
|
||||
Node labeledItem(YieldHandling yieldHandling);
|
||||
|
||||
Node ifStatement(YieldHandling yieldHandling);
|
||||
TernaryNodeType ifStatement(YieldHandling yieldHandling);
|
||||
Node consequentOrAlternative(YieldHandling yieldHandling);
|
||||
|
||||
// While on a |let| TOK_NAME token, examine |next|. Indicate whether
|
||||
|
|
@ -1395,11 +1395,11 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
|||
|
||||
bool checkExportedNameForClause(Node node);
|
||||
bool checkExportedNameForFunction(Node node);
|
||||
bool checkExportedNameForClass(Node node);
|
||||
bool checkExportedNameForClass(ClassNodeType classNode);
|
||||
|
||||
enum ClassContext { ClassStatement, ClassExpression };
|
||||
Node classDefinition(YieldHandling yieldHandling, ClassContext classContext,
|
||||
DefaultHandling defaultHandling);
|
||||
ClassNodeType classDefinition(YieldHandling yieldHandling, ClassContext classContext,
|
||||
DefaultHandling defaultHandling);
|
||||
|
||||
bool checkLabelOrIdentifierReference(HandlePropertyName ident,
|
||||
uint32_t offset,
|
||||
|
|
|
|||
|
|
@ -249,7 +249,9 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
template <class Boxer>
|
||||
Node newRegExp(RegExpObject* reobj, const TokenPos& pos, Boxer& boxer) { return NodeGeneric; }
|
||||
|
||||
Node newConditional(Node cond, Node thenExpr, Node elseExpr) { return NodeGeneric; }
|
||||
ConditionalExpressionType newConditional(Node cond, Node thenExpr, Node elseExpr) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
Node newElision() { return NodeGeneric; }
|
||||
|
||||
|
|
@ -312,7 +314,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
ListNodeType newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; }
|
||||
ListNodeType newClassMethodList(uint32_t begin) { return NodeGeneric; }
|
||||
Node newClassNames(Node outer, Node inner, const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newClass(Node name, Node heritage, Node methodBlock, const TokenPos& pos) { return NodeGeneric; }
|
||||
ClassNodeType newClass(Node name, Node heritage, Node methodBlock, const TokenPos& pos) { return NodeGeneric; }
|
||||
|
||||
Node newNewTarget(Node newHolder, Node targetHolder) { return NodeGeneric; }
|
||||
Node newPosHolder(const TokenPos& pos) { return NodeGeneric; }
|
||||
|
|
@ -353,7 +355,9 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
return expr == NodeUnparenthesizedString ? NodeStringExprStatement : NodeGeneric;
|
||||
}
|
||||
|
||||
Node newIfStatement(uint32_t begin, Node cond, Node then, Node else_) { return NodeGeneric; }
|
||||
TernaryNodeType newIfStatement(uint32_t begin, Node cond, Node thenBranch, Node elseBranch) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
Node newDoWhileStatement(Node body, Node cond, const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newWhileStatement(uint32_t begin, Node cond, Node body) { return NodeGeneric; }
|
||||
Node newSwitchStatement(uint32_t begin, Node discriminant, Node lexicalForCaseList, bool hasDefault)
|
||||
|
|
@ -393,7 +397,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
|
||||
Node newOptionalPropertyByValue(Node pn, Node kid, uint32_t end) { return NodeOptionalElement; }
|
||||
|
||||
MOZ_MUST_USE bool addCatchBlock(ListNodeType catchList, Node letBlock, Node catchName,
|
||||
MOZ_MUST_USE bool addCatchBlock(ListNodeType catchList, Node letBlock, Node catchBinding,
|
||||
Node catchGuard, Node catchBody) { return true; }
|
||||
|
||||
MOZ_MUST_USE bool setLastFunctionFormalParameterDefault(Node funcpn, Node pn) { return true; }
|
||||
|
|
@ -410,7 +414,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
void setFunctionBox(Node pn, FunctionBox* funbox) {}
|
||||
void addFunctionFormalParameter(Node pn, Node argpn) {}
|
||||
|
||||
Node newForStatement(uint32_t begin, Node forHead, Node body, unsigned iflags) {
|
||||
Node newForStatement(uint32_t begin, TernaryNodeType forHead, Node body, unsigned iflags) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
|
|
@ -426,11 +430,11 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
return NodeGeneric;
|
||||
}
|
||||
|
||||
Node newForHead(Node init, Node test, Node update, const TokenPos& pos) {
|
||||
TernaryNodeType newForHead(Node init, Node test, Node update, const TokenPos& pos) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
Node newForInOrOfHead(ParseNodeKind kind, Node target, Node iteratedExpr, const TokenPos& pos) {
|
||||
TernaryNodeType newForInOrOfHead(ParseNodeKind kind, Node target, Node iteratedExpr, const TokenPos& pos) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -429,22 +429,19 @@ ReturnExpr(ParseNode* pn)
|
|||
static inline ParseNode*
|
||||
TernaryKid1(ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->isArity(PN_TERNARY));
|
||||
return pn->pn_kid1;
|
||||
return pn->as<TernaryNode>().kid1();
|
||||
}
|
||||
|
||||
static inline ParseNode*
|
||||
TernaryKid2(ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->isArity(PN_TERNARY));
|
||||
return pn->pn_kid2;
|
||||
return pn->as<TernaryNode>().kid2();
|
||||
}
|
||||
|
||||
static inline ParseNode*
|
||||
TernaryKid3(ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->isArity(PN_TERNARY));
|
||||
return pn->pn_kid3;
|
||||
return pn->as<TernaryNode>().kid3();
|
||||
}
|
||||
|
||||
static inline ParseNode*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue