Issue #2173 - Add accessors to ListNode

Based-on: m-c 1479659/{1,12}
This commit is contained in:
Martok 2023-03-25 22:16:04 +01:00 • committed by roytam1
commit 9c17ec0533
14 changed files with 1251 additions and 1049 deletions

View file

@ -1172,7 +1172,7 @@ ModuleBuilder::processImport(frontend::ParseNode* pn)
if (!maybeAppendRequestedModule(module))
return false;
for (ParseNode* spec = pn->pn_left->pn_head; spec; spec = spec->pn_next) {
for (ParseNode* spec : pn->pn_left->as<ListNode>().contents()) {
MOZ_ASSERT(spec->isKind(PNK_IMPORT_SPEC));
MOZ_ASSERT(spec->pn_left->isArity(PN_NAME));
MOZ_ASSERT(spec->pn_right->isArity(PN_NAME));
@ -1215,7 +1215,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
switch (kid->getKind()) {
case PNK_EXPORT_SPEC_LIST:
MOZ_ASSERT(!isDefault);
for (ParseNode* spec = kid->pn_head; spec; spec = spec->pn_next) {
for (ParseNode* spec : kid->as<ListNode>().contents()) {
MOZ_ASSERT(spec->isKind(PNK_EXPORT_SPEC));
RootedAtom localName(cx_, spec->pn_left->pn_atom);
RootedAtom exportName(cx_, spec->pn_right->pn_atom);
@ -1238,7 +1238,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
case PNK_CONST:
case PNK_LET: {
MOZ_ASSERT(kid->isArity(PN_LIST));
for (ParseNode* binding = kid->pn_head; binding; binding = binding->pn_next) {
for (ParseNode* binding : kid->as<ListNode>().contents()) {
if (binding->isKind(PNK_ASSIGN))
binding = binding->pn_left;
else
@ -1250,11 +1250,11 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
if (!appendExportEntry(exportName, localName))
return false;
} else if (binding->isKind(PNK_ARRAY)) {
if (!processExportArrayBinding(binding))
if (!processExportArrayBinding(&binding->as<ListNode>()))
return false;
} else {
MOZ_ASSERT(binding->isKind(PNK_OBJECT));
if (!processExportObjectBinding(binding))
if (!processExportObjectBinding(&binding->as<ListNode>()))
return false;
}
}
@ -1288,19 +1288,18 @@ ModuleBuilder::processExportBinding(frontend::ParseNode* binding)
}
if (binding->isKind(PNK_ARRAY))
return processExportArrayBinding(binding);
return processExportArrayBinding(&binding->as<ListNode>());
MOZ_ASSERT(binding->isKind(PNK_OBJECT));
return processExportObjectBinding(binding);
return processExportObjectBinding(&binding->as<ListNode>());
}
bool
ModuleBuilder::processExportArrayBinding(frontend::ParseNode* pn)
ModuleBuilder::processExportArrayBinding(frontend::ListNode* array)
{
MOZ_ASSERT(pn->isKind(PNK_ARRAY));
MOZ_ASSERT(pn->isArity(PN_LIST));
MOZ_ASSERT(array->isKind(PNK_ARRAY));
for (ParseNode* node = pn->pn_head; node; node = node->pn_next) {
for (ParseNode* node : array->contents()) {
if (node->isKind(PNK_ELISION))
continue;
@ -1317,12 +1316,11 @@ ModuleBuilder::processExportArrayBinding(frontend::ParseNode* pn)
}
bool
ModuleBuilder::processExportObjectBinding(frontend::ParseNode* pn)
ModuleBuilder::processExportObjectBinding(frontend::ListNode* obj)
{
MOZ_ASSERT(pn->isKind(PNK_OBJECT));
MOZ_ASSERT(pn->isArity(PN_LIST));
MOZ_ASSERT(obj->isKind(PNK_OBJECT));
for (ParseNode* node = pn->pn_head; node; node = node->pn_next) {
for (ParseNode* node : obj->contents()) {
MOZ_ASSERT(node->isKind(PNK_MUTATEPROTO) ||
node->isKind(PNK_COLON) ||
node->isKind(PNK_SHORTHAND) ||
@ -1360,7 +1358,7 @@ ModuleBuilder::processExportFrom(frontend::ParseNode* pn)
if (!maybeAppendRequestedModule(module))
return false;
for (ParseNode* spec = pn->pn_left->pn_head; spec; spec = spec->pn_next) {
for (ParseNode* spec : pn->pn_left->as<ListNode>().contents()) {
if (spec->isKind(PNK_EXPORT_SPEC)) {
RootedAtom bindingName(cx_, spec->pn_left->pn_atom);
RootedAtom exportName(cx_, spec->pn_right->pn_atom);

View file

@ -24,6 +24,7 @@ class ModuleEnvironmentObject;
class ModuleObject;
namespace frontend {
class ListNode;
class ParseNode;
class TokenStream;
} /* namespace frontend */
@ -353,8 +354,8 @@ class MOZ_STACK_CLASS ModuleBuilder
ImportEntryObject* importEntryFor(JSAtom* localName) const;
bool processExportBinding(frontend::ParseNode* pn);
bool processExportArrayBinding(frontend::ParseNode* pn);
bool processExportObjectBinding(frontend::ParseNode* pn);
bool processExportArrayBinding(frontend::ListNode* pn);
bool processExportObjectBinding(frontend::ListNode* pn);
bool appendExportEntry(HandleAtom exportName, HandleAtom localName,
frontend::ParseNode* node = nullptr);

View file

@ -1790,17 +1790,17 @@ class ASTSerializer
UnaryOperator unop(ParseNodeKind kind, JSOp op);
AssignmentOperator aop(JSOp op);
bool statements(ParseNode* pn, NodeVector& elts);
bool expressions(ParseNode* pn, NodeVector& elts);
bool leftAssociate(ParseNode* pn, MutableHandleValue dst);
bool rightAssociate(ParseNode* pn, MutableHandleValue dst);
bool functionArgs(ParseNode* pn, ParseNode* pnargs,
bool statements(ListNode* stmtList, NodeVector& elts);
bool expressions(ListNode* exprList, NodeVector& elts);
bool leftAssociate(ListNode* node, MutableHandleValue dst);
bool rightAssociate(ListNode* node, MutableHandleValue dst);
bool functionArgs(ParseNode* pn, ListNode* argsList,
NodeVector& args, NodeVector& defaults, MutableHandleValue rest);
bool sourceElement(ParseNode* pn, MutableHandleValue dst);
bool declaration(ParseNode* pn, MutableHandleValue dst);
bool variableDeclaration(ParseNode* pn, bool lexical, MutableHandleValue dst);
bool variableDeclaration(ListNode* declList, bool lexical, MutableHandleValue dst);
bool variableDeclarator(ParseNode* pn, MutableHandleValue dst);
bool importDeclaration(ParseNode* pn, MutableHandleValue dst);
bool importSpecifier(ParseNode* pn, MutableHandleValue dst);
@ -1822,7 +1822,7 @@ class ASTSerializer
bool forOf(ParseNode* loop, ParseNode* head, HandleValue var, HandleValue stmt,
MutableHandleValue dst);
bool statement(ParseNode* pn, MutableHandleValue dst);
bool blockStatement(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);
@ -1864,8 +1864,8 @@ class ASTSerializer
}
bool pattern(ParseNode* pn, MutableHandleValue dst);
bool arrayPattern(ParseNode* pn, MutableHandleValue dst);
bool objectPattern(ParseNode* pn, MutableHandleValue dst);
bool arrayPattern(ListNode* array, MutableHandleValue dst);
bool objectPattern(ListNode* obj, MutableHandleValue dst);
bool function(ParseNode* pn, ASTType type, MutableHandleValue dst);
bool functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector& defaults,
@ -1897,7 +1897,7 @@ class ASTSerializer
builder.setTokenStream(&p->tokenStream);
}
bool program(ParseNode* pn, MutableHandleValue dst);
bool program(ListNode* node, MutableHandleValue dst);
};
} /* anonymous namespace */
@ -2021,19 +2021,18 @@ ASTSerializer::binop(ParseNodeKind kind, JSOp op)
}
bool
ASTSerializer::statements(ParseNode* pn, NodeVector& elts)
ASTSerializer::statements(ListNode* stmtList, NodeVector& elts)
{
MOZ_ASSERT(pn->isKind(PNK_STATEMENTLIST));
MOZ_ASSERT(pn->isArity(PN_LIST));
MOZ_ASSERT(stmtList->isKind(PNK_STATEMENTLIST));
if (!elts.reserve(pn->pn_count))
if (!elts.reserve(stmtList->count()))
return false;
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
for (ParseNode* stmt : stmtList->contents()) {
MOZ_ASSERT(stmtList->pn_pos.encloses(stmt->pn_pos));
RootedValue elt(cx);
if (!sourceElement(next, &elt))
if (!sourceElement(stmt, &elt))
return false;
elts.infallibleAppend(elt);
}
@ -2042,16 +2041,16 @@ ASTSerializer::statements(ParseNode* pn, NodeVector& elts)
}
bool
ASTSerializer::expressions(ParseNode* pn, NodeVector& elts)
ASTSerializer::expressions(ListNode* exprList, NodeVector& elts)
{
if (!elts.reserve(pn->pn_count))
if (!elts.reserve(exprList->count()))
return false;
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
for (ParseNode* expr : exprList->contents()) {
MOZ_ASSERT(exprList->pn_pos.encloses(expr->pn_pos));
RootedValue elt(cx);
if (!expression(next, &elt))
if (!expression(expr, &elt))
return false;
elts.infallibleAppend(elt);
}
@ -2060,23 +2059,23 @@ ASTSerializer::expressions(ParseNode* pn, NodeVector& elts)
}
bool
ASTSerializer::blockStatement(ParseNode* pn, MutableHandleValue dst)
ASTSerializer::blockStatement(ListNode* node, MutableHandleValue dst)
{
MOZ_ASSERT(pn->isKind(PNK_STATEMENTLIST));
MOZ_ASSERT(node->isKind(PNK_STATEMENTLIST));
NodeVector stmts(cx);
return statements(pn, stmts) &&
builder.blockStatement(stmts, &pn->pn_pos, dst);
return statements(node, stmts) &&
builder.blockStatement(stmts, &node->pn_pos, dst);
}
bool
ASTSerializer::program(ParseNode* pn, MutableHandleValue dst)
ASTSerializer::program(ListNode* node, MutableHandleValue dst)
{
MOZ_ASSERT(parser->tokenStream.srcCoords.lineNum(pn->pn_pos.begin) == lineno);
MOZ_ASSERT(parser->tokenStream.srcCoords.lineNum(node->pn_pos.begin) == lineno);
NodeVector stmts(cx);
return statements(pn, stmts) &&
builder.program(stmts, &pn->pn_pos, dst);
return statements(node, stmts) &&
builder.program(stmts, &node->pn_pos, dst);
}
bool
@ -2099,38 +2098,38 @@ ASTSerializer::declaration(ParseNode* pn, MutableHandleValue dst)
return function(pn, AST_FUNC_DECL, dst);
case PNK_VAR:
return variableDeclaration(pn, false, dst);
return variableDeclaration(&pn->as<ListNode>(), false, dst);
default:
MOZ_ASSERT(pn->isKind(PNK_LET) || pn->isKind(PNK_CONST));
return variableDeclaration(pn, true, dst);
return variableDeclaration(&pn->as<ListNode>(), true, dst);
}
}
bool
ASTSerializer::variableDeclaration(ParseNode* pn, bool lexical, MutableHandleValue dst)
ASTSerializer::variableDeclaration(ListNode* declList, bool lexical, MutableHandleValue dst)
{
MOZ_ASSERT_IF(lexical, pn->isKind(PNK_LET) || pn->isKind(PNK_CONST));
MOZ_ASSERT_IF(!lexical, pn->isKind(PNK_VAR));
MOZ_ASSERT_IF(lexical, declList->isKind(PNK_LET) || declList->isKind(PNK_CONST));
MOZ_ASSERT_IF(!lexical, declList->isKind(PNK_VAR));
VarDeclKind kind = VARDECL_ERR;
// Treat both the toplevel const binding (secretly var-like) and the lexical const
// the same way
if (lexical)
kind = pn->isKind(PNK_LET) ? VARDECL_LET : VARDECL_CONST;
kind = declList->isKind(PNK_LET) ? VARDECL_LET : VARDECL_CONST;
else
kind = pn->isKind(PNK_VAR) ? VARDECL_VAR : VARDECL_CONST;
kind = declList->isKind(PNK_VAR) ? VARDECL_VAR : VARDECL_CONST;
NodeVector dtors(cx);
if (!dtors.reserve(pn->pn_count))
if (!dtors.reserve(declList->count()))
return false;
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
for (ParseNode* decl : declList->contents()) {
RootedValue child(cx);
if (!variableDeclarator(next, &child))
if (!variableDeclarator(decl, &child))
return false;
dtors.infallibleAppend(child);
}
return builder.variableDeclaration(dtors, kind, &pn->pn_pos, dst);
return builder.variableDeclaration(dtors, kind, &declList->pn_pos, dst);
}
bool
@ -2168,13 +2167,15 @@ ASTSerializer::importDeclaration(ParseNode* pn, MutableHandleValue dst)
MOZ_ASSERT(pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST));
MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING));
ListNode* specList = &pn->pn_left->as<ListNode>();
NodeVector elts(cx);
if (!elts.reserve(pn->pn_left->pn_count))
if (!elts.reserve(specList->count()))
return false;
for (ParseNode* next = pn->pn_left->pn_head; next; next = next->pn_next) {
for (ParseNode* spec : specList->contents()) {
RootedValue elt(cx);
if (!importSpecifier(next, &elt))
if (!importSpecifier(spec, &elt))
return false;
elts.infallibleAppend(elt);
}
@ -2210,14 +2211,15 @@ ASTSerializer::exportDeclaration(ParseNode* pn, MutableHandleValue dst)
ParseNode* kid = pn->isKind(PNK_EXPORT) ? pn->pn_kid : pn->pn_left;
switch (ParseNodeKind kind = kid->getKind()) {
case PNK_EXPORT_SPEC_LIST:
if (!elts.reserve(pn->pn_left->pn_count))
case PNK_EXPORT_SPEC_LIST: {
ListNode* specList = &pn->pn_left->as<ListNode>();
if (!elts.reserve(specList->count()))
return false;
for (ParseNode* next = pn->pn_left->pn_head; next; next = next->pn_next) {
for (ParseNode* spec : specList->contents()) {
RootedValue elt(cx);
if (next->isKind(PNK_EXPORT_SPEC)) {
if (!exportSpecifier(next, &elt))
if (spec->isKind(PNK_EXPORT_SPEC)) {
if (!exportSpecifier(spec, &elt))
return false;
} else {
if (!builder.exportBatchSpecifier(&pn->pn_pos, &elt))
@ -2226,6 +2228,7 @@ ASTSerializer::exportDeclaration(ParseNode* pn, MutableHandleValue dst)
elts.infallibleAppend(elt);
}
break;
}
case PNK_FUNCTION:
if (!function(kid, AST_FUNC_DECL, &decl))
@ -2240,7 +2243,7 @@ ASTSerializer::exportDeclaration(ParseNode* pn, MutableHandleValue dst)
case PNK_VAR:
case PNK_CONST:
case PNK_LET:
if (!variableDeclaration(kid, kind != PNK_VAR, &decl))
if (!variableDeclaration(&kid->as<ListNode>(), kind != PNK_VAR, &decl))
return false;
break;
@ -2299,29 +2302,22 @@ ASTSerializer::switchStatement(ParseNode* pn, MutableHandleValue dst)
if (!expression(pn->pn_left, &disc))
return false;
ParseNode* listNode;
bool lexical;
if (pn->pn_right->isKind(PNK_LEXICALSCOPE)) {
listNode = pn->pn_right->pn_expr;
lexical = true;
} else {
listNode = pn->pn_right;
lexical = false;
}
MOZ_ASSERT(pn->pn_right->isKind(PNK_LEXICALSCOPE));
ListNode* caseList = &pn->pn_right->scopeBody()->as<ListNode>();
NodeVector cases(cx);
if (!cases.reserve(listNode->pn_count))
if (!cases.reserve(caseList->count()))
return false;
for (ParseNode* next = listNode->pn_head; next; next = next->pn_next) {
for (ParseNode* caseNode : caseList->contents()) {
RootedValue child(cx);
if (!switchCase(next, &child))
if (!switchCase(caseNode, &child))
return false;
cases.infallibleAppend(child);
}
return builder.switchStatement(disc, cases, lexical, &pn->pn_pos, dst);
return builder.switchStatement(disc, cases, /* lexical = */ true, &pn->pn_pos, dst);
}
bool
@ -2358,11 +2354,11 @@ ASTSerializer::tryStatement(ParseNode* pn, MutableHandleValue dst)
NodeVector guarded(cx);
RootedValue unguarded(cx, NullValue());
if (ParseNode* catchList = pn->pn_kid2) {
if (!guarded.reserve(catchList->pn_count))
if (ListNode* catchList = &pn->pn_kid2->as<ListNode>()) {
if (!guarded.reserve(catchList->count()))
return false;
for (ParseNode* next = catchList->pn_head; next; next = next->pn_next) {
for (ParseNode* next : catchList->contents()) {
RootedValue clause(cx);
bool isGuarded;
if (!catchClause(next->pn_expr, &isGuarded, &clause))
@ -2389,7 +2385,7 @@ ASTSerializer::forInit(ParseNode* pn, MutableHandleValue dst)
bool lexical = pn->isKind(PNK_LET) || pn->isKind(PNK_CONST);
return (lexical || pn->isKind(PNK_VAR))
? variableDeclaration(pn, lexical, dst)
? variableDeclaration(&pn->as<ListNode>(), lexical, dst)
: expression(pn, dst);
}
@ -2467,7 +2463,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
MOZ_FALLTHROUGH;
case PNK_STATEMENTLIST:
return blockStatement(pn, dst);
return blockStatement(&pn->as<ListNode>(), dst);
case PNK_IF:
{
@ -2535,7 +2531,7 @@ 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->pn_expr, true, &var))
if (!variableDeclaration(&head->pn_kid1->scopeBody()->as<ListNode>(), true, &var))
return false;
} else if (!head->pn_kid1->isKind(PNK_VAR) &&
!head->pn_kid1->isKind(PNK_LET) &&
@ -2544,7 +2540,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
if (!pattern(head->pn_kid1, &var))
return false;
} else {
if (!variableDeclaration(head->pn_kid1,
if (!variableDeclaration(&head->pn_kid1->as<ListNode>(),
head->pn_kid1->isKind(PNK_LET) ||
head->pn_kid1->isKind(PNK_CONST),
&var))
@ -2615,15 +2611,16 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
case PNK_CLASSMETHODLIST:
{
ListNode* methodList = &pn->as<ListNode>();
NodeVector methods(cx);
if (!methods.reserve(pn->pn_count))
if (!methods.reserve(methodList->count()))
return false;
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
for (ParseNode* method : methodList->contents()) {
MOZ_ASSERT(methodList->pn_pos.encloses(method->pn_pos));
RootedValue prop(cx);
if (!classMethod(next, &prop))
if (!classMethod(method, &prop))
return false;
methods.infallibleAppend(prop);
}
@ -2668,32 +2665,31 @@ ASTSerializer::classMethod(ParseNode* pn, MutableHandleValue dst)
}
bool
ASTSerializer::leftAssociate(ParseNode* pn, MutableHandleValue dst)
ASTSerializer::leftAssociate(ListNode* node, MutableHandleValue dst)
{
MOZ_ASSERT(pn->isArity(PN_LIST));
MOZ_ASSERT(pn->pn_count >= 1);
MOZ_ASSERT(!node->empty());
ParseNodeKind kind = pn->getKind();
ParseNodeKind kind = node->getKind();
bool logop = (kind == PNK_COALESCE ||
kind == PNK_OR ||
kind == PNK_AND);
ParseNode* head = pn->pn_head;
ParseNode* head = node->head();
RootedValue left(cx);
if (!expression(head, &left))
return false;
for (ParseNode* next = head->pn_next; next; next = next->pn_next) {
for (ParseNode* next : node->contentsFrom(head->pn_next)) {
RootedValue right(cx);
if (!expression(next, &right))
return false;
TokenPos subpos(pn->pn_pos.begin, next->pn_pos.end);
TokenPos subpos(node->pn_pos.begin, next->pn_pos.end);
if (logop) {
if (!builder.logicalExpression(kind, left, right, &subpos, &left))
return false;
} else {
BinaryOperator op = binop(pn->getKind(), pn->getOp());
BinaryOperator op = binop(node->getKind(), node->getOp());
LOCAL_ASSERT(op > BINOP_ERR && op < BINOP_LIMIT);
if (!builder.binaryExpression(op, left, right, &subpos, &left))
@ -2706,15 +2702,14 @@ ASTSerializer::leftAssociate(ParseNode* pn, MutableHandleValue dst)
}
bool
ASTSerializer::rightAssociate(ParseNode* pn, MutableHandleValue dst)
ASTSerializer::rightAssociate(ListNode* node, MutableHandleValue dst)
{
MOZ_ASSERT(pn->isArity(PN_LIST));
MOZ_ASSERT(pn->pn_count >= 1);
MOZ_ASSERT(!node->empty());
// First, we need to reverse the list, so that we can traverse it in the right order.
// It's OK to destructively reverse the list, because there are no other consumers.
ParseNode* head = pn->pn_head;
ParseNode* head = node->head();
ParseNode* prev = nullptr;
ParseNode* current = head;
ParseNode* next;
@ -2735,9 +2730,9 @@ ASTSerializer::rightAssociate(ParseNode* pn, MutableHandleValue dst)
if (!expression(next, &left))
return false;
TokenPos subpos(pn->pn_pos.begin, next->pn_pos.end);
TokenPos subpos(node->pn_pos.begin, next->pn_pos.end);
BinaryOperator op = binop(pn->getKind(), pn->getOp());
BinaryOperator op = binop(node->getKind(), node->getOp());
LOCAL_ASSERT(op > BINOP_ERR && op < BINOP_LIMIT);
if (!builder.binaryExpression(op, left, right, &subpos, &right))
@ -2760,13 +2755,15 @@ ASTSerializer::comprehensionBlock(ParseNode* pn, MutableHandleValue dst)
bool isForEach = in->isKind(PNK_FORIN) && (pn->pn_iflags & JSITER_FOREACH);
bool isForOf = in->isKind(PNK_FOROF);
ParseNode* decl = in->pn_kid1;
if (decl->isKind(PNK_LEXICALSCOPE))
decl = decl->pn_expr;
MOZ_ASSERT(decl->pn_count == 1);
ListNode* decl;
if (in->pn_kid1->isKind(PNK_LEXICALSCOPE))
decl = &in->pn_kid1->pn_expr->as<ListNode>();
else
decl = &in->pn_kid1->as<ListNode>();
MOZ_ASSERT(decl->count() == 1);
RootedValue patt(cx), src(cx);
return pattern(decl->pn_head, &patt) &&
return pattern(decl->head(), &patt) &&
expression(in->pn_kid3, &src) &&
builder.comprehensionBlock(patt, src, isForEach, isForOf, &in->pn_pos, dst);
}
@ -2885,7 +2882,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_COMMA:
{
NodeVector exprs(cx);
return expressions(pn, exprs) &&
return expressions(&pn->as<ListNode>(), exprs) &&
builder.sequenceExpression(exprs, &pn->pn_pos, dst);
}
@ -2906,7 +2903,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_COALESCE:
case PNK_OR:
case PNK_AND:
return leftAssociate(pn, dst);
return leftAssociate(&pn->as<ListNode>(), dst);
case PNK_PREINCREMENT:
case PNK_PREDECREMENT:
@ -2977,10 +2974,10 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_BITAND:
case PNK_IN:
case PNK_INSTANCEOF:
return leftAssociate(pn, dst);
return leftAssociate(&pn->as<ListNode>(), dst);
case PNK_POW:
return rightAssociate(pn, dst);
return rightAssociate(&pn->as<ListNode>(), dst);
case PNK_DELETENAME:
case PNK_DELETEPROP:
@ -3004,8 +3001,19 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
builder.unaryExpression(op, expr, &pn->pn_pos, dst);
}
case PNK_GENEXP:
return generatorExpression(pn->generatorExpr(), dst);
case PNK_GENEXP: {
ParseNode* callee = pn->pn_left;
MOZ_ASSERT(callee->isKind(PNK_FUNCTION));
ListNode* paramsBody = &callee->pn_body->as<ListNode>();
MOZ_ASSERT(paramsBody->isKind(PNK_PARAMSBODY));
ListNode* body = &paramsBody->last()->as<ListNode>();
MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST));
MOZ_ASSERT(body->last()->isKind(PNK_LEXICALSCOPE) ||
body->last()->isKind(PNK_COMPREHENSIONFOR));
return generatorExpression(body->last(), dst);
}
case PNK_DELETEOPTCHAIN: {
RootedValue expr(cx);
@ -3026,7 +3034,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_SUPERCALL:
{
ParseNode* pn_callee = pn->pn_left;
ParseNode* pn_args = pn->pn_right;
ListNode* argsList = &pn->pn_right->as<ListNode>();
MOZ_ASSERT(pn->pn_pos.encloses(pn_callee->pn_pos));
RootedValue callee(cx);
@ -3040,14 +3048,14 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
}
NodeVector args(cx);
if (!args.reserve(pn_args->pn_count))
if (!args.reserve(argsList->count()))
return false;
for (ParseNode* next = pn_args->pn_head; next; next = next->pn_next) {
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
for (ParseNode* argNode : argsList->contents()) {
MOZ_ASSERT(pn->pn_pos.encloses(argNode->pn_pos));
RootedValue arg(cx);
if (!expression(next, &arg))
if (!expression(argNode, &arg))
return false;
args.infallibleAppend(arg);
}
@ -3118,57 +3126,62 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_CALLSITEOBJ:
{
CallSiteNode* callSiteObj = &pn->as<CallSiteNode>();
ListNode* rawNodes = callSiteObj->rawNodes();
NodeVector raw(cx);
if (!raw.reserve(pn->pn_head->pn_count))
if (!raw.reserve(rawNodes->count()))
return false;
for (ParseNode* next = pn->pn_head->pn_head; next; next = next->pn_next) {
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
for (ParseNode* rawItem : rawNodes->contents()) {
MOZ_ASSERT(callSiteObj->pn_pos.encloses(rawItem->pn_pos));
RootedValue expr(cx);
expr.setString(next->pn_atom);
expr.setString(rawItem->pn_atom);
raw.infallibleAppend(expr);
}
NodeVector cooked(cx);
if (!cooked.reserve(pn->pn_count - 1))
if (!cooked.reserve(callSiteObj->count() - 1))
return false;
for (ParseNode* next = pn->pn_head->pn_next; next; next = next->pn_next) {
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
for (ParseNode* cookedItem = callSiteObj->head()->pn_next;
cookedItem;
cookedItem = cookedItem->pn_next) {
MOZ_ASSERT(callSiteObj->pn_pos.encloses(cookedItem->pn_pos));
RootedValue expr(cx);
if (next->isKind(PNK_RAW_UNDEFINED)) {
if (cookedItem->isKind(PNK_RAW_UNDEFINED)) {
expr.setUndefined();
} else {
MOZ_ASSERT(next->isKind(PNK_TEMPLATE_STRING));
expr.setString(next->pn_atom);
MOZ_ASSERT(cookedItem->isKind(PNK_TEMPLATE_STRING));
expr.setString(cookedItem->pn_atom);
}
cooked.infallibleAppend(expr);
}
return builder.callSiteObj(raw, cooked, &pn->pn_pos, dst);
return builder.callSiteObj(raw, cooked, &callSiteObj->pn_pos, dst);
}
case PNK_ARRAY:
{
ListNode* array = &pn->as<ListNode>();
NodeVector elts(cx);
if (!elts.reserve(pn->pn_count))
if (!elts.reserve(array->count()))
return false;
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
for (ParseNode* item : array->contents()) {
MOZ_ASSERT(array->pn_pos.encloses(item->pn_pos));
if (next->isKind(PNK_ELISION)) {
if (item->isKind(PNK_ELISION)) {
elts.infallibleAppend(NullValue());
} else {
RootedValue expr(cx);
if (!expression(next, &expr))
if (!expression(item, &expr))
return false;
elts.infallibleAppend(expr);
}
}
return builder.arrayExpression(elts, &pn->pn_pos, dst);
return builder.arrayExpression(elts, &array->pn_pos, dst);
}
case PNK_SPREAD:
@ -3187,20 +3200,21 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_OBJECT:
{
ListNode* obj = &pn->as<ListNode>();
NodeVector elts(cx);
if (!elts.reserve(pn->pn_count))
if (!elts.reserve(obj->count()))
return false;
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
for (ParseNode* item : obj->contents()) {
MOZ_ASSERT(obj->pn_pos.encloses(item->pn_pos));
RootedValue prop(cx);
if (!property(next, &prop))
if (!property(item, &prop))
return false;
elts.infallibleAppend(prop);
}
return builder.objectExpression(elts, &pn->pn_pos, dst);
return builder.objectExpression(elts, &obj->pn_pos, dst);
}
case PNK_NAME:
@ -3211,20 +3225,21 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_TEMPLATE_STRING_LIST:
{
ListNode* list = &pn->as<ListNode>();
NodeVector elts(cx);
if (!elts.reserve(pn->pn_count))
if (!elts.reserve(list->count()))
return false;
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
for (ParseNode* item : list->contents()) {
MOZ_ASSERT(list->pn_pos.encloses(item->pn_pos));
RootedValue expr(cx);
if (!expression(next, &expr))
if (!expression(item, &expr))
return false;
elts.infallibleAppend(expr);
}
return builder.templateLiteral(elts, &pn->pn_pos, dst);
return builder.templateLiteral(elts, &list->pn_pos, dst);
}
case PNK_TEMPLATE_STRING:
@ -3256,11 +3271,14 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
}
case PNK_ARRAYCOMP:
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_head->pn_pos));
{
ListNode* literal = &pn->as<ListNode>();
MOZ_ASSERT(pn->pn_pos.encloses(literal->head()->pn_pos));
/* NB: it's no longer the case that pn_count could be 2. */
LOCAL_ASSERT(pn->pn_count == 1);
return comprehension(pn->pn_head, dst);
LOCAL_ASSERT(literal->count() == 1);
return comprehension(literal->head(), dst);
}
case PNK_CLASS:
return classDefinition(pn, true, dst);
@ -3397,46 +3415,46 @@ ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst)
}
bool
ASTSerializer::arrayPattern(ParseNode* pn, MutableHandleValue dst)
ASTSerializer::arrayPattern(ListNode* array, MutableHandleValue dst)
{
MOZ_ASSERT(pn->isKind(PNK_ARRAY));
MOZ_ASSERT(array->isKind(PNK_ARRAY));
NodeVector elts(cx);
if (!elts.reserve(pn->pn_count))
if (!elts.reserve(array->count()))
return false;
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
if (next->isKind(PNK_ELISION)) {
for (ParseNode* item : array->contents()) {
if (item->isKind(PNK_ELISION)) {
elts.infallibleAppend(NullValue());
} else if (next->isKind(PNK_SPREAD)) {
} else if (item->isKind(PNK_SPREAD)) {
RootedValue target(cx);
RootedValue spread(cx);
if (!pattern(next->pn_kid, &target))
if (!pattern(item->pn_kid, &target))
return false;
if(!builder.spreadExpression(target, &next->pn_pos, &spread))
if(!builder.spreadExpression(target, &item->pn_pos, &spread))
return false;
elts.infallibleAppend(spread);
} else {
RootedValue patt(cx);
if (!pattern(next, &patt))
if (!pattern(item, &patt))
return false;
elts.infallibleAppend(patt);
}
}
return builder.arrayPattern(elts, &pn->pn_pos, dst);
return builder.arrayPattern(elts, &array->pn_pos, dst);
}
bool
ASTSerializer::objectPattern(ParseNode* pn, MutableHandleValue dst)
ASTSerializer::objectPattern(ListNode* obj, MutableHandleValue dst)
{
MOZ_ASSERT(pn->isKind(PNK_OBJECT));
MOZ_ASSERT(obj->isKind(PNK_OBJECT));
NodeVector elts(cx);
if (!elts.reserve(pn->pn_count))
if (!elts.reserve(obj->count()))
return false;
for (ParseNode* propdef = pn->pn_head; propdef; propdef = propdef->pn_next) {
for (ParseNode* propdef : obj->contents()) {
if (propdef->isKind(PNK_SPREAD)) {
RootedValue target(cx);
RootedValue spread(cx);
@ -3473,7 +3491,7 @@ ASTSerializer::objectPattern(ParseNode* pn, MutableHandleValue dst)
elts.infallibleAppend(prop);
}
return builder.objectPattern(elts, &pn->pn_pos, dst);
return builder.objectPattern(elts, &obj->pn_pos, dst);
}
bool
@ -3482,10 +3500,10 @@ ASTSerializer::pattern(ParseNode* pn, MutableHandleValue dst)
JS_CHECK_RECURSION(cx, return false);
switch (pn->getKind()) {
case PNK_OBJECT:
return objectPattern(pn, dst);
return objectPattern(&pn->as<ListNode>(), dst);
case PNK_ARRAY:
return arrayPattern(pn, dst);
return arrayPattern(&pn->as<ListNode>(), dst);
default:
return expression(pn, dst);
@ -3547,15 +3565,15 @@ ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector&
bool isAsync, bool isExpression,
MutableHandleValue body, MutableHandleValue rest)
{
ParseNode* pnargs;
ListNode* argsList;
ParseNode* pnbody;
/* Extract the args and body separately. */
if (pn->isKind(PNK_PARAMSBODY)) {
pnargs = pn;
pnbody = pn->last();
argsList = &pn->as<ListNode>();
pnbody = argsList->last();
} else {
pnargs = nullptr;
argsList = nullptr;
pnbody = pn;
}
@ -3565,29 +3583,29 @@ ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector&
/* Serialize the arguments and body. */
switch (pnbody->getKind()) {
case PNK_RETURN: /* expression closure, no destructured args */
return functionArgs(pn, pnargs, args, defaults, rest) &&
return functionArgs(pn, argsList, args, defaults, rest) &&
expression(pnbody->pn_kid, body);
case PNK_STATEMENTLIST: /* statement closure */
{
ParseNode* pnstart = pnbody->pn_head;
ParseNode* firstNode = pnbody->as<ListNode>().head();
// Skip over initial yield in generator.
if (pnstart && pnstart->isKind(PNK_INITIALYIELD)) {
MOZ_ASSERT(pnstart->getOp() == JSOP_INITIALYIELD);
pnstart = pnstart->pn_next;
if (firstNode && firstNode->isKind(PNK_INITIALYIELD)) {
MOZ_ASSERT(firstNode->getOp() == JSOP_INITIALYIELD);
firstNode = firstNode->pn_next;
}
// Async arrow with expression body is converted into STATEMENTLIST
// to insert initial yield.
if (isAsync && isExpression) {
MOZ_ASSERT(pnstart->getKind() == PNK_RETURN);
return functionArgs(pn, pnargs, args, defaults, rest) &&
expression(pnstart->pn_kid, body);
MOZ_ASSERT(firstNode->getKind() == PNK_RETURN);
return functionArgs(pn, argsList, args, defaults, rest) &&
expression(firstNode->pn_kid, body);
}
return functionArgs(pn, pnargs, args, defaults, rest) &&
functionBody(pnstart, &pnbody->pn_pos, body);
return functionArgs(pn, argsList, args, defaults, rest) &&
functionBody(firstNode, &pnbody->pn_pos, body);
}
default:
@ -3596,11 +3614,11 @@ ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector&
}
bool
ASTSerializer::functionArgs(ParseNode* pn, ParseNode* pnargs,
ASTSerializer::functionArgs(ParseNode* pn, ListNode* argsList,
NodeVector& args, NodeVector& defaults,
MutableHandleValue rest)
{
if (!pnargs)
if (!argsList)
return true;
RootedValue node(cx);
@ -3609,7 +3627,7 @@ ASTSerializer::functionArgs(ParseNode* pn, ParseNode* pnargs,
"must be initially empty for it to be proper to clear this "
"when there are no defaults");
for (ParseNode* arg = pnargs->pn_head; arg && arg != pnargs->last(); arg = arg->pn_next) {
for (ParseNode* arg : argsList->contentsTo(argsList->last())) {
ParseNode* pat;
ParseNode* defNode;
if (arg->isKind(PNK_NAME) || arg->isKind(PNK_ARRAY) || arg->isKind(PNK_OBJECT)) {
@ -3625,7 +3643,7 @@ ASTSerializer::functionArgs(ParseNode* pn, ParseNode* pnargs,
MOZ_ASSERT(pat->isKind(PNK_NAME) || pat->isKind(PNK_ARRAY) || pat->isKind(PNK_OBJECT));
if (!pattern(pat, &node))
return false;
if (rest.isUndefined() && arg->pn_next == pnargs->last()) {
if (rest.isUndefined() && arg->pn_next == argsList->last()) {
rest.setObject(node.toObject());
} else {
if (!args.append(node))
@ -3837,7 +3855,7 @@ reflect_parse(JSContext* cx, uint32_t argc, Value* vp)
}
RootedValue val(cx);
if (!serialize.program(pn, &val)) {
if (!serialize.program(&pn->as<ListNode>(), &val)) {
args.rval().setNull();
return false;
}

File diff suppressed because it is too large Load diff

View file

@ -498,9 +498,9 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitAtomOp(JSAtom* atom, JSOp op);
MOZ_MUST_USE bool emitAtomOp(uint32_t atomIndex, JSOp op);
MOZ_MUST_USE bool emitArrayLiteral(ParseNode* pn);
MOZ_MUST_USE bool emitArray(ParseNode* pn, uint32_t count, JSOp op);
MOZ_MUST_USE bool emitArrayComp(ParseNode* pn);
MOZ_MUST_USE bool emitArrayLiteral(ListNode* array);
MOZ_MUST_USE bool emitArray(ParseNode* arrayHead, uint32_t count, JSOp op);
MOZ_MUST_USE bool emitArrayComp(ListNode* pn);
MOZ_MUST_USE bool emitInternedScopeOp(uint32_t index, JSOp op);
MOZ_MUST_USE bool emitInternedObjectOp(uint32_t index, JSOp op);
@ -509,13 +509,13 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitRegExp(uint32_t index);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitFunction(ParseNode* pn, bool needsProto = false);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitObject(ParseNode* pn);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitObject(ListNode* objNode);
MOZ_MUST_USE bool replaceNewInitWithNewObject(JSObject* obj, ptrdiff_t offset);
MOZ_MUST_USE bool emitHoistedFunctionsInList(ParseNode* pn);
MOZ_MUST_USE bool emitHoistedFunctionsInList(ListNode* stmtList);
MOZ_MUST_USE bool emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
MOZ_MUST_USE bool emitPropertyList(ListNode* obj, MutableHandlePlainObject objp,
PropListType type);
// To catch accidental misuse, emitUint16Operand/emit3 assert that they are
@ -538,8 +538,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitNameIncDec(ParseNode* incDec);
MOZ_MUST_USE bool emitDeclarationList(ParseNode* decls);
MOZ_MUST_USE bool emitSingleDeclaration(ParseNode* decls, ParseNode* decl,
MOZ_MUST_USE bool emitDeclarationList(ListNode* declList);
MOZ_MUST_USE bool emitSingleDeclaration(ParseNode* declList, ParseNode* decl,
ParseNode* initializer);
MOZ_MUST_USE bool emitNewInit(JSProtoKey key);
@ -624,21 +624,18 @@ struct MOZ_STACK_CLASS BytecodeEmitter
// emitDestructuringObjRestExclusionSet emits the property exclusion set
// for the rest-property in an object pattern.
MOZ_MUST_USE bool emitDestructuringObjRestExclusionSet(ParseNode* pattern);
MOZ_MUST_USE bool emitDestructuringObjRestExclusionSet(ListNode* pattern);
// emitDestructuringOps assumes the to-be-destructured value has been
// pushed on the stack and emits code to destructure each part of a [] or
// {} lhs expression.
MOZ_MUST_USE bool emitDestructuringOps(ParseNode* pattern, DestructuringFlavor flav);
MOZ_MUST_USE bool emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlavor flav);
MOZ_MUST_USE bool emitDestructuringOpsObject(ParseNode* pattern, DestructuringFlavor flav);
MOZ_MUST_USE bool emitDestructuringOps(ListNode* pattern, DestructuringFlavor flav);
MOZ_MUST_USE bool emitDestructuringOpsArray(ListNode* pattern, DestructuringFlavor flav);
MOZ_MUST_USE bool emitDestructuringOpsObject(ListNode* pattern, DestructuringFlavor flav);
typedef bool
(*DestructuringDeclEmitter)(BytecodeEmitter* bce, ParseNode* pn);
template <typename NameEmitter>
MOZ_MUST_USE bool emitDestructuringDeclsWithEmitter(ParseNode* pattern, NameEmitter emitName);
// Throw a TypeError if the value atop the stack isn't convertible to an
// object, with no overall effect on the stack.
MOZ_MUST_USE bool emitRequireObjectCoercible();
@ -694,13 +691,13 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitInitializer(ParseNode* initializer, ParseNode* pattern);
MOZ_MUST_USE bool emitInitializerInBranch(ParseNode* initializer, ParseNode* pattern);
MOZ_MUST_USE bool emitCallSiteObject(ParseNode* pn);
MOZ_MUST_USE bool emitTemplateString(ParseNode* pn);
MOZ_MUST_USE bool emitCallSiteObject(CallSiteNode* callSiteObj);
MOZ_MUST_USE bool emitTemplateString(ListNode* templateString);
MOZ_MUST_USE bool emitAssignment(ParseNode* lhs, JSOp compoundOp, ParseNode* rhs);
MOZ_MUST_USE bool emitReturn(ParseNode* pn);
MOZ_MUST_USE bool emitStatement(ParseNode* pn);
MOZ_MUST_USE bool emitStatementList(ParseNode* pn);
MOZ_MUST_USE bool emitStatementList(ListNode* stmtList);
MOZ_MUST_USE bool emitDeleteName(ParseNode* pn);
MOZ_MUST_USE bool emitDeleteProperty(ParseNode* pn);
@ -735,10 +732,10 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitTypeof(ParseNode* node, JSOp op);
MOZ_MUST_USE bool emitUnary(ParseNode* pn);
MOZ_MUST_USE bool emitRightAssociative(ParseNode* pn);
MOZ_MUST_USE bool emitLeftAssociative(ParseNode* pn);
MOZ_MUST_USE bool emitLogical(ParseNode* pn);
MOZ_MUST_USE bool emitSequenceExpr(ParseNode* pn,
MOZ_MUST_USE bool emitRightAssociative(ListNode* node);
MOZ_MUST_USE bool emitLeftAssociative(ListNode* node);
MOZ_MUST_USE bool emitLogical(ListNode* node);
MOZ_MUST_USE bool emitSequenceExpr(ListNode* node,
ValueUsage valueUsage = ValueUsage::WantValue);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitIncOrDec(ParseNode* pn);
@ -750,8 +747,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitOptimizeSpread(ParseNode* arg0, JumpList* jmp, bool* emitted);
MOZ_MUST_USE ParseNode* getCoordNode(ParseNode* callNode, ParseNode* calleeNode,
ParseNode* firstArgNode);
MOZ_MUST_USE bool emitArguments(ParseNode* argsList, bool isCall, bool isSpread,
ListNode* argsList);
MOZ_MUST_USE bool emitArguments(ListNode* argsList, bool isCall, bool isSpread,
CallOrNewEmitter& cone);
MOZ_MUST_USE bool emitCallOrNew(ParseNode* pn,
ValueUsage valueUsage = ValueUsage::WantValue);
@ -786,8 +783,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitBreak(PropertyName* label);
MOZ_MUST_USE bool emitContinue(PropertyName* label);
MOZ_MUST_USE bool emitFunctionFormalParametersAndBody(ParseNode* pn);
MOZ_MUST_USE bool emitFunctionFormalParameters(ParseNode* pn);
MOZ_MUST_USE bool emitFunctionFormalParametersAndBody(ListNode* paramsBody);
MOZ_MUST_USE bool emitFunctionFormalParameters(ListNode* paramsBody);
MOZ_MUST_USE bool emitInitializeFunctionSpecialNames();
MOZ_MUST_USE bool emitFunctionBody(ParseNode* pn);
MOZ_MUST_USE bool emitLexicalInitialization(ParseNode* pn);

View file

@ -33,7 +33,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result);
static bool
ListContainsHoistedDeclaration(ExclusiveContext* cx, ListNode* list, bool* result)
{
for (ParseNode* node = list->pn_head; node; node = node->pn_next) {
for (ParseNode* node : list->contents()) {
if (!ContainsHoistedDeclaration(cx, node, result))
return false;
if (*result)
@ -74,7 +74,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
// Non-global lexical declarations are block-scoped (ergo not hoistable).
case PNK_LET:
case PNK_CONST:
MOZ_ASSERT(node->isArity(PN_LIST));
MOZ_ASSERT(node->is<ListNode>());
*result = false;
return true;
@ -202,21 +202,20 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
if (*result)
return true;
if (ParseNode* catchList = node->pn_kid2) {
for (ParseNode* lexicalScope = catchList->pn_head;
lexicalScope;
lexicalScope = lexicalScope->pn_next)
{
MOZ_ASSERT(lexicalScope->isKind(PNK_LEXICALSCOPE));
if (node->pn_kid2) {
if (ListNode* catchList = &node->pn_kid2->as<ListNode>()) {
for (ParseNode* lexicalScope : catchList->contents()) {
MOZ_ASSERT(lexicalScope->isKind(PNK_LEXICALSCOPE));
ParseNode* catchNode = lexicalScope->pn_expr;
MOZ_ASSERT(catchNode->isKind(PNK_CATCH));
ParseNode* catchNode = lexicalScope->scopeBody();
MOZ_ASSERT(catchNode->isKind(PNK_CATCH));
ParseNode* catchStatements = catchNode->pn_kid3;
if (!ContainsHoistedDeclaration(cx, catchStatements, result))
return false;
if (*result)
return true;
ParseNode* catchStatements = catchNode->pn_kid3;
if (!ContainsHoistedDeclaration(cx, catchStatements, result))
return false;
if (*result)
return true;
}
}
}
@ -764,16 +763,15 @@ static bool
FoldLogical(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& parser,
bool inGenexpLambda)
{
ParseNode* node = *nodePtr;
ListNode* node = &(*nodePtr)->as<ListNode>();
bool isCoalesceNode = node->isKind(PNK_COALESCE);
bool isOrNode = node->isKind(PNK_OR);
bool isAndNode = node->isKind(PNK_AND);
MOZ_ASSERT(isCoalesceNode || isOrNode || isAndNode);
MOZ_ASSERT(node->isArity(PN_LIST));
ParseNode** elem = &node->pn_head;
ParseNode** elem = node->unsafeHeadReference();
do {
if (!Fold(cx, elem, parser, inGenexpLambda))
return false;
@ -802,7 +800,7 @@ FoldLogical(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>&
for (ParseNode* next = (*elem)->pn_next; next; next = afterNext) {
afterNext = next->pn_next;
parser.handler.freeTree(next);
--node->pn_count;
node->unsafeDecrementCount();
}
// Terminate the original and/or list at the known-truthiness
@ -820,7 +818,7 @@ FoldLogical(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>&
ParseNode* elt = *elem;
*elem = elt->pn_next;
parser.handler.freeTree(elt);
--node->pn_count;
node->unsafeDecrementCount();
} else {
// Otherwise this node is the result of the overall expression,
// so leave it alone. And we're done.
@ -829,16 +827,12 @@ FoldLogical(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>&
}
} while (*elem);
// If the last node in the list was replaced, we need to update the
// tail pointer in the original and/or node.
node->pn_tail = elem;
node->checkListConsistency();
node->unsafeReplaceTail(elem);
// If we removed nodes, we may have to replace a one-element list with
// its element.
if (node->pn_count == 1) {
ParseNode* first = node->pn_head;
if (node->count() == 1) {
ParseNode* first = node->head();
ReplaceNode(nodePtr, first);
node->setKind(PNK_NULL);
@ -999,7 +993,7 @@ FoldIf(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& pars
parser.prepareNodeForMutation(node);
node->setKind(PNK_STATEMENTLIST);
node->setArity(PN_LIST);
node->makeEmpty();
node->as<ListNode>().makeEmpty();
} else {
// Replacement invalidates |nextNode|, so reset it (if the
// replacement requires folding) or clear it (if |alternative|
@ -1013,9 +1007,9 @@ FoldIf(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& pars
// any bugs in the preceding logic.
node->setKind(PNK_STATEMENTLIST);
node->setArity(PN_LIST);
node->makeEmpty();
node->as<ListNode>().makeEmpty();
if (discarded)
node->append(discarded);
node->as<ListNode>().append(discarded);
parser.freeTree(node);
}
} while (nextNode);
@ -1098,7 +1092,7 @@ FoldModule(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& pars
}
static bool
FoldBinaryArithmetic(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
FoldBinaryArithmetic(ExclusiveContext* cx, ListNode* node, Parser<FullParseHandler>& parser,
bool inGenexpLambda)
{
MOZ_ASSERT(node->isKind(PNK_SUB) ||
@ -1108,11 +1102,10 @@ FoldBinaryArithmetic(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHand
node->isKind(PNK_URSH) ||
node->isKind(PNK_DIV) ||
node->isKind(PNK_MOD));
MOZ_ASSERT(node->isArity(PN_LIST));
MOZ_ASSERT(node->pn_count >= 2);
MOZ_ASSERT(node->count() >= 2);
// Fold each operand, ideally into a number.
ParseNode** listp = &node->pn_head;
ParseNode** listp = node->unsafeHeadReference();
for (; *listp; listp = &(*listp)->pn_next) {
if (!Fold(cx, listp, parser, inGenexpLambda))
return false;
@ -1121,15 +1114,14 @@ FoldBinaryArithmetic(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHand
return false;
}
// Repoint the list's tail pointer.
node->pn_tail = listp;
node->unsafeReplaceTail(listp);
// Now fold all leading numeric terms together into a single number.
// (Trailing terms for the non-shift operations can't be folded together
// due to floating point imprecision. For example, if |x === -2**53|,
// |x - 1 - 1 === -2**53| but |x - 2 === -2**53 - 2|. Shifts could be
// folded, but it doesn't seem worth the effort.)
ParseNode* elem = node->pn_head;
ParseNode* elem = node->head();
ParseNode* next = elem->pn_next;
if (elem->isKind(PNK_NUMBER)) {
ParseNodeKind kind = node->getKind();
@ -1149,11 +1141,11 @@ FoldBinaryArithmetic(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHand
elem->setArity(PN_NULLARY);
elem->pn_dval = d;
node->pn_count--;
node->unsafeDecrementCount();
}
if (node->pn_count == 1) {
MOZ_ASSERT(node->pn_head == elem);
if (node->count() == 1) {
MOZ_ASSERT(node->head() == elem);
MOZ_ASSERT(elem->isKind(PNK_NUMBER));
double d = elem->pn_dval;
@ -1170,15 +1162,14 @@ FoldBinaryArithmetic(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHand
}
static bool
FoldExponentiation(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
FoldExponentiation(ExclusiveContext* cx, ListNode* node, Parser<FullParseHandler>& parser,
bool inGenexpLambda)
{
MOZ_ASSERT(node->isKind(PNK_POW));
MOZ_ASSERT(node->isArity(PN_LIST));
MOZ_ASSERT(node->pn_count >= 2);
MOZ_ASSERT(node->count() >= 2);
// Fold each operand, ideally into a number.
ParseNode** listp = &node->pn_head;
ParseNode** listp = node->unsafeHeadReference();
for (; *listp; listp = &(*listp)->pn_next) {
if (!Fold(cx, listp, parser, inGenexpLambda))
return false;
@ -1187,18 +1178,17 @@ FoldExponentiation(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandle
return false;
}
// Repoint the list's tail pointer.
node->pn_tail = listp;
node->unsafeReplaceTail(listp);
// Unlike all other binary arithmetic operators, ** is right-associative:
// 2**3**5 is 2**(3**5), not (2**3)**5. As list nodes singly-link their
// children, full constant-folding requires either linear space or dodgy
// in-place linked list reversal. So we only fold one exponentiation: it's
// easy and addresses common cases like |2**32|.
if (node->pn_count > 2)
if (node->count() > 2)
return true;
ParseNode* base = node->pn_head;
ParseNode* base = node->head();
ParseNode* exponent = base->pn_next;
if (!base->isKind(PNK_NUMBER) || !exponent->isKind(PNK_NUMBER))
return true;
@ -1214,21 +1204,16 @@ FoldExponentiation(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandle
}
static bool
FoldList(ExclusiveContext* cx, ParseNode* list, Parser<FullParseHandler>& parser,
FoldList(ExclusiveContext* cx, ListNode* list, Parser<FullParseHandler>& parser,
bool inGenexpLambda)
{
MOZ_ASSERT(list->isArity(PN_LIST));
ParseNode** elem = &list->pn_head;
ParseNode** elem = list->unsafeHeadReference();
for (; *elem; elem = &(*elem)->pn_next) {
if (!Fold(cx, elem, parser, inGenexpLambda))
return false;
}
// Repoint the list's tail pointer if the final element was replaced.
list->pn_tail = elem;
list->checkListConsistency();
list->unsafeReplaceTail(elem);
return true;
}
@ -1400,11 +1385,10 @@ static bool
FoldAdd(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& parser,
bool inGenexpLambda)
{
ParseNode* node = *nodePtr;
ListNode* node = &(*nodePtr)->as<ListNode>();
MOZ_ASSERT(node->isKind(PNK_ADD));
MOZ_ASSERT(node->isArity(PN_LIST));
MOZ_ASSERT(node->pn_count >= 2);
MOZ_ASSERT(node->count() >= 2);
// Generically fold all operands first.
if (!FoldList(cx, node, parser, inGenexpLambda))
@ -1416,7 +1400,7 @@ FoldAdd(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& par
//
// Don't go past the leading operands: additions after a string are
// string concatenations, not additions: ("1" + 2 + 3 === "123").
ParseNode* current = node->pn_head;
ParseNode* current = node->head();
ParseNode* next = current->pn_next;
if (current->isKind(PNK_NUMBER)) {
do {
@ -1428,8 +1412,7 @@ FoldAdd(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& par
parser.freeTree(next);
next = current->pn_next;
MOZ_ASSERT(node->pn_count > 1);
node->pn_count--;
node->unsafeDecrementCount();
} while (next);
}
@ -1490,8 +1473,7 @@ FoldAdd(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& par
parser.freeTree(next);
next = current->pn_next;
MOZ_ASSERT(node->pn_count > 1);
node->pn_count--;
node->unsafeDecrementCount();
} while (next);
// Replace |current|'s string with the entire combination.
@ -1529,10 +1511,9 @@ FoldAdd(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& par
MOZ_ASSERT(!next, "must have considered all nodes here");
MOZ_ASSERT(!current->pn_next, "current node must be the last node");
node->pn_tail = &current->pn_next;
node->checkListConsistency();
node->unsafeReplaceTail(&current->pn_next);
if (node->pn_count == 1) {
if (node->count() == 1) {
// We reduced the list to a constant. Replace the PNK_ADD node
// with that constant.
ReplaceNode(nodePtr, current);
@ -1583,23 +1564,18 @@ FoldCall(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser
}
static bool
FoldArguments(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
FoldArguments(ExclusiveContext* cx, ListNode* node, Parser<FullParseHandler>& parser,
bool inGenexpLambda)
{
MOZ_ASSERT(node->isKind(PNK_ARGUMENTS));
MOZ_ASSERT(node->isArity(PN_LIST));
ParseNode** listp = &node->pn_head;
ParseNode** listp = node->unsafeHeadReference();
for (; *listp; listp = &(*listp)->pn_next) {
if (!Fold(cx, listp, parser, inGenexpLambda))
return false;
}
// If the last node in the list was replaced, pn_tail points into the wrong node.
node->pn_tail = listp;
node->checkListConsistency();
node->unsafeReplaceTail(listp);
return true;
}
@ -1779,6 +1755,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
case PNK_COALESCE:
case PNK_AND:
case PNK_OR:
MOZ_ASSERT((*pnp)->is<ListNode>());
return FoldLogical(cx, pnp, parser, inGenexpLambda);
case PNK_FUNCTION:
@ -1794,10 +1771,10 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
case PNK_URSH:
case PNK_DIV:
case PNK_MOD:
return FoldBinaryArithmetic(cx, pn, parser, inGenexpLambda);
return FoldBinaryArithmetic(cx, &pn->as<ListNode>(), parser, inGenexpLambda);
case PNK_POW:
return FoldExponentiation(cx, pn, parser, inGenexpLambda);
return FoldExponentiation(cx, &pn->as<ListNode>(), parser, inGenexpLambda);
// Various list nodes not requiring care to minimally fold. Some of
// these could be further folded/optimized, but we don't make the effort.
@ -1829,7 +1806,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
case PNK_CALLSITEOBJ:
case PNK_EXPORT_SPEC_LIST:
case PNK_IMPORT_SPEC_LIST:
return FoldList(cx, pn, parser, inGenexpLambda);
return FoldList(cx, &pn->as<ListNode>(), parser, inGenexpLambda);
case PNK_INITIALYIELD:
MOZ_ASSERT(pn->isArity(PN_UNARY));
@ -1866,6 +1843,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
return FoldElement(cx, pnp, parser, inGenexpLambda);
case PNK_ADD:
MOZ_ASSERT((*pnp)->is<ListNode>());
return FoldAdd(cx, pnp, parser, inGenexpLambda);
case PNK_CALL:
@ -1876,7 +1854,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
return FoldCall(cx, pn, parser, inGenexpLambda);
case PNK_ARGUMENTS:
return FoldArguments(cx, pn, parser, inGenexpLambda);
return FoldArguments(cx, &pn->as<ListNode>(), parser, inGenexpLambda);
case PNK_SWITCH:
case PNK_COLON:

View file

@ -9,6 +9,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/PodOperations.h"
#include <cstddef> // std::nullptr_t
#include <string.h>
#include "frontend/ParseNode.h"
@ -68,7 +69,15 @@ class FullParseHandler
/* new_ methods for creating parse nodes. These report OOM on context. */
JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline)
typedef ParseNode* Node;
// FIXME: Use ListNode instead of ListNodeType as an alias (bug 1489008).
using Node = ParseNode*;
#define DECLARE_TYPE(typeName, longTypeName, asMethodName) \
using longTypeName = typeName*;
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
#undef DECLARE_TYPE
using NullNode = std::nullptr_t;
bool isPropertyAccess(ParseNode* node) {
return node->isKind(PNK_DOT) || node->isKind(PNK_ELEM);
@ -111,7 +120,14 @@ class FullParseHandler
syntaxParser(syntaxParser)
{}
static ParseNode* null() { return nullptr; }
static NullNode null() { return NullNode(); }
#define DECLARE_AS(typeName, longTypeName, asMethodName) \
static longTypeName asMethodName(Node node) { \
return &node->as<typeName>(); \
}
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
#undef DECLARE_AS
ParseNode* freeTree(ParseNode* pn) { return allocator.freeTree(pn); }
void prepareNodeForMutation(ParseNode* pn) { return allocator.prepareNodeForMutation(pn); }
@ -151,31 +167,32 @@ class FullParseHandler
return new_<NullaryNode>(PNK_TEMPLATE_STRING, JSOP_NOP, pos, atom);
}
ParseNode* newCallSiteObject(uint32_t begin) {
ParseNode* callSite = new_<CallSiteNode>(begin);
if (!callSite)
CallSiteNodeType newCallSiteObject(uint32_t begin) {
CallSiteNode* callSiteObj = new_<CallSiteNode>(begin);
if (!callSiteObj)
return null();
Node propExpr = newArrayLiteral(getPosition(callSite).begin);
if (!propExpr)
ListNode* rawNodes = newArrayLiteral(callSiteObj->pn_pos.begin);
if (!rawNodes)
return null();
addArrayElement(callSite, propExpr);
addArrayElement(callSiteObj, rawNodes);
return callSite;
return callSiteObj;
}
void addToCallSiteObject(ParseNode* callSiteObj, ParseNode* rawNode, ParseNode* cookedNode) {
void addToCallSiteObject(CallSiteNodeType callSiteObj, ParseNode* rawNode,
ParseNode* cookedNode) {
MOZ_ASSERT(callSiteObj->isKind(PNK_CALLSITEOBJ));
addArrayElement(callSiteObj, cookedNode);
addArrayElement(callSiteObj->pn_head, rawNode);
addArrayElement(callSiteObj->rawNodes(), rawNode);
/*
* We don't know when the last noSubstTemplate will come in, and we
* don't want to deal with this outside this method
*/
setEndPosition(callSiteObj, callSiteObj->pn_head);
setEndPosition(callSiteObj, callSiteObj->rawNodes());
}
ParseNode* newThisLiteral(const TokenPos& pos, ParseNode* thisName) {
@ -289,45 +306,37 @@ class FullParseHandler
// Expressions
ParseNode* newArrayComprehension(ParseNode* body, const TokenPos& pos) {
MOZ_ASSERT(pos.begin <= body->pn_pos.begin);
MOZ_ASSERT(body->pn_pos.end <= pos.end);
ParseNode* pn = new_<ListNode>(PNK_ARRAYCOMP, pos);
if (!pn)
return nullptr;
pn->append(body);
return pn;
}
ParseNode* newArrayLiteral(uint32_t begin) {
ParseNode* literal = new_<ListNode>(PNK_ARRAY, TokenPos(begin, begin + 1));
ListNodeType newArrayLiteral(uint32_t begin) {
ListNode* literal = new_<ListNode>(PNK_ARRAY, TokenPos(begin, begin + 1));
// Later in this stack: remove dependency on this opcode.
if (literal)
literal->setOp(JSOP_NEWINIT);
return literal;
}
MOZ_MUST_USE bool addElision(ParseNode* literal, const TokenPos& pos) {
MOZ_MUST_USE bool addElision(ListNodeType literal, const TokenPos& pos) {
ParseNode* elision = new_<NullaryNode>(PNK_ELISION, pos);
if (!elision)
return false;
literal->append(elision);
literal->pn_xflags |= PNX_ARRAYHOLESPREAD | PNX_NONCONST;
literal->setHasArrayHoleOrSpread();
literal->setHasNonConstInitializer();
return true;
}
MOZ_MUST_USE bool addSpreadElement(ParseNode* literal, uint32_t begin, ParseNode* inner) {
MOZ_MUST_USE bool addSpreadElement(ListNodeType literal, uint32_t begin, Node inner) {
ParseNode* spread = newSpread(begin, inner);
if (!spread)
return false;
literal->append(spread);
literal->pn_xflags |= PNX_ARRAYHOLESPREAD | PNX_NONCONST;
literal->setHasArrayHoleOrSpread();
literal->setHasNonConstInitializer();
return true;
}
void addArrayElement(ParseNode* literal, ParseNode* element) {
void addArrayElement(ListNodeType literal, Node element) {
if (!element->isConstant())
literal->pn_xflags |= PNX_NONCONST;
literal->setHasNonConstInitializer();
literal->append(element);
}
@ -339,7 +348,7 @@ class FullParseHandler
return new_<BinaryNode>(PNK_OPTCALL, JSOP_CALL, callee, args);
}
ParseNode* newArguments(const TokenPos& pos) {
ListNodeType newArguments(const TokenPos& pos) {
return new_<ListNode>(PNK_ARGUMENTS, JSOP_NOP, pos);
}
@ -355,8 +364,8 @@ class FullParseHandler
return new_<BinaryNode>(PNK_GENEXP, JSOP_CALL, callee, args);
}
ParseNode* newObjectLiteral(uint32_t begin) {
ParseNode* literal = new_<ListNode>(PNK_OBJECT, TokenPos(begin, begin + 1));
ListNodeType newObjectLiteral(uint32_t begin) {
ListNode* literal = new_<ListNode>(PNK_OBJECT, TokenPos(begin, begin + 1));
// Later in this stack: remove dependency on this opcode.
if (literal)
literal->setOp(JSOP_NEWINIT);
@ -368,7 +377,7 @@ class FullParseHandler
{
return new_<ClassNode>(name, heritage, methodBlock, pos);
}
ParseNode* newClassMethodList(uint32_t begin) {
ListNodeType newClassMethodList(uint32_t begin) {
return new_<ListNode>(PNK_CLASSMETHODLIST, TokenPos(begin, begin + 1));
}
ParseNode* newClassNames(ParseNode* outer, ParseNode* inner, const TokenPos& pos) {
@ -384,10 +393,10 @@ class FullParseHandler
return new_<UnaryNode>(PNK_SUPERBASE, JSOP_NOP, pos, thisName);
}
MOZ_MUST_USE bool addPrototypeMutation(ParseNode* literal, uint32_t begin, ParseNode* expr) {
MOZ_MUST_USE bool addPrototypeMutation(ListNodeType literal, uint32_t begin, ParseNode* expr) {
// Object literals with mutated [[Prototype]] are non-constant so that
// singleton objects will have Object.prototype as their [[Prototype]].
setListFlag(literal, PNX_NONCONST);
literal->setHasNonConstInitializer();
ParseNode* mutation = newUnary(PNK_MUTATEPROTO, JSOP_NOP, begin, expr);
if (!mutation)
@ -396,9 +405,8 @@ class FullParseHandler
return true;
}
MOZ_MUST_USE bool addPropertyDefinition(ParseNode* literal, ParseNode* key, ParseNode* val) {
MOZ_MUST_USE bool addPropertyDefinition(ListNodeType literal, ParseNode* key, ParseNode* val) {
MOZ_ASSERT(literal->isKind(PNK_OBJECT));
MOZ_ASSERT(literal->isArity(PN_LIST));
MOZ_ASSERT(key->isKind(PNK_NUMBER) ||
key->isKind(PNK_OBJECT_PROPERTY_NAME) ||
key->isKind(PNK_STRING) ||
@ -407,18 +415,21 @@ class FullParseHandler
ParseNode* propdef = newBinary(PNK_COLON, key, val, JSOP_INITPROP);
if (!propdef)
return false;
if (!val->isConstant()) {
literal->setHasNonConstInitializer();
}
literal->append(propdef);
return true;
}
MOZ_MUST_USE bool addShorthand(ParseNode* literal, ParseNode* name, ParseNode* expr) {
MOZ_MUST_USE bool addShorthand(ListNodeType literal, ParseNode* name, ParseNode* expr) {
MOZ_ASSERT(literal->isKind(PNK_OBJECT));
MOZ_ASSERT(literal->isArity(PN_LIST));
MOZ_ASSERT(name->isKind(PNK_OBJECT_PROPERTY_NAME));
MOZ_ASSERT(expr->isKind(PNK_NAME));
MOZ_ASSERT(name->pn_atom == expr->pn_atom);
setListFlag(literal, PNX_NONCONST);
literal->setHasNonConstInitializer();
ParseNode* propdef = newBinary(PNK_SHORTHAND, name, expr, JSOP_INITPROP);
if (!propdef)
return false;
@ -426,11 +437,10 @@ class FullParseHandler
return true;
}
MOZ_MUST_USE bool addSpreadProperty(ParseNode* literal, uint32_t begin, ParseNode* inner) {
MOZ_MUST_USE bool addSpreadProperty(ListNodeType literal, uint32_t begin, ParseNode* inner) {
MOZ_ASSERT(literal->isKind(PNK_OBJECT));
MOZ_ASSERT(literal->isArity(PN_LIST));
setListFlag(literal, PNX_NONCONST);
literal->setHasNonConstInitializer();
ParseNode* spread = newSpread(begin, inner);
if (!spread)
return false;
@ -438,15 +448,14 @@ class FullParseHandler
return true;
}
MOZ_MUST_USE bool addObjectMethodDefinition(ParseNode* literal, ParseNode* key, ParseNode* fn,
MOZ_MUST_USE bool addObjectMethodDefinition(ListNodeType literal, Node key, Node fn,
JSOp op)
{
MOZ_ASSERT(literal->isArity(PN_LIST));
MOZ_ASSERT(key->isKind(PNK_NUMBER) ||
key->isKind(PNK_OBJECT_PROPERTY_NAME) ||
key->isKind(PNK_STRING) ||
key->isKind(PNK_COMPUTED_NAME));
literal->pn_xflags |= PNX_NONCONST;
literal->setHasNonConstInitializer();
ParseNode* propdef = newBinary(PNK_COLON, key, fn, op);
if (!propdef)
@ -455,7 +464,7 @@ class FullParseHandler
return true;
}
MOZ_MUST_USE bool addClassMethodDefinition(ParseNode* methodList, ParseNode* key, ParseNode* fn,
MOZ_MUST_USE bool addClassMethodDefinition(ListNodeType methodList, Node key, Node fn,
JSOp op, bool isStatic)
{
MOZ_ASSERT(methodList->isKind(PNK_CLASSMETHODLIST));
@ -498,7 +507,7 @@ class FullParseHandler
// Statements
ParseNode* newStatementList(const TokenPos& pos) {
ListNodeType newStatementList(const TokenPos& pos) {
return new_<ListNode>(PNK_STATEMENTLIST, pos);
}
@ -508,31 +517,30 @@ class FullParseHandler
return stmt->isKind(PNK_FUNCTION);
}
void addStatementToList(ParseNode* list, ParseNode* stmt) {
void addStatementToList(ListNodeType list, ParseNode* stmt) {
MOZ_ASSERT(list->isKind(PNK_STATEMENTLIST));
list->append(stmt);
if (isFunctionStmt(stmt)) {
// PNX_FUNCDEFS notifies the emitter that the block contains
// body-level function definitions that should be processed
// before the rest of nodes.
list->pn_xflags |= PNX_FUNCDEFS;
// Notify the emitter that the block contains body-level function
// definitions that should be processed before the rest of nodes.
list->setHasTopLevelFunctionDeclarations();
}
}
void addCaseStatementToList(ParseNode* list, ParseNode* casepn) {
void addCaseStatementToList(ListNodeType list, ParseNode* caseClause) {
MOZ_ASSERT(list->isKind(PNK_STATEMENTLIST));
MOZ_ASSERT(casepn->isKind(PNK_CASE));
MOZ_ASSERT(casepn->pn_right->isKind(PNK_STATEMENTLIST));
MOZ_ASSERT(caseClause->isKind(PNK_CASE));
MOZ_ASSERT(caseClause->pn_right->isKind(PNK_STATEMENTLIST));
list->append(casepn);
list->append(caseClause);
if (casepn->pn_right->pn_xflags & PNX_FUNCDEFS)
list->pn_xflags |= PNX_FUNCDEFS;
if (caseClause->pn_right->as<ListNode>().hasTopLevelFunctionDeclarations())
list->setHasTopLevelFunctionDeclarations();
}
MOZ_MUST_USE bool prependInitialYield(ParseNode* stmtList, ParseNode* genName) {
MOZ_MUST_USE bool prependInitialYield(ListNodeType stmtList, Node genName) {
MOZ_ASSERT(stmtList->isKind(PNK_STATEMENTLIST));
TokenPos yieldPos(stmtList->pn_pos.begin, stmtList->pn_pos.begin + 1);
@ -699,7 +707,7 @@ class FullParseHandler
return new_<UnaryNode>(PNK_THROW, JSOP_THROW, pos, expr);
}
ParseNode* newTryStatement(uint32_t begin, ParseNode* body, ParseNode* catchList,
ParseNode* newTryStatement(uint32_t begin, ParseNode* body, ListNodeType catchList,
ParseNode* finallyBlock) {
TokenPos pos(begin, (finallyBlock ? finallyBlock : catchList)->pn_pos.end);
return new_<TernaryNode>(PNK_TRY, JSOP_NOP, body, catchList, finallyBlock, pos);
@ -729,7 +737,7 @@ class FullParseHandler
return new_<OptionalPropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
}
inline MOZ_MUST_USE bool addCatchBlock(ParseNode* catchList, ParseNode* lexicalScope,
inline MOZ_MUST_USE bool addCatchBlock(ListNodeType catchList, ParseNode* lexicalScope,
ParseNode* catchName, ParseNode* catchGuard,
ParseNode* catchBody);
@ -772,11 +780,11 @@ class FullParseHandler
funbox->functionNode = pn;
}
void addFunctionFormalParameter(ParseNode* pn, ParseNode* argpn) {
pn->pn_body->append(argpn);
addList(/* list = */ &pn->pn_body->as<ListNode>(), /* child = */ argpn);
}
void setFunctionBody(ParseNode* fn, ParseNode* body) {
MOZ_ASSERT(fn->pn_body->isKind(PNK_PARAMSBODY));
fn->pn_body->append(body);
addList(/* list = */ &fn->pn_body->as<ListNode>(), /* child = */ body);
}
ParseNode* newModule() {
@ -869,27 +877,27 @@ class FullParseHandler
return kind == PNK_VAR || kind == PNK_LET || kind == PNK_CONST;
}
ParseNode* newList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
ListNodeType newList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
MOZ_ASSERT(!isDeclarationKind(kind));
return new_<ListNode>(kind, op, pos());
}
ParseNode* newList(ParseNodeKind kind, uint32_t begin, JSOp op = JSOP_NOP) {
ListNodeType newList(ParseNodeKind kind, uint32_t begin, JSOp op = JSOP_NOP) {
MOZ_ASSERT(!isDeclarationKind(kind));
return new_<ListNode>(kind, op, TokenPos(begin, begin + 1));
}
ParseNode* newList(ParseNodeKind kind, ParseNode* kid, JSOp op = JSOP_NOP) {
ListNodeType newList(ParseNodeKind kind, ParseNode* kid, JSOp op = JSOP_NOP) {
MOZ_ASSERT(!isDeclarationKind(kind));
return new_<ListNode>(kind, op, kid);
}
ParseNode* newDeclarationList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
ListNodeType newDeclarationList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
MOZ_ASSERT(isDeclarationKind(kind));
return new_<ListNode>(kind, op, pos());
}
ParseNode* newDeclarationList(ParseNodeKind kind, ParseNode* kid, JSOp op = JSOP_NOP) {
ListNodeType newDeclarationList(ParseNodeKind kind, ParseNode* kid, JSOp op = JSOP_NOP) {
MOZ_ASSERT(isDeclarationKind(kind));
return new_<ListNode>(kind, op, kid);
}
@ -898,30 +906,29 @@ class FullParseHandler
return isDeclarationKind(node->getKind());
}
ParseNode* singleBindingFromDeclaration(ParseNode* decl) {
Node singleBindingFromDeclaration(ListNodeType decl) {
MOZ_ASSERT(isDeclarationList(decl));
MOZ_ASSERT(decl->pn_count == 1);
return decl->pn_head;
MOZ_ASSERT(decl->count() == 1);
return decl->head();
}
ParseNode* newCatchList() {
ListNodeType newCatchList() {
return new_<ListNode>(PNK_CATCHLIST, JSOP_NOP, pos());
}
ParseNode* newCommaExpressionList(ParseNode* kid) {
ListNodeType newCommaExpressionList(Node kid) {
return newList(PNK_COMMA, kid, JSOP_NOP);
}
void addList(ParseNode* list, ParseNode* kid) {
void addList(ListNodeType list, Node kid) {
list->append(kid);
}
void setOp(ParseNode* pn, JSOp op) {
pn->setOp(op);
}
void setListFlag(ParseNode* pn, unsigned flag) {
MOZ_ASSERT(pn->isArity(PN_LIST));
pn->pn_xflags |= flag;
void setListHasNonConstInitializer(ListNodeType literal) {
literal->setHasNonConstInitializer();
}
MOZ_MUST_USE ParseNode* parenthesize(ParseNode* pn) {
pn->setInParens(true);
@ -1015,7 +1022,7 @@ class FullParseHandler
};
inline bool
FullParseHandler::addCatchBlock(ParseNode* catchList, ParseNode* lexicalScope,
FullParseHandler::addCatchBlock(ListNodeType catchList, ParseNode* lexicalScope,
ParseNode* catchName, ParseNode* catchGuard, ParseNode* catchBody)
{
ParseNode* catchpn = newTernary(PNK_CATCH, catchName, catchGuard, catchBody);
@ -1029,27 +1036,15 @@ FullParseHandler::addCatchBlock(ParseNode* catchList, ParseNode* lexicalScope,
inline bool
FullParseHandler::setLastFunctionFormalParameterDefault(ParseNode* funcpn, ParseNode* defaultValue)
{
ParseNode* arg = funcpn->pn_body->last();
ListNode* body = &funcpn->pn_body->as<ListNode>();
ParseNode* arg = body->last();
ParseNode* pn = newBinary(PNK_ASSIGN, arg, defaultValue, JSOP_NOP);
if (!pn)
return false;
checkAndSetIsDirectRHSAnonFunction(defaultValue);
funcpn->pn_body->pn_pos.end = pn->pn_pos.end;
ParseNode* pnchild = funcpn->pn_body->pn_head;
ParseNode* pnlast = funcpn->pn_body->last();
MOZ_ASSERT(pnchild);
if (pnchild == pnlast) {
funcpn->pn_body->pn_head = pn;
} else {
while (pnchild->pn_next != pnlast) {
MOZ_ASSERT(pnchild->pn_next);
pnchild = pnchild->pn_next;
}
pnchild->pn_next = pn;
}
funcpn->pn_body->pn_tail = &pn->pn_next;
body->replaceLast(pn);
return true;
}

View file

@ -284,12 +284,12 @@ class NameResolver
* for new variables and then return an anonymous function using this scope.
*/
bool isDirectCall(int pos, ParseNode* cur) {
return pos >= 0 && call(parents[pos]) && parents[pos]->pn_head == cur;
return pos >= 0 && call(parents[pos]) && parents[pos]->pn_left == cur;
}
bool resolveTemplateLiteral(ParseNode* node, HandleAtom prefix) {
bool resolveTemplateLiteral(ListNode* node, HandleAtom prefix) {
MOZ_ASSERT(node->isKind(PNK_TEMPLATE_STRING_LIST));
ParseNode* element = node->pn_head;
ParseNode* element = node->head();
while (true) {
MOZ_ASSERT(element->isKind(PNK_TEMPLATE_STRING));
@ -317,16 +317,18 @@ class NameResolver
// The callsite object node is first. This node only contains
// internal strings or undefined and an array -- no user-controlled
// expressions.
ParseNode* element = node->pn_right->pn_head;
CallSiteNode* element = &node->pn_right->as<ListNode>().head()->as<CallSiteNode>();
#ifdef DEBUG
{
MOZ_ASSERT(element->isKind(PNK_CALLSITEOBJ));
ParseNode* array = element->pn_head;
MOZ_ASSERT(array->isKind(PNK_ARRAY));
for (ParseNode* kid = array->pn_head; kid; kid = kid->pn_next)
MOZ_ASSERT(kid->isKind(PNK_TEMPLATE_STRING));
for (ParseNode* next = array->pn_next; next; next = next->pn_next)
MOZ_ASSERT(next->isKind(PNK_TEMPLATE_STRING) || next->isKind(PNK_RAW_UNDEFINED));
ListNode* rawNodes = &element->head()->as<ListNode>();
MOZ_ASSERT(rawNodes->isKind(PNK_ARRAY));
for (ParseNode* raw : rawNodes->contents()) {
MOZ_ASSERT(raw->isKind(PNK_TEMPLATE_STRING));
}
for (ParseNode* cooked : element->contentsFrom(rawNodes->pn_next)) {
MOZ_ASSERT(cooked->isKind(PNK_TEMPLATE_STRING) ||
cooked->isKind(PNK_RAW_UNDEFINED));
}
}
#endif
@ -697,8 +699,7 @@ class NameResolver
case PNK_VAR:
case PNK_CONST:
case PNK_LET:
MOZ_ASSERT(cur->isArity(PN_LIST));
for (ParseNode* element = cur->pn_head; element; element = element->pn_next) {
for (ParseNode* element : cur->as<ListNode>().contents()) {
if (!resolve(element, prefix))
return false;
}
@ -708,19 +709,19 @@ class NameResolver
// PNK_COMPREHENSIONFOR for comprehensions, PNK_LEXICALSCOPE for
// legacy comprehensions. Probably this should be a non-list
// eventually.
case PNK_ARRAYCOMP:
MOZ_ASSERT(cur->isArity(PN_LIST));
MOZ_ASSERT(cur->pn_count == 1);
MOZ_ASSERT(cur->pn_head->isKind(PNK_LEXICALSCOPE) ||
cur->pn_head->isKind(PNK_COMPREHENSIONFOR));
if (!resolve(cur->pn_head, prefix))
case PNK_ARRAYCOMP: {
ListNode* literal = &cur->as<ListNode>();
MOZ_ASSERT(literal->count() == 1);
MOZ_ASSERT(literal->head()->isKind(PNK_LEXICALSCOPE) ||
literal->head()->isKind(PNK_COMPREHENSIONFOR));
if (!resolve(literal->head(), prefix))
return false;
break;
}
case PNK_OBJECT:
case PNK_CLASSMETHODLIST:
MOZ_ASSERT(cur->isArity(PN_LIST));
for (ParseNode* element = cur->pn_head; element; element = element->pn_next) {
for (ParseNode* element : cur->as<ListNode>().contents()) {
if (!resolve(element, prefix))
return false;
}
@ -729,8 +730,7 @@ class NameResolver
// A template string list's contents alternate raw template string
// contents with expressions interpolated into the overall literal.
case PNK_TEMPLATE_STRING_LIST:
MOZ_ASSERT(cur->isArity(PN_LIST));
if (!resolveTemplateLiteral(cur, prefix))
if (!resolveTemplateLiteral(&cur->as<ListNode>(), prefix))
return false;
break;
@ -755,8 +755,7 @@ class NameResolver
// the Arguments node used by tagged template literals, since that is
// special-cased inside of resolveTaggedTemplate.
case PNK_ARGUMENTS:
MOZ_ASSERT(cur->isArity(PN_LIST));
for (ParseNode* element = cur->pn_head; element; element = element->pn_next) {
for (ParseNode* element : cur->as<ListNode>().contents()) {
if (!resolve(element, prefix))
return false;
}
@ -767,15 +766,15 @@ class NameResolver
// contain a single export batch specifier.
case PNK_EXPORT_SPEC_LIST:
case PNK_IMPORT_SPEC_LIST: {
MOZ_ASSERT(cur->isArity(PN_LIST));
#ifdef DEBUG
bool isImport = cur->isKind(PNK_IMPORT_SPEC_LIST);
ParseNode* item = cur->pn_head;
ListNode* list = &cur->as<ListNode>();
ParseNode* item = list->head();
if (!isImport && item && item->isKind(PNK_EXPORT_BATCH_SPEC)) {
MOZ_ASSERT(item->isArity(PN_NULLARY));
break;
}
for (; item; item = item->pn_next) {
for (ParseNode* item : list->contents()) {
MOZ_ASSERT(item->isKind(isImport ? PNK_IMPORT_SPEC : PNK_EXPORT_SPEC));
MOZ_ASSERT(item->isArity(PN_BINARY));
MOZ_ASSERT(item->pn_left->isKind(PNK_NAME));
@ -788,8 +787,8 @@ class NameResolver
}
case PNK_CATCHLIST: {
MOZ_ASSERT(cur->isArity(PN_LIST));
for (ParseNode* catchNode = cur->pn_head; catchNode; catchNode = catchNode->pn_next) {
ListNode* catchList = &cur->as<ListNode>();
for (ParseNode* catchNode : catchList->contents()) {
MOZ_ASSERT(catchNode->isKind(PNK_LEXICALSCOPE));
MOZ_ASSERT(catchNode->scopeBody()->isKind(PNK_CATCH));
MOZ_ASSERT(catchNode->scopeBody()->isArity(PN_TERNARY));

View file

@ -17,26 +17,24 @@ using mozilla::IsFinite;
#ifdef DEBUG
void
ParseNode::checkListConsistency()
ListNode::checkConsistency() const
{
MOZ_ASSERT(isArity(PN_LIST));
ParseNode** tail;
uint32_t count = 0;
if (pn_head) {
ParseNode* last = pn_head;
ParseNode* pn = last;
ParseNode* const* tailNode;
uint32_t actualCount = 0;
if (const ParseNode* last = head()) {
const ParseNode* pn = last;
while (pn) {
last = pn;
pn = pn->pn_next;
count++;
actualCount++;
}
tail = &last->pn_next;
tailNode = &last->pn_next;
} else {
tail = &pn_head;
tailNode = &pn_u.list.head;
}
MOZ_ASSERT(pn_tail == tail);
MOZ_ASSERT(pn_count == count);
MOZ_ASSERT(tail() == tailNode);
MOZ_ASSERT(count() == actualCount);
}
#endif
@ -76,10 +74,10 @@ class NodeStack {
top = pn;
}
/* Push the children of the PN_LIST node |pn| on the stack. */
void pushList(ParseNode* pn) {
void pushList(ListNode* pn) {
/* This clobbers pn->pn_head if the list is empty; should be okay. */
*pn->pn_tail = top;
top = pn->pn_head;
pn->unsafeSetTail(top);
top = pn->head();
}
ParseNode* pop() {
MOZ_ASSERT(!empty());
@ -148,10 +146,10 @@ PushScopeNodeChildren(ParseNode* node, NodeStack* stack)
}
static PushResult
PushListNodeChildren(ParseNode* node, NodeStack* stack)
PushListNodeChildren(ListNode* node, NodeStack* stack)
{
MOZ_ASSERT(node->isArity(PN_LIST));
node->checkListConsistency();
node->checkConsistency();
stack->pushList(node);
@ -335,7 +333,7 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
MOZ_ASSERT_IF(pn->isKind(PNK_EXPORT_FROM), pn->pn_left->isKind(PNK_EXPORT_SPEC_LIST));
MOZ_ASSERT(pn->pn_left->isArity(PN_LIST));
MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING));
stack->pushList(pn->pn_left);
stack->pushList(&pn->pn_left->as<ListNode>());
stack->push(pn->pn_right);
return PushResult::Recyclable;
}
@ -474,20 +472,17 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
case PNK_EXPORT_SPEC_LIST:
case PNK_PARAMSBODY:
case PNK_CLASSMETHODLIST:
return PushListNodeChildren(pn, stack);
return PushListNodeChildren(&pn->as<ListNode>(), stack);
// Array comprehension nodes are lists with a single child:
// PNK_COMPREHENSIONFOR for comprehensions, PNK_LEXICALSCOPE for legacy
// comprehensions. Probably this should be a non-list eventually.
case PNK_ARRAYCOMP: {
#ifdef DEBUG
MOZ_ASSERT(pn->isKind(PNK_ARRAYCOMP));
MOZ_ASSERT(pn->isArity(PN_LIST));
MOZ_ASSERT(pn->pn_count == 1);
MOZ_ASSERT(pn->pn_head->isKind(PNK_LEXICALSCOPE) ||
pn->pn_head->isKind(PNK_COMPREHENSIONFOR));
#endif
return PushListNodeChildren(pn, stack);
ListNode* literal = &pn->as<ListNode>();
MOZ_ASSERT(literal->count() == 1);
MOZ_ASSERT(literal->head()->isKind(PNK_LEXICALSCOPE) ||
literal->head()->isKind(PNK_COMPREHENSIONFOR));
return PushListNodeChildren(literal, stack);
}
case PNK_LABEL:
@ -614,7 +609,7 @@ ParseNode::appendOrCreateList(ParseNodeKind kind, JSOp op, ParseNode* left, Pars
}
}
ParseNode* list = handler->new_<ListNode>(kind, op, left);
ListNode* list = handler->new_<ListNode>(kind, op, left);
if (!list)
return nullptr;
@ -674,7 +669,7 @@ ParseNode::dump(int indent)
((CodeNode*) this)->dump(indent);
break;
case PN_LIST:
((ListNode*) this)->dump(indent);
as<ListNode>().dump(indent);
break;
case PN_NAME:
((NameNode*) this)->dump(indent);
@ -785,14 +780,12 @@ ListNode::dump(int indent)
{
const char* name = parseNodeNames[getKind()];
fprintf(stderr, "(%s [", name);
if (pn_head != nullptr) {
if (ParseNode* listHead = head()) {
indent += strlen(name) + 3;
DumpParseTree(pn_head, indent);
ParseNode* pn = pn_head->pn_next;
while (pn != nullptr) {
DumpParseTree(listHead, indent);
for (ParseNode* item : contentsFrom(listHead->pn_next)) {
IndentNewLine(indent);
DumpParseTree(pn, indent);
pn = pn->pn_next;
DumpParseTree(item, indent);
}
}
fprintf(stderr, "])");

View file

@ -220,8 +220,6 @@ IsTypeofKind(ParseNodeKind kind)
}
/*
* Label Variant Members
* ----- ------- -------
* <Definitions>
* PNK_FUNCTION name pn_funbox: ptr to js::FunctionBox holding function
* object containing arg and var properties. We
@ -229,27 +227,25 @@ IsTypeofKind(ParseNodeKind kind)
* time to specialize arg and var bytecodes early.
* pn_body: PNK_PARAMSBODY, ordinarily;
* PNK_LEXICALSCOPE for implicit function in genexpr
* PNK_PARAMSBODY list list of formal parameters with
* PNK_NAME node with non-empty name for
* SingleNameBinding without Initializer
* PNK_ASSIGN node for SingleNameBinding with
* Initializer
* PNK_NAME node with empty name for destructuring
* pn_expr: PNK_ARRAY, PNK_OBJECT, or PNK_ASSIGN
* PNK_ARRAY or PNK_OBJECT for BindingPattern
* without Initializer
* PNK_ASSIGN for BindingPattern with
* Initializer
* followed by:
* PNK_STATEMENTLIST node for function body
* statements,
* PNK_RETURN for expression closure
* pn_count: 1 + number of formal parameters
* pn_tree: PNK_PARAMSBODY or PNK_STATEMENTLIST node
* PNK_PARAMSBODY (ListNode)
* head: list of formal parameters with
* * Name node with non-empty name for SingleNameBinding without
* Initializer
* * Assign node for SingleNameBinding with Initializer
* * Name node with empty name for destructuring
* pn_expr: Array or Object for BindingPattern without
* Initializer, Assign for BindingPattern with
* Initializer
* followed by either:
* * StatementList node for function body statements
* * Return for expression closure
* count: number of formal parameters + 1
* PNK_SPREAD unary pn_kid: expression being spread
*
* <Statements>
* PNK_STATEMENTLIST list pn_head: list of pn_count 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,
@ -293,19 +289,21 @@ IsTypeofKind(ParseNodeKind kind)
* 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;
* PNK_VAR, list pn_head: list of PNK_NAME or PNK_ASSIGN nodes
* PNK_LET, each name node has either
* PNK_CONST pn_used: false
* pn_atom: variable name
* pn_expr: initializer or null
* or
* pn_used: true
* pn_atom: variable name
* pn_lexdef: def node
* each assignment node has
* pn_left: PNK_NAME with pn_used true and
* pn_lexdef (NOT pn_expr) set
* pn_right: initializer
* PNK_VAR, PNK_LET, PNK_CONST (ListNode)
* head: list of N Name or Assign nodes
* each name node has either
* pn_used: false
* pn_atom: variable name
* pn_expr: initializer or null
* or
* pn_used: true
* pn_atom: variable name
* pn_lexdef: def node
* each assignment node has
* pn_left: Name with pn_used true and
* pn_lexdef (NOT pn_expr) set
* pn_right: initializer
* count: N > 0
* PNK_RETURN unary pn_kid: return expr or null
* PNK_SEMI unary pn_kid: expr or null statement
* pn_prologue: true if Directive Prologue member
@ -314,15 +312,23 @@ IsTypeofKind(ParseNodeKind kind)
* PNK_LABEL name pn_atom: label, pn_expr: labeled statement
* PNK_IMPORT binary pn_left: PNK_IMPORT_SPEC_LIST import specifiers
* pn_right: PNK_STRING module specifier
* PNK_IMPORT_SPEC_LIST (ListNode)
* head: list of N ImportSpec nodes
* count: N >= 0 (N = 0 for `import {} from ...`)
* PNK_EXPORT unary pn_kid: declaration expression
* PNK_EXPORT_FROM binary pn_left: PNK_EXPORT_SPEC_LIST export specifiers
* pn_right: PNK_STRING module specifier
* PNK_EXPORT_SPEC_LIST (ListNode)
* head: list of N ExportSpec nodes
* count: N >= 0 (N = 0 for `export {}`)
* PNK_EXPORT_DEFAULT unary pn_kid: export default declaration or expression
*
* <Expressions>
* All left-associated binary trees of the same type are optimized into lists
* to avoid recursion when processing expression chains.
* PNK_COMMA list pn_head: list of pn_count comma-separated exprs
* PNK_COMMA (ListNode)
* head: list of N comma-separated exprs
* count: N >= 2
* PNK_ASSIGN binary pn_left: lvalue, pn_right: rvalue
* PNK_ADDASSIGN, binary pn_left: lvalue, pn_right: rvalue
* PNK_SUBASSIGN, pn_op: JSOP_ADD for +=, etc.
@ -339,29 +345,18 @@ IsTypeofKind(ParseNodeKind kind)
* PNK_CONDITIONAL ternary (cond ? trueExpr : falseExpr)
* pn_kid1: cond, pn_kid2: then, pn_kid3: else
* PNK_COALESCE, list pn_head; list of pn_count subexpressions
* PNK_OR, All of these operators are left-associative except (**).
* PNK_AND
* PNK_BITOR,
* PNK_BITXOR,
* PNK_BITAND,
* PNK_EQ,
* PNK_NE,
* PNK_STRICTEQ,
* PNK_STRICTNE,
* PNK_LT,
* PNK_LE,
* PNK_GT,
* PNK_GE,
* PNK_LSH,
* PNK_RSH,
* PNK_URSH,
* PNK_ADD,
* PNK_SUB,
* PNK_STAR,
* PNK_DIV,
* PNK_MOD,
* PNK_POW (**) is right-associative, but forms a list
* nonetheless. Special hacks everywhere.
* PNK_OR, PNK_AND, PNK_BITOR,
* PNK_BITXOR, PNK_BITAND, PNK_EQ,
* PNK_NE, PNK_STRICTEQ, PNK_STRICTNE,
* PNK_LT, PNK_LE, PNK_GT, PNK_GE,
* PNK_LSH, PNK_RSH, PNK_URSH,
* PNK_ADD, PNK_SUB, PNK_STAR,
* PNK_DIV, PNK_MOD, PNK_POW (ListNode)
* head: list of N subexpressions
* All of these operators are left-associative except Pow which is
* right-associative, but still forms a list (see comments in
* ParseNode::appendOrCreateList).
* count: N >= 2
*
* PNK_POS, unary pn_kid: UNARY expr
* PNK_NEG
@ -420,10 +415,21 @@ IsTypeofKind(ParseNodeKind kind)
* pn_count: N (where N is number of args)
* PNK_GENEXP binary Exactly like PNK_CALL, used for the implicit call
* in the desugaring of a generator-expression.
* PNK_ARRAY list pn_head: list of pn_count array element exprs
* [,,] holes are represented by PNK_ELISION nodes
* pn_xflags: PN_ENDCOMMA if extra comma at end
* PNK_OBJECT list pn_head: list of pn_count binary PNK_COLON nodes
* PNK_ARGUMENTS (ListNode)
* head: list of arg1, arg2, ... argN
* count: N >= 0
* PNK_ARRAY (ListNode)
* head: list of N array element expressions
* holes ([,,]) are represented by Elision nodes,
* spread elements ([...X]) are represented by Spread nodes
* count: N >= 0
* PNK_OBJECT (ListNode)
* head: list of N nodes, each item is one of:
* * MutateProto
* * Colon
* * Shorthand
* * Spread
* count: N >= 0
* PNK_COLON binary key-value pair in object initializer or
* destructuring lhs
* pn_left: property id, pn_right: value
@ -435,14 +441,21 @@ IsTypeofKind(ParseNodeKind kind)
* PNK_STRING pn_op: JSOP_GETNAME, JSOP_STRING, or JSOP_OBJECT
* If JSOP_GETNAME, pn_op may be JSOP_*ARG or JSOP_*VAR
* telling const-ness and static analysis results
* PNK_TEMPLATE_STRING_LIST pn_head: list of alternating expr and template strings
* list
* PNK_TEMPLATE_STRING_LIST (ListNode)
* head: list of alternating expr and template strings
* TemplateString [, expression, TemplateString]+
* there's at least one expression. If the template literal contains
* no ${}-delimited expression, it's parsed as a single TemplateString
* PNK_TEMPLATE_STRING pn_atom: template string atom
nullary pn_op: JSOP_NOP
* PNK_TAGGED_TEMPLATE pn_left: tag expression
* binary pn_right: Arguments, with the first being the call site object, then arg1, arg2, ... argN
* PNK_CALLSITEOBJ list pn_head: a PNK_ARRAY node followed by
* list of pn_count - 1 PNK_TEMPLATE_STRING nodes
* PNK_CALLSITEOBJ (CallSiteNode)
* head: an Array of raw TemplateString, then corresponding cooked
* TemplateString nodes
* Array [, cooked TemplateString]+
* where the Array is
* [raw TemplateString]+
* PNK_REGEXP nullary pn_objbox: RegExp model object
* PNK_NUMBER dval pn_dval: double value of numeric literal
* PNK_TRUE, nullary pn_op: JSOp bytecode
@ -483,12 +496,21 @@ enum ParseNodeArity
PN_SCOPE /* lexical scope */
};
#define FOR_EACH_PARSENODE_SUBCLASS(macro) \
macro(ListNode, ListNodeType, asList) \
macro(CallSiteNode, CallSiteNodeType, asCallSite)
class LoopControlStatement;
class BreakStatement;
class ContinueStatement;
class ConditionalExpression;
class PropertyAccess;
#define DECLARE_CLASS(typeName, longTypeName, asMethodName) \
class typeName;
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_CLASS)
#undef DECLARE_CLASS
class ParseNode
{
uint16_t pn_type; /* PNK_* type */
@ -574,10 +596,12 @@ class ParseNode
union {
struct { /* list of next-linked nodes */
private:
friend class ListNode;
ParseNode* head; /* first node in list */
ParseNode** tail; /* ptr to ptr to last node in list */
ParseNode** tail; /* ptr to last node's pn_next in list */
uint32_t count; /* number of nodes in list */
uint32_t xflags; /* see PNX_* below */
uint32_t xflags; /* see ListNode class */
} list;
struct { /* ternary: if, for(;;), ?: */
ParseNode* kid1; /* condition, discriminant, etc. */
@ -624,10 +648,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_head pn_u.list.head
#define pn_tail pn_u.list.tail
#define pn_count pn_u.list.count
#define pn_xflags pn_u.list.xflags
#define pn_kid1 pn_u.ternary.kid1
#define pn_kid2 pn_u.ternary.kid2
#define pn_kid3 pn_u.ternary.kid3
@ -682,13 +702,6 @@ class ParseNode
pn_u.scope.body = body;
}
/* PN_LIST pn_xflags bits. */
#define PNX_FUNCDEFS 0x01 /* contains top-level function statements */
#define PNX_ARRAYHOLESPREAD 0x02 /* one or more of
1. array initialiser has holes
2. array initializer has spread node */
#define PNX_NONCONST 0x04 /* initialiser has non-constants */
bool functionIsHoisted() const {
MOZ_ASSERT(pn_arity == PN_CODE && getKind() == PNK_FUNCTION);
MOZ_ASSERT(isOp(JSOP_LAMBDA) || // lambda, genexpr
@ -738,41 +751,7 @@ class ParseNode
bool isDirectivePrologueMember() const { return pn_prologue; }
// True iff this is a for-in/of loop variable declaration (var/let/const).
bool isForLoopDeclaration() const {
if (isKind(PNK_VAR) || isKind(PNK_LET) || isKind(PNK_CONST)) {
MOZ_ASSERT(isArity(PN_LIST));
MOZ_ASSERT(pn_count > 0);
return true;
}
return false;
}
ParseNode* generatorExpr() const {
MOZ_ASSERT(isKind(PNK_GENEXP));
ParseNode* callee = this->pn_left;
MOZ_ASSERT(callee->isKind(PNK_FUNCTION));
ParseNode* paramsBody = callee->pn_body;
MOZ_ASSERT(paramsBody->isKind(PNK_PARAMSBODY));
ParseNode* body = paramsBody->last();
MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST));
MOZ_ASSERT(body->last()->isKind(PNK_LEXICALSCOPE) ||
body->last()->isKind(PNK_COMPREHENSIONFOR));
return body->last();
}
/*
* Compute a pointer to the last element in a singly-linked list. NB: list
* must be non-empty for correct PN_LAST usage -- this is asserted!
*/
ParseNode* last() const {
MOZ_ASSERT(pn_arity == PN_LIST);
MOZ_ASSERT(pn_count != 0);
return (ParseNode*)(uintptr_t(pn_tail) - offsetof(ParseNode, pn_next));
}
bool isForLoopDeclaration() const;
void initNumber(double value, DecimalPoint decimalPoint) {
MOZ_ASSERT(pn_arity == PN_NULLARY);
@ -781,49 +760,6 @@ class ParseNode
pn_u.number.decimalPoint = decimalPoint;
}
void makeEmpty() {
MOZ_ASSERT(pn_arity == PN_LIST);
pn_head = nullptr;
pn_tail = &pn_head;
pn_count = 0;
pn_xflags = 0;
}
void initList(ParseNode* pn) {
MOZ_ASSERT(pn_arity == PN_LIST);
if (pn->pn_pos.begin < pn_pos.begin)
pn_pos.begin = pn->pn_pos.begin;
pn_pos.end = pn->pn_pos.end;
pn_head = pn;
pn_tail = &pn->pn_next;
pn_count = 1;
pn_xflags = 0;
}
void append(ParseNode* pn) {
MOZ_ASSERT(pn_arity == PN_LIST);
MOZ_ASSERT(pn->pn_pos.begin >= pn_pos.begin);
pn_pos.end = pn->pn_pos.end;
*pn_tail = pn;
pn_tail = &pn->pn_next;
pn_count++;
}
void prepend(ParseNode* pn) {
MOZ_ASSERT(pn_arity == PN_LIST);
pn->pn_next = pn_head;
pn_head = pn;
if (pn_tail == &pn_head)
pn_tail = &pn->pn_next;
pn_count++;
}
void checkListConsistency()
#ifndef DEBUG
{}
#endif
;
enum AllowConstantObjects {
DontAllowObjects = 0,
AllowObjects,
@ -944,8 +880,33 @@ struct TernaryNode : public ParseNode
#endif
};
struct ListNode : public ParseNode
class ListNode : public ParseNode
{
private:
// xflags bits.
// Statement list has top-level function statements.
static constexpr uint32_t hasTopLevelFunctionDeclarationsBit = 0x01;
// One or more of
// * array has holes
// * array has spread node
static constexpr uint32_t hasArrayHoleOrSpreadBit = 0x02;
// Array/Object/Class initializer has non-constants.
// * array has holes
// * array has spread node
// * array has element which is known not to be constant
// * array has no element
// * object/class has __proto__
// * object/class has property which is known not to be constant
// * object/class shorthand property
// * object/class spread property
// * object/class has method
// * object/class has computed property
static constexpr uint32_t hasNonConstInitializerBit = 0x04;
public:
ListNode(ParseNodeKind kind, const TokenPos& pos)
: ParseNode(kind, JSOP_NOP, PN_LIST, pos)
{
@ -961,7 +922,15 @@ struct ListNode : public ParseNode
ListNode(ParseNodeKind kind, JSOp op, ParseNode* kid)
: ParseNode(kind, op, PN_LIST, kid->pn_pos)
{
initList(kid);
if (kid->pn_pos.begin < pn_pos.begin) {
pn_pos.begin = kid->pn_pos.begin;
}
pn_pos.end = kid->pn_pos.end;
pn_u.list.head = kid;
pn_u.list.tail = &kid->pn_next;
pn_u.list.count = 1;
pn_u.list.xflags = 0;
}
static bool test(const ParseNode& node) {
@ -971,8 +940,278 @@ struct ListNode : public ParseNode
#ifdef DEBUG
void dump(int indent);
#endif
ParseNode* head() const {
return pn_u.list.head;
}
ParseNode** tail() const {
return pn_u.list.tail;
}
uint32_t count() const {
return pn_u.list.count;
}
bool empty() const {
return count() == 0;
}
MOZ_MUST_USE bool hasTopLevelFunctionDeclarations() const {
MOZ_ASSERT(isKind(PNK_STATEMENTLIST));
return pn_u.list.xflags & hasTopLevelFunctionDeclarationsBit;
}
MOZ_MUST_USE bool hasArrayHoleOrSpread() const {
MOZ_ASSERT(isKind(PNK_ARRAY));
return pn_u.list.xflags & hasArrayHoleOrSpreadBit;
}
MOZ_MUST_USE bool hasNonConstInitializer() const {
MOZ_ASSERT(isKind(PNK_ARRAY) ||
isKind(PNK_OBJECT) ||
isKind(PNK_CLASSMETHODLIST));
return pn_u.list.xflags & hasNonConstInitializerBit;
}
void setHasTopLevelFunctionDeclarations() {
MOZ_ASSERT(isKind(PNK_STATEMENTLIST));
pn_u.list.xflags |= hasTopLevelFunctionDeclarationsBit;
}
void setHasArrayHoleOrSpread() {
MOZ_ASSERT(isKind(PNK_ARRAY));
pn_u.list.xflags |= hasArrayHoleOrSpreadBit;
}
void setHasNonConstInitializer() {
MOZ_ASSERT(isKind(PNK_ARRAY) ||
isKind(PNK_OBJECT) ||
isKind(PNK_CLASSMETHODLIST));
pn_u.list.xflags |= hasNonConstInitializerBit;
}
void checkConsistency() const
#ifndef DEBUG
{}
#endif
;
/*
* Compute a pointer to the last element in a singly-linked list. NB: list
* must be non-empty -- this is asserted!
*/
ParseNode* last() const {
MOZ_ASSERT(!empty());
//
// ParseNode ParseNode
// +-----+---------+-----+ +-----+---------+-----+
// | ... | pn_next | ... | +-...->| ... | pn_next | ... |
// +-----+---------+-----+ | +-----+---------+-----+
// ^ | | ^ ^
// | +---------------+ | |
// | | tail()
// | |
// head() last()
//
return (ParseNode*)(uintptr_t(tail()) - offsetof(ParseNode, pn_next));
}
void replaceLast(ParseNode* node) {
MOZ_ASSERT(!empty());
pn_pos.end = node->pn_pos.end;
ParseNode* item = head();
ParseNode* lastNode = last();
MOZ_ASSERT(item);
if (item == lastNode) {
pn_u.list.head = node;
} else {
while (item->pn_next != lastNode) {
MOZ_ASSERT(item->pn_next);
item = item->pn_next;
}
item->pn_next = node;
}
pn_u.list.tail = &node->pn_next;
}
void makeEmpty() {
pn_u.list.head = nullptr;
pn_u.list.tail = &pn_u.list.head;
pn_u.list.count = 0;
pn_u.list.xflags = 0;
}
void append(ParseNode* item) {
MOZ_ASSERT(item->pn_pos.begin >= pn_pos.begin);
pn_pos.end = item->pn_pos.end;
*pn_u.list.tail = item;
pn_u.list.tail = &item->pn_next;
pn_u.list.count++;
}
void prepend(ParseNode* item) {
item->pn_next = pn_u.list.head;
pn_u.list.head = item;
if (pn_u.list.tail == &pn_u.list.head) {
pn_u.list.tail = &item->pn_next;
}
pn_u.list.count++;
}
// Methods used by FoldConstants.cpp.
// Caller is responsible for keeping the list consistent.
ParseNode** unsafeHeadReference() {
return &pn_u.list.head;
}
void unsafeReplaceTail(ParseNode** newTail) {
pn_u.list.tail = newTail;
checkConsistency();
}
void unsafeSetTail(ParseNode* newTail) {
*pn_u.list.tail = newTail;
}
void unsafeDecrementCount() {
MOZ_ASSERT(count() > 1);
pn_u.list.count--;
}
private:
// Classes to iterate over ListNode contents:
//
// Usage:
// ListNode* list;
// for (ParseNode* item : list->contents()) {
// // item is ParseNode* typed.
// }
class iterator
{
private:
ParseNode* node_;
friend class ListNode;
explicit iterator(ParseNode* node)
: node_(node)
{}
public:
bool operator==(const iterator& other) const {
return node_ == other.node_;
}
bool operator!=(const iterator& other) const {
return !(*this == other);
}
iterator& operator++() {
node_ = node_->pn_next;
return *this;
}
ParseNode* operator*() {
return node_;
}
const ParseNode* operator*() const {
return node_;
}
};
class range
{
private:
ParseNode* begin_;
ParseNode* end_;
friend class ListNode;
range(ParseNode* begin, ParseNode* end)
: begin_(begin),
end_(end)
{}
public:
iterator begin() {
return iterator(begin_);
}
iterator end() {
return iterator(end_);
}
const iterator begin() const {
return iterator(begin_);
}
const iterator end() const {
return iterator(end_);
}
const iterator cbegin() const {
return begin();
}
const iterator cend() const {
return end();
}
};
#ifdef DEBUG
MOZ_MUST_USE bool contains(ParseNode* target) const {
MOZ_ASSERT(target);
for (ParseNode* node : contents()) {
if (target == node) {
return true;
}
}
return false;
}
#endif
public:
range contents() {
return range(head(), nullptr);
}
const range contents() const {
return range(head(), nullptr);
}
range contentsFrom(ParseNode* begin) {
MOZ_ASSERT_IF(begin, contains(begin));
return range(begin, nullptr);
}
const range contentsFrom(ParseNode* begin) const {
MOZ_ASSERT_IF(begin, contains(begin));
return range(begin, nullptr);
}
range contentsTo(ParseNode* end) {
MOZ_ASSERT_IF(end, contains(end));
return range(head(), end);
}
const range contentsTo(ParseNode* end) const {
MOZ_ASSERT_IF(end, contains(end));
return range(head(), end);
}
};
inline bool
ParseNode::isForLoopDeclaration() const
{
if (isKind(PNK_VAR) || isKind(PNK_LET) || isKind(PNK_CONST)) {
MOZ_ASSERT(!as<ListNode>().empty());
return true;
}
return false;
}
struct CodeNode : public ParseNode
{
CodeNode(ParseNodeKind kind, JSOp op, const TokenPos& pos)
@ -1066,10 +1305,7 @@ class CaseClause : public BinaryNode
ParseNode* caseExpression() const { return pn_left; }
bool isDefault() const { return !caseExpression(); }
ParseNode* statementList() const { return pn_right; }
// The next CaseClause in the same switch statement.
CaseClause* next() const { return pn_next ? &pn_next->as<CaseClause>() : nullptr; }
ListNode* statementList() const { return &pn_right->as<ListNode>(); }
static bool test(const ParseNode& node) {
bool match = node.isKind(PNK_CASE);
@ -1363,15 +1599,24 @@ class OptionalPropertyByValue : public PropertyByValueBase {
/*
* A CallSiteNode represents the implicit call site object argument in a TaggedTemplate.
*/
struct CallSiteNode : public ListNode {
class CallSiteNode : public ListNode
{
public:
explicit CallSiteNode(uint32_t begin): ListNode(PNK_CALLSITEOBJ, TokenPos(begin, begin + 1)) {}
static bool test(const ParseNode& node) {
return node.isKind(PNK_CALLSITEOBJ);
bool match = node.isKind(PNK_CALLSITEOBJ);
MOZ_ASSERT_IF(match, node.is<ListNode>());
return match;
}
MOZ_MUST_USE bool getRawArrayValue(ExclusiveContext* cx, MutableHandleValue vp) {
return pn_head->getConstantValue(cx, AllowObjects, vp);
return head()->getConstantValue(cx, AllowObjects, vp);
}
ListNode* rawNodes() const {
MOZ_ASSERT(head());
return &head()->as<ListNode>();
}
};
@ -1412,11 +1657,11 @@ struct SwitchStatement : public BinaryNode {
{
#ifdef DEBUG
MOZ_ASSERT(lexicalForCaseList->isKind(PNK_LEXICALSCOPE));
ParseNode* cases = lexicalForCaseList->scopeBody();
ListNode* cases = &lexicalForCaseList->scopeBody()->as<ListNode>();
MOZ_ASSERT(cases->isKind(PNK_STATEMENTLIST));
bool found = false;
CaseClause* firstCase = cases->pn_head ? &cases->pn_head->as<CaseClause>() : nullptr;
for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
for (ParseNode* item : cases->contents()) {
CaseClause* caseNode = &item->as<CaseClause>();
if (caseNode->isDefault()) {
found = true;
break;
@ -1498,12 +1743,12 @@ struct ClassNode : public TernaryNode {
ParseNode* heritage() const {
return pn_kid2;
}
ParseNode* methodList() const {
ListNode* methodList() const {
if (pn_kid3->isKind(PNK_CLASSMETHODLIST))
return pn_kid3;
return &pn_kid3->as<ListNode>();
MOZ_ASSERT(pn_kid3->is<LexicalScopeNode>());
ParseNode* list = pn_kid3->scopeBody();
ListNode* list = &pn_kid3->scopeBody()->as<ListNode>();
MOZ_ASSERT(list->isKind(PNK_CLASSMETHODLIST));
return list;
}
@ -1550,7 +1795,7 @@ ParseNode::isConstant()
case PNK_ARRAY:
case PNK_OBJECT:
MOZ_ASSERT(isOp(JSOP_NEWINIT));
return !(pn_xflags & PNX_NONCONST);
return !as<ListNode>().hasNonConstInitializer();
default:
return false;
}
@ -1628,17 +1873,16 @@ static inline ParseNode*
FunctionFormalParametersList(ParseNode* fn, unsigned* numFormals)
{
MOZ_ASSERT(fn->isKind(PNK_FUNCTION));
ParseNode* argsBody = fn->pn_body;
ListNode* argsBody = &fn->pn_body->as<ListNode>();
MOZ_ASSERT(argsBody->isKind(PNK_PARAMSBODY));
*numFormals = argsBody->pn_count;
*numFormals = argsBody->count();
if (*numFormals > 0 &&
argsBody->last()->isKind(PNK_LEXICALSCOPE) &&
argsBody->last()->scopeBody()->isKind(PNK_STATEMENTLIST))
{
(*numFormals)--;
}
MOZ_ASSERT(argsBody->isArity(PN_LIST));
return argsBody->pn_head;
return argsBody->head();
}
bool

View file

@ -969,7 +969,7 @@ MarkParser(JSTracer* trc, AutoGCRooter* parser)
* Parse a top-level JS script.
*/
template <typename ParseHandler>
typename ParseHandler::Node
typename ParseHandler::ListNodeType
Parser<ParseHandler>::parse()
{
MOZ_ASSERT(checkOptionsCalled);
@ -985,8 +985,8 @@ Parser<ParseHandler>::parse()
if (!varScope.init(pc))
return null();
Node pn = statementList(YieldIsName);
if (!pn)
ListNodeType stmtList = statementList(YieldIsName);
if (!stmtList)
return null();
TokenKind tt;
@ -997,11 +997,14 @@ Parser<ParseHandler>::parse()
return null();
}
if (foldConstants) {
if (!FoldConstants(context, &pn, this))
Node node = stmtList;
if (!FoldConstants(context, &node, this)) {
return null();
}
stmtList = handler.asList(node);
}
return pn;
return stmtList;
}
/*
@ -2179,7 +2182,7 @@ Parser<FullParseHandler>::evalBody(EvalSharedContext* evalsc)
}
template <>
ParseNode*
ListNode*
Parser<FullParseHandler>::globalBody(GlobalSharedContext* globalsc)
{
ParseContext globalpc(this, globalsc, /* newDirectives = */ nullptr);
@ -2190,15 +2193,18 @@ Parser<FullParseHandler>::globalBody(GlobalSharedContext* globalsc)
if (!varScope.init(pc))
return nullptr;
ParseNode* body = statementList(YieldIsName);
ListNode* body = statementList(YieldIsName);
if (!body)
return nullptr;
if (!checkStatementsEOF())
return nullptr;
if (!FoldConstants(context, &body, this))
return nullptr;
ParseNode* node = body;
if (!FoldConstants(context, &node, this)) {
return null();
}
body = &node->as<ListNode>();
Maybe<GlobalScope::Data*> bindings = newGlobalScopeData(pc->varScope());
if (!bindings)
@ -2227,12 +2233,13 @@ Parser<FullParseHandler>::moduleBody(ModuleSharedContext* modulesc)
return null();
AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, true);
ParseNode* pn = statementList(YieldIsKeyword);
if (!pn)
ListNode* stmtList = statementList(YieldIsName);
if (!stmtList) {
return null();
}
MOZ_ASSERT(pn->isKind(PNK_STATEMENTLIST));
mn->pn_body = pn;
MOZ_ASSERT(stmtList->isKind(PNK_STATEMENTLIST));
mn->pn_body = stmtList;
TokenKind tt;
if (!tokenStream.getToken(&tt, TokenStream::Operand))
@ -2264,8 +2271,11 @@ Parser<FullParseHandler>::moduleBody(ModuleSharedContext* modulesc)
p->value()->setClosedOver();
}
if (!FoldConstants(context, &pn, this))
ParseNode* node = stmtList;
if (!FoldConstants(context, &node, this)) {
return null();
}
stmtList = &node->as<ListNode>();
if (!propagateFreeNamesAndMarkClosedOverBindings(modulepc.varScope()))
return null();
@ -2536,7 +2546,7 @@ Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
if (!fn)
return null();
ParseNode* argsbody = handler.newList(PNK_PARAMSBODY);
ListNodeType argsbody = handler.newList(PNK_PARAMSBODY);
if (!argsbody)
return null();
fn->pn_body = argsbody;
@ -2662,11 +2672,11 @@ Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHan
uint32_t startYieldOffset = pc->lastYieldOffset;
#endif
Node pn;
Node body;
if (type == StatementListBody) {
bool inheritedStrict = pc->sc()->strict();
pn = statementList(yieldHandling);
if (!pn)
body = statementList(yieldHandling);
if (!body)
return null();
// When we transitioned from non-strict to strict mode, we need to
@ -2687,7 +2697,7 @@ Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHan
// Async functions are implemented as star generators, and star
// generators are assumed to be statement lists, to prepend initial
// `yield`.
Node stmtList = null();
ListNodeType stmtList = null();
if (pc->isAsync()) {
stmtList = handler.newStatementList(pos());
if (!stmtList)
@ -2698,13 +2708,13 @@ Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHan
if (!kid)
return null();
pn = handler.newReturnStatement(kid, handler.getPosition(kid));
if (!pn)
body = handler.newReturnStatement(kid, handler.getPosition(kid));
if (!body)
return null();
if (pc->isAsync()) {
handler.addStatementToList(stmtList, pn);
pn = stmtList;
handler.addStatementToList(stmtList, body);
body = stmtList;
}
}
@ -2738,7 +2748,7 @@ Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHan
Node generator = newDotGeneratorName();
if (!generator)
return null();
if (!handler.prependInitialYield(pn, generator))
if (!handler.prependInitialYield(handler.asList(body), generator))
return null();
}
@ -2752,7 +2762,7 @@ Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHan
return null();
}
return finishLexicalScope(pc->varScope(), pn);
return finishLexicalScope(pc->varScope(), body);
}
template <typename ParseHandler>
@ -3000,7 +3010,7 @@ Parser<ParseHandler>::functionArguments(YieldHandling yieldHandling, FunctionSyn
funbox->setStart(tokenStream);
}
Node argsbody = handler.newList(PNK_PARAMSBODY);
ListNodeType argsbody = handler.newList(PNK_PARAMSBODY);
if (!argsbody)
return false;
handler.setFunctionFormalParametersAndBody(funcpn, argsbody);
@ -3259,7 +3269,7 @@ Parser<SyntaxParseHandler>::skipLazyInnerFunction(Node pn, uint32_t toStringStar
template <typename ParseHandler>
bool
Parser<ParseHandler>::addExprAndGetNextTemplStrToken(YieldHandling yieldHandling, Node nodeList,
Parser<ParseHandler>::addExprAndGetNextTemplStrToken(YieldHandling yieldHandling, ListNodeType nodeList,
TokenKind* ttp)
{
Node pn = expr(InAllowed, yieldHandling, TripledotProhibited);
@ -3280,9 +3290,9 @@ Parser<ParseHandler>::addExprAndGetNextTemplStrToken(YieldHandling yieldHandling
template <typename ParseHandler>
bool
Parser<ParseHandler>::taggedTemplate(YieldHandling yieldHandling, Node tagArgsList, TokenKind tt)
Parser<ParseHandler>::taggedTemplate(YieldHandling yieldHandling, ListNodeType tagArgsList, TokenKind tt)
{
Node callSiteObjNode = handler.newCallSiteObject(pos().begin);
CallSiteNodeType callSiteObjNode = handler.newCallSiteObject(pos().begin);
if (!callSiteObjNode)
return false;
handler.addList(tagArgsList, callSiteObjNode);
@ -3301,14 +3311,14 @@ Parser<ParseHandler>::taggedTemplate(YieldHandling yieldHandling, Node tagArgsLi
}
template <typename ParseHandler>
typename ParseHandler::Node
typename ParseHandler::ListNodeType
Parser<ParseHandler>::templateLiteral(YieldHandling yieldHandling)
{
Node pn = noSubstitutionUntaggedTemplate();
if (!pn)
return null();
Node nodeList = handler.newList(PNK_TEMPLATE_STRING_LIST, pn);
ListNodeType nodeList = handler.newList(PNK_TEMPLATE_STRING_LIST, pn);
if (!nodeList)
return null();
@ -3543,7 +3553,7 @@ Parser<ParseHandler>::innerFunction(Node pn, ParseContext* outerpc, HandleFuncti
template <typename ParseHandler>
bool
Parser<ParseHandler>::appendToCallSiteObj(Node callSiteObj)
Parser<ParseHandler>::appendToCallSiteObj(CallSiteNodeType callSiteObj)
{
Node cookedNode = noSubstitutionTaggedTemplate();
if (!cookedNode)
@ -3914,7 +3924,7 @@ IsEscapeFreeStringLiteral(const TokenPos& pos, JSAtom* str)
template <>
bool
Parser<SyntaxParseHandler>::asmJS(Node list)
Parser<SyntaxParseHandler>::asmJS(ListNodeType list)
{
// While asm.js could technically be validated and compiled during syntax
// parsing, we have no guarantee that some later JS wouldn't abort the
@ -3928,7 +3938,7 @@ Parser<SyntaxParseHandler>::asmJS(Node list)
template <>
bool
Parser<FullParseHandler>::asmJS(Node list)
Parser<FullParseHandler>::asmJS(ListNodeType list)
{
// Disable syntax parsing in anything nested inside the asm.js module.
handler.disableSyntaxParser();
@ -3984,7 +3994,7 @@ Parser<FullParseHandler>::asmJS(Node list)
*/
template <typename ParseHandler>
bool
Parser<ParseHandler>::maybeParseDirective(Node list, Node possibleDirective, bool* cont)
Parser<ParseHandler>::maybeParseDirective(ListNodeType list, Node possibleDirective, bool* cont)
{
TokenPos directivePos;
JSAtom* directive = handler.isStringExprStatement(possibleDirective, &directivePos);
@ -4046,13 +4056,13 @@ Parser<ParseHandler>::maybeParseDirective(Node list, Node possibleDirective, boo
}
template <typename ParseHandler>
typename ParseHandler::Node
typename ParseHandler::ListNodeType
Parser<ParseHandler>::statementList(YieldHandling yieldHandling)
{
JS_CHECK_RECURSION(context, return null());
Node pn = handler.newStatementList(pos());
if (!pn)
ListNodeType stmtList = handler.newStatementList(pos());
if (!stmtList)
return null();
bool canHaveDirectives = pc->atBodyLevel();
@ -4094,14 +4104,14 @@ Parser<ParseHandler>::statementList(YieldHandling yieldHandling)
}
if (canHaveDirectives) {
if (!maybeParseDirective(pn, next, &canHaveDirectives))
if (!maybeParseDirective(stmtList, next, &canHaveDirectives))
return null();
}
handler.addStatementToList(pn, next);
handler.addStatementToList(stmtList, next);
}
return pn;
return stmtList;
}
template <typename ParseHandler>
@ -4357,7 +4367,7 @@ Parser<ParseHandler>::bindingIdentifierOrPattern(DeclarationKind kind, YieldHand
}
template <typename ParseHandler>
typename ParseHandler::Node
typename ParseHandler::ListNodeType
Parser<ParseHandler>::objectBindingPattern(DeclarationKind kind, YieldHandling yieldHandling)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
@ -4365,7 +4375,7 @@ Parser<ParseHandler>::objectBindingPattern(DeclarationKind kind, YieldHandling y
JS_CHECK_RECURSION(context, return null());
uint32_t begin = pos().begin;
Node literal = handler.newObjectLiteral(begin);
ListNodeType literal = handler.newObjectLiteral(begin);
if (!literal)
return null();
@ -4477,7 +4487,7 @@ Parser<ParseHandler>::objectBindingPattern(DeclarationKind kind, YieldHandling y
}
template <typename ParseHandler>
typename ParseHandler::Node
typename ParseHandler::ListNodeType
Parser<ParseHandler>::arrayBindingPattern(DeclarationKind kind, YieldHandling yieldHandling)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LB));
@ -4485,7 +4495,7 @@ Parser<ParseHandler>::arrayBindingPattern(DeclarationKind kind, YieldHandling yi
JS_CHECK_RECURSION(context, return null());
uint32_t begin = pos().begin;
Node literal = handler.newArrayLiteral(begin);
ListNodeType literal = handler.newArrayLiteral(begin);
if (!literal)
return null();
@ -4611,7 +4621,7 @@ Parser<ParseHandler>::blockStatement(YieldHandling yieldHandling, unsigned error
if (!scope.init(pc))
return null();
Node list = statementList(yieldHandling);
ListNodeType list = statementList(yieldHandling);
if (!list)
return null();
@ -4871,7 +4881,7 @@ Parser<ParseHandler>::declarationName(Node decl, DeclarationKind declKind, Token
}
template <typename ParseHandler>
typename ParseHandler::Node
typename ParseHandler::ListNodeType
Parser<ParseHandler>::declarationList(YieldHandling yieldHandling,
ParseNodeKind kind,
ParseNodeKind* forHeadKind /* = nullptr */,
@ -4898,7 +4908,7 @@ Parser<ParseHandler>::declarationList(YieldHandling yieldHandling,
MOZ_CRASH("Unknown declaration kind");
}
Node decl = handler.newDeclarationList(kind, op);
ListNodeType decl = handler.newDeclarationList(kind, op);
if (!decl)
return null();
@ -4935,7 +4945,7 @@ Parser<ParseHandler>::declarationList(YieldHandling yieldHandling,
}
template <typename ParseHandler>
typename ParseHandler::Node
typename ParseHandler::ListNodeType
Parser<ParseHandler>::lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind)
{
MOZ_ASSERT(kind == DeclarationKind::Const || kind == DeclarationKind::Let);
@ -4951,8 +4961,8 @@ Parser<ParseHandler>::lexicalDeclaration(YieldHandling yieldHandling, Declaratio
*
* See 8.1.1.1.6 and the note in 13.2.1.
*/
Node decl = declarationList(yieldHandling,
kind == DeclarationKind::Const ? PNK_CONST : PNK_LET);
ListNodeType decl = declarationList(yieldHandling,
kind == DeclarationKind::Const ? PNK_CONST : PNK_LET);
if (!decl || !matchOrInsertSemicolonAfterExpression())
return null();
@ -4961,7 +4971,7 @@ Parser<ParseHandler>::lexicalDeclaration(YieldHandling yieldHandling, Declaratio
template <>
bool
Parser<FullParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet)
Parser<FullParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, ListNodeType importSpecSet)
{
if (tt == TOK_LC) {
while (true) {
@ -5092,7 +5102,7 @@ Parser<FullParseHandler>::importDeclaration()
if (!tokenStream.getToken(&tt))
return null();
Node importSpecSet = handler.newList(PNK_IMPORT_SPEC_LIST);
ListNodeType importSpecSet = handler.newList(PNK_IMPORT_SPEC_LIST);
if (!importSpecSet)
return null();
@ -5204,12 +5214,11 @@ Parser<SyntaxParseHandler>::checkExportedName(JSAtom* exportName)
template<>
bool
Parser<FullParseHandler>::checkExportedNamesForArrayBinding(ParseNode* pn)
Parser<FullParseHandler>::checkExportedNamesForArrayBinding(ListNode* array)
{
MOZ_ASSERT(pn->isKind(PNK_ARRAY));
MOZ_ASSERT(pn->isArity(PN_LIST));
MOZ_ASSERT(array->isKind(PNK_ARRAY));
for (ParseNode* node = pn->pn_head; node; node = node->pn_next) {
for (ParseNode* node : array->contents()) {
if (node->isKind(PNK_ELISION))
continue;
@ -5230,7 +5239,7 @@ Parser<FullParseHandler>::checkExportedNamesForArrayBinding(ParseNode* pn)
template<>
inline bool
Parser<SyntaxParseHandler>::checkExportedNamesForArrayBinding(Node node)
Parser<SyntaxParseHandler>::checkExportedNamesForArrayBinding(ListNodeType array)
{
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
return false;
@ -5238,12 +5247,11 @@ Parser<SyntaxParseHandler>::checkExportedNamesForArrayBinding(Node node)
template<>
bool
Parser<FullParseHandler>::checkExportedNamesForObjectBinding(ParseNode* pn)
Parser<FullParseHandler>::checkExportedNamesForObjectBinding(ListNode* obj)
{
MOZ_ASSERT(pn->isKind(PNK_OBJECT));
MOZ_ASSERT(pn->isArity(PN_LIST));
MOZ_ASSERT(obj->isKind(PNK_OBJECT));
for (ParseNode* node = pn->pn_head; node; node = node->pn_next) {
for (ParseNode* node : obj->contents()) {
MOZ_ASSERT(node->isKind(PNK_MUTATEPROTO) ||
node->isKind(PNK_COLON) ||
node->isKind(PNK_SHORTHAND) ||
@ -5271,7 +5279,7 @@ Parser<FullParseHandler>::checkExportedNamesForObjectBinding(ParseNode* pn)
template<>
inline bool
Parser<SyntaxParseHandler>::checkExportedNamesForObjectBinding(Node node)
Parser<SyntaxParseHandler>::checkExportedNamesForObjectBinding(ListNodeType obj)
{
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
return false;
@ -5285,11 +5293,11 @@ Parser<FullParseHandler>::checkExportedNamesForDeclaration(ParseNode* node)
if (!checkExportedName(node->pn_atom))
return false;
} else if (node->isKind(PNK_ARRAY)) {
if (!checkExportedNamesForArrayBinding(node))
if (!checkExportedNamesForArrayBinding(&node->as<ListNode>()))
return false;
} else {
MOZ_ASSERT(node->isKind(PNK_OBJECT));
if (!checkExportedNamesForObjectBinding(node))
if (!checkExportedNamesForObjectBinding(&node->as<ListNode>()))
return false;
}
@ -5306,10 +5314,9 @@ Parser<SyntaxParseHandler>::checkExportedNamesForDeclaration(Node node)
template<>
bool
Parser<FullParseHandler>::checkExportedNamesForDeclarationList(ParseNode* node)
Parser<FullParseHandler>::checkExportedNamesForDeclarationList(ListNode* node)
{
MOZ_ASSERT(node->isArity(PN_LIST));
for (ParseNode* binding = node->pn_head; binding; binding = binding->pn_next) {
for (ParseNode* binding : node->contents()) {
if (binding->isKind(PNK_ASSIGN))
binding = binding->pn_left;
else
@ -5324,7 +5331,7 @@ Parser<FullParseHandler>::checkExportedNamesForDeclarationList(ParseNode* node)
template<>
bool
Parser<SyntaxParseHandler>::checkExportedNamesForDeclarationList(Node node)
Parser<SyntaxParseHandler>::checkExportedNamesForDeclarationList(ListNodeType node)
{
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
return false;
@ -5447,7 +5454,7 @@ Parser<ParseHandler>::exportBatch(uint32_t begin)
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_MUL));
Node kid = handler.newList(PNK_EXPORT_SPEC_LIST);
ListNodeType kid = handler.newList(PNK_EXPORT_SPEC_LIST);
if (!kid)
return null();
@ -5466,10 +5473,10 @@ Parser<ParseHandler>::exportBatch(uint32_t begin)
template<>
bool
Parser<FullParseHandler>::checkLocalExportNames(ParseNode* node)
Parser<FullParseHandler>::checkLocalExportNames(ListNode* node)
{
// ES 2017 draft 15.2.3.1.
for (ParseNode* next = node->pn_head; next; next = next->pn_next) {
for (ParseNode* next : node->contents()) {
ParseNode* name = next->pn_left;
MOZ_ASSERT(name->isKind(PNK_NAME));
@ -5483,7 +5490,7 @@ Parser<FullParseHandler>::checkLocalExportNames(ParseNode* node)
template<>
bool
Parser<SyntaxParseHandler>::checkLocalExportNames(Node node)
Parser<SyntaxParseHandler>::checkLocalExportNames(ListNodeType node)
{
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
return false;
@ -5498,7 +5505,7 @@ Parser<ParseHandler>::exportClause(uint32_t begin)
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
Node kid = handler.newList(PNK_EXPORT_SPEC_LIST);
ListNodeType kid = handler.newList(PNK_EXPORT_SPEC_LIST);
if (!kid)
return null();
@ -5598,7 +5605,7 @@ Parser<ParseHandler>::exportVariableStatement(uint32_t begin)
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_VAR));
Node kid = declarationList(YieldIsName, PNK_VAR);
ListNodeType kid = declarationList(YieldIsName, PNK_VAR);
if (!kid)
return null();
if (!matchOrInsertSemicolonAfterExpression())
@ -5679,7 +5686,7 @@ Parser<ParseHandler>::exportLexicalDeclaration(uint32_t begin, DeclarationKind k
MOZ_ASSERT_IF(kind == DeclarationKind::Const, tokenStream.isCurrentTokenType(TOK_CONST));
MOZ_ASSERT_IF(kind == DeclarationKind::Let, tokenStream.isCurrentTokenType(TOK_LET));
Node kid = lexicalDeclaration(YieldIsName, kind);
ListNodeType kid = lexicalDeclaration(YieldIsName, kind);
if (!kid)
return null();
if (!checkExportedNamesForDeclarationList(kid))
@ -5947,7 +5954,7 @@ Parser<ParseHandler>::consequentOrAlternative(YieldHandling yieldHandling)
if (!fun)
return null();
Node block = handler.newStatementList(funcPos);
ListNodeType block = handler.newStatementList(funcPos);
if (!block)
return null();
@ -6436,7 +6443,7 @@ Parser<ParseHandler>::switchStatement(YieldHandling yieldHandling)
if (!scope.init(pc))
return null();
Node caseList = handler.newStatementList(pos());
ListNodeType caseList = handler.newStatementList(pos());
if (!caseList)
return null();
@ -6473,7 +6480,7 @@ Parser<ParseHandler>::switchStatement(YieldHandling yieldHandling)
MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE);
Node body = handler.newStatementList(pos());
ListNodeType body = handler.newStatementList(pos());
if (!body)
return null();
@ -6513,13 +6520,13 @@ Parser<ParseHandler>::switchStatement(YieldHandling yieldHandling)
handler.addCaseStatementToList(caseList, casepn);
}
caseList = finishLexicalScope(scope, caseList);
if (!caseList)
Node lexicalForCaseList = finishLexicalScope(scope, caseList);
if (!lexicalForCaseList)
return null();
handler.setEndPosition(caseList, pos().end);
handler.setEndPosition(lexicalForCaseList, pos().end);
return handler.newSwitchStatement(begin, discriminant, caseList, seenDefault);
return handler.newSwitchStatement(begin, discriminant, lexicalForCaseList, seenDefault);
}
template <typename ParseHandler>
@ -6989,7 +6996,7 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
}
bool hasUnconditionalCatch = false;
Node catchList = null();
ListNodeType catchList = null();
TokenKind tt;
if (!tokenStream.getToken(&tt))
return null();
@ -7158,7 +7165,7 @@ Parser<ParseHandler>::catchBlockStatement(YieldHandling yieldHandling,
if (!scope.addCatchParameters(pc, catchParamScope))
return null();
Node list = statementList(yieldHandling);
ListNodeType list = statementList(yieldHandling);
if (!list)
return null();
@ -7281,7 +7288,7 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling,
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_CLASS);
Node classMethods = handler.newClassMethodList(pos().begin);
ListNodeType classMethods = handler.newClassMethodList(pos().begin);
if (!classMethods)
return null();
@ -7494,7 +7501,7 @@ template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::variableStatement(YieldHandling yieldHandling)
{
Node vars = declarationList(yieldHandling, PNK_VAR);
ListNodeType vars = declarationList(yieldHandling, PNK_VAR);
if (!vars)
return null();
if (!matchOrInsertSemicolonAfterExpression())
@ -7909,7 +7916,7 @@ Parser<ParseHandler>::expr(InHandling inHandling, YieldHandling yieldHandling,
if (!matched)
return pn;
Node seq = handler.newCommaExpressionList(pn);
ListNodeType seq = handler.newCommaExpressionList(pn);
if (!seq)
return null();
while (true) {
@ -8815,7 +8822,7 @@ Parser<ParseHandler>::generatorComprehensionLambda(unsigned begin)
if (!declareDotGeneratorName())
return null();
Node body = handler.newStatementList(TokenPos(begin, pos().end));
ListNodeType body = handler.newStatementList(TokenPos(begin, pos().end));
if (!body)
return null();
@ -9014,7 +9021,7 @@ Parser<ParseHandler>::comprehension(GeneratorKind comprehensionKind)
}
template <typename ParseHandler>
typename ParseHandler::Node
typename ParseHandler::ListNodeType
Parser<ParseHandler>::arrayComprehension(uint32_t begin)
{
Node inner = comprehension(NotGenerator);
@ -9023,7 +9030,7 @@ Parser<ParseHandler>::arrayComprehension(uint32_t begin)
MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_ARRAY_COMPREHENSION);
Node comp = handler.newList(PNK_ARRAYCOMP, inner);
ListNodeType comp = handler.newList(PNK_ARRAYCOMP, inner);
if (!comp)
return null();
@ -9086,11 +9093,11 @@ Parser<ParseHandler>::assignExprWithoutYieldOrAwait(YieldHandling yieldHandling)
}
template <typename ParseHandler>
typename ParseHandler::Node
typename ParseHandler::ListNodeType
Parser<ParseHandler>::argumentList(YieldHandling yieldHandling, bool* isSpread,
PossibleError* possibleError /* = nullptr */)
{
Node argsList = handler.newArguments(pos());
ListNodeType argsList = handler.newArguments(pos());
if (!argsList)
return null();
@ -9473,7 +9480,7 @@ Parser<ParseHandler>::memberCall(
if (!nextMember)
return null();
} else {
Node args = handler.newArguments(pos());
ListNodeType args = handler.newArguments(pos());
if (!args)
return null();
@ -9752,13 +9759,13 @@ Parser<ParseHandler>::checkDestructuringAssignmentElement(Node expr, TokenPos ex
}
template <typename ParseHandler>
typename ParseHandler::Node
typename ParseHandler::ListNodeType
Parser<ParseHandler>::arrayInitializer(YieldHandling yieldHandling, PossibleError* possibleError)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LB));
uint32_t begin = pos().begin;
Node literal = handler.newArrayLiteral(begin);
ListNodeType literal = handler.newArrayLiteral(begin);
if (!literal)
return null();
@ -9775,7 +9782,7 @@ Parser<ParseHandler>::arrayInitializer(YieldHandling yieldHandling, PossibleErro
* Mark empty arrays as non-constant, since we cannot easily
* determine their type.
*/
handler.setListFlag(literal, PNX_NONCONST);
handler.setListHasNonConstInitializer(literal);
} else {
tokenStream.ungetToken();
@ -9861,7 +9868,7 @@ DoubleToAtom(ExclusiveContext* cx, double value)
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::propertyName(YieldHandling yieldHandling,
const Maybe<DeclarationKind>& maybeDecl, Node propList,
const Maybe<DeclarationKind>& maybeDecl, ListNodeType propList,
PropertyType* propType, MutableHandleAtom propAtom)
{
TokenKind ltok;
@ -10054,7 +10061,7 @@ template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::computedPropertyName(YieldHandling yieldHandling,
const Maybe<DeclarationKind>& maybeDecl,
Node literal)
ListNodeType literal)
{
uint32_t begin = pos().begin;
@ -10062,7 +10069,7 @@ Parser<ParseHandler>::computedPropertyName(YieldHandling yieldHandling,
if (*maybeDecl == DeclarationKind::FormalParameter)
pc->functionBox()->hasParameterExprs = true;
} else {
handler.setListFlag(literal, PNX_NONCONST);
handler.setListHasNonConstInitializer(literal);
}
Node assignNode = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
@ -10074,14 +10081,14 @@ Parser<ParseHandler>::computedPropertyName(YieldHandling yieldHandling,
}
template <typename ParseHandler>
typename ParseHandler::Node
typename ParseHandler::ListNodeType
Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
uint32_t openedPos = pos().begin;
Node literal = handler.newObjectLiteral(pos().begin);
ListNodeType literal = handler.newObjectLiteral(pos().begin);
if (!literal)
return null();
@ -10164,7 +10171,7 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
return null();
} else {
if (!handler.isConstant(propExpr))
handler.setListFlag(literal, PNX_NONCONST);
handler.setListHasNonConstInitializer(literal);
if (!handler.addPropertyDefinition(literal, propName, propExpr))
return null();

View file

@ -903,6 +903,11 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
private:
using Node = typename ParseHandler::Node;
#define DECLARE_TYPE(typeName, longTypeName, asMethodName) \
using longTypeName = typename ParseHandler::longTypeName;
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
#undef DECLARE_TYPE
/*
* A class for temporarily stashing errors while parsing continues.
*
@ -1073,7 +1078,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
/*
* Parse a top-level JS script.
*/
Node parse();
ListNodeType parse();
/*
* Allocate a new parsed object or function container from
@ -1103,10 +1108,10 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
Node stringLiteral();
Node noSubstitutionTaggedTemplate();
Node noSubstitutionUntaggedTemplate();
Node templateLiteral(YieldHandling yieldHandling);
bool taggedTemplate(YieldHandling yieldHandling, Node nodeList, TokenKind tt);
bool appendToCallSiteObj(Node callSiteObj);
bool addExprAndGetNextTemplStrToken(YieldHandling yieldHandling, Node nodeList,
ListNodeType templateLiteral(YieldHandling yieldHandling);
bool taggedTemplate(YieldHandling yieldHandling, ListNodeType tagArgsList, TokenKind tt);
bool appendToCallSiteObj(CallSiteNodeType callSiteObj);
bool addExprAndGetNextTemplStrToken(YieldHandling yieldHandling, ListNodeType nodeList,
TokenKind* ttp);
bool checkStatementsEOF();
@ -1120,7 +1125,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
Node statement(YieldHandling yieldHandling);
Node statementListItem(YieldHandling yieldHandling, bool canHaveDirectives = false);
bool maybeParseDirective(Node list, Node pn, bool* cont);
bool maybeParseDirective(ListNodeType list, Node pn, bool* cont);
// Parse the body of an eval.
//
@ -1130,7 +1135,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
Node evalBody(EvalSharedContext* evalsc);
// Parse the body of a global script.
Node globalBody(GlobalSharedContext* globalsc);
ListNodeType globalBody(GlobalSharedContext* globalsc);
// Parse a module.
Node moduleBody(ModuleSharedContext* modulesc);
@ -1189,7 +1194,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
Node functionExpr(uint32_t toStringStart, InvokedPrediction invoked = PredictUninvoked,
FunctionAsyncKind asyncKind = SyncFunction);
Node statementList(YieldHandling yieldHandling);
ListNodeType statementList(YieldHandling yieldHandling);
Node blockStatement(YieldHandling yieldHandling,
unsigned errorNumber = JSMSG_CURLY_IN_COMPOUND);
@ -1228,7 +1233,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
// continues a LexicalDeclaration.
bool nextTokenContinuesLetDeclaration(TokenKind next, YieldHandling yieldHandling);
Node lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind);
ListNodeType lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind);
Node importDeclaration();
@ -1237,7 +1242,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
Node exportFrom(uint32_t begin, Node specList);
Node exportBatch(uint32_t begin);
bool checkLocalExportNames(Node node);
bool checkLocalExportNames(ListNodeType node);
Node exportClause(uint32_t begin);
Node exportFunctionDeclaration(uint32_t begin);
Node exportVariableStatement(uint32_t begin);
@ -1273,10 +1278,10 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
// Otherwise, for for-in/of loops, the next token is the ')' ending the
// loop-head. Additionally, the expression that the loop iterates over was
// parsed into |*forInOrOfExpression|.
Node declarationList(YieldHandling yieldHandling,
ParseNodeKind kind,
ParseNodeKind* forHeadKind = nullptr,
Node* forInOrOfExpression = nullptr);
ListNodeType declarationList(YieldHandling yieldHandling,
ParseNodeKind kind,
ParseNodeKind* forHeadKind = nullptr,
Node* forInOrOfExpression = nullptr);
// The items in a declaration list are either patterns or names, with or
// without initializers. These two methods parse a single pattern/name and
@ -1371,22 +1376,22 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
Node comprehensionIf(GeneratorKind comprehensionKind);
Node comprehensionTail(GeneratorKind comprehensionKind);
Node comprehension(GeneratorKind comprehensionKind);
Node arrayComprehension(uint32_t begin);
ListNodeType arrayComprehension(uint32_t begin);
Node generatorComprehension(uint32_t begin);
Node argumentList(YieldHandling yieldHandling, bool* isSpread,
PossibleError* possibleError = nullptr);
ListNodeType argumentList(YieldHandling yieldHandling, bool* isSpread,
PossibleError* possibleError = nullptr);
Node destructuringDeclaration(DeclarationKind kind, YieldHandling yieldHandling,
TokenKind tt);
Node destructuringDeclarationWithoutYieldOrAwait(DeclarationKind kind, YieldHandling yieldHandling,
TokenKind tt);
bool namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet);
bool namedImportsOrNamespaceImport(TokenKind tt, ListNodeType importSpecSet);
bool checkExportedName(JSAtom* exportName);
bool checkExportedNamesForArrayBinding(Node node);
bool checkExportedNamesForObjectBinding(Node node);
bool checkExportedNamesForArrayBinding(ListNodeType array);
bool checkExportedNamesForObjectBinding(ListNodeType obj);
bool checkExportedNamesForDeclaration(Node node);
bool checkExportedNamesForDeclarationList(Node node);
bool checkExportedNamesForDeclarationList(ListNodeType node);
bool checkExportedNameForClause(Node node);
bool checkExportedNameForFunction(Node node);
@ -1512,21 +1517,21 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
Node finishLexicalScope(ParseContext::Scope& scope, Node body);
Node propertyName(YieldHandling yieldHandling,
const mozilla::Maybe<DeclarationKind>& maybeDecl, Node propList,
const mozilla::Maybe<DeclarationKind>& maybeDecl, ListNodeType propList,
PropertyType* propType, MutableHandleAtom propAtom);
Node computedPropertyName(YieldHandling yieldHandling,
const mozilla::Maybe<DeclarationKind>& maybeDecl, Node literal);
Node arrayInitializer(YieldHandling yieldHandling, PossibleError* possibleError);
const mozilla::Maybe<DeclarationKind>& maybeDecl, ListNodeType literal);
ListNodeType arrayInitializer(YieldHandling yieldHandling, PossibleError* possibleError);
Node newRegExp();
Node objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError);
ListNodeType objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError);
Node bindingInitializer(Node lhs, DeclarationKind kind, YieldHandling yieldHandling);
Node bindingIdentifier(DeclarationKind kind, YieldHandling yieldHandling);
Node bindingIdentifierOrPattern(DeclarationKind kind, YieldHandling yieldHandling,
TokenKind tt);
Node objectBindingPattern(DeclarationKind kind, YieldHandling yieldHandling);
Node arrayBindingPattern(DeclarationKind kind, YieldHandling yieldHandling);
ListNodeType objectBindingPattern(DeclarationKind kind, YieldHandling yieldHandling);
ListNodeType arrayBindingPattern(DeclarationKind kind, YieldHandling yieldHandling);
void checkDestructuringAssignmentTarget(Node expr, TokenPos exprPos,
PossibleError* possibleError);
@ -1537,11 +1542,11 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
return handler.newNumber(tok.number(), tok.decimalPoint(), tok.pos);
}
static Node null() { return ParseHandler::null(); }
static typename ParseHandler::NullNode null() { return ParseHandler::null(); }
JSAtom* prefixAccessorName(PropertyType propType, HandleAtom propAtom);
bool asmJS(Node list);
bool asmJS(ListNodeType list);
enum class OptionalKind {
NonOptional = 0,

View file

@ -145,6 +145,13 @@ class SyntaxParseHandler
NodeSuperBase
};
#define DECLARE_TYPE(typeName, longTypeName, asMethodName) \
using longTypeName = Node;
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
#undef DECLARE_TYPE
using NullNode = Node;
bool isPropertyAccess(Node node) {
return node == NodeDottedProperty || node == NodeElement;
}
@ -183,7 +190,14 @@ class SyntaxParseHandler
tokenStream(tokenStream)
{}
static Node null() { return NodeFailure; }
static NullNode null() { return NodeFailure; }
#define DECLARE_AS(typeName, longTypeName, asMethodName) \
static longTypeName asMethodName(Node node) { \
return node; \
}
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
#undef DECLARE_AS
void prepareNodeForMutation(Node node) {}
void freeTree(Node node) {}
@ -222,11 +236,11 @@ class SyntaxParseHandler
return NodeGeneric;
}
Node newCallSiteObject(uint32_t begin) {
CallSiteNodeType newCallSiteObject(uint32_t begin) {
return NodeGeneric;
}
void addToCallSiteObject(Node callSiteObj, Node rawNode, Node cookedNode) {}
void addToCallSiteObject(CallSiteNodeType callSiteObj, Node rawNode, Node cookedNode) {}
Node newThisLiteral(const TokenPos& pos, Node thisName) { return NodeGeneric; }
Node newNullLiteral(const TokenPos& pos) { return NodeGeneric; }
@ -283,21 +297,20 @@ class SyntaxParseHandler
// Expressions
Node newArrayComprehension(Node body, const TokenPos& pos) { return NodeGeneric; }
Node newArrayLiteral(uint32_t begin) { return NodeUnparenthesizedArray; }
MOZ_MUST_USE bool addElision(Node literal, const TokenPos& pos) { return true; }
MOZ_MUST_USE bool addSpreadElement(Node literal, uint32_t begin, Node inner) { return true; }
void addArrayElement(Node literal, Node element) { }
ListNodeType newArrayLiteral(uint32_t begin) { return NodeUnparenthesizedArray; }
MOZ_MUST_USE bool addElision(ListNodeType literal, const TokenPos& pos) { return true; }
MOZ_MUST_USE bool addSpreadElement(ListNodeType literal, uint32_t begin, Node inner) { return true; }
void addArrayElement(ListNodeType literal, Node element) { }
Node newCall(Node callee, Node args) { return NodeFunctionCall; }
Node newOptionalCall(Node callee, Node args) { return NodeOptionalFunctionCall; }
Node newArguments(const TokenPos& pos) { return NodeGeneric; }
ListNodeType newArguments(const TokenPos& pos) { return NodeGeneric; }
Node newSuperCall(Node callee, Node args) { return NodeGeneric; }
Node newTaggedTemplate(Node callee, Node args) { return NodeGeneric; }
Node newGenExp(Node callee, Node args) { return NodeGeneric; }
Node newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; }
Node newClassMethodList(uint32_t begin) { return NodeGeneric; }
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; }
@ -305,12 +318,12 @@ class SyntaxParseHandler
Node newPosHolder(const TokenPos& pos) { return NodeGeneric; }
Node newSuperBase(Node thisName, const TokenPos& pos) { return NodeSuperBase; }
MOZ_MUST_USE bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
MOZ_MUST_USE bool addPropertyDefinition(Node literal, Node name, Node expr) { return true; }
MOZ_MUST_USE bool addShorthand(Node literal, Node name, Node expr) { return true; }
MOZ_MUST_USE bool addSpreadProperty(Node literal, uint32_t begin, Node inner) { return true; }
MOZ_MUST_USE bool addObjectMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
MOZ_MUST_USE bool addClassMethodDefinition(Node literal, Node name, Node fn, JSOp op, bool isStatic) { return true; }
MOZ_MUST_USE bool addPrototypeMutation(ListNodeType literal, uint32_t begin, Node expr) { return true; }
MOZ_MUST_USE bool addPropertyDefinition(ListNodeType literal, Node name, Node expr) { return true; }
MOZ_MUST_USE bool addShorthand(ListNodeType literal, Node name, Node expr) { return true; }
MOZ_MUST_USE bool addSpreadProperty(ListNodeType literal, uint32_t begin, Node inner) { return true; }
MOZ_MUST_USE bool addObjectMethodDefinition(ListNodeType literal, Node name, Node fn, JSOp op) { return true; }
MOZ_MUST_USE bool addClassMethodDefinition(ListNodeType literal, Node name, Node fn, JSOp op, bool isStatic) { return true; }
Node newYieldExpression(uint32_t begin, Node value) { return NodeGeneric; }
Node newYieldStarExpression(uint32_t begin, Node value) { return NodeGeneric; }
Node newAwaitExpression(uint32_t begin, Node value) { return NodeGeneric; }
@ -318,10 +331,10 @@ class SyntaxParseHandler
// Statements
Node newStatementList(const TokenPos& pos) { return NodeGeneric; }
void addStatementToList(Node list, Node stmt) {}
void addCaseStatementToList(Node list, Node stmt) {}
MOZ_MUST_USE bool prependInitialYield(Node stmtList, Node gen) { return true; }
ListNodeType newStatementList(const TokenPos& pos) { return NodeGeneric; }
void addStatementToList(ListNodeType list, Node stmt) {}
void addCaseStatementToList(ListNodeType list, Node caseClause) {}
MOZ_MUST_USE bool prependInitialYield(ListNodeType stmtList, Node genName) { return true; }
Node newEmptyStatement(const TokenPos& pos) { return NodeEmptyStatement; }
Node newExportDeclaration(Node kid, const TokenPos& pos) {
@ -358,7 +371,7 @@ class SyntaxParseHandler
}
Node newThrowStatement(Node expr, const TokenPos& pos) { return NodeThrow; }
Node newTryStatement(uint32_t begin, Node body, Node catchList, Node finallyBlock) {
Node newTryStatement(uint32_t begin, Node body, ListNodeType catchList, Node finallyBlock) {
return NodeGeneric;
}
Node newDebuggerStatement(const TokenPos& pos) { return NodeGeneric; }
@ -380,7 +393,7 @@ class SyntaxParseHandler
Node newOptionalPropertyByValue(Node pn, Node kid, uint32_t end) { return NodeOptionalElement; }
MOZ_MUST_USE bool addCatchBlock(Node catchList, Node letBlock, Node catchName,
MOZ_MUST_USE bool addCatchBlock(ListNodeType catchList, Node letBlock, Node catchName,
Node catchGuard, Node catchBody) { return true; }
MOZ_MUST_USE bool setLastFunctionFormalParameterDefault(Node funcpn, Node pn) { return true; }
@ -434,26 +447,26 @@ class SyntaxParseHandler
return tokenStream.currentToken().pos;
}
Node newList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
ListNodeType newList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
MOZ_ASSERT(kind != PNK_VAR);
MOZ_ASSERT(kind != PNK_LET);
MOZ_ASSERT(kind != PNK_CONST);
return NodeGeneric;
}
Node newList(ParseNodeKind kind, uint32_t begin, JSOp op = JSOP_NOP) {
ListNodeType newList(ParseNodeKind kind, uint32_t begin, JSOp op = JSOP_NOP) {
return newList(kind, op);
}
Node newList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
ListNodeType newList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
return newList(kind, op);
}
Node newDeclarationList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
ListNodeType newDeclarationList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
if (kind == PNK_VAR)
return NodeVarDeclaration;
MOZ_ASSERT(kind == PNK_LET || kind == PNK_CONST);
return NodeLexicalDeclaration;
}
Node newDeclarationList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
ListNodeType newDeclarationList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
return newDeclarationList(kind, op);
}
@ -461,7 +474,7 @@ class SyntaxParseHandler
return node == NodeVarDeclaration || node == NodeLexicalDeclaration;
}
Node singleBindingFromDeclaration(Node decl) {
Node singleBindingFromDeclaration(ListNodeType decl) {
MOZ_ASSERT(isDeclarationList(decl));
// This is, unfortunately, very dodgy. Obviously NodeVarDeclaration
@ -485,11 +498,11 @@ class SyntaxParseHandler
return newList(PNK_CATCHLIST, JSOP_NOP);
}
Node newCommaExpressionList(Node kid) {
ListNodeType newCommaExpressionList(Node kid) {
return NodeUnparenthesizedCommaExpr;
}
void addList(Node list, Node kid) {
void addList(ListNodeType list, Node kid) {
MOZ_ASSERT(list == NodeGeneric ||
list == NodeUnparenthesizedArray ||
list == NodeUnparenthesizedObject ||
@ -539,7 +552,7 @@ class SyntaxParseHandler
}
void setOp(Node pn, JSOp op) {}
void setListFlag(Node pn, unsigned flag) {}
void setListHasNonConstInitializer(ListNodeType literal) {}
MOZ_MUST_USE Node parenthesize(Node node) {
// A number of nodes have different behavior upon parenthesization, but
// only in some circumstances. Convert these nodes to special

View file

@ -450,15 +450,13 @@ TernaryKid3(ParseNode* pn)
static inline ParseNode*
ListHead(ParseNode* pn)
{
MOZ_ASSERT(pn->isArity(PN_LIST));
return pn->pn_head;
return pn->as<ListNode>().head();
}
static inline unsigned
ListLength(ParseNode* pn)
{
MOZ_ASSERT(pn->isArity(PN_LIST));
return pn->pn_count;
return pn->as<ListNode>().count();
}
static inline ParseNode*
@ -511,8 +509,7 @@ static inline ParseNode*
BinaryOpLeft(ParseNode* pn)
{
MOZ_ASSERT(pn->isBinaryOperation());
MOZ_ASSERT(pn->isArity(PN_LIST));
MOZ_ASSERT(pn->pn_count == 2);
MOZ_ASSERT(pn->as<ListNode>().count() == 2);
return ListHead(pn);
}
@ -520,8 +517,7 @@ static inline ParseNode*
BinaryOpRight(ParseNode* pn)
{
MOZ_ASSERT(pn->isBinaryOperation());
MOZ_ASSERT(pn->isArity(PN_LIST));
MOZ_ASSERT(pn->pn_count == 2);
MOZ_ASSERT(pn->as<ListNode>().count() == 2);
return NextNode(ListHead(pn));
}
@ -688,7 +684,7 @@ static inline ParseNode*
FunctionStatementList(ParseNode* fn)
{
MOZ_ASSERT(fn->pn_body->isKind(PNK_PARAMSBODY));
ParseNode* last = fn->pn_body->last();
ParseNode* last = fn->pn_body->as<ListNode>().last();
MOZ_ASSERT(last->isKind(PNK_LEXICALSCOPE));
MOZ_ASSERT(last->isEmptyScope());
ParseNode* body = last->scopeBody();