summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/src/builtin/ReflectParse.cpp201
-rw-r--r--js/src/frontend/BytecodeEmitter.cpp149
-rw-r--r--js/src/frontend/BytecodeEmitter.h10
-rw-r--r--js/src/frontend/FoldConstants.cpp198
-rw-r--r--js/src/frontend/FullParseHandler.h42
-rw-r--r--js/src/frontend/NameFunctions.cpp107
-rw-r--r--js/src/frontend/ParseNode.cpp86
-rw-r--r--js/src/frontend/ParseNode.h173
-rw-r--r--js/src/frontend/Parser.cpp32
-rw-r--r--js/src/frontend/Parser.h10
-rw-r--r--js/src/frontend/SyntaxParseHandler.h18
-rw-r--r--js/src/wasm/AsmJS.cpp9
12 files changed, 560 insertions, 475 deletions
diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp
index 4c7d7cad8c..e1dad1f4b6 100644
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -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>();
+
+ 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));
- 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* 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:
{
diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index ffaf99a444..861d0c51d6 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -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();
+ ClassNames* names = classNode->names();
+ ParseNode* heritageExpression = classNode->heritage();
+ ListNode* classMethods = classNode->methodList();
- 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;
diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h
index e2fb16e224..416c3cf4bc 100644
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -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 {
diff --git a/js/src/frontend/FoldConstants.cpp b/js/src/frontend/FoldConstants.cpp
index 4ad1b4d6fe..ee1d5983aa 100644
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -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));
diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h
index 249b0aa276..0ce3f86567 100644
--- a/js/src/frontend/FullParseHandler.h
+++ b/js/src/frontend/FullParseHandler.h
@@ -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);
diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp
index 1b981876c2..26ea434c89 100644
--- a/js/src/frontend/NameFunctions.cpp
+++ b/js/src/frontend/NameFunctions.cpp
@@ -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:
diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp
index 218b08ef48..97ddbc482b 100644
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -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, ")");
}
diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h
index a19e4c3389..ebc29ef851 100644
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -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();
}
};
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
index b6f834c876..4a6a629d28 100644
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -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();
diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h
index 59ce925464..89b89674a4 100644
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -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,
diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h
index 0f4c66e8e7..d37dd4e20b 100644
--- a/js/src/frontend/SyntaxParseHandler.h
+++ b/js/src/frontend/SyntaxParseHandler.h
@@ -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;
}
diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp
index 4af6e51a5f..e6d6018fee 100644
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -430,22 +430,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*