Issue #2173 - Add accessors to BinaryNode and subclasses

Based-on: m-c 1479659/3
This commit is contained in:
Martok 2023-03-26 06:08:53 +02:00 • committed by roytam1
commit 662419c507
14 changed files with 1134 additions and 919 deletions

View file

@ -1161,31 +1161,40 @@ ModuleBuilder::initModule()
} }
bool bool
ModuleBuilder::processImport(frontend::ParseNode* pn) ModuleBuilder::processImport(frontend::BinaryNode* importNode)
{ {
MOZ_ASSERT(pn->isKind(PNK_IMPORT)); MOZ_ASSERT(importNode->isKind(PNK_IMPORT));
MOZ_ASSERT(pn->isArity(PN_BINARY));
MOZ_ASSERT(pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST)); ListNode* specList = &importNode->left()->as<ListNode>();
MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING)); MOZ_ASSERT(specList->isKind(PNK_IMPORT_SPEC_LIST));
ParseNode* moduleSpec = importNode->right();
MOZ_ASSERT(moduleSpec->isKind(PNK_STRING));
RootedAtom module(cx_, pn->pn_right->pn_atom); RootedAtom module(cx_, moduleSpec->pn_atom);
if (!maybeAppendRequestedModule(module)) if (!maybeAppendRequestedModule(module))
return false; return false;
for (ParseNode* spec : pn->pn_left->as<ListNode>().contents()) { RootedAtom importName(cx_);
RootedAtom localName(cx_);
for (ParseNode* item : specList->contents()) {
BinaryNode* spec = &item->as<BinaryNode>();
MOZ_ASSERT(spec->isKind(PNK_IMPORT_SPEC)); MOZ_ASSERT(spec->isKind(PNK_IMPORT_SPEC));
MOZ_ASSERT(spec->pn_left->isArity(PN_NAME));
MOZ_ASSERT(spec->pn_right->isArity(PN_NAME)); ParseNode* importNameNode = spec->left();
MOZ_ASSERT(importNameNode->isArity(PN_NAME));
ParseNode* localNameNode = spec->right();
MOZ_ASSERT(localNameNode->isArity(PN_NAME));
RootedAtom importName(cx_, spec->pn_left->pn_atom); RootedAtom importName(cx_, importNameNode->pn_atom);
RootedAtom localName(cx_, spec->pn_right->pn_atom); RootedAtom localName(cx_, localNameNode->pn_atom);
if (!importedBoundNames_.append(localName)) if (!importedBoundNames_.append(localName))
return false; return false;
uint32_t line; uint32_t line;
uint32_t column; uint32_t column;
tokenStream_.srcCoords.lineNumAndColumnIndex(spec->pn_left->pn_pos.begin, &line, &column); tokenStream_.srcCoords.lineNumAndColumnIndex(importNameNode->pn_pos.begin, &line, &column);
RootedImportEntryObject importEntry(cx_); RootedImportEntryObject importEntry(cx_);
importEntry = ImportEntryObject::create(cx_, module, importName, localName, line, column); importEntry = ImportEntryObject::create(cx_, module, importName, localName, line, column);
@ -1197,15 +1206,16 @@ ModuleBuilder::processImport(frontend::ParseNode* pn)
} }
bool bool
ModuleBuilder::processExport(frontend::ParseNode* pn) ModuleBuilder::processExport(frontend::ParseNode* exportNode)
{ {
MOZ_ASSERT(pn->isKind(PNK_EXPORT) || pn->isKind(PNK_EXPORT_DEFAULT)); MOZ_ASSERT(exportNode->isKind(PNK_EXPORT) ||
MOZ_ASSERT(pn->getArity() == (pn->isKind(PNK_EXPORT) ? PN_UNARY : PN_BINARY)); exportNode->isKind(PNK_EXPORT_DEFAULT));
MOZ_ASSERT_IF(exportNode->isKind(PNK_EXPORT), exportNode->is<UnaryNode>());
bool isDefault = pn->getKind() == PNK_EXPORT_DEFAULT; bool isDefault = exportNode->isKind(PNK_EXPORT_DEFAULT);
ParseNode* kid = isDefault ? pn->pn_left : pn->pn_kid; ParseNode* kid = isDefault ? exportNode->as<BinaryNode>().left() : exportNode->pn_kid;
if (isDefault && pn->pn_right) { if (isDefault && exportNode->as<BinaryNode>().right()) {
// This is an export default containing an expression. // This is an export default containing an expression.
RootedAtom localName(cx_, cx_->names().starDefaultStar); RootedAtom localName(cx_, cx_->names().starDefaultStar);
RootedAtom exportName(cx_, cx_->names().default_); RootedAtom exportName(cx_, cx_->names().default_);
@ -1213,16 +1223,23 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
} }
switch (kid->getKind()) { switch (kid->getKind()) {
case PNK_EXPORT_SPEC_LIST: case PNK_EXPORT_SPEC_LIST: {
MOZ_ASSERT(!isDefault); MOZ_ASSERT(!isDefault);
for (ParseNode* spec : kid->as<ListNode>().contents()) { RootedAtom localName(cx_);
RootedAtom exportName(cx_);
for (ParseNode* item : kid->as<ListNode>().contents()) {
BinaryNode* spec = &item->as<BinaryNode>();
MOZ_ASSERT(spec->isKind(PNK_EXPORT_SPEC)); MOZ_ASSERT(spec->isKind(PNK_EXPORT_SPEC));
RootedAtom localName(cx_, spec->pn_left->pn_atom);
RootedAtom exportName(cx_, spec->pn_right->pn_atom); ParseNode* localNameNode = spec->left();
ParseNode* exportNameNode = spec->right();
localName = localNameNode->pn_atom;
exportName = exportNameNode->pn_atom;
if (!appendExportEntry(exportName, localName, spec)) if (!appendExportEntry(exportName, localName, spec))
return false; return false;
} }
break; break;
}
case PNK_CLASS: { case PNK_CLASS: {
const ClassNode& cls = kid->as<ClassNode>(); const ClassNode& cls = kid->as<ClassNode>();
@ -1240,7 +1257,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
MOZ_ASSERT(kid->isArity(PN_LIST)); MOZ_ASSERT(kid->isArity(PN_LIST));
for (ParseNode* binding : kid->as<ListNode>().contents()) { for (ParseNode* binding : kid->as<ListNode>().contents()) {
if (binding->isKind(PNK_ASSIGN)) if (binding->isKind(PNK_ASSIGN))
binding = binding->pn_left; binding = binding->as<AssignmentNode>().left();
else else
MOZ_ASSERT(binding->isKind(PNK_NAME)); MOZ_ASSERT(binding->isKind(PNK_NAME));
@ -1306,7 +1323,7 @@ ModuleBuilder::processExportArrayBinding(frontend::ListNode* array)
if (node->isKind(PNK_SPREAD)) if (node->isKind(PNK_SPREAD))
node = node->pn_kid; node = node->pn_kid;
else if (node->isKind(PNK_ASSIGN)) else if (node->isKind(PNK_ASSIGN))
node = node->pn_left; node = node->as<AssignmentNode>().left();
if (!processExportBinding(node)) if (!processExportBinding(node))
return false; return false;
@ -1333,10 +1350,10 @@ ModuleBuilder::processExportObjectBinding(frontend::ListNode* obj)
if (node->isKind(PNK_MUTATEPROTO)) if (node->isKind(PNK_MUTATEPROTO))
target = node->pn_kid; target = node->pn_kid;
else else
target = node->pn_right; target = node->as<BinaryNode>().right();
if (target->isKind(PNK_ASSIGN)) if (target->isKind(PNK_ASSIGN))
target = target->pn_left; target = target->as<AssignmentNode>().left();
} }
if (!processExportBinding(target)) if (!processExportBinding(target))
@ -1347,27 +1364,34 @@ ModuleBuilder::processExportObjectBinding(frontend::ListNode* obj)
} }
bool bool
ModuleBuilder::processExportFrom(frontend::ParseNode* pn) ModuleBuilder::processExportFrom(frontend::BinaryNode* exportNode)
{ {
MOZ_ASSERT(pn->isKind(PNK_EXPORT_FROM)); MOZ_ASSERT(exportNode->isKind(PNK_EXPORT_FROM));
MOZ_ASSERT(pn->isArity(PN_BINARY));
MOZ_ASSERT(pn->pn_left->isKind(PNK_EXPORT_SPEC_LIST));
MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING));
RootedAtom module(cx_, pn->pn_right->pn_atom); ListNode* specList = &exportNode->left()->as<ListNode>();
MOZ_ASSERT(specList->isKind(PNK_EXPORT_SPEC_LIST));
ParseNode* moduleSpec = exportNode->right();
MOZ_ASSERT(moduleSpec->isKind(PNK_STRING));
RootedAtom module(cx_, moduleSpec->pn_atom);
if (!maybeAppendRequestedModule(module)) if (!maybeAppendRequestedModule(module))
return false; return false;
for (ParseNode* spec : pn->pn_left->as<ListNode>().contents()) { RootedAtom bindingName(cx_);
RootedAtom exportName(cx_);
for (ParseNode* spec : specList->contents()) {
if (spec->isKind(PNK_EXPORT_SPEC)) { if (spec->isKind(PNK_EXPORT_SPEC)) {
RootedAtom bindingName(cx_, spec->pn_left->pn_atom); ParseNode* localNameNode = spec->as<BinaryNode>().left();
RootedAtom exportName(cx_, spec->pn_right->pn_atom); ParseNode* exportNameNode = spec->as<BinaryNode>().right();
if (!appendExportFromEntry(exportName, module, bindingName, spec->pn_left)) bindingName = localNameNode->pn_atom;
exportName = exportNameNode->pn_atom;
if (!appendExportFromEntry(exportName, module, bindingName, localNameNode))
return false; return false;
} else { } else {
MOZ_ASSERT(spec->isKind(PNK_EXPORT_BATCH_SPEC)); MOZ_ASSERT(spec->isKind(PNK_EXPORT_BATCH_SPEC));
RootedAtom importName(cx_, cx_->names().star); exportName = cx_->names().star;
if (!appendExportFromEntry(nullptr, module, importName, spec)) if (!appendExportFromEntry(nullptr, module, exportName, spec))
return false; return false;
} }
} }

View file

@ -24,6 +24,7 @@ class ModuleEnvironmentObject;
class ModuleObject; class ModuleObject;
namespace frontend { namespace frontend {
class BinaryNode;
class ListNode; class ListNode;
class ParseNode; class ParseNode;
class TokenStream; class TokenStream;
@ -319,9 +320,9 @@ class MOZ_STACK_CLASS ModuleBuilder
explicit ModuleBuilder(ExclusiveContext* cx, HandleModuleObject module, explicit ModuleBuilder(ExclusiveContext* cx, HandleModuleObject module,
const frontend::TokenStream& tokenStream); const frontend::TokenStream& tokenStream);
bool processImport(frontend::ParseNode* pn); bool processImport(frontend::BinaryNode* importNode);
bool processExport(frontend::ParseNode* pn); bool processExport(frontend::ParseNode* exportNode);
bool processExportFrom(frontend::ParseNode* pn); bool processExportFrom(frontend::BinaryNode* exportNode);
bool hasExportedName(JSAtom* name) const; bool hasExportedName(JSAtom* name) const;

View file

@ -1802,10 +1802,10 @@ class ASTSerializer
bool declaration(ParseNode* pn, MutableHandleValue dst); bool declaration(ParseNode* pn, MutableHandleValue dst);
bool variableDeclaration(ListNode* declList, bool lexical, MutableHandleValue dst); bool variableDeclaration(ListNode* declList, bool lexical, MutableHandleValue dst);
bool variableDeclarator(ParseNode* pn, MutableHandleValue dst); bool variableDeclarator(ParseNode* pn, MutableHandleValue dst);
bool importDeclaration(ParseNode* pn, MutableHandleValue dst); bool importDeclaration(BinaryNode* importNode, MutableHandleValue dst);
bool importSpecifier(ParseNode* pn, MutableHandleValue dst); bool importSpecifier(BinaryNode* importSpec, MutableHandleValue dst);
bool exportDeclaration(ParseNode* pn, MutableHandleValue dst); bool exportDeclaration(ParseNode* exportNode, MutableHandleValue dst);
bool exportSpecifier(ParseNode* pn, MutableHandleValue dst); bool exportSpecifier(BinaryNode* exportSpec, MutableHandleValue dst);
bool classDefinition(ClassNode* pn, bool expr, MutableHandleValue dst); bool classDefinition(ClassNode* pn, bool expr, MutableHandleValue dst);
bool optStatement(ParseNode* pn, MutableHandleValue dst) { bool optStatement(ParseNode* pn, MutableHandleValue dst) {
@ -1817,14 +1817,14 @@ class ASTSerializer
} }
bool forInit(ParseNode* pn, MutableHandleValue dst); bool forInit(ParseNode* pn, MutableHandleValue dst);
bool forIn(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, bool forIn(ForNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt,
MutableHandleValue dst); MutableHandleValue dst);
bool forOf(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, bool forOf(ForNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt,
MutableHandleValue dst); MutableHandleValue dst);
bool statement(ParseNode* pn, MutableHandleValue dst); bool statement(ParseNode* pn, MutableHandleValue dst);
bool blockStatement(ListNode* node, MutableHandleValue dst); bool blockStatement(ListNode* node, MutableHandleValue dst);
bool switchStatement(ParseNode* pn, MutableHandleValue dst); bool switchStatement(SwitchStatement* switchStmt, MutableHandleValue dst);
bool switchCase(ParseNode* pn, MutableHandleValue dst); bool switchCase(CaseClause* caseClause, MutableHandleValue dst);
bool tryStatement(TernaryNode* tryNode, MutableHandleValue dst); bool tryStatement(TernaryNode* tryNode, MutableHandleValue dst);
bool catchClause(TernaryNode* clauseNode, bool* isGuarded, MutableHandleValue dst); bool catchClause(TernaryNode* clauseNode, bool* isGuarded, MutableHandleValue dst);
@ -1841,7 +1841,7 @@ class ASTSerializer
bool propertyName(ParseNode* pn, MutableHandleValue dst); bool propertyName(ParseNode* pn, MutableHandleValue dst);
bool property(ParseNode* pn, MutableHandleValue dst); bool property(ParseNode* pn, MutableHandleValue dst);
bool classMethod(ParseNode* pn, MutableHandleValue dst); bool classMethod(ClassMethod* classMethod, MutableHandleValue dst);
bool optIdentifier(HandleAtom atom, TokenPos* pos, MutableHandleValue dst) { bool optIdentifier(HandleAtom atom, TokenPos* pos, MutableHandleValue dst) {
if (!atom) { if (!atom) {
@ -1873,7 +1873,7 @@ class ASTSerializer
MutableHandleValue body, MutableHandleValue rest); MutableHandleValue body, MutableHandleValue rest);
bool functionBody(ParseNode* pn, TokenPos* pos, MutableHandleValue dst); bool functionBody(ParseNode* pn, TokenPos* pos, MutableHandleValue dst);
bool comprehensionBlock(ParseNode* pn, MutableHandleValue dst); bool comprehensionBlock(ForNode* forNode, MutableHandleValue dst);
bool comprehensionIf(TernaryNode* ifNode, MutableHandleValue dst); bool comprehensionIf(TernaryNode* ifNode, MutableHandleValue dst);
bool comprehension(ParseNode* pn, MutableHandleValue dst); bool comprehension(ParseNode* pn, MutableHandleValue dst);
bool generatorExpression(ParseNode* pn, MutableHandleValue dst); bool generatorExpression(ParseNode* pn, MutableHandleValue dst);
@ -2135,45 +2135,48 @@ ASTSerializer::variableDeclaration(ListNode* declList, bool lexical, MutableHand
bool bool
ASTSerializer::variableDeclarator(ParseNode* pn, MutableHandleValue dst) ASTSerializer::variableDeclarator(ParseNode* pn, MutableHandleValue dst)
{ {
ParseNode* pnleft; ParseNode* patternNode;
ParseNode* pnright; ParseNode* initNode;
if (pn->isKind(PNK_NAME)) { if (pn->isKind(PNK_NAME)) {
pnleft = pn; patternNode = pn;
pnright = pn->pn_expr; initNode = pn->pn_expr;
MOZ_ASSERT_IF(pnright, pn->pn_pos.encloses(pnright->pn_pos)); MOZ_ASSERT_IF(initNode, pn->pn_pos.encloses(initNode->pn_pos));
} else if (pn->isKind(PNK_ASSIGN)) { } else if (pn->isKind(PNK_ASSIGN)) {
pnleft = pn->pn_left; AssignmentNode* assignNode = &pn->as<AssignmentNode>();
pnright = pn->pn_right; patternNode = assignNode->left();
MOZ_ASSERT(pn->pn_pos.encloses(pnleft->pn_pos)); initNode = assignNode->right();
MOZ_ASSERT(pn->pn_pos.encloses(pnright->pn_pos)); MOZ_ASSERT(pn->pn_pos.encloses(patternNode->pn_pos));
MOZ_ASSERT(pn->pn_pos.encloses(initNode->pn_pos));
} else { } else {
/* This happens for a destructuring declarator in a for-in/of loop. */ /* This happens for a destructuring declarator in a for-in/of loop. */
pnleft = pn; patternNode = pn;
pnright = nullptr; initNode = nullptr;
} }
RootedValue left(cx), right(cx); RootedValue patternVal(cx), init(cx);
return pattern(pnleft, &left) && return pattern(patternNode, &patternVal) &&
optExpression(pnright, &right) && optExpression(initNode, &init) &&
builder.variableDeclarator(left, right, &pn->pn_pos, dst); builder.variableDeclarator(patternVal, init, &pn->pn_pos, dst);
} }
bool bool
ASTSerializer::importDeclaration(ParseNode* pn, MutableHandleValue dst) ASTSerializer::importDeclaration(BinaryNode* importNode, MutableHandleValue dst)
{ {
MOZ_ASSERT(pn->isKind(PNK_IMPORT)); MOZ_ASSERT(importNode->isKind(PNK_IMPORT));
MOZ_ASSERT(pn->isArity(PN_BINARY));
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>(); ListNode* specList = &importNode->left()->as<ListNode>();
MOZ_ASSERT(specList->isKind(PNK_IMPORT_SPEC_LIST));
ParseNode* moduleSpecNode = importNode->right();
MOZ_ASSERT(moduleSpecNode->isKind(PNK_STRING));
NodeVector elts(cx); NodeVector elts(cx);
if (!elts.reserve(specList->count())) if (!elts.reserve(specList->count()))
return false; return false;
for (ParseNode* spec : specList->contents()) { for (ParseNode* item : specList->contents()) {
BinaryNode* spec = &item->as<BinaryNode>();
RootedValue elt(cx); RootedValue elt(cx);
if (!importSpecifier(spec, &elt)) if (!importSpecifier(spec, &elt))
return false; return false;
@ -2181,48 +2184,51 @@ ASTSerializer::importDeclaration(ParseNode* pn, MutableHandleValue dst)
} }
RootedValue moduleSpec(cx); RootedValue moduleSpec(cx);
return literal(pn->pn_right, &moduleSpec) && return literal(moduleSpecNode, &moduleSpec) &&
builder.importDeclaration(elts, moduleSpec, &pn->pn_pos, dst); builder.importDeclaration(elts, moduleSpec, &importNode->pn_pos, dst);
} }
bool bool
ASTSerializer::importSpecifier(ParseNode* pn, MutableHandleValue dst) ASTSerializer::importSpecifier(BinaryNode* importSpec, MutableHandleValue dst)
{ {
MOZ_ASSERT(pn->isKind(PNK_IMPORT_SPEC)); MOZ_ASSERT(importSpec->isKind(PNK_IMPORT_SPEC));
RootedValue importName(cx); RootedValue importName(cx);
RootedValue bindingName(cx); RootedValue bindingName(cx);
return identifier(pn->pn_left, &importName) && return identifier(importSpec->left(), &importName) &&
identifier(pn->pn_right, &bindingName) && identifier(importSpec->right(), &bindingName) &&
builder.importSpecifier(importName, bindingName, &pn->pn_pos, dst); builder.importSpecifier(importName, bindingName, &importSpec->pn_pos, dst);
} }
bool bool
ASTSerializer::exportDeclaration(ParseNode* pn, MutableHandleValue dst) ASTSerializer::exportDeclaration(ParseNode* exportNode, MutableHandleValue dst)
{ {
MOZ_ASSERT(pn->isKind(PNK_EXPORT) || MOZ_ASSERT(exportNode->isKind(PNK_EXPORT) ||
pn->isKind(PNK_EXPORT_FROM) || exportNode->isKind(PNK_EXPORT_FROM) ||
pn->isKind(PNK_EXPORT_DEFAULT)); exportNode->isKind(PNK_EXPORT_DEFAULT));
MOZ_ASSERT(pn->getArity() == (pn->isKind(PNK_EXPORT) ? PN_UNARY : PN_BINARY)); MOZ_ASSERT_IF(exportNode->isKind(PNK_EXPORT), exportNode->is<UnaryNode>());
MOZ_ASSERT_IF(pn->isKind(PNK_EXPORT_FROM), pn->pn_right->isKind(PNK_STRING)); MOZ_ASSERT_IF(exportNode->isKind(PNK_EXPORT_FROM),
exportNode->as<BinaryNode>().right()->isKind(PNK_STRING));
RootedValue decl(cx, NullValue()); RootedValue decl(cx, NullValue());
NodeVector elts(cx); NodeVector elts(cx);
ParseNode* kid = pn->isKind(PNK_EXPORT) ? pn->pn_kid : pn->pn_left; ParseNode* kid = exportNode->isKind(PNK_EXPORT)
? exportNode->pn_kid
: exportNode->as<BinaryNode>().left();
switch (ParseNodeKind kind = kid->getKind()) { switch (ParseNodeKind kind = kid->getKind()) {
case PNK_EXPORT_SPEC_LIST: { case PNK_EXPORT_SPEC_LIST: {
ListNode* specList = &pn->pn_left->as<ListNode>(); ListNode* specList = &kid->as<ListNode>();
if (!elts.reserve(specList->count())) if (!elts.reserve(specList->count()))
return false; return false;
for (ParseNode* spec : specList->contents()) { for (ParseNode* spec : specList->contents()) {
RootedValue elt(cx); RootedValue elt(cx);
if (spec->isKind(PNK_EXPORT_SPEC)) { if (spec->isKind(PNK_EXPORT_SPEC)) {
if (!exportSpecifier(spec, &elt)) if (!exportSpecifier(&spec->as<BinaryNode>(), &elt))
return false; return false;
} else { } else {
if (!builder.exportBatchSpecifier(&pn->pn_pos, &elt)) if (!builder.exportBatchSpecifier(&exportNode->pn_pos, &elt))
return false; return false;
} }
elts.infallibleAppend(elt); elts.infallibleAppend(elt);
@ -2254,70 +2260,72 @@ ASTSerializer::exportDeclaration(ParseNode* pn, MutableHandleValue dst)
} }
RootedValue moduleSpec(cx, NullValue()); RootedValue moduleSpec(cx, NullValue());
if (pn->isKind(PNK_EXPORT_FROM) && !literal(pn->pn_right, &moduleSpec)) if (exportNode->isKind(PNK_EXPORT_FROM)) {
return false; if (!literal(exportNode->as<BinaryNode>().right(), &moduleSpec)) {
return false;
}
}
RootedValue isDefault(cx, BooleanValue(false)); RootedValue isDefault(cx, BooleanValue(false));
if (pn->isKind(PNK_EXPORT_DEFAULT)) if (exportNode->isKind(PNK_EXPORT_DEFAULT))
isDefault.setBoolean(true); isDefault.setBoolean(true);
return builder.exportDeclaration(decl, elts, moduleSpec, isDefault, &pn->pn_pos, dst); return builder.exportDeclaration(decl, elts, moduleSpec, isDefault, &exportNode->pn_pos, dst);
} }
bool bool
ASTSerializer::exportSpecifier(ParseNode* pn, MutableHandleValue dst) ASTSerializer::exportSpecifier(BinaryNode* exportSpec, MutableHandleValue dst)
{ {
MOZ_ASSERT(pn->isKind(PNK_EXPORT_SPEC)); MOZ_ASSERT(exportSpec->isKind(PNK_EXPORT_SPEC));
RootedValue bindingName(cx); RootedValue bindingName(cx);
RootedValue exportName(cx); RootedValue exportName(cx);
return identifier(pn->pn_left, &bindingName) && return identifier(exportSpec->left(), &bindingName) &&
identifier(pn->pn_right, &exportName) && identifier(exportSpec->right(), &exportName) &&
builder.exportSpecifier(bindingName, exportName, &pn->pn_pos, dst); builder.exportSpecifier(bindingName, exportName, &exportSpec->pn_pos, dst);
} }
bool bool
ASTSerializer::switchCase(ParseNode* pn, MutableHandleValue dst) ASTSerializer::switchCase(CaseClause* caseClause, MutableHandleValue dst)
{ {
MOZ_ASSERT_IF(pn->pn_left, pn->pn_pos.encloses(pn->pn_left->pn_pos)); MOZ_ASSERT_IF(caseClause->caseExpression(),
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); caseClause->pn_pos.encloses(caseClause->caseExpression()->pn_pos));
MOZ_ASSERT(caseClause->pn_pos.encloses(caseClause->statementList()->pn_pos));
NodeVector stmts(cx); NodeVector stmts(cx);
RootedValue expr(cx); RootedValue expr(cx);
return optExpression(caseClause->caseExpression(), &expr) &&
return optExpression(pn->as<CaseClause>().caseExpression(), &expr) && statements(caseClause->statementList(), stmts) &&
statements(pn->as<CaseClause>().statementList(), stmts) && builder.switchCase(expr, stmts, &caseClause->pn_pos, dst);
builder.switchCase(expr, stmts, &pn->pn_pos, dst);
} }
bool bool
ASTSerializer::switchStatement(ParseNode* pn, MutableHandleValue dst) ASTSerializer::switchStatement(SwitchStatement* switchStmt, MutableHandleValue dst)
{ {
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); MOZ_ASSERT(switchStmt->pn_pos.encloses(switchStmt->discriminant().pn_pos));
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); MOZ_ASSERT(switchStmt->pn_pos.encloses(switchStmt->lexicalForCaseList().pn_pos));
RootedValue disc(cx); RootedValue disc(cx);
if (!expression(pn->pn_left, &disc)) if (!expression(&switchStmt->discriminant(), &disc))
return false; return false;
MOZ_ASSERT(pn->pn_right->isKind(PNK_LEXICALSCOPE)); ListNode* caseList = &switchStmt->lexicalForCaseList().scopeBody()->as<ListNode>();
ListNode* caseList = &pn->pn_right->scopeBody()->as<ListNode>();
NodeVector cases(cx); NodeVector cases(cx);
if (!cases.reserve(caseList->count())) if (!cases.reserve(caseList->count()))
return false; return false;
for (ParseNode* caseNode : caseList->contents()) { for (ParseNode* item : caseList->contents()) {
CaseClause* caseClause = &item->as<CaseClause>();
RootedValue child(cx); RootedValue child(cx);
if (!switchCase(caseNode, &child)) if (!switchCase(caseClause, &child))
return false; return false;
cases.infallibleAppend(child); cases.infallibleAppend(child);
} }
return builder.switchStatement(disc, cases, /* lexical = */ true, &pn->pn_pos, dst); return builder.switchStatement(disc, cases, /* lexical = */ true, &switchStmt->pn_pos, dst);
} }
bool bool
@ -2401,8 +2409,8 @@ ASTSerializer::forInit(ParseNode* pn, MutableHandleValue dst)
} }
bool bool
ASTSerializer::forOf(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, ASTSerializer::forOf(ForNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt,
MutableHandleValue dst) MutableHandleValue dst)
{ {
RootedValue expr(cx); RootedValue expr(cx);
@ -2411,11 +2419,11 @@ ASTSerializer::forOf(ParseNode* loop, ParseNode* iterExpr, HandleValue var, Hand
} }
bool bool
ASTSerializer::forIn(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, ASTSerializer::forIn(ForNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt,
MutableHandleValue dst) MutableHandleValue dst)
{ {
RootedValue expr(cx); RootedValue expr(cx);
bool isForEach = loop->pn_iflags & JSITER_FOREACH; bool isForEach = loop->iflags() & JSITER_FOREACH;
return expression(iterExpr, &expr) && return expression(iterExpr, &expr) &&
builder.forInStatement(var, expr, stmt, isForEach, &loop->pn_pos, dst); builder.forInStatement(var, expr, stmt, isForEach, &loop->pn_pos, dst);
@ -2452,7 +2460,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
return declaration(pn, dst); return declaration(pn, dst);
case PNK_IMPORT: case PNK_IMPORT:
return importDeclaration(pn, dst); return importDeclaration(&pn->as<BinaryNode>(), dst);
case PNK_EXPORT: case PNK_EXPORT:
case PNK_EXPORT_DEFAULT: case PNK_EXPORT_DEFAULT:
@ -2498,7 +2506,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
} }
case PNK_SWITCH: case PNK_SWITCH:
return switchStatement(pn, dst); return switchStatement(&pn->as<SwitchStatement>(), dst);
case PNK_TRY: case PNK_TRY:
return tryStatement(&pn->as<TernaryNode>(), dst); return tryStatement(&pn->as<TernaryNode>(), dst);
@ -2506,37 +2514,50 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
case PNK_WITH: case PNK_WITH:
case PNK_WHILE: case PNK_WHILE:
{ {
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); BinaryNode* node = &pn->as<BinaryNode>();
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
ParseNode* exprNode = node->left();
MOZ_ASSERT(node->pn_pos.encloses(exprNode->pn_pos));
ParseNode* stmtNode = node->right();
MOZ_ASSERT(node->pn_pos.encloses(stmtNode->pn_pos));
RootedValue expr(cx), stmt(cx); RootedValue expr(cx), stmt(cx);
return expression(pn->pn_left, &expr) && return expression(exprNode, &expr) &&
statement(pn->pn_right, &stmt) && statement(stmtNode, &stmt) &&
(pn->isKind(PNK_WITH) (node->isKind(PNK_WITH)
? builder.withStatement(expr, stmt, &pn->pn_pos, dst) ? builder.withStatement(expr, stmt, &node->pn_pos, dst)
: builder.whileStatement(expr, stmt, &pn->pn_pos, dst)); : builder.whileStatement(expr, stmt, &node->pn_pos, dst));
} }
case PNK_DOWHILE: case PNK_DOWHILE:
{ {
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); BinaryNode* node = &pn->as<BinaryNode>();
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
ParseNode* stmtNode = node->left();
MOZ_ASSERT(node->pn_pos.encloses(stmtNode->pn_pos));
ParseNode* testNode = node->right();
MOZ_ASSERT(node->pn_pos.encloses(testNode->pn_pos));
RootedValue stmt(cx), test(cx); RootedValue stmt(cx), test(cx);
return statement(pn->pn_left, &stmt) && return statement(stmtNode, &stmt) &&
expression(pn->pn_right, &test) && expression(testNode, &test) &&
builder.doWhileStatement(stmt, test, &pn->pn_pos, dst); builder.doWhileStatement(stmt, test, &node->pn_pos, dst);
} }
case PNK_FOR: case PNK_FOR:
case PNK_COMPREHENSIONFOR: case PNK_COMPREHENSIONFOR:
{ {
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); ForNode* forNode = &pn->as<ForNode>();
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
TernaryNode* head = &pn->pn_left->as<TernaryNode>(); TernaryNode* head = forNode->head();
MOZ_ASSERT(forNode->pn_pos.encloses(head->pn_pos));
ParseNode* stmtNode = forNode->right();
MOZ_ASSERT(forNode->pn_pos.encloses(stmtNode->pn_pos));
ParseNode* initNode = head->kid1(); ParseNode* initNode = head->kid1();
MOZ_ASSERT_IF(initNode, head->pn_pos.encloses(initNode->pn_pos)); MOZ_ASSERT_IF(initNode, head->pn_pos.encloses(initNode->pn_pos));
@ -2548,7 +2569,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
MOZ_ASSERT_IF(updateOrIter, head->pn_pos.encloses(updateOrIter->pn_pos)); MOZ_ASSERT_IF(updateOrIter, head->pn_pos.encloses(updateOrIter->pn_pos));
RootedValue stmt(cx); RootedValue stmt(cx);
if (!statement(pn->pn_right, &stmt)) if (!statement(stmtNode, &stmt))
return false; return false;
if (head->isKind(PNK_FORIN) || head->isKind(PNK_FOROF)) { if (head->isKind(PNK_FORIN) || head->isKind(PNK_FOROF)) {
@ -2572,8 +2593,8 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
} }
} }
if (head->isKind(PNK_FORIN)) if (head->isKind(PNK_FORIN))
return forIn(pn, updateOrIter, var, stmt, dst); return forIn(forNode, updateOrIter, var, stmt, dst);
return forOf(pn, updateOrIter, var, stmt, dst); return forOf(forNode, updateOrIter, var, stmt, dst);
} }
RootedValue init(cx), test(cx), update(cx); RootedValue init(cx), test(cx), update(cx);
@ -2581,7 +2602,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
return forInit(initNode, &init) && return forInit(initNode, &init) &&
optExpression(maybeTest, &test) && optExpression(maybeTest, &test) &&
optExpression(updateOrIter, &update) && optExpression(updateOrIter, &update) &&
builder.forStatement(init, test, update, stmt, &pn->pn_pos, dst); builder.forStatement(init, test, update, stmt, &forNode->pn_pos, dst);
} }
case PNK_BREAK: case PNK_BREAK:
@ -2639,7 +2660,8 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
if (!methods.reserve(methodList->count())) if (!methods.reserve(methodList->count()))
return false; return false;
for (ParseNode* method : methodList->contents()) { for (ParseNode* item : methodList->contents()) {
ClassMethod* method = &item->as<ClassMethod>();
MOZ_ASSERT(methodList->pn_pos.encloses(method->pn_pos)); MOZ_ASSERT(methodList->pn_pos.encloses(method->pn_pos));
RootedValue prop(cx); RootedValue prop(cx);
@ -2660,10 +2682,10 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
} }
bool bool
ASTSerializer::classMethod(ParseNode* pn, MutableHandleValue dst) ASTSerializer::classMethod(ClassMethod* classMethod, MutableHandleValue dst)
{ {
PropKind kind; PropKind kind;
switch (pn->getOp()) { switch (classMethod->getOp()) {
case JSOP_INITPROP: case JSOP_INITPROP:
kind = PROP_INIT; kind = PROP_INIT;
break; break;
@ -2681,10 +2703,10 @@ ASTSerializer::classMethod(ParseNode* pn, MutableHandleValue dst)
} }
RootedValue key(cx), val(cx); RootedValue key(cx), val(cx);
bool isStatic = pn->as<ClassMethod>().isStatic(); bool isStatic = classMethod->isStatic();
return propertyName(pn->pn_left, &key) && return propertyName(&classMethod->name(), &key) &&
expression(pn->pn_right, &val) && expression(&classMethod->method(), &val) &&
builder.classMethod(key, val, kind, isStatic, &pn->pn_pos, dst); builder.classMethod(key, val, kind, isStatic, &classMethod->pn_pos, dst);
} }
bool bool
@ -2767,15 +2789,13 @@ ASTSerializer::rightAssociate(ListNode* node, MutableHandleValue dst)
} }
bool bool
ASTSerializer::comprehensionBlock(ParseNode* pn, MutableHandleValue dst) ASTSerializer::comprehensionBlock(ForNode* forNode, MutableHandleValue dst)
{ {
LOCAL_ASSERT(pn->isArity(PN_BINARY)); TernaryNode* in = forNode->head();
TernaryNode* in = &pn->pn_left->as<TernaryNode>();
LOCAL_ASSERT(in && (in->isKind(PNK_FORIN) || in->isKind(PNK_FOROF))); LOCAL_ASSERT(in && (in->isKind(PNK_FORIN) || in->isKind(PNK_FOROF)));
bool isForEach = in->isKind(PNK_FORIN) && (pn->pn_iflags & JSITER_FOREACH); bool isForEach = in->isKind(PNK_FORIN) && (forNode->iflags() & JSITER_FOREACH);
bool isForOf = in->isKind(PNK_FOROF); bool isForOf = in->isKind(PNK_FOROF);
ListNode* decl; ListNode* decl;
@ -2817,10 +2837,11 @@ ASTSerializer::comprehension(ParseNode* pn, MutableHandleValue dst)
RootedValue filter(cx, MagicValue(JS_SERIALIZE_NO_NODE)); RootedValue filter(cx, MagicValue(JS_SERIALIZE_NO_NODE));
while (true) { while (true) {
if (next->isKind(PNK_COMPREHENSIONFOR)) { if (next->isKind(PNK_COMPREHENSIONFOR)) {
ForNode* forNode = &next->as<ForNode>();
RootedValue block(cx); RootedValue block(cx);
if (!comprehensionBlock(next, &block) || !blocks.append(block)) if (!comprehensionBlock(forNode, &block) || !blocks.append(block))
return false; return false;
next = next->pn_right; next = forNode->body();
} else if (next->isKind(PNK_IF)) { } else if (next->isKind(PNK_IF)) {
TernaryNode* tn = &next->as<TernaryNode>(); TernaryNode* tn = &next->as<TernaryNode>();
if (isLegacy) { if (isLegacy) {
@ -2862,10 +2883,11 @@ ASTSerializer::generatorExpression(ParseNode* pn, MutableHandleValue dst)
RootedValue filter(cx, MagicValue(JS_SERIALIZE_NO_NODE)); RootedValue filter(cx, MagicValue(JS_SERIALIZE_NO_NODE));
while (true) { while (true) {
if (next->isKind(PNK_COMPREHENSIONFOR)) { if (next->isKind(PNK_COMPREHENSIONFOR)) {
ForNode* forNode = &next->as<ForNode>();
RootedValue block(cx); RootedValue block(cx);
if (!comprehensionBlock(next, &block) || !blocks.append(block)) if (!comprehensionBlock(forNode, &block) || !blocks.append(block))
return false; return false;
next = next->pn_right; next = forNode->body();
} else if (next->isKind(PNK_IF)) { } else if (next->isKind(PNK_IF)) {
TernaryNode* tn = &next->as<TernaryNode>(); TernaryNode* tn = &next->as<TernaryNode>();
if (isLegacy) { if (isLegacy) {
@ -2972,16 +2994,19 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_MODASSIGN: case PNK_MODASSIGN:
case PNK_POWASSIGN: case PNK_POWASSIGN:
{ {
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); AssignmentNode* assignNode = &pn->as<AssignmentNode>();
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); ParseNode* lhsNode = assignNode->left();
ParseNode* rhsNode = assignNode->right();
MOZ_ASSERT(assignNode->pn_pos.encloses(lhsNode->pn_pos));
MOZ_ASSERT(assignNode->pn_pos.encloses(rhsNode->pn_pos));
AssignmentOperator op = aop(pn->getOp()); AssignmentOperator op = aop(assignNode->getOp());
LOCAL_ASSERT(op > AOP_ERR && op < AOP_LIMIT); LOCAL_ASSERT(op > AOP_ERR && op < AOP_LIMIT);
RootedValue lhs(cx), rhs(cx); RootedValue lhs(cx), rhs(cx);
return pattern(pn->pn_left, &lhs) && return pattern(lhsNode, &lhs) &&
expression(pn->pn_right, &rhs) && expression(rhsNode, &rhs) &&
builder.assignmentExpression(op, lhs, rhs, &pn->pn_pos, dst); builder.assignmentExpression(op, lhs, rhs, &assignNode->pn_pos, dst);
} }
case PNK_ADD: case PNK_ADD:
@ -3033,7 +3058,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
} }
case PNK_GENEXP: { case PNK_GENEXP: {
ParseNode* callee = pn->pn_left; ParseNode* callee = pn->as<BinaryNode>().left();
MOZ_ASSERT(callee->isKind(PNK_FUNCTION)); MOZ_ASSERT(callee->isKind(PNK_FUNCTION));
ListNode* paramsBody = &callee->pn_body->as<ListNode>(); ListNode* paramsBody = &callee->pn_body->as<ListNode>();
@ -3064,17 +3089,18 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_OPTCALL: case PNK_OPTCALL:
case PNK_SUPERCALL: case PNK_SUPERCALL:
{ {
ParseNode* pn_callee = pn->pn_left; BinaryNode* node = &pn->as<BinaryNode>();
ListNode* argsList = &pn->pn_right->as<ListNode>(); ParseNode* calleeNode = node->left();
MOZ_ASSERT(pn->pn_pos.encloses(pn_callee->pn_pos)); ListNode* argsList = &node->right()->as<ListNode>();
MOZ_ASSERT(node->pn_pos.encloses(calleeNode->pn_pos));
RootedValue callee(cx); RootedValue callee(cx);
if (pn->isKind(PNK_SUPERCALL)) { if (node->isKind(PNK_SUPERCALL)) {
MOZ_ASSERT(pn_callee->isKind(PNK_SUPERBASE)); MOZ_ASSERT(calleeNode->isKind(PNK_SUPERBASE));
if (!builder.super(&pn_callee->pn_pos, &callee)) if (!builder.super(&calleeNode->pn_pos, &callee))
return false; return false;
} else { } else {
if (!expression(pn_callee, &callee)) if (!expression(calleeNode, &callee))
return false; return false;
} }
@ -3083,7 +3109,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
return false; return false;
for (ParseNode* argNode : argsList->contents()) { for (ParseNode* argNode : argsList->contents()) {
MOZ_ASSERT(pn->pn_pos.encloses(argNode->pn_pos)); MOZ_ASSERT(node->pn_pos.encloses(argNode->pn_pos));
RootedValue arg(cx); RootedValue arg(cx);
if (!expression(argNode, &arg)) if (!expression(argNode, &arg))
@ -3091,67 +3117,63 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
args.infallibleAppend(arg); args.infallibleAppend(arg);
} }
if (pn->getKind() == PNK_TAGGED_TEMPLATE) if (node->getKind() == PNK_TAGGED_TEMPLATE)
return builder.taggedTemplate(callee, args, &pn->pn_pos, dst); return builder.taggedTemplate(callee, args, &node->pn_pos, dst);
bool isOptional = pn->isKind(PNK_OPTCALL); bool isOptional = node->isKind(PNK_OPTCALL);
// SUPERCALL is Call(super, args) // SUPERCALL is Call(super, args)
return pn->isKind(PNK_NEW) return node->isKind(PNK_NEW)
? builder.newExpression(callee, args, &pn->pn_pos, dst) ? builder.newExpression(callee, args, &node->pn_pos, dst)
: builder.callExpression(callee, args, &pn->pn_pos, dst, isOptional); : builder.callExpression(callee, args, &node->pn_pos, dst, isOptional);
} }
case PNK_OPTDOT: case PNK_OPTDOT:
case PNK_DOT: case PNK_DOT:
{ {
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); PropertyAccess* prop = &pn->as<PropertyAccess>();
MOZ_ASSERT(prop->pn_pos.encloses(prop->expression().pn_pos));
RootedValue expr(cx); RootedValue expr(cx);
RootedValue propname(cx); RootedValue propname(cx);
RootedAtom pnAtom(cx, pn->pn_right->pn_atom); RootedAtom pnAtom(cx, prop->key().pn_atom);
bool isSuper = pn->is<PropertyAccess>() && if (prop->isSuper()) {
pn->as<PropertyAccess>().isSuper(); if (!builder.super(&prop->expression().pn_pos, &expr))
if (isSuper) {
if (!builder.super(&pn->pn_left->pn_pos, &expr))
return false; return false;
} else { } else {
if (!expression(pn->pn_left, &expr)) if (!expression(&prop->expression(), &expr))
return false; return false;
} }
bool isOptional = pn->isKind(PNK_OPTDOT); bool isOptional = prop->isKind(PNK_OPTDOT);
return identifier(pnAtom, nullptr, &propname) && return identifier(pnAtom, nullptr, &propname) &&
builder.memberExpression(false, expr, propname, &pn->pn_pos, builder.memberExpression(false, expr, propname, &prop->pn_pos,
dst, isOptional); dst, isOptional);
} }
case PNK_OPTELEM: case PNK_OPTELEM:
case PNK_ELEM: case PNK_ELEM:
{ {
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); PropertyByValueBase* elem = &pn->as<PropertyByValueBase>();
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); MOZ_ASSERT(elem->pn_pos.encloses(elem->expression().pn_pos));
MOZ_ASSERT(elem->pn_pos.encloses(elem->key().pn_pos));
RootedValue left(cx), right(cx); RootedValue expr(cx), key(cx);
bool isSuper = pn->is<PropertyByValue>() && if (elem->isSuper()) {
pn->as<PropertyByValue>().isSuper(); if (!builder.super(&elem->expression().pn_pos, &expr))
if (isSuper) {
if (!builder.super(&pn->pn_left->pn_pos, &left))
return false; return false;
} else { } else {
if (!expression(pn->pn_left, &left)) if (!expression(&elem->expression(), &expr))
return false; return false;
} }
bool isOptional = pn->isKind(PNK_OPTELEM); bool isOptional = elem->isKind(PNK_OPTELEM);
return expression(pn->pn_right, &right) && return expression(&elem->key(), &key) &&
builder.memberExpression(true, left, right, &pn->pn_pos, dst, builder.memberExpression(true, expr, key, &elem->pn_pos, dst,
isOptional); isOptional);
} }
@ -3288,7 +3310,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos)); MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos));
RootedValue arg(cx); RootedValue arg(cx);
return expression(pn->pn_left, &arg) && return expression(pn->pn_kid, &arg) &&
builder.yieldExpression(arg, Delegating, &pn->pn_pos, dst); builder.yieldExpression(arg, Delegating, &pn->pn_pos, dst);
} }
@ -3316,10 +3338,14 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_NEWTARGET: case PNK_NEWTARGET:
{ {
MOZ_ASSERT(pn->pn_left->isKind(PNK_POSHOLDER)); BinaryNode* node = &pn->as<BinaryNode>();
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); ParseNode* firstNode = node->left();
MOZ_ASSERT(pn->pn_right->isKind(PNK_POSHOLDER)); MOZ_ASSERT(firstNode->isKind(PNK_POSHOLDER));
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); MOZ_ASSERT(node->pn_pos.encloses(firstNode->pn_pos));
ParseNode* secondNode = node->right();
MOZ_ASSERT(secondNode->isKind(PNK_POSHOLDER));
MOZ_ASSERT(node->pn_pos.encloses(secondNode->pn_pos));
RootedValue newIdent(cx); RootedValue newIdent(cx);
RootedValue targetIdent(cx); RootedValue targetIdent(cx);
@ -3327,16 +3353,18 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
RootedAtom newStr(cx, cx->names().new_); RootedAtom newStr(cx, cx->names().new_);
RootedAtom targetStr(cx, cx->names().target); RootedAtom targetStr(cx, cx->names().target);
return identifier(newStr, &pn->pn_left->pn_pos, &newIdent) && return identifier(newStr, &firstNode->pn_pos, &newIdent) &&
identifier(targetStr, &pn->pn_right->pn_pos, &targetIdent) && identifier(targetStr, &secondNode->pn_pos, &targetIdent) &&
builder.metaProperty(newIdent, targetIdent, &pn->pn_pos, dst); builder.metaProperty(newIdent, targetIdent, &node->pn_pos, dst);
} }
case PNK_SETTHIS: case PNK_SETTHIS: {
// SETTHIS is used to assign the result of a super() call to |this|. // SETTHIS is used to assign the result of a super() call to |this|.
// It's not part of the original AST, so just forward to the call. // It's not part of the original AST, so just forward to the call.
MOZ_ASSERT(pn->pn_left->isKind(PNK_NAME)); BinaryNode* node = &pn->as<BinaryNode>();
return expression(pn->pn_right, dst); MOZ_ASSERT(node->left()->isKind(PNK_NAME));
return expression(node->right(), dst);
}
default: default:
LOCAL_NOT_REACHED("unexpected expression type"); LOCAL_NOT_REACHED("unexpected expression type");
@ -3385,14 +3413,18 @@ ASTSerializer::property(ParseNode* pn, MutableHandleValue dst)
LOCAL_NOT_REACHED("unexpected object-literal property"); LOCAL_NOT_REACHED("unexpected object-literal property");
} }
bool isShorthand = pn->isKind(PNK_SHORTHAND); BinaryNode* node = &pn->as<BinaryNode>();
ParseNode* keyNode = node->left();
ParseNode* valNode = node->right();
bool isShorthand = node->isKind(PNK_SHORTHAND);
bool isMethod = bool isMethod =
pn->pn_right->isKind(PNK_FUNCTION) && valNode->isKind(PNK_FUNCTION) &&
pn->pn_right->pn_funbox->function()->kind() == JSFunction::Method; valNode->pn_funbox->function()->kind() == JSFunction::Method;
RootedValue key(cx), val(cx); RootedValue key(cx), val(cx);
return propertyName(pn->pn_left, &key) && return propertyName(keyNode, &key) &&
expression(pn->pn_right, &val) && expression(valNode, &val) &&
builder.propertyInitializer(key, val, kind, isShorthand, isMethod, &pn->pn_pos, dst); builder.propertyInitializer(key, val, kind, isShorthand, isMethod, &node->pn_pos, dst);
} }
bool bool
@ -3506,9 +3538,10 @@ ASTSerializer::objectPattern(ListNode* obj, MutableHandleValue dst)
return false; return false;
target = propdef->pn_kid; target = propdef->pn_kid;
} else { } else {
if (!propertyName(propdef->pn_left, &key)) BinaryNode* prop = &propdef->as<BinaryNode>();
if (!propertyName(prop->left(), &key))
return false; return false;
target = propdef->pn_right; target = prop->right();
} }
RootedValue patt(cx), prop(cx); RootedValue patt(cx), prop(cx);
@ -3665,9 +3698,9 @@ ASTSerializer::functionArgs(ParseNode* pn, ListNode* argsList,
pat = arg; pat = arg;
defNode = nullptr; defNode = nullptr;
} else { } else {
MOZ_ASSERT(arg->isKind(PNK_ASSIGN)); AssignmentNode* assignNode = &arg->as<AssignmentNode>();
pat = arg->pn_left; pat = assignNode->left();
defNode = arg->pn_right; defNode = assignNode->right();
} }
// Process the name or pattern. // Process the name or pattern.

File diff suppressed because it is too large Load diff

View file

@ -469,7 +469,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitGetFunctionThis(ParseNode* pn); MOZ_MUST_USE bool emitGetFunctionThis(ParseNode* pn);
MOZ_MUST_USE bool emitGetFunctionThis(const mozilla::Maybe<uint32_t>& offset); MOZ_MUST_USE bool emitGetFunctionThis(const mozilla::Maybe<uint32_t>& offset);
MOZ_MUST_USE bool emitGetThisForSuperBase(ParseNode* pn); MOZ_MUST_USE bool emitGetThisForSuperBase(ParseNode* pn);
MOZ_MUST_USE bool emitSetThis(ParseNode* pn); MOZ_MUST_USE bool emitSetThis(BinaryNode* setThisNode);
MOZ_MUST_USE bool emitCheckDerivedClassConstructorReturn(); MOZ_MUST_USE bool emitCheckDerivedClassConstructorReturn();
// Handle jump opcodes and jump targets. // Handle jump opcodes and jump targets.
@ -564,7 +564,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
} }
MOZ_MUST_USE bool emitAwaitInInnermostScope(ParseNode* pn); MOZ_MUST_USE bool emitAwaitInInnermostScope(ParseNode* pn);
MOZ_MUST_USE bool emitAwaitInScope(EmitterScope& currentScope); MOZ_MUST_USE bool emitAwaitInScope(EmitterScope& currentScope);
MOZ_MUST_USE bool emitPropLHS(ParseNode* pn); MOZ_MUST_USE bool emitPropLHS(PropertyAccess* prop);
MOZ_MUST_USE bool emitPropIncDec(ParseNode* pn); MOZ_MUST_USE bool emitPropIncDec(ParseNode* pn);
MOZ_MUST_USE bool emitAsyncWrapperLambda(unsigned index, bool isArrow); MOZ_MUST_USE bool emitAsyncWrapperLambda(unsigned index, bool isArrow);
@ -577,7 +577,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
// opcode onto the stack in the right order. In the case of SETELEM, the // opcode onto the stack in the right order. In the case of SETELEM, the
// value to be assigned must already be pushed. // value to be assigned must already be pushed.
enum class EmitElemOption { Get, Set, Call, IncDec, CompoundAssign, Ref }; enum class EmitElemOption { Get, Set, Call, IncDec, CompoundAssign, Ref };
MOZ_MUST_USE bool emitElemOperands(ParseNode* pn, EmitElemOption opts); MOZ_MUST_USE bool emitElemOperands(PropertyByValue* elem, EmitElemOption opts);
MOZ_MUST_USE bool emitElemObjAndKey(PropertyByValue* elem, bool isSuper, ElemOpEmitter& eoe); MOZ_MUST_USE bool emitElemObjAndKey(PropertyByValue* elem, bool isSuper, ElemOpEmitter& eoe);
MOZ_MUST_USE bool emitElemOpBase(JSOp op); MOZ_MUST_USE bool emitElemOpBase(JSOp op);
@ -585,13 +585,13 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitCatch(TernaryNode* catchNode); MOZ_MUST_USE bool emitCatch(TernaryNode* catchNode);
MOZ_MUST_USE bool emitIf(TernaryNode* ifNode); MOZ_MUST_USE bool emitIf(TernaryNode* ifNode);
MOZ_MUST_USE bool emitWith(ParseNode* pn); MOZ_MUST_USE bool emitWith(BinaryNode* withNode);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLabeledStatement(const LabeledStatement* pn); MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLabeledStatement(const LabeledStatement* pn);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLexicalScope(ParseNode* pn); MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLexicalScope(ParseNode* pn);
MOZ_MUST_USE bool emitLexicalScopeBody(ParseNode* body, MOZ_MUST_USE bool emitLexicalScopeBody(ParseNode* body,
EmitLineNumberNote emitLineNote = EMIT_LINENOTE); EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitSwitch(SwitchStatement* pn); MOZ_NEVER_INLINE MOZ_MUST_USE bool emitSwitch(SwitchStatement* switchStmt);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitTry(TernaryNode* tryNode); MOZ_NEVER_INLINE MOZ_MUST_USE bool emitTry(TernaryNode* tryNode);
enum DestructuringFlavor { enum DestructuringFlavor {
@ -720,7 +720,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitOptionalElemExpression(PropertyByValueBase* elem, MOZ_MUST_USE bool emitOptionalElemExpression(PropertyByValueBase* elem,
ElemOpEmitter& eoe, bool isSuper, ElemOpEmitter& eoe, bool isSuper,
OptionalEmitter& oe); OptionalEmitter& oe);
MOZ_MUST_USE bool emitOptionalCall(ParseNode* callNode, MOZ_MUST_USE bool emitOptionalCall(BinaryNode* callNode,
OptionalEmitter& oe, OptionalEmitter& oe,
ValueUsage valueUsage); ValueUsage valueUsage);
MOZ_MUST_USE bool emitDeletePropertyInOptChain(PropertyAccessBase* propExpr, MOZ_MUST_USE bool emitDeletePropertyInOptChain(PropertyAccessBase* propExpr,
@ -750,7 +750,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
ListNode* argsList); ListNode* argsList);
MOZ_MUST_USE bool emitArguments(ListNode* argsList, bool isCall, bool isSpread, MOZ_MUST_USE bool emitArguments(ListNode* argsList, bool isCall, bool isSpread,
CallOrNewEmitter& cone); CallOrNewEmitter& cone);
MOZ_MUST_USE bool emitCallOrNew(ParseNode* pn, MOZ_MUST_USE bool emitCallOrNew(BinaryNode* pn,
ValueUsage valueUsage = ValueUsage::WantValue); ValueUsage valueUsage = ValueUsage::WantValue);
MOZ_MUST_USE bool emitCalleeAndThis(ParseNode* callNode, MOZ_MUST_USE bool emitCalleeAndThis(ParseNode* callNode,
ParseNode* calleeNode, ParseNode* calleeNode,
@ -760,23 +760,23 @@ struct MOZ_STACK_CLASS BytecodeEmitter
CallOrNewEmitter& cone, CallOrNewEmitter& cone,
OptionalEmitter& oe); OptionalEmitter& oe);
MOZ_MUST_USE bool emitSelfHostedCallFunction(ParseNode* pn); MOZ_MUST_USE bool emitSelfHostedCallFunction(BinaryNode* callNode);
MOZ_MUST_USE bool emitSelfHostedResumeGenerator(ParseNode* pn); MOZ_MUST_USE bool emitSelfHostedResumeGenerator(BinaryNode* callNode);
MOZ_MUST_USE bool emitSelfHostedForceInterpreter(ParseNode* pn); MOZ_MUST_USE bool emitSelfHostedForceInterpreter(ParseNode* pn);
MOZ_MUST_USE bool emitSelfHostedAllowContentIter(ParseNode* pn); MOZ_MUST_USE bool emitSelfHostedAllowContentIter(BinaryNode* callNode);
MOZ_MUST_USE bool emitComprehensionFor(ParseNode* compFor); MOZ_MUST_USE bool emitComprehensionFor(ForNode* forNode);
MOZ_MUST_USE bool emitComprehensionForIn(ParseNode* pn); MOZ_MUST_USE bool emitComprehensionForIn(ForNode* forNode);
MOZ_MUST_USE bool emitComprehensionForInOrOfVariables(ParseNode* pn, bool* lexicalScope); MOZ_MUST_USE bool emitComprehensionForInOrOfVariables(ParseNode* pn, bool* lexicalScope);
MOZ_MUST_USE bool emitComprehensionForOf(ParseNode* pn); MOZ_MUST_USE bool emitComprehensionForOf(ForNode* forNode);
MOZ_MUST_USE bool emitDo(ParseNode* pn); MOZ_MUST_USE bool emitDo(BinaryNode* doNode);
MOZ_MUST_USE bool emitWhile(ParseNode* pn); MOZ_MUST_USE bool emitWhile(BinaryNode* whileNode);
MOZ_MUST_USE bool emitFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope = nullptr); MOZ_MUST_USE bool emitFor(ForNode* forNode, EmitterScope* headLexicalEmitterScope = nullptr);
MOZ_MUST_USE bool emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope); MOZ_MUST_USE bool emitCStyleFor(ForNode* forNode, EmitterScope* headLexicalEmitterScope);
MOZ_MUST_USE bool emitForIn(ParseNode* pn, EmitterScope* headLexicalEmitterScope); MOZ_MUST_USE bool emitForIn(ForNode* forNode, EmitterScope* headLexicalEmitterScope);
MOZ_MUST_USE bool emitForOf(ParseNode* pn, EmitterScope* headLexicalEmitterScope); MOZ_MUST_USE bool emitForOf(ForNode* forNode, EmitterScope* headLexicalEmitterScope);
MOZ_MUST_USE bool emitInitializeForInOrOfTarget(TernaryNode* forHead); MOZ_MUST_USE bool emitInitializeForInOrOfTarget(TernaryNode* forHead);

View file

@ -141,14 +141,14 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
// Statements possibly containing hoistable declarations only in the left // Statements possibly containing hoistable declarations only in the left
// half, in ParseNode terms -- the loop body in AST terms. // half, in ParseNode terms -- the loop body in AST terms.
case PNK_DOWHILE: case PNK_DOWHILE:
return ContainsHoistedDeclaration(cx, node->pn_left, result); return ContainsHoistedDeclaration(cx, node->as<BinaryNode>().left(), result);
// Statements possibly containing hoistable declarations only in the // Statements possibly containing hoistable declarations only in the
// right half, in ParseNode terms -- the loop body or nested statement // right half, in ParseNode terms -- the loop body or nested statement
// (usually a block statement), in AST terms. // (usually a block statement), in AST terms.
case PNK_WHILE: case PNK_WHILE:
case PNK_WITH: case PNK_WITH:
return ContainsHoistedDeclaration(cx, node->pn_right, result); return ContainsHoistedDeclaration(cx, node->as<BinaryNode>().right(), result);
case PNK_LABEL: case PNK_LABEL:
return ContainsHoistedDeclaration(cx, node->pn_expr, result); return ContainsHoistedDeclaration(cx, node->pn_expr, result);
@ -228,18 +228,20 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
// A switch node's left half is an expression; only its right half (a // A switch node's left half is an expression; only its right half (a
// list of cases/defaults, or a block node) could contain hoisted // list of cases/defaults, or a block node) could contain hoisted
// declarations. // declarations.
case PNK_SWITCH: case PNK_SWITCH: {
MOZ_ASSERT(node->isArity(PN_BINARY)); SwitchStatement* switchNode = &node->as<SwitchStatement>();
return ContainsHoistedDeclaration(cx, node->pn_right, result); return ContainsHoistedDeclaration(cx, &switchNode->lexicalForCaseList(), result);
}
case PNK_CASE: case PNK_CASE: {
return ContainsHoistedDeclaration(cx, node->as<CaseClause>().statementList(), result); CaseClause* caseClause = &node->as<CaseClause>();
return ContainsHoistedDeclaration(cx, caseClause->statementList(), result);
}
case PNK_FOR: case PNK_FOR:
case PNK_COMPREHENSIONFOR: { case PNK_COMPREHENSIONFOR: {
MOZ_ASSERT(node->isArity(PN_BINARY)); ForNode* forNode = &node->as<ForNode>();
TernaryNode* loopHead = forNode->head();
TernaryNode* loopHead = &node->pn_left->as<TernaryNode>();
MOZ_ASSERT(loopHead->isKind(PNK_FORHEAD) || MOZ_ASSERT(loopHead->isKind(PNK_FORHEAD) ||
loopHead->isKind(PNK_FORIN) || loopHead->isKind(PNK_FORIN) ||
loopHead->isKind(PNK_FOROF)); loopHead->isKind(PNK_FOROF));
@ -275,7 +277,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
} }
} }
ParseNode* loopBody = node->pn_right; ParseNode* loopBody = forNode->body();
return ContainsHoistedDeclaration(cx, loopBody, result); return ContainsHoistedDeclaration(cx, loopBody, result);
} }
@ -1301,19 +1303,16 @@ static bool
FoldElement(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& parser, FoldElement(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& parser,
bool inGenexpLambda) bool inGenexpLambda)
{ {
ParseNode* node = *nodePtr; PropertyByValueBase* elem = &(*nodePtr)->as<PropertyByValueBase>();
MOZ_ASSERT(node->isKind(PNK_ELEM) || node->isKind(PNK_OPTELEM)); if (!Fold(cx, elem->unsafeLeftReference(), parser, inGenexpLambda))
MOZ_ASSERT(node->isArity(PN_BINARY));
ParseNode*& expr = node->pn_left;
if (!Fold(cx, &expr, parser, inGenexpLambda))
return false; return false;
ParseNode*& key = node->pn_right; if (!Fold(cx, elem->unsafeRightReference(), parser, inGenexpLambda))
if (!Fold(cx, &key, parser, inGenexpLambda))
return false; return false;
ParseNode* expr = &elem->expression();
ParseNode* key = &elem->key();
PropertyName* name = nullptr; PropertyName* name = nullptr;
if (key->isKind(PNK_STRING)) { if (key->isKind(PNK_STRING)) {
JSAtom* atom = key->pn_atom; JSAtom* atom = key->pn_atom;
@ -1351,7 +1350,7 @@ FoldElement(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>&
if (!nameNode) if (!nameNode)
return false; return false;
ParseNode* dottedAccess; ParseNode* dottedAccess;
if (node->isKind(PNK_OPTELEM)) { if (elem->isKind(PNK_OPTELEM)) {
dottedAccess = parser.handler.newOptionalPropertyAccess(expr, nameNode); dottedAccess = parser.handler.newOptionalPropertyAccess(expr, nameNode);
} else { } else {
dottedAccess = parser.handler.newPropertyAccess(expr, nameNode); dottedAccess = parser.handler.newPropertyAccess(expr, nameNode);
@ -1359,7 +1358,7 @@ FoldElement(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>&
if (!dottedAccess) { if (!dottedAccess) {
return false; return false;
} }
dottedAccess->setInParens(node->isInParens()); dottedAccess->setInParens(elem->isInParens());
ReplaceNode(nodePtr, dottedAccess); ReplaceNode(nodePtr, dottedAccess);
// If we've replaced |expr["prop"]| with |expr.prop|, we can now free the // If we've replaced |expr["prop"]| with |expr.prop|, we can now free the
@ -1367,10 +1366,10 @@ FoldElement(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>&
// now using as a sub-node of |dottedAccess|. Munge |expr["prop"]| into a // now using as a sub-node of |dottedAccess|. Munge |expr["prop"]| into a
// node with |"prop"| as its only child, that'll pass AST sanity-checking // node with |"prop"| as its only child, that'll pass AST sanity-checking
// assertions during freeing, then free it. // assertions during freeing, then free it.
node->setKind(PNK_TYPEOFEXPR); elem->setKind(PNK_TYPEOFEXPR);
node->setArity(PN_UNARY); elem->setArity(PN_UNARY);
node->pn_kid = key; elem->pn_kid = key;
parser.freeTree(node); parser.freeTree(elem);
return true; return true;
} }
@ -1523,7 +1522,7 @@ FoldAdd(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& par
} }
static bool static bool
FoldCall(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser, FoldCall(ExclusiveContext* cx, BinaryNode* node, Parser<FullParseHandler>& parser,
bool inGenexpLambda) bool inGenexpLambda)
{ {
MOZ_ASSERT(node->isKind(PNK_CALL) || MOZ_ASSERT(node->isKind(PNK_CALL) ||
@ -1531,7 +1530,6 @@ FoldCall(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser
node->isKind(PNK_SUPERCALL) || node->isKind(PNK_SUPERCALL) ||
node->isKind(PNK_NEW) || node->isKind(PNK_NEW) ||
node->isKind(PNK_TAGGED_TEMPLATE)); node->isKind(PNK_TAGGED_TEMPLATE));
MOZ_ASSERT(node->isArity(PN_BINARY));
// Don't fold a parenthesized callable component in an invocation, as this // Don't fold a parenthesized callable component in an invocation, as this
// might cause a different |this| value to be used, changing semantics: // might cause a different |this| value to be used, changing semantics:
@ -1544,14 +1542,13 @@ FoldCall(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser
// assertEq(obj.f``, "obj"); // assertEq(obj.f``, "obj");
// //
// See bug 537673 and bug 1182373. // See bug 537673 and bug 1182373.
ParseNode** pn_callee = &node->pn_left; ParseNode* callee = node->left();
if (node->isKind(PNK_NEW) || !(*pn_callee)->isInParens()) { if (node->isKind(PNK_NEW) || !callee->isInParens()) {
if (!Fold(cx, pn_callee, parser, inGenexpLambda)) if (!Fold(cx, node->unsafeLeftReference(), parser, inGenexpLambda))
return false; return false;
} }
ParseNode** pn_args = &node->pn_right; if (!Fold(cx, node->unsafeRightReference(), parser, inGenexpLambda))
if (!Fold(cx, pn_args, parser, inGenexpLambda))
return false; return false;
return true; return true;
@ -1616,18 +1613,14 @@ FoldForHead(ExclusiveContext* cx, TernaryNode* node, Parser<FullParseHandler>& p
} }
static bool static bool
FoldDottedProperty(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser, FoldDottedProperty(ExclusiveContext* cx, PropertyAccessBase* prop, Parser<FullParseHandler>& parser,
bool inGenexpLambda) bool inGenexpLambda)
{ {
MOZ_ASSERT(node->isKind(PNK_DOT) || node->isKind(PNK_OPTDOT));
MOZ_ASSERT(node->isArity(PN_BINARY));
// Iterate through a long chain of dotted property accesses to find the // Iterate through a long chain of dotted property accesses to find the
// most-nested non-dotted property node, then fold that. // most-nested non-dotted property node, then fold that.
ParseNode** nested = &node->pn_left; ParseNode** nested = prop->unsafeLeftReference();
while ((*nested)->isKind(PNK_DOT) || (*nested)->isKind(PNK_OPTDOT)) { while ((*nested)->isKind(PNK_DOT) || (*nested)->isKind(PNK_OPTDOT)) {
MOZ_ASSERT((*nested)->isArity(PN_BINARY)); nested = (*nested)->as<PropertyAccessBase>().unsafeLeftReference();
nested = &(*nested)->pn_left;
} }
return Fold(cx, nested, parser, inGenexpLambda); return Fold(cx, nested, parser, inGenexpLambda);
@ -1736,8 +1729,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
case PNK_EXPORT_DEFAULT: case PNK_EXPORT_DEFAULT:
case PNK_GENEXP: case PNK_GENEXP:
MOZ_ASSERT(pn->isArity(PN_BINARY)); return Fold(cx, pn->as<BinaryNode>().unsafeLeftReference(), parser, inGenexpLambda);
return Fold(cx, &pn->pn_left, parser, inGenexpLambda);
case PNK_DELETEOPTCHAIN: case PNK_DELETEOPTCHAIN:
case PNK_OPTCHAIN: case PNK_OPTCHAIN:
@ -1804,12 +1796,15 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
case PNK_IMPORT_SPEC_LIST: case PNK_IMPORT_SPEC_LIST:
return FoldList(cx, &pn->as<ListNode>(), parser, inGenexpLambda); return FoldList(cx, &pn->as<ListNode>(), parser, inGenexpLambda);
case PNK_INITIALYIELD: case PNK_INITIALYIELD: {
MOZ_ASSERT(pn->isArity(PN_UNARY)); MOZ_ASSERT(pn->isArity(PN_UNARY));
MOZ_ASSERT(pn->pn_kid->isKind(PNK_ASSIGN) && #ifdef DEBUG
pn->pn_kid->pn_left->isKind(PNK_NAME) && AssignmentNode* assignNode = &pn->pn_kid->as<AssignmentNode>();
pn->pn_kid->pn_right->isKind(PNK_GENERATOR)); MOZ_ASSERT(assignNode->left()->isKind(PNK_NAME));
MOZ_ASSERT(assignNode->right()->isKind(PNK_GENERATOR));
#endif
return true; return true;
}
case PNK_YIELD_STAR: case PNK_YIELD_STAR:
MOZ_ASSERT(pn->isArity(PN_UNARY)); MOZ_ASSERT(pn->isArity(PN_UNARY));
@ -1836,6 +1831,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
case PNK_OPTELEM: case PNK_OPTELEM:
case PNK_ELEM: case PNK_ELEM:
MOZ_ASSERT((*pnp)->is<PropertyByValueBase>());
return FoldElement(cx, pnp, parser, inGenexpLambda); return FoldElement(cx, pnp, parser, inGenexpLambda);
case PNK_ADD: case PNK_ADD:
@ -1847,7 +1843,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
case PNK_NEW: case PNK_NEW:
case PNK_SUPERCALL: case PNK_SUPERCALL:
case PNK_TAGGED_TEMPLATE: case PNK_TAGGED_TEMPLATE:
return FoldCall(cx, pn, parser, inGenexpLambda); return FoldCall(cx, &pn->as<BinaryNode>(), parser, inGenexpLambda);
case PNK_ARGUMENTS: case PNK_ARGUMENTS:
return FoldArguments(cx, &pn->as<ListNode>(), parser, inGenexpLambda); return FoldArguments(cx, &pn->as<ListNode>(), parser, inGenexpLambda);
@ -1875,50 +1871,59 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
case PNK_CLASSMETHOD: case PNK_CLASSMETHOD:
case PNK_IMPORT_SPEC: case PNK_IMPORT_SPEC:
case PNK_EXPORT_SPEC: case PNK_EXPORT_SPEC:
case PNK_SETTHIS: case PNK_SETTHIS: {
MOZ_ASSERT(pn->isArity(PN_BINARY)); BinaryNode* node = &pn->as<BinaryNode>();
return Fold(cx, &pn->pn_left, parser, inGenexpLambda) && return Fold(cx, node->unsafeLeftReference(), parser, inGenexpLambda) &&
Fold(cx, &pn->pn_right, parser, inGenexpLambda); Fold(cx, node->unsafeRightReference(), parser, inGenexpLambda);
case PNK_NEWTARGET:
MOZ_ASSERT(pn->isArity(PN_BINARY));
MOZ_ASSERT(pn->pn_left->isKind(PNK_POSHOLDER));
MOZ_ASSERT(pn->pn_right->isKind(PNK_POSHOLDER));
return true;
case PNK_CLASSNAMES:
MOZ_ASSERT(pn->isArity(PN_BINARY));
if (ParseNode*& outerBinding = pn->pn_left) {
if (!Fold(cx, &outerBinding, parser, inGenexpLambda))
return false;
}
return Fold(cx, &pn->pn_right, parser, inGenexpLambda);
case PNK_DOWHILE:
MOZ_ASSERT(pn->isArity(PN_BINARY));
return Fold(cx, &pn->pn_left, parser, inGenexpLambda) &&
FoldCondition(cx, &pn->pn_right, parser, inGenexpLambda);
case PNK_WHILE:
MOZ_ASSERT(pn->isArity(PN_BINARY));
return FoldCondition(cx, &pn->pn_left, parser, inGenexpLambda) &&
Fold(cx, &pn->pn_right, parser, inGenexpLambda);
case PNK_CASE: {
MOZ_ASSERT(pn->isArity(PN_BINARY));
// pn_left is null for DefaultClauses.
if (pn->pn_left) {
if (!Fold(cx, &pn->pn_left, parser, inGenexpLambda))
return false;
}
return Fold(cx, &pn->pn_right, parser, inGenexpLambda);
} }
case PNK_WITH: case PNK_NEWTARGET:{
MOZ_ASSERT(pn->isArity(PN_BINARY)); #ifdef DEBUG
return Fold(cx, &pn->pn_left, parser, inGenexpLambda) && BinaryNode* node = &pn->as<BinaryNode>();
Fold(cx, &pn->pn_right, parser, inGenexpLambda); MOZ_ASSERT(node->left()->isKind(PNK_POSHOLDER));
MOZ_ASSERT(node->right()->isKind(PNK_POSHOLDER));
#endif
return true;
}
case PNK_CLASSNAMES: {
ClassNames* names = &pn->as<ClassNames>();
if (names->outerBinding()) {
if (!Fold(cx, names->unsafeLeftReference(), parser, inGenexpLambda)) {
return false;
}
}
return Fold(cx, names->unsafeRightReference(), parser, inGenexpLambda);
}
case PNK_DOWHILE: {
BinaryNode* node = &pn->as<BinaryNode>();
return Fold(cx, node->unsafeLeftReference(), parser, inGenexpLambda) &&
FoldCondition(cx, node->unsafeRightReference(), parser, inGenexpLambda);
}
case PNK_WHILE: {
BinaryNode* node = &pn->as<BinaryNode>();
return FoldCondition(cx, node->unsafeLeftReference(), parser, inGenexpLambda) &&
Fold(cx, node->unsafeRightReference(), parser, inGenexpLambda);
}
case PNK_CASE: {
CaseClause* caseClause = &pn->as<CaseClause>();
// left (caseExpression) is null for DefaultClauses.
if (caseClause->left()) {
if (!Fold(cx, caseClause->unsafeLeftReference(), parser, inGenexpLambda))
return false;
}
return Fold(cx, caseClause->unsafeRightReference(), parser, inGenexpLambda);
}
case PNK_WITH: {
BinaryNode* node = &pn->as<BinaryNode>();
return Fold(cx, node->unsafeLeftReference(), parser, inGenexpLambda) &&
Fold(cx, node->unsafeRightReference(), parser, inGenexpLambda);
}
case PNK_FORIN: case PNK_FORIN:
case PNK_FOROF: case PNK_FOROF:
@ -1936,7 +1941,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
case PNK_OPTDOT: case PNK_OPTDOT:
case PNK_DOT: case PNK_DOT:
return FoldDottedProperty(cx, pn, parser, inGenexpLambda); return FoldDottedProperty(cx, &pn->as<PropertyAccessBase>(), parser, inGenexpLambda);
case PNK_LEXICALSCOPE: case PNK_LEXICALSCOPE:
MOZ_ASSERT(pn->isArity(PN_SCOPE)); MOZ_ASSERT(pn->isArity(PN_SCOPE));

View file

@ -279,14 +279,14 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return new_<UnaryNode>(PNK_ARRAYPUSH, JSOP_ARRAYPUSH, pos, kid); return new_<UnaryNode>(PNK_ARRAYPUSH, JSOP_ARRAYPUSH, pos, kid);
} }
ParseNode* newBinary(ParseNodeKind kind, JSOp op = JSOP_NOP) { BinaryNodeType newBinary(ParseNodeKind kind, JSOp op = JSOP_NOP) {
return new_<BinaryNode>(kind, op, pos(), (ParseNode*) nullptr, (ParseNode*) nullptr); return new_<BinaryNode>(kind, op, pos(), (ParseNode*) nullptr, (ParseNode*) nullptr);
} }
ParseNode* newBinary(ParseNodeKind kind, ParseNode* left, BinaryNodeType newBinary(ParseNodeKind kind, ParseNode* left,
JSOp op = JSOP_NOP) { JSOp op = JSOP_NOP) {
return new_<BinaryNode>(kind, op, left->pn_pos, left, (ParseNode*) nullptr); return new_<BinaryNode>(kind, op, left->pn_pos, left, (ParseNode*) nullptr);
} }
ParseNode* newBinary(ParseNodeKind kind, ParseNode* left, ParseNode* right, BinaryNodeType newBinary(ParseNodeKind kind, ParseNode* left, ParseNode* right,
JSOp op = JSOP_NOP) { JSOp op = JSOP_NOP) {
TokenPos pos(left->pn_pos.begin, right->pn_pos.end); TokenPos pos(left->pn_pos.begin, right->pn_pos.end);
return new_<BinaryNode>(kind, op, pos, left, right); return new_<BinaryNode>(kind, op, pos, left, right);
@ -340,11 +340,11 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
literal->append(element); literal->append(element);
} }
ParseNode* newCall(ParseNode* callee, ParseNode* args) { BinaryNodeType newCall(ParseNode* callee, ParseNode* args) {
return new_<BinaryNode>(PNK_CALL, JSOP_CALL, callee, args); return new_<BinaryNode>(PNK_CALL, JSOP_CALL, callee, args);
} }
ParseNode* newOptionalCall(ParseNode* callee, ParseNode* args) { BinaryNodeType newOptionalCall(ParseNode* callee, ParseNode* args) {
return new_<BinaryNode>(PNK_OPTCALL, JSOP_CALL, callee, args); return new_<BinaryNode>(PNK_OPTCALL, JSOP_CALL, callee, args);
} }
@ -352,15 +352,15 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return new_<ListNode>(PNK_ARGUMENTS, JSOP_NOP, pos); return new_<ListNode>(PNK_ARGUMENTS, JSOP_NOP, pos);
} }
ParseNode* newSuperCall(ParseNode* callee, ParseNode* args) { BinaryNodeType newSuperCall(ParseNode* callee, ParseNode* args) {
return new_<BinaryNode>(PNK_SUPERCALL, JSOP_SUPERCALL, callee, args); return new_<BinaryNode>(PNK_SUPERCALL, JSOP_SUPERCALL, callee, args);
} }
ParseNode* newTaggedTemplate(ParseNode* tag, ParseNode* args) { BinaryNodeType newTaggedTemplate(ParseNode* tag, ParseNode* args) {
return new_<BinaryNode>(PNK_TAGGED_TEMPLATE, JSOP_CALL, tag, args); return new_<BinaryNode>(PNK_TAGGED_TEMPLATE, JSOP_CALL, tag, args);
} }
ParseNode* newGenExp(ParseNode* callee, ParseNode* args) { BinaryNodeType newGenExp(ParseNode* callee, ParseNode* args) {
return new_<BinaryNode>(PNK_GENEXP, JSOP_CALL, callee, args); return new_<BinaryNode>(PNK_GENEXP, JSOP_CALL, callee, args);
} }
@ -378,10 +378,10 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
ListNodeType newClassMethodList(uint32_t begin) { ListNodeType newClassMethodList(uint32_t begin) {
return new_<ListNode>(PNK_CLASSMETHODLIST, TokenPos(begin, begin + 1)); return new_<ListNode>(PNK_CLASSMETHODLIST, TokenPos(begin, begin + 1));
} }
ParseNode* newClassNames(ParseNode* outer, ParseNode* inner, const TokenPos& pos) { ClassNamesType newClassNames(ParseNode* outer, ParseNode* inner, const TokenPos& pos) {
return new_<ClassNames>(outer, inner, pos); return new_<ClassNames>(outer, inner, pos);
} }
ParseNode* newNewTarget(ParseNode* newHolder, ParseNode* targetHolder) { BinaryNodeType newNewTarget(ParseNode* newHolder, ParseNode* targetHolder) {
return new_<BinaryNode>(PNK_NEWTARGET, JSOP_NOP, newHolder, targetHolder); return new_<BinaryNode>(PNK_NEWTARGET, JSOP_NOP, newHolder, targetHolder);
} }
ParseNode* newPosHolder(const TokenPos& pos) { ParseNode* newPosHolder(const TokenPos& pos) {
@ -410,7 +410,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
key->isKind(PNK_STRING) || key->isKind(PNK_STRING) ||
key->isKind(PNK_COMPUTED_NAME)); key->isKind(PNK_COMPUTED_NAME));
ParseNode* propdef = newBinary(PNK_COLON, key, val, JSOP_INITPROP); BinaryNode* propdef = newBinary(PNK_COLON, key, val, JSOP_INITPROP);
if (!propdef) if (!propdef)
return false; return false;
@ -428,7 +428,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
MOZ_ASSERT(name->pn_atom == expr->pn_atom); MOZ_ASSERT(name->pn_atom == expr->pn_atom);
literal->setHasNonConstInitializer(); literal->setHasNonConstInitializer();
ParseNode* propdef = newBinary(PNK_SHORTHAND, name, expr, JSOP_INITPROP); BinaryNode* propdef = newBinary(PNK_SHORTHAND, name, expr, JSOP_INITPROP);
if (!propdef) if (!propdef)
return false; return false;
literal->append(propdef); literal->append(propdef);
@ -471,7 +471,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
key->isKind(PNK_STRING) || key->isKind(PNK_STRING) ||
key->isKind(PNK_COMPUTED_NAME)); key->isKind(PNK_COMPUTED_NAME));
ParseNode* classMethod = new_<ClassMethod>(key, fn, op, isStatic); ClassMethod* classMethod = new_<ClassMethod>(key, fn, op, isStatic);
if (!classMethod) if (!classMethod)
return false; return false;
methodList->append(classMethod); methodList->append(classMethod);
@ -527,14 +527,12 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
} }
} }
void addCaseStatementToList(ListNodeType list, ParseNode* caseClause) { void addCaseStatementToList(ListNodeType list, CaseClauseType caseClause) {
MOZ_ASSERT(list->isKind(PNK_STATEMENTLIST)); MOZ_ASSERT(list->isKind(PNK_STATEMENTLIST));
MOZ_ASSERT(caseClause->isKind(PNK_CASE));
MOZ_ASSERT(caseClause->pn_right->isKind(PNK_STATEMENTLIST));
list->append(caseClause); list->append(caseClause);
if (caseClause->pn_right->as<ListNode>().hasTopLevelFunctionDeclarations()) if (caseClause->statementList()->hasTopLevelFunctionDeclarations())
list->setHasTopLevelFunctionDeclarations(); list->setHasTopLevelFunctionDeclarations();
} }
@ -560,7 +558,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return true; return true;
} }
ParseNode* newSetThis(ParseNode* thisName, ParseNode* val) { BinaryNodeType newSetThis(ParseNode* thisName, ParseNode* val) {
MOZ_ASSERT(thisName->getOp() == JSOP_GETNAME); MOZ_ASSERT(thisName->getOp() == JSOP_GETNAME);
thisName->setOp(JSOP_SETNAME); thisName->setOp(JSOP_SETNAME);
return newBinary(PNK_SETTHIS, thisName, val); return newBinary(PNK_SETTHIS, thisName, val);
@ -570,13 +568,10 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, pos, (ParseNode*) nullptr); return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, pos, (ParseNode*) nullptr);
} }
ParseNode* newImportDeclaration(ParseNode* importSpecSet, BinaryNodeType newImportDeclaration(Node importSpecSet, Node moduleSpec, const TokenPos& pos)
ParseNode* moduleSpec, const TokenPos& pos)
{ {
ParseNode* pn = new_<BinaryNode>(PNK_IMPORT, JSOP_NOP, pos, BinaryNode* pn = new_<BinaryNode>(PNK_IMPORT, JSOP_NOP, pos,
importSpecSet, moduleSpec); importSpecSet, moduleSpec);
if (!pn)
return null();
return pn; return pn;
} }
@ -584,18 +579,21 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return new_<UnaryNode>(PNK_EXPORT, JSOP_NOP, pos, kid); return new_<UnaryNode>(PNK_EXPORT, JSOP_NOP, pos, kid);
} }
ParseNode* newExportFromDeclaration(uint32_t begin, ParseNode* exportSpecSet, BinaryNodeType newExportFromDeclaration(uint32_t begin, Node exportSpecSet, Node moduleSpec) {
ParseNode* moduleSpec) BinaryNode* decl = new_<BinaryNode>(PNK_EXPORT_FROM, JSOP_NOP, exportSpecSet, moduleSpec);
{ if (!decl)
ParseNode* pn = new_<BinaryNode>(PNK_EXPORT_FROM, JSOP_NOP, exportSpecSet, moduleSpec);
if (!pn)
return null(); return null();
pn->pn_pos.begin = begin; decl->pn_pos.begin = begin;
return pn; return decl;
} }
ParseNode* newExportDefaultDeclaration(ParseNode* kid, ParseNode* maybeBinding, BinaryNodeType newExportDefaultDeclaration(Node kid, Node maybeBinding, const TokenPos& pos) {
const TokenPos& pos) { if (maybeBinding) {
MOZ_ASSERT(maybeBinding->isKind(PNK_NAME));
MOZ_ASSERT(!maybeBinding->isInParens());
checkAndSetIsDirectRHSAnonFunction(kid);
}
return new_<BinaryNode>(PNK_EXPORT_DEFAULT, JSOP_NOP, pos, kid, maybeBinding); return new_<BinaryNode>(PNK_EXPORT_DEFAULT, JSOP_NOP, pos, kid, maybeBinding);
} }
@ -612,36 +610,28 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return node; return node;
} }
ParseNode* newDoWhileStatement(ParseNode* body, ParseNode* cond, const TokenPos& pos) { BinaryNodeType newDoWhileStatement(Node body, Node cond, const TokenPos& pos) {
return new_<BinaryNode>(PNK_DOWHILE, JSOP_NOP, pos, body, cond); return new_<BinaryNode>(PNK_DOWHILE, JSOP_NOP, pos, body, cond);
} }
ParseNode* newWhileStatement(uint32_t begin, ParseNode* cond, ParseNode* body) { BinaryNodeType newWhileStatement(uint32_t begin, Node cond, Node body) {
TokenPos pos(begin, body->pn_pos.end); TokenPos pos(begin, body->pn_pos.end);
return new_<BinaryNode>(PNK_WHILE, JSOP_NOP, pos, cond, body); return new_<BinaryNode>(PNK_WHILE, JSOP_NOP, pos, cond, body);
} }
Node newForStatement(uint32_t begin, TernaryNodeType forHead, Node body, unsigned iflags) { ForNodeType newForStatement(uint32_t begin, TernaryNodeType forHead, Node body, unsigned iflags)
/* A FOR node is binary, left is loop control and right is the body. */ {
JSOp op = forHead->isKind(PNK_FORIN) ? JSOP_ITER : JSOP_NOP; return new_<ForNode>(TokenPos(begin, body->pn_pos.end), forHead, body, iflags);
BinaryNode* pn = new_<BinaryNode>(PNK_FOR, op, TokenPos(begin, body->pn_pos.end),
forHead, body);
if (!pn)
return null();
pn->pn_iflags = iflags;
return pn;
} }
Node newComprehensionFor(uint32_t begin, TernaryNodeType forHead, Node body) { ForNodeType newComprehensionFor(uint32_t begin, TernaryNodeType forHead, Node body) {
// A PNK_COMPREHENSIONFOR node is binary: left is loop control, right // A PNK_COMPREHENSIONFOR node is binary: left is loop control, right
// is the body. // is the body.
MOZ_ASSERT(forHead->isKind(PNK_FORIN) || forHead->isKind(PNK_FOROF)); MOZ_ASSERT(forHead->isKind(PNK_FORIN) || forHead->isKind(PNK_FOROF));
JSOp op = forHead->isKind(PNK_FORIN) ? JSOP_ITER : JSOP_NOP; ForNode* pn = new_<ForNode>(TokenPos(begin, body->pn_pos.end), forHead, body, JSOP_ITER);
BinaryNode* pn = new_<BinaryNode>(PNK_COMPREHENSIONFOR, op,
TokenPos(begin, body->pn_pos.end), forHead, body);
if (!pn) if (!pn)
return null(); return null();
pn->pn_iflags = JSOP_ITER; pn->setKind(PNK_COMPREHENSIONFOR);
return pn; return pn;
} }
@ -661,14 +651,13 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return new_<TernaryNode>(kind, JSOP_NOP, target, nullptr, iteratedExpr, pos); return new_<TernaryNode>(kind, JSOP_NOP, target, nullptr, iteratedExpr, pos);
} }
ParseNode* newSwitchStatement(uint32_t begin, ParseNode* discriminant, SwitchStatementType newSwitchStatement(uint32_t begin, Node discriminant,
ParseNode* lexicalForCaseList, bool hasDefault) Node lexicalForCaseList, bool hasDefault)
{ {
return new_<SwitchStatement>(begin, discriminant, lexicalForCaseList, hasDefault); return new_<SwitchStatement>(begin, discriminant, lexicalForCaseList, hasDefault);
} }
ParseNode* newCaseOrDefault(uint32_t begin, ParseNode* expr, ParseNode* body) { CaseClauseType newCaseOrDefault(uint32_t begin, Node expr, Node body) {
return new_<CaseClause>(expr, body, begin); return new_<CaseClause>(expr, body, begin);
} }
@ -685,7 +674,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return new_<UnaryNode>(PNK_RETURN, JSOP_RETURN, pos, expr); return new_<UnaryNode>(PNK_RETURN, JSOP_RETURN, pos, expr);
} }
ParseNode* newWithStatement(uint32_t begin, ParseNode* expr, ParseNode* body) { BinaryNodeType newWithStatement(uint32_t begin, Node expr, Node body) {
return new_<BinaryNode>(PNK_WITH, JSOP_NOP, TokenPos(begin, body->pn_pos.end), return new_<BinaryNode>(PNK_WITH, JSOP_NOP, TokenPos(begin, body->pn_pos.end),
expr, body); expr, body);
} }
@ -713,11 +702,11 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return new_<NameNode>(PNK_PROPERTYNAME, JSOP_NOP, name, pos); return new_<NameNode>(PNK_PROPERTYNAME, JSOP_NOP, name, pos);
} }
ParseNode* newPropertyAccess(ParseNode* expr, ParseNode* key) { PropertyAccessType newPropertyAccess(Node expr, Node key) {
return new_<PropertyAccess>(expr, key, expr->pn_pos.begin, key->pn_pos.end); return new_<PropertyAccess>(expr, key, expr->pn_pos.begin, key->pn_pos.end);
} }
ParseNode* newPropertyByValue(ParseNode* lhs, ParseNode* index, uint32_t end) { PropertyByValueType newPropertyByValue(Node lhs, Node index, uint32_t end) {
return new_<PropertyByValue>(lhs, index, lhs->pn_pos.begin, end); return new_<PropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
} }
@ -783,7 +772,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return new_<CodeNode>(PNK_MODULE, JSOP_NOP, pos()); return new_<CodeNode>(PNK_MODULE, JSOP_NOP, pos());
} }
Node newNewExpression(uint32_t begin, ParseNode* ctor, ParseNode* args) { BinaryNodeType newNewExpression(uint32_t begin, Node ctor, Node args) {
return new_<BinaryNode>(PNK_NEW, JSOP_NEW, TokenPos(begin, args->pn_pos.end), ctor, args); return new_<BinaryNode>(PNK_NEW, JSOP_NEW, TokenPos(begin, args->pn_pos.end), ctor, args);
} }
@ -791,10 +780,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return new_<LexicalScopeNode>(bindings, body); return new_<LexicalScopeNode>(bindings, body);
} }
ParseNode* newAssignment(ParseNodeKind kind, ParseNode* lhs, ParseNode* rhs, AssignmentNodeType newAssignment(ParseNodeKind kind, Node lhs, Node rhs, JSOp op) {
JSOp op) return new_<AssignmentNode>(kind, op, lhs, rhs);
{
return newBinary(kind, lhs, rhs, op);
} }
bool isUnparenthesizedYieldExpression(ParseNode* node) { bool isUnparenthesizedYieldExpression(ParseNode* node) {

View file

@ -73,12 +73,14 @@ class NameResolver
*/ */
bool nameExpression(ParseNode* n, bool* foundName) { bool nameExpression(ParseNode* n, bool* foundName) {
switch (n->getKind()) { switch (n->getKind()) {
case PNK_DOT: case PNK_DOT: {
if (!nameExpression(n->pn_left, foundName)) PropertyAccess* prop = &n->as<PropertyAccess>();
if (!nameExpression(&prop->expression(), foundName))
return false; return false;
if (!*foundName) if (!*foundName)
return true; return true;
return appendPropertyReference(n->pn_right->pn_atom); return appendPropertyReference(prop->right()->pn_atom);
}
case PNK_NAME: case PNK_NAME:
*foundName = true; *foundName = true;
@ -88,16 +90,18 @@ class NameResolver
*foundName = true; *foundName = true;
return buf->append("this"); return buf->append("this");
case PNK_ELEM: case PNK_ELEM: {
if (!nameExpression(n->pn_left, foundName)) PropertyByValue* elem = &n->as<PropertyByValue>();
if (!nameExpression(&elem->expression(), foundName))
return false; return false;
if (!*foundName) if (!*foundName)
return true; return true;
if (!buf->append('[') || !nameExpression(n->pn_right, foundName)) if (!buf->append('[') || !nameExpression(elem->right(), foundName))
return false; return false;
if (!*foundName) if (!*foundName)
return true; return true;
return buf->append(']'); return buf->append(']');
}
case PNK_NUMBER: case PNK_NUMBER:
*foundName = true; *foundName = true;
@ -128,7 +132,7 @@ class NameResolver
for (int pos = nparents - 1; pos >= 0; pos--) { for (int pos = nparents - 1; pos >= 0; pos--) {
ParseNode* cur = parents[pos]; ParseNode* cur = parents[pos];
if (cur->isAssignment()) if (cur->is<AssignmentNode>())
return cur; return cur;
switch (cur->getKind()) { switch (cur->getKind()) {
@ -222,8 +226,8 @@ class NameResolver
/* If the function is assigned to something, then that is very relevant */ /* If the function is assigned to something, then that is very relevant */
if (assignment) { if (assignment) {
if (assignment->isAssignment()) if (assignment->is<AssignmentNode>())
assignment = assignment->pn_left; assignment = assignment->as<AssignmentNode>().left();
bool foundName = false; bool foundName = false;
if (!nameExpression(assignment, &foundName)) if (!nameExpression(assignment, &foundName))
return false; return false;
@ -240,7 +244,7 @@ class NameResolver
ParseNode* node = toName[pos]; ParseNode* node = toName[pos];
if (node->isKind(PNK_COLON) || node->isKind(PNK_SHORTHAND)) { if (node->isKind(PNK_COLON) || node->isKind(PNK_SHORTHAND)) {
ParseNode* left = node->pn_left; ParseNode* left = node->as<BinaryNode>().left();
if (left->isKind(PNK_OBJECT_PROPERTY_NAME) || left->isKind(PNK_STRING)) { if (left->isKind(PNK_OBJECT_PROPERTY_NAME) || left->isKind(PNK_STRING)) {
if (!appendPropertyReference(left->pn_atom)) if (!appendPropertyReference(left->pn_atom))
return false; return false;
@ -284,7 +288,7 @@ class NameResolver
* for new variables and then return an anonymous function using this scope. * for new variables and then return an anonymous function using this scope.
*/ */
bool isDirectCall(int pos, ParseNode* cur) { bool isDirectCall(int pos, ParseNode* cur) {
return pos >= 0 && call(parents[pos]) && parents[pos]->pn_left == cur; return pos >= 0 && call(parents[pos]) && parents[pos]->as<BinaryNode>().left() == cur;
} }
bool resolveTemplateLiteral(ListNode* node, HandleAtom prefix) { bool resolveTemplateLiteral(ListNode* node, HandleAtom prefix) {
@ -304,10 +308,10 @@ class NameResolver
} }
} }
bool resolveTaggedTemplate(ParseNode* node, HandleAtom prefix) { bool resolveTaggedTemplate(BinaryNode* taggedTemplate, HandleAtom prefix) {
MOZ_ASSERT(node->isKind(PNK_TAGGED_TEMPLATE)); MOZ_ASSERT(taggedTemplate->isKind(PNK_TAGGED_TEMPLATE));
ParseNode* tag = node->pn_left; ParseNode* tag = taggedTemplate->left();
// The leading expression, e.g. |tag| in |tag`foo`|, // The leading expression, e.g. |tag| in |tag`foo`|,
// that might contain functions. // that might contain functions.
@ -317,7 +321,8 @@ class NameResolver
// The callsite object node is first. This node only contains // The callsite object node is first. This node only contains
// internal strings or undefined and an array -- no user-controlled // internal strings or undefined and an array -- no user-controlled
// expressions. // expressions.
CallSiteNode* element = &node->pn_right->as<ListNode>().head()->as<CallSiteNode>(); CallSiteNode* element =
&taggedTemplate->right()->as<ListNode>().head()->as<CallSiteNode>();
#ifdef DEBUG #ifdef DEBUG
{ {
ListNode* rawNodes = &element->head()->as<ListNode>(); ListNode* rawNodes = &element->head()->as<ListNode>();
@ -404,11 +409,11 @@ class NameResolver
MOZ_ASSERT(!cur->pn_kid->expr()); MOZ_ASSERT(!cur->pn_kid->expr());
break; break;
case PNK_NEWTARGET: case PNK_NEWTARGET: {
MOZ_ASSERT(cur->isArity(PN_BINARY)); MOZ_ASSERT(cur->as<BinaryNode>().left()->isKind(PNK_POSHOLDER));
MOZ_ASSERT(cur->pn_left->isKind(PNK_POSHOLDER)); MOZ_ASSERT(cur->as<BinaryNode>().right()->isKind(PNK_POSHOLDER));
MOZ_ASSERT(cur->pn_right->isKind(PNK_POSHOLDER));
break; break;
}
// Nodes with a single non-null child requiring name resolution. // Nodes with a single non-null child requiring name resolution.
case PNK_TYPEOFEXPR: case PNK_TYPEOFEXPR:
@ -468,45 +473,54 @@ class NameResolver
case PNK_FOR: case PNK_FOR:
case PNK_COMPREHENSIONFOR: case PNK_COMPREHENSIONFOR:
case PNK_CLASSMETHOD: case PNK_CLASSMETHOD:
case PNK_SETTHIS: case PNK_SETTHIS: {
MOZ_ASSERT(cur->isArity(PN_BINARY)); BinaryNode* node = &cur->as<BinaryNode>();
if (!resolve(cur->pn_left, prefix)) if (!resolve(node->left(), prefix)) {
return false; return false;
if (!resolve(cur->pn_right, prefix)) }
if (!resolve(node->right(), prefix)) {
return false;
}
break;
}
case PNK_ELEM: {
PropertyByValue* elem = &cur->as<PropertyByValue>();
if (!elem->isSuper() && !resolve(&elem->expression(), prefix))
return false;
if (!resolve(&elem->key(), prefix))
return false; return false;
break; break;
}
case PNK_ELEM: case PNK_WITH: {
MOZ_ASSERT(cur->isArity(PN_BINARY)); BinaryNode* node = &cur->as<BinaryNode>();
if (!cur->as<PropertyByValue>().isSuper() && !resolve(cur->pn_left, prefix)) if (!resolve(node->left(), prefix))
return false; return false;
if (!resolve(cur->pn_right, prefix)) if (!resolve(node->right(), prefix))
return false; return false;
break; break;
}
case PNK_WITH: case PNK_CASE: {
MOZ_ASSERT(cur->isArity(PN_BINARY)); CaseClause* caseClause = &cur->as<CaseClause>();
if (!resolve(cur->pn_left, prefix)) if (ParseNode* caseExpr = caseClause->caseExpression()) {
return false;
if (!resolve(cur->pn_right, prefix))
return false;
break;
case PNK_CASE:
MOZ_ASSERT(cur->isArity(PN_BINARY));
if (ParseNode* caseExpr = cur->pn_left) {
if (!resolve(caseExpr, prefix)) if (!resolve(caseExpr, prefix))
return false; return false;
} }
if (!resolve(cur->pn_right, prefix)) if (!resolve(caseClause->statementList(), prefix))
return false; return false;
break; break;
}
case PNK_INITIALYIELD: case PNK_INITIALYIELD: {
MOZ_ASSERT(cur->pn_kid->isKind(PNK_ASSIGN) && #ifdef DEBUG
cur->pn_kid->pn_left->isKind(PNK_NAME) && AssignmentNode* assignNode = &cur->pn_kid->as<AssignmentNode>();
cur->pn_kid->pn_right->isKind(PNK_GENERATOR)); MOZ_ASSERT(assignNode->left()->isKind(PNK_NAME));
MOZ_ASSERT(assignNode->right()->isKind(PNK_GENERATOR));
#endif
break; break;
}
case PNK_YIELD_STAR: case PNK_YIELD_STAR:
MOZ_ASSERT(cur->isArity(PN_UNARY)); MOZ_ASSERT(cur->isArity(PN_UNARY));
@ -533,16 +547,18 @@ class NameResolver
case PNK_IMPORT: case PNK_IMPORT:
case PNK_EXPORT_FROM: case PNK_EXPORT_FROM:
case PNK_EXPORT_DEFAULT: case PNK_EXPORT_DEFAULT: {
BinaryNode* node = &cur->as<BinaryNode>();
MOZ_ASSERT(cur->isArity(PN_BINARY)); MOZ_ASSERT(cur->isArity(PN_BINARY));
// The left halves of these nodes don't contain any unconstrained // The left halves of these nodes don't contain any unconstrained
// expressions, but it's very hard to assert this to safely rely on // expressions, but it's very hard to assert this to safely rely on
// it. So recur anyway. // it. So recur anyway.
if (!resolve(cur->pn_left, prefix)) if (!resolve(node->left(), prefix))
return false; return false;
MOZ_ASSERT_IF(!cur->isKind(PNK_EXPORT_DEFAULT), MOZ_ASSERT_IF(!node->isKind(PNK_EXPORT_DEFAULT),
cur->pn_right->isKind(PNK_STRING)); node->right()->isKind(PNK_STRING));
break; break;
}
// Ternary nodes with three expression children. // Ternary nodes with three expression children.
case PNK_CONDITIONAL: { case PNK_CONDITIONAL: {
@ -601,13 +617,15 @@ class NameResolver
ClassNode* classNode = &cur->as<ClassNode>(); ClassNode* classNode = &cur->as<ClassNode>();
#ifdef DEBUG #ifdef DEBUG
if (classNode->names()) { if (classNode->names()) {
ParseNode* name = classNode->names(); ClassNames* names = classNode->names();
MOZ_ASSERT(name->isKind(PNK_CLASSNAMES)); if (ParseNode* outerBinding = names->outerBinding()) {
MOZ_ASSERT(name->isArity(PN_BINARY)); MOZ_ASSERT(outerBinding->isKind(PNK_NAME));
MOZ_ASSERT_IF(name->pn_left, name->pn_left->isKind(PNK_NAME)); MOZ_ASSERT(!outerBinding->expr());
MOZ_ASSERT_IF(name->pn_left, !name->pn_left->expr()); }
MOZ_ASSERT(name->pn_right->isKind(PNK_NAME));
MOZ_ASSERT(!name->pn_right->expr()); ParseNode* innerBinding = names->innerBinding();
MOZ_ASSERT(innerBinding->isKind(PNK_NAME));
MOZ_ASSERT(!innerBinding->expr());
} }
#endif #endif
if (ParseNode* heritage = classNode->heritage()) { if (ParseNode* heritage = classNode->heritage()) {
@ -744,21 +762,21 @@ class NameResolver
break; break;
case PNK_TAGGED_TEMPLATE: case PNK_TAGGED_TEMPLATE:
MOZ_ASSERT(cur->isArity(PN_BINARY)); if (!resolveTaggedTemplate(&cur->as<BinaryNode>(), prefix))
if (!resolveTaggedTemplate(cur, prefix))
return false; return false;
break; break;
case PNK_NEW: case PNK_NEW:
case PNK_CALL: case PNK_CALL:
case PNK_GENEXP: case PNK_GENEXP:
case PNK_SUPERCALL: case PNK_SUPERCALL: {
MOZ_ASSERT(cur->isArity(PN_BINARY)); BinaryNode* callNode = &cur->as<BinaryNode>();
if (!resolve(cur->pn_left, prefix)) if (!resolve(callNode->left(), prefix))
return false; return false;
if (!resolve(cur->pn_right, prefix)) if (!resolve(callNode->right(), prefix))
return false; return false;
break; break;
}
// Handles the arguments for new/call/supercall, but does _not_ handle // Handles the arguments for new/call/supercall, but does _not_ handle
// the Arguments node used by tagged template literals, since that is // the Arguments node used by tagged template literals, since that is
@ -784,12 +802,12 @@ class NameResolver
break; break;
} }
for (ParseNode* item : list->contents()) { for (ParseNode* item : list->contents()) {
MOZ_ASSERT(item->isKind(isImport ? PNK_IMPORT_SPEC : PNK_EXPORT_SPEC)); BinaryNode* spec = &item->as<BinaryNode>();
MOZ_ASSERT(item->isArity(PN_BINARY)); MOZ_ASSERT(spec->isKind(isImport ? PNK_IMPORT_SPEC : PNK_EXPORT_SPEC));
MOZ_ASSERT(item->pn_left->isKind(PNK_NAME)); MOZ_ASSERT(spec->left()->isKind(PNK_NAME));
MOZ_ASSERT(!item->pn_left->expr()); MOZ_ASSERT(!spec->left()->expr());
MOZ_ASSERT(item->pn_right->isKind(PNK_NAME)); MOZ_ASSERT(spec->right()->isKind(PNK_NAME));
MOZ_ASSERT(!item->pn_right->expr()); MOZ_ASSERT(!spec->right()->expr());
} }
#endif #endif
break; break;
@ -807,15 +825,17 @@ class NameResolver
break; break;
} }
case PNK_DOT: case PNK_DOT: {
MOZ_ASSERT(cur->isArity(PN_BINARY));
// Super prop nodes do not have a meaningful LHS // Super prop nodes do not have a meaningful LHS
if (cur->as<PropertyAccess>().isSuper()) PropertyAccess* prop = &cur->as<PropertyAccess>();
if (prop->isSuper()) {
break; break;
if (!resolve(cur->pn_left, prefix)) }
if (!resolve(&prop->expression(), prefix)) {
return false; return false;
}
break; break;
}
case PNK_LABEL: case PNK_LABEL:
MOZ_ASSERT(cur->isArity(PN_NAME)); MOZ_ASSERT(cur->isArity(PN_NAME));

View file

@ -276,9 +276,9 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
case PNK_FOR: case PNK_FOR:
case PNK_COMPREHENSIONFOR: case PNK_COMPREHENSIONFOR:
case PNK_WITH: { case PNK_WITH: {
MOZ_ASSERT(pn->isArity(PN_BINARY)); BinaryNode* bn = &pn->as<BinaryNode>();
stack->push(pn->pn_left); stack->push(bn->left());
stack->push(pn->pn_right); stack->push(bn->right());
return PushResult::Recyclable; return PushResult::Recyclable;
} }
@ -287,10 +287,10 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
// So both are binary nodes with a possibly-null pn_left. // So both are binary nodes with a possibly-null pn_left.
case PNK_CASE: case PNK_CASE:
case PNK_CLASSNAMES: { case PNK_CLASSNAMES: {
MOZ_ASSERT(pn->isArity(PN_BINARY)); BinaryNode* bn = &pn->as<BinaryNode>();
if (pn->pn_left) if (bn->left())
stack->push(pn->pn_left); stack->push(bn->left());
stack->push(pn->pn_right); stack->push(bn->right());
return PushResult::Recyclable; return PushResult::Recyclable;
} }
@ -298,9 +298,12 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
// '.generator' local, for a synthesized, prepended initial yield. // '.generator' local, for a synthesized, prepended initial yield.
case PNK_INITIALYIELD: { case PNK_INITIALYIELD: {
MOZ_ASSERT(pn->isArity(PN_UNARY)); MOZ_ASSERT(pn->isArity(PN_UNARY));
MOZ_ASSERT(pn->pn_kid->isKind(PNK_ASSIGN) && #ifdef DEBUG
pn->pn_kid->pn_left->isKind(PNK_NAME) && MOZ_ASSERT(pn->pn_kid->isKind(PNK_ASSIGN));
pn->pn_kid->pn_right->isKind(PNK_GENERATOR)); BinaryNode* bn = &pn->pn_kid->as<BinaryNode>();
MOZ_ASSERT(bn->left()->isKind(PNK_NAME) &&
bn->right()->isKind(PNK_GENERATOR));
#endif
stack->push(pn->pn_kid); stack->push(pn->pn_kid);
return PushResult::Recyclable; return PushResult::Recyclable;
} }
@ -328,22 +331,22 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
// and a module string on the right. // and a module string on the right.
case PNK_IMPORT: case PNK_IMPORT:
case PNK_EXPORT_FROM: { case PNK_EXPORT_FROM: {
MOZ_ASSERT(pn->isArity(PN_BINARY)); BinaryNode* bn = &pn->as<BinaryNode>();
MOZ_ASSERT_IF(pn->isKind(PNK_IMPORT), pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST)); MOZ_ASSERT_IF(pn->isKind(PNK_IMPORT), bn->left()->isKind(PNK_IMPORT_SPEC_LIST));
MOZ_ASSERT_IF(pn->isKind(PNK_EXPORT_FROM), pn->pn_left->isKind(PNK_EXPORT_SPEC_LIST)); MOZ_ASSERT_IF(pn->isKind(PNK_EXPORT_FROM), bn->left()->isKind(PNK_EXPORT_SPEC_LIST));
MOZ_ASSERT(pn->pn_left->isArity(PN_LIST)); MOZ_ASSERT(bn->left()->isArity(PN_LIST));
MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING)); MOZ_ASSERT(bn->right()->isKind(PNK_STRING));
stack->pushList(&pn->pn_left->as<ListNode>()); stack->pushList(&bn->left()->as<ListNode>());
stack->push(pn->pn_right); stack->push(bn->right());
return PushResult::Recyclable; return PushResult::Recyclable;
} }
case PNK_EXPORT_DEFAULT: { case PNK_EXPORT_DEFAULT: {
MOZ_ASSERT(pn->isArity(PN_BINARY)); BinaryNode* bn = &pn->as<BinaryNode>();
MOZ_ASSERT_IF(pn->pn_right, pn->pn_right->isKind(PNK_NAME)); MOZ_ASSERT_IF(bn->right(), bn->right()->isKind(PNK_NAME));
stack->push(pn->pn_left); stack->push(bn->left());
if (pn->pn_right) if (bn->right())
stack->push(pn->pn_right); stack->push(bn->right());
return PushResult::Recyclable; return PushResult::Recyclable;
} }
@ -660,7 +663,7 @@ ParseNode::dump(int indent)
((UnaryNode*) this)->dump(indent); ((UnaryNode*) this)->dump(indent);
break; break;
case PN_BINARY: case PN_BINARY:
((BinaryNode*) this)->dump(indent); as<BinaryNode>().dump(indent);
break; break;
case PN_TERNARY: case PN_TERNARY:
as<TernaryNode>().dump(indent); as<TernaryNode>().dump(indent);
@ -730,13 +733,13 @@ BinaryNode::dump(int indent)
if (isKind(PNK_DOT)) { if (isKind(PNK_DOT)) {
fprintf(stderr, "(."); fprintf(stderr, "(.");
DumpParseTree(pn_right, indent + 2); DumpParseTree(right(), indent + 2);
fprintf(stderr, " "); fprintf(stderr, " ");
if (as<PropertyAccess>().isSuper()) if (as<PropertyAccess>().isSuper())
fprintf(stderr, "super"); fprintf(stderr, "super");
else else
DumpParseTree(pn_left, indent + 2); DumpParseTree(left(), indent + 2);
fprintf(stderr, ")"); fprintf(stderr, ")");
return; return;
@ -745,9 +748,9 @@ BinaryNode::dump(int indent)
const char* name = parseNodeNames[getKind()]; const char* name = parseNodeNames[getKind()];
fprintf(stderr, "(%s ", name); fprintf(stderr, "(%s ", name);
indent += strlen(name) + 2; indent += strlen(name) + 2;
DumpParseTree(pn_left, indent); DumpParseTree(left(), indent);
IndentNewLine(indent); IndentNewLine(indent);
DumpParseTree(pn_right, indent); DumpParseTree(right(), indent);
fprintf(stderr, ")"); fprintf(stderr, ")");
} }

View file

@ -249,8 +249,9 @@ IsTypeofKind(ParseNodeKind kind)
* * PNK_LEXICALSCOPE which contains PNK_CLASSMETHODLIST as scopeBody, * * PNK_LEXICALSCOPE which contains PNK_CLASSMETHODLIST as scopeBody,
* if named class * if named class
* PNK_CLASSNAMES (ClassNames) * PNK_CLASSNAMES (ClassNames)
* pn_left: Name node for outer binding. can be null * left: Name node for outer binding, or null if the class is an expression
* pn_right: Name node for inner binding * that doesn't create an outer binding
* right: Name node for inner binding
* PNK_CLASSMETHODLIST (ListNode) * PNK_CLASSMETHODLIST (ListNode)
* head: list of N PNK_CLASSMETHOD nodes * head: list of N PNK_CLASSMETHOD nodes
* count: N >= 0 * count: N >= 0
@ -266,21 +267,29 @@ IsTypeofKind(ParseNodeKind kind)
* kid1: cond * kid1: cond
* kid2: then = PNK_YIELD, PNK_ARRAYPUSH, (empty) PNK_STATEMENTLIST * kid2: then = PNK_YIELD, PNK_ARRAYPUSH, (empty) PNK_STATEMENTLIST
* kid3: else or null * kid3: else or null
* PNK_SWITCH binary pn_left: discriminant * PNK_SWITCH (SwitchStatement)
* pn_right: PNK_LEXICALSCOPE node that contains the list * left: discriminant
* of PNK_CASE nodes, with at most one default node. * right: LexicalScope node that contains the list of Case nodes, with at
* hasDefault: true if there's a default case * most one default node.
* PNK_CASE binary pn_left: case-expression if CaseClause, or * hasDefault: true if there's a default case
* null if DefaultClause * PNK_CASE (CaseClause)
* pn_right: PNK_STATEMENTLIST node for this case's * left: case-expression if CaseClause, or null if DefaultClause
* statements * right: StatementList node for this case's statements
* PNK_WHILE binary pn_left: cond, pn_right: body * PNK_WHILE (BinaryNode)
* PNK_DOWHILE binary pn_left: body, pn_right: cond * left: cond
* PNK_FOR binary pn_left: either PNK_FORIN (for-in statement), * right: body
* PNK_FOROF (for-of) or PNK_FORHEAD (for(;;)) * PNK_DOWHILE (BinaryNode)
* pn_right: body * left: body
* PNK_COMPREHENSIONFOR pn_left: either PNK_FORIN or PNK_FOROF * right: cond
* binary pn_right: body * PNK_FOR (ForNode)
* left: one of
* * PNK_FORIN: for (x in y) ...
* * PNK_FOROF: for (x of x) ...
* * PNK_FORHEAD: for (;;) ...
* right: body
* PNK_COMPREHENSIONFOR (ForNode)
* left: either PNK_FORIN or PNK_FOROF
* right: body
* PNK_FORIN (TernaryNode) * PNK_FORIN (TernaryNode)
* kid1: declaration or expression to left of 'in' * kid1: declaration or expression to left of 'in'
* kid2: null * kid2: null
@ -307,7 +316,9 @@ IsTypeofKind(ParseNodeKind kind)
* kid3: catch block statements * kid3: catch block statements
* PNK_BREAK name pn_atom: label or null * PNK_BREAK name pn_atom: label or null
* PNK_CONTINUE 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_WITH (BinaryNode)
* left: head expr
* right: body
* PNK_VAR, PNK_LET, PNK_CONST (ListNode) * PNK_VAR, PNK_LET, PNK_CONST (ListNode)
* head: list of N Name or Assign nodes * head: list of N Name or Assign nodes
* each name node has either * each name node has either
@ -319,9 +330,9 @@ IsTypeofKind(ParseNodeKind kind)
* pn_atom: variable name * pn_atom: variable name
* pn_lexdef: def node * pn_lexdef: def node
* each assignment node has * each assignment node has
* pn_left: Name with pn_used true and * left: Name with pn_used true and
* pn_lexdef (NOT pn_expr) set * pn_lexdef (NOT pn_expr) set
* pn_right: initializer * right: initializer
* count: N > 0 * count: N > 0
* PNK_RETURN unary pn_kid: return expr or null * PNK_RETURN unary pn_kid: return expr or null
* PNK_SEMI unary pn_kid: expr or null statement * PNK_SEMI unary pn_kid: expr or null statement
@ -329,18 +340,28 @@ IsTypeofKind(ParseNodeKind kind)
* in original source, not introduced via * in original source, not introduced via
* constant folding or other tree rewriting * constant folding or other tree rewriting
* PNK_LABEL name pn_atom: label, pn_expr: labeled statement * PNK_LABEL name pn_atom: label, pn_expr: labeled statement
* PNK_IMPORT binary pn_left: PNK_IMPORT_SPEC_LIST import specifiers * PNK_IMPORT (BinaryNode)
* pn_right: PNK_STRING module specifier * left: PNK_IMPORT_SPEC_LIST import specifiers
* right: PNK_STRING module specifier
* PNK_IMPORT_SPEC_LIST (ListNode) * PNK_IMPORT_SPEC_LIST (ListNode)
* head: list of N ImportSpec nodes * head: list of N ImportSpec nodes
* count: N >= 0 (N = 0 for `import {} from ...`) * count: N >= 0 (N = 0 for `import {} from ...`)
* PNK_IMPORT_SPEC (BinaryNode)
* left: import name
* right: local binding name
* PNK_EXPORT unary pn_kid: declaration expression * PNK_EXPORT unary pn_kid: declaration expression
* PNK_EXPORT_FROM binary pn_left: PNK_EXPORT_SPEC_LIST export specifiers * PNK_EXPORT_FROM (BinaryNode)
* pn_right: PNK_STRING module specifier * left: PNK_EXPORT_SPEC_LIST export specifiers
* right: PNK_STRING module specifier
* PNK_EXPORT_SPEC_LIST (ListNode) * PNK_EXPORT_SPEC_LIST (ListNode)
* head: list of N ExportSpec nodes * head: list of N ExportSpec nodes
* count: N >= 0 (N = 0 for `export {}`) * count: N >= 0 (N = 0 for `export {}`)
* PNK_EXPORT_DEFAULT unary pn_kid: export default declaration or expression * PNK_EXPORT (BinaryNode)
* left: local binding name
* right: export name
* PNK_EXPORT_DEFAULT (BinaryNode)
* left: export default declaration or expression
* right: PNK_NAME node for assignment
* *
* <Expressions> * <Expressions>
* All left-associated binary trees of the same type are optimized into lists * All left-associated binary trees of the same type are optimized into lists
@ -348,19 +369,15 @@ IsTypeofKind(ParseNodeKind kind)
* PNK_COMMA (ListNode) * PNK_COMMA (ListNode)
* head: list of N comma-separated exprs * head: list of N comma-separated exprs
* count: N >= 2 * count: N >= 2
* PNK_ASSIGN binary pn_left: lvalue, pn_right: rvalue * PNK_ASSIGN (BinaryNode)
* PNK_ADDASSIGN, binary pn_left: lvalue, pn_right: rvalue * left: target of assignment
* PNK_SUBASSIGN, pn_op: JSOP_ADD for +=, etc. * right: value to assign
* PNK_BITORASSIGN, * PNK_ADDASSIGN, PNK_SUBASSIGN, PNK_BITORASSIGN, PNK_BITXORASSIGN,
* PNK_BITXORASSIGN, * PNK_BITANDASSIGN, PNK_LSHASSIGN, PNK_RSHASSIGN, PNK_URSHASSIGN,
* PNK_BITANDASSIGN, * PNK_MULASSIGN, PNK_DIVASSIGN, PNK_MODASSIGN, PNK_POWASSIGN (AssignmentNode)
* PNK_LSHASSIGN, * left: target of assignment
* PNK_RSHASSIGN, * right: value to assign
* PNK_URSHASSIGN, * pn_op: JSOP_ADD for +=, etc
* PNK_MULASSIGN,
* PNK_DIVASSIGN,
* PNK_MODASSIGN,
* PNK_POWASSIGN
* PNK_CONDITIONAL (ConditionalExpression) * PNK_CONDITIONAL (ConditionalExpression)
* (cond ? thenExpr : elseExpr) * (cond ? thenExpr : elseExpr)
* kid1: cond * kid1: cond
@ -392,8 +409,9 @@ IsTypeofKind(ParseNodeKind kind)
* PNK_POSTINCREMENT, * PNK_POSTINCREMENT,
* PNK_PREDECREMENT, * PNK_PREDECREMENT,
* PNK_POSTDECREMENT * PNK_POSTDECREMENT
* PNK_NEW binary pn_left: ctor expression on the left of the ( * PNK_NEW (BinaryNode)
* pn_right: Arguments * left: ctor expression on the left of the '('
* right: Arguments
* PNK_DELETENAME unary pn_kid: PNK_NAME expr * PNK_DELETENAME unary pn_kid: PNK_NAME expr
* PNK_DELETEPROP unary pn_kid: PNK_DOT expr * PNK_DELETEPROP unary pn_kid: PNK_DOT expr
* PNK_DELETEELEM unary pn_kid: PNK_ELEM expr * PNK_DELETEELEM unary pn_kid: PNK_ELEM expr
@ -415,26 +433,16 @@ IsTypeofKind(ParseNodeKind kind)
* contains are nullish. An optional chain can also * contains are nullish. An optional chain can also
* contain nodes such as PNK_DOT, PNK_ELEM, PNK_NAME, * contain nodes such as PNK_DOT, PNK_ELEM, PNK_NAME,
* PNK_CALL, etc. These are evaluated normally. * PNK_CALL, etc. These are evaluated normally.
* PNK_OPTDOT binary pn_left: MEMBER expr to left of . * PNK_PROPERTYNAME name pn_atom: property being accessed
* short circuits back to PNK_OPTCHAIN if nullish. * PNK_DOT, PNK_OPTDOT (PropertyAccess) short circuits back to PNK_OPTCHAIN if nullish.
* pn_right: PropertyName to right of . * left: MEMBER expr to left of '.'
* PNK_OPTELEM binary pn_left: MEMBER expr to left of [ * right: PropertyName to right of '.'
* short circuits back to PNK_OPTCHAIN if nullish. * PNK_ELEM, PNK_OPTELEM (PropertyByValue) short circuits back to PNK_OPTCHAIN if nullish.
* pn_right: expr between [ and ] * left: MEMBER expr to left of '['
* PNK_OPTCALL list pn_head: list of call, arg1, arg2, ... argN * right: expr between '[' and ']'
* pn_count: 1 + N (where N is number of args) * PNK_CALL, PNK_OPTCALL (BinaryNode) short circuits back to PNK_OPTCHAIN if nullish.
* call is a MEMBER expr naming a callable object, * left: callee expression on the left of the '('
* short circuits back to PNK_OPTCHAIN if nullish. * right: Arguments
* PNK_PROPERTYNAME pn_atom: property being accessed
* name
* PNK_DOT binary pn_left: MEMBER expr to left of .
* pn_right: PropertyName to right of .
* PNK_ELEM binary pn_left: MEMBER expr to left of [
* pn_right: expr between [ and ]
* PNK_CALL binary pn_left: callee expression on the left of the (
* pn_right: Arguments
* PNK_ARGUMENTS list pn_head: list of arg1, arg2, ... argN
* pn_count: N (where N is number of args)
* PNK_GENEXP binary Exactly like PNK_CALL, used for the implicit call * PNK_GENEXP binary Exactly like PNK_CALL, used for the implicit call
* in the desugaring of a generator-expression. * in the desugaring of a generator-expression.
* PNK_ARGUMENTS (ListNode) * PNK_ARGUMENTS (ListNode)
@ -452,11 +460,13 @@ IsTypeofKind(ParseNodeKind kind)
* * Shorthand * * Shorthand
* * Spread * * Spread
* count: N >= 0 * count: N >= 0
* PNK_COLON binary key-value pair in object initializer or * PNK_COLON (BinaryNode)
* destructuring lhs * key-value pair in object initializer or destructuring lhs
* pn_left: property id, pn_right: value * left: property id
* PNK_SHORTHAND binary Same fields as PNK_COLON. This is used for object * right: value
* literal properties using shorthand ({x}). * PNK_SHORTHAND (BinaryNode)
* Same fields as Colon. This is used for object literal properties using
* shorthand ({x}).
* PNK_COMPUTED_NAME unary ES6 ComputedPropertyName. * PNK_COMPUTED_NAME unary ES6 ComputedPropertyName.
* pn_kid: the AssignmentExpression inside the square brackets * pn_kid: the AssignmentExpression inside the square brackets
* PNK_NAME, name pn_atom: name, string, or object atom * PNK_NAME, name pn_atom: name, string, or object atom
@ -470,8 +480,10 @@ IsTypeofKind(ParseNodeKind kind)
* no ${}-delimited expression, it's parsed as a single TemplateString * no ${}-delimited expression, it's parsed as a single TemplateString
* PNK_TEMPLATE_STRING pn_atom: template string atom * PNK_TEMPLATE_STRING pn_atom: template string atom
nullary pn_op: JSOP_NOP nullary pn_op: JSOP_NOP
* PNK_TAGGED_TEMPLATE pn_left: tag expression * PNK_TAGGED_TEMPLATE (BinaryNode)
* binary pn_right: Arguments, with the first being the call site object, then arg1, arg2, ... argN * left: tag expression
* right: Arguments, with the first being the call site object, then
* arg1, arg2, ... argN
* PNK_CALLSITEOBJ (CallSiteNode) * PNK_CALLSITEOBJ (CallSiteNode)
* head: an Array of raw TemplateString, then corresponding cooked * head: an Array of raw TemplateString, then corresponding cooked
* TemplateString nodes * TemplateString nodes
@ -488,16 +500,18 @@ IsTypeofKind(ParseNodeKind kind)
* PNK_THIS, unary pn_kid: '.this' Name if function `this`, else nullptr * PNK_THIS, unary pn_kid: '.this' Name if function `this`, else nullptr
* PNK_SUPERBASE unary pn_kid: '.this' Name * PNK_SUPERBASE unary pn_kid: '.this' Name
* *
* PNK_SUPERCALL binary pn_left: SuperBase pn_right: Arguments * PNK_SUPERCALL (BinaryNode)
* * left: SuperBase
* PNK_SETTHIS binary pn_left: '.this' Name, pn_right: SuperCall * right: Arguments
* * PNK_SETTHIS (BinaryNode)
* left: '.this' Name
* right: SuperCall
* PNK_LEXICALSCOPE scope pn_u.scope.bindings: scope bindings * PNK_LEXICALSCOPE scope pn_u.scope.bindings: scope bindings
* pn_u.scope.body: scope body * pn_u.scope.body: scope body
* PNK_GENERATOR nullary * PNK_GENERATOR nullary
* PNK_INITIALYIELD unary pn_kid: generator object * PNK_INITIALYIELD unary pn_kid: generator object
* PNK_YIELD, unary pn_kid: expr or null * PNK_YIELD, unary pn_kid: expr or null
* PNK_YIELD_STAR, * PNK_YIELD_STAR
* PNK_ARRAYCOMP list pn_count: 1 * PNK_ARRAYCOMP list pn_count: 1
* pn_head: list of 1 element, which is block * pn_head: list of 1 element, which is block
* enclosing for loop(s) and optionally * enclosing for loop(s) and optionally
@ -519,6 +533,16 @@ enum ParseNodeArity
}; };
#define FOR_EACH_PARSENODE_SUBCLASS(macro) \ #define FOR_EACH_PARSENODE_SUBCLASS(macro) \
macro(BinaryNode, BinaryNodeType, asBinary) \
macro(AssignmentNode, AssignmentNodeType, asAssignment) \
macro(CaseClause, CaseClauseType, asCaseClause) \
macro(ClassMethod, ClassMethodType, asClassMethod) \
macro(ClassNames, ClassNamesType, asClassNames) \
macro(ForNode, ForNodeType, asFor) \
macro(PropertyAccess, PropertyAccessType, asPropertyAccess) \
macro(PropertyByValue, PropertyByValueType, asPropertyByValue) \
macro(SwitchStatement, SwitchStatementType, asSwitchStatement) \
\
macro(ListNode, ListNodeType, asList) \ macro(ListNode, ListNodeType, asList) \
macro(CallSiteNode, CallSiteNodeType, asCallSite) \ macro(CallSiteNode, CallSiteNodeType, asCallSite) \
\ \
@ -529,7 +553,6 @@ enum ParseNodeArity
class LoopControlStatement; class LoopControlStatement;
class BreakStatement; class BreakStatement;
class ContinueStatement; class ContinueStatement;
class PropertyAccess;
#define DECLARE_CLASS(typeName, longTypeName, asMethodName) \ #define DECLARE_CLASS(typeName, longTypeName, asMethodName) \
class typeName; class typeName;
@ -594,11 +617,6 @@ class ParseNode
bool isArity(ParseNodeArity a) const { return getArity() == a; } bool isArity(ParseNodeArity a) const { return getArity() == a; }
void setArity(ParseNodeArity a) { pn_arity = a; } void setArity(ParseNodeArity a) { pn_arity = a; }
bool isAssignment() const {
ParseNodeKind kind = getKind();
return PNK_ASSIGNMENT_START <= kind && kind <= PNK_ASSIGNMENT_LAST;
}
bool isBinaryOperation() const { bool isBinaryOperation() const {
ParseNodeKind kind = getKind(); ParseNodeKind kind = getKind();
return PNK_BINOP_FIRST <= kind && kind <= PNK_BINOP_LAST; return PNK_BINOP_FIRST <= kind && kind <= PNK_BINOP_LAST;
@ -636,6 +654,12 @@ class ParseNode
ParseNode* kid3; /* else-part, default case, etc. */ ParseNode* kid3; /* else-part, default case, etc. */
} ternary; } ternary;
struct { /* two kids if binary */ struct { /* two kids if binary */
private:
friend class BinaryNode;
friend class ForNode;
friend class ClassMethod;
friend class PropertyAccessBase;
friend class SwitchStatement;
ParseNode* left; ParseNode* left;
ParseNode* right; ParseNode* right;
union { union {
@ -675,10 +699,6 @@ class ParseNode
#define pn_objbox pn_u.name.objbox #define pn_objbox pn_u.name.objbox
#define pn_funbox pn_u.name.funbox #define pn_funbox pn_u.name.funbox
#define pn_body pn_u.name.expr #define pn_body pn_u.name.expr
#define pn_left pn_u.binary.left
#define pn_right pn_u.binary.right
#define pn_pval pn_u.binary.pval
#define pn_iflags pn_u.binary.iflags
#define pn_kid pn_u.unary.kid #define pn_kid pn_u.unary.kid
#define pn_prologue pn_u.unary.prologue #define pn_prologue pn_u.unary.prologue
#define pn_atom pn_u.name.atom #define pn_atom pn_u.name.atom
@ -857,25 +877,97 @@ struct UnaryNode : public ParseNode
#endif #endif
}; };
struct BinaryNode : public ParseNode class BinaryNode : public ParseNode
{ {
public:
BinaryNode(ParseNodeKind kind, JSOp op, const TokenPos& pos, ParseNode* left, ParseNode* right) BinaryNode(ParseNodeKind kind, JSOp op, const TokenPos& pos, ParseNode* left, ParseNode* right)
: ParseNode(kind, op, PN_BINARY, pos) : ParseNode(kind, op, PN_BINARY, pos)
{ {
pn_left = left; pn_u.binary.left = left;
pn_right = right; pn_u.binary.right = right;
} }
BinaryNode(ParseNodeKind kind, JSOp op, ParseNode* left, ParseNode* right) BinaryNode(ParseNodeKind kind, JSOp op, ParseNode* left, ParseNode* right)
: ParseNode(kind, op, PN_BINARY, TokenPos::box(left->pn_pos, right->pn_pos)) : ParseNode(kind, op, PN_BINARY, TokenPos::box(left->pn_pos, right->pn_pos))
{ {
pn_left = left; pn_u.binary.left = left;
pn_right = right; pn_u.binary.right = right;
}
static bool test(const ParseNode& node) {
return node.isArity(PN_BINARY);
} }
#ifdef DEBUG #ifdef DEBUG
void dump(int indent); void dump(int indent);
#endif #endif
ParseNode* left() const {
return pn_u.binary.left;
}
ParseNode* right() const {
return pn_u.binary.right;
}
// Methods used by FoldConstants.cpp.
// caller are responsible for keeping the list consistent.
ParseNode** unsafeLeftReference() {
return &pn_u.binary.left;
}
ParseNode** unsafeRightReference() {
return &pn_u.binary.right;
}
};
class AssignmentNode : public BinaryNode
{
public:
AssignmentNode(ParseNodeKind kind, JSOp op, ParseNode* left, ParseNode* right)
: BinaryNode(kind, op, TokenPos(left->pn_pos.begin, right->pn_pos.end), left, right)
{}
static bool test(const ParseNode& node) {
ParseNodeKind kind = node.getKind();
bool match = PNK_ASSIGNMENT_START <= kind &&
kind <= PNK_ASSIGNMENT_LAST;
MOZ_ASSERT_IF(match, node.is<BinaryNode>());
return match;
}
};
class ForNode : public BinaryNode
{
public:
ForNode(const TokenPos& pos, ParseNode* forHead, ParseNode* body, unsigned iflags)
: BinaryNode(PNK_FOR,
forHead->isKind(PNK_FORIN) ? JSOP_ITER : JSOP_NOP,
pos, forHead, body)
{
MOZ_ASSERT(forHead->isKind(PNK_FORIN) ||
forHead->isKind(PNK_FOROF) ||
forHead->isKind(PNK_FORHEAD));
pn_u.binary.iflags = iflags;
}
static bool test(const ParseNode& node) {
bool match = node.isKind(PNK_FOR) || node.isKind(PNK_COMPREHENSIONFOR);
MOZ_ASSERT_IF(match, node.is<BinaryNode>());
return match;
}
TernaryNode* head() const {
return &left()->as<TernaryNode>();
}
ParseNode* body() const {
return right();
}
unsigned iflags() const {
return pn_u.binary.iflags;
}
}; };
class TernaryNode : public ParseNode class TernaryNode : public ParseNode
@ -1353,13 +1445,21 @@ class CaseClause : public BinaryNode
CaseClause(ParseNode* expr, ParseNode* stmts, uint32_t begin) CaseClause(ParseNode* expr, ParseNode* stmts, uint32_t begin)
: BinaryNode(PNK_CASE, JSOP_NOP, TokenPos(begin, stmts->pn_pos.end), expr, stmts) {} : BinaryNode(PNK_CASE, JSOP_NOP, TokenPos(begin, stmts->pn_pos.end), expr, stmts) {}
ParseNode* caseExpression() const { return pn_left; } ParseNode* caseExpression() const {
bool isDefault() const { return !caseExpression(); } return left();
ListNode* statementList() const { return &pn_right->as<ListNode>(); } }
bool isDefault() const {
return !caseExpression();
}
ListNode* statementList() const {
return &right()->as<ListNode>();
}
static bool test(const ParseNode& node) { static bool test(const ParseNode& node) {
bool match = node.isKind(PNK_CASE); bool match = node.isKind(PNK_CASE);
MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); MOZ_ASSERT_IF(match, node.is<BinaryNode>());
MOZ_ASSERT_IF(match, node.isOp(JSOP_NOP)); MOZ_ASSERT_IF(match, node.isOp(JSOP_NOP));
return match; return match;
} }
@ -1515,7 +1615,7 @@ class PropertyAccessBase : public BinaryNode
public: public:
/* /*
* PropertyAccess nodes can have any expression/'super' as left-hand * PropertyAccess nodes can have any expression/'super' as left-hand
* side, but the name must be a ParseNodeKind::PropertyName node. * side, but the name must be a PNK_PROPERTYNAME node.
*/ */
PropertyAccessBase(ParseNodeKind kind, ParseNode* lhs, ParseNode* name, uint32_t begin, uint32_t end) PropertyAccessBase(ParseNodeKind kind, ParseNode* lhs, ParseNode* name, uint32_t begin, uint32_t end)
: BinaryNode(kind, JSOP_NOP, TokenPos(begin, end), lhs, name) : BinaryNode(kind, JSOP_NOP, TokenPos(begin, end), lhs, name)
@ -1527,21 +1627,37 @@ class PropertyAccessBase : public BinaryNode
static bool test(const ParseNode& node) { static bool test(const ParseNode& node) {
bool match = node.isKind(PNK_DOT) || bool match = node.isKind(PNK_DOT) ||
node.isKind(PNK_OPTDOT); node.isKind(PNK_OPTDOT);
MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); MOZ_ASSERT_IF(match, node.is<BinaryNode>());
MOZ_ASSERT_IF(match, node.pn_right->isKind(PNK_PROPERTYNAME)); MOZ_ASSERT_IF(match, node.as<BinaryNode>().right()->isKind(PNK_PROPERTYNAME));
return match; return match;
} }
ParseNode& expression() const { ParseNode& expression() const {
return *pn_u.binary.left; return *left();
}
ParseNode& key() const {
return *right();
}
// Method used by BytecodeEmitter::emitPropLHS for optimization.
// Those methods allow expression to temporarily be nullptr for
// optimization purpose.
ParseNode* maybeExpression() const {
return left();
}
void setExpression(ParseNode* pn) {
pn_u.binary.left = pn;
} }
PropertyName& name() const { PropertyName& name() const {
return *pn_u.binary.right->pn_atom->asPropertyName(); return *right()->pn_atom->asPropertyName();
} }
JSAtom* nameAtom() const { bool isSuper() const {
return pn_u.binary.right->pn_atom; // PNK_SUPERBASE cannot result from any expression syntax.
return expression().isKind(PNK_SUPERBASE);
} }
}; };
@ -1557,15 +1673,10 @@ class PropertyAccess : public PropertyAccessBase
static bool test(const ParseNode& node) { static bool test(const ParseNode& node) {
bool match = node.isKind(PNK_DOT); bool match = node.isKind(PNK_DOT);
MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); MOZ_ASSERT_IF(match, node.is<BinaryNode>());
MOZ_ASSERT_IF(match, node.pn_right->isKind(PNK_PROPERTYNAME)); MOZ_ASSERT_IF(match, node.as<BinaryNode>().right()->isKind(PNK_PROPERTYNAME));
return match; return match;
} }
bool isSuper() const {
// PNK_SUPERBASE cannot result from any expression syntax.
return expression().isKind(PNK_SUPERBASE);
}
}; };
class OptionalPropertyAccess : public PropertyAccessBase class OptionalPropertyAccess : public PropertyAccessBase
@ -1580,35 +1691,36 @@ class OptionalPropertyAccess : public PropertyAccessBase
static bool test(const ParseNode& node) { static bool test(const ParseNode& node) {
bool match = node.isKind(PNK_OPTDOT); bool match = node.isKind(PNK_OPTDOT);
MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); MOZ_ASSERT_IF(match, node.is<BinaryNode>());
MOZ_ASSERT_IF(match, node.pn_right->isKind(PNK_PROPERTYNAME)); MOZ_ASSERT_IF(match, node.as<BinaryNode>().right()->isKind(PNK_PROPERTYNAME));
return match; return match;
} }
}; };
class PropertyByValueBase : public ParseNode class PropertyByValueBase : public BinaryNode
{ {
public: public:
PropertyByValueBase(ParseNodeKind kind, ParseNode* lhs, ParseNode* propExpr, PropertyByValueBase(ParseNodeKind kind, ParseNode* lhs, ParseNode* propExpr,
uint32_t begin, uint32_t end) uint32_t begin, uint32_t end)
: ParseNode(kind, JSOP_NOP, PN_BINARY, TokenPos(begin, end)) : BinaryNode(kind, JSOP_NOP, TokenPos(begin, end), lhs, propExpr)
{ {}
pn_u.binary.left = lhs;
pn_u.binary.right = propExpr;
}
ParseNode& expression() const { ParseNode& expression() const {
return *pn_u.binary.left; return *left();
} }
ParseNode& key() const { ParseNode& key() const {
return *pn_u.binary.right; return *right();
}
bool isSuper() const {
return left()->isKind(PNK_SUPERBASE);
} }
static bool test(const ParseNode& node) { static bool test(const ParseNode& node) {
bool match = node.isKind(PNK_ELEM) || bool match = node.isKind(PNK_ELEM) ||
node.isKind(PNK_OPTELEM); node.isKind(PNK_OPTELEM);
MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); MOZ_ASSERT_IF(match, node.is<BinaryNode>());
return match; return match;
} }
}; };
@ -1624,10 +1736,6 @@ class PropertyByValue : public PropertyByValueBase {
MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); MOZ_ASSERT_IF(match, node.isArity(PN_BINARY));
return match; return match;
} }
bool isSuper() const {
return pn_left->isKind(PNK_SUPERBASE);
}
}; };
class OptionalPropertyByValue : public PropertyByValueBase { class OptionalPropertyByValue : public PropertyByValueBase {
@ -1667,7 +1775,9 @@ class CallSiteNode : public ListNode
} }
}; };
struct ClassMethod : public BinaryNode { class ClassMethod : public BinaryNode
{
public:
/* /*
* Method definitions often keep a name and function body that overlap, * Method definitions often keep a name and function body that overlap,
* so explicitly define the beginning and end here. * so explicitly define the beginning and end here.
@ -1680,22 +1790,24 @@ struct ClassMethod : public BinaryNode {
static bool test(const ParseNode& node) { static bool test(const ParseNode& node) {
bool match = node.isKind(PNK_CLASSMETHOD); bool match = node.isKind(PNK_CLASSMETHOD);
MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); MOZ_ASSERT_IF(match, node.is<BinaryNode>());
return match; return match;
} }
ParseNode& name() const { ParseNode& name() const {
return *pn_u.binary.left; return *left();
} }
ParseNode& method() const { ParseNode& method() const {
return *pn_u.binary.right; return *right();
} }
bool isStatic() const { bool isStatic() const {
return pn_u.binary.isStatic; return pn_u.binary.isStatic;
} }
}; };
struct SwitchStatement : public BinaryNode { class SwitchStatement : public BinaryNode
{
public:
SwitchStatement(uint32_t begin, ParseNode* discriminant, ParseNode* lexicalForCaseList, SwitchStatement(uint32_t begin, ParseNode* discriminant, ParseNode* lexicalForCaseList,
bool hasDefault) bool hasDefault)
: BinaryNode(PNK_SWITCH, JSOP_NOP, : BinaryNode(PNK_SWITCH, JSOP_NOP,
@ -1722,22 +1834,24 @@ struct SwitchStatement : public BinaryNode {
static bool test(const ParseNode& node) { static bool test(const ParseNode& node) {
bool match = node.isKind(PNK_SWITCH); bool match = node.isKind(PNK_SWITCH);
MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); MOZ_ASSERT_IF(match, node.is<BinaryNode>());
return match; return match;
} }
ParseNode& discriminant() const { ParseNode& discriminant() const {
return *pn_u.binary.left; return *left();
} }
ParseNode& lexicalForCaseList() const { ParseNode& lexicalForCaseList() const {;
return *pn_u.binary.right; return *right();
} }
bool hasDefault() const { bool hasDefault() const {
return pn_u.binary.hasDefault; return pn_u.binary.hasDefault;
} }
}; };
struct ClassNames : public BinaryNode { class ClassNames : public BinaryNode
{
public:
ClassNames(ParseNode* outerBinding, ParseNode* innerBinding, const TokenPos& pos) ClassNames(ParseNode* outerBinding, ParseNode* innerBinding, const TokenPos& pos)
: BinaryNode(PNK_CLASSNAMES, JSOP_NOP, pos, outerBinding, innerBinding) : BinaryNode(PNK_CLASSNAMES, JSOP_NOP, pos, outerBinding, innerBinding)
{ {
@ -1748,7 +1862,7 @@ struct ClassNames : public BinaryNode {
static bool test(const ParseNode& node) { static bool test(const ParseNode& node) {
bool match = node.isKind(PNK_CLASSNAMES); bool match = node.isKind(PNK_CLASSNAMES);
MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); MOZ_ASSERT_IF(match, node.is<BinaryNode>());
return match; return match;
} }
@ -1761,10 +1875,10 @@ struct ClassNames : public BinaryNode {
* the outer binding has been overwritten. * the outer binding has been overwritten.
*/ */
ParseNode* outerBinding() const { ParseNode* outerBinding() const {
return pn_u.binary.left; return left();
} }
ParseNode* innerBinding() const { ParseNode* innerBinding() const {
return pn_u.binary.right; return right();
} }
}; };

View file

@ -4307,7 +4307,7 @@ Parser<ParseHandler>::PossibleError::transferErrorsTo(PossibleError* other)
} }
template <typename ParseHandler> template <typename ParseHandler>
typename ParseHandler::Node typename ParseHandler::BinaryNodeType
Parser<ParseHandler>::bindingInitializer(Node lhs, DeclarationKind kind, Parser<ParseHandler>::bindingInitializer(Node lhs, DeclarationKind kind,
YieldHandling yieldHandling) YieldHandling yieldHandling)
{ {
@ -4322,12 +4322,17 @@ Parser<ParseHandler>::bindingInitializer(Node lhs, DeclarationKind kind,
handler.checkAndSetIsDirectRHSAnonFunction(rhs); handler.checkAndSetIsDirectRHSAnonFunction(rhs);
Node assign = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP); BinaryNodeType assign = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP);
if (!assign) if (!assign)
return null(); return null();
if (foldConstants && !FoldConstants(context, &assign, this)) if (foldConstants) {
return null(); Node node = assign;
if (!FoldConstants(context, &node, this)) {
return null();
}
assign = handler.asBinary(node);
}
return assign; return assign;
} }
@ -4454,7 +4459,7 @@ Parser<ParseHandler>::objectBindingPattern(DeclarationKind kind, YieldHandling y
tokenStream.consumeKnownToken(TOK_ASSIGN); tokenStream.consumeKnownToken(TOK_ASSIGN);
Node bindingExpr = bindingInitializer(binding, kind, yieldHandling); BinaryNodeType bindingExpr = bindingInitializer(binding, kind, yieldHandling);
if (!bindingExpr) if (!bindingExpr)
return null(); return null();
@ -5030,7 +5035,7 @@ Parser<FullParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, ListNodeTy
if (!importNameNode) if (!importNameNode)
return false; return false;
Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importNameNode, bindingName); BinaryNodeType importSpec = handler.newBinary(PNK_IMPORT_SPEC, importNameNode, bindingName);
if (!importSpec) if (!importSpec)
return false; return false;
@ -5076,7 +5081,7 @@ Parser<FullParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, ListNodeTy
// environment. // environment.
pc->varScope().lookupDeclaredName(bindingName)->value()->setClosedOver(); pc->varScope().lookupDeclaredName(bindingName)->value()->setClosedOver();
Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingNameNode); BinaryNodeType importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingNameNode);
if (!importSpec) if (!importSpec)
return false; return false;
@ -5087,7 +5092,7 @@ Parser<FullParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, ListNodeTy
} }
template<> template<>
ParseNode* BinaryNode*
Parser<FullParseHandler>::importDeclaration() Parser<FullParseHandler>::importDeclaration()
{ {
MOZ_ASSERT(tokenStream.currentToken().type == TOK_IMPORT); MOZ_ASSERT(tokenStream.currentToken().type == TOK_IMPORT);
@ -5134,7 +5139,7 @@ Parser<FullParseHandler>::importDeclaration()
if (!noteDeclaredName(bindingAtom, DeclarationKind::Import, pos())) if (!noteDeclaredName(bindingAtom, DeclarationKind::Import, pos()))
return null(); return null();
Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName); BinaryNodeType importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName);
if (!importSpec) if (!importSpec)
return null(); return null();
@ -5173,7 +5178,7 @@ Parser<FullParseHandler>::importDeclaration()
if (!matchOrInsertSemicolonAfterNonExpression()) if (!matchOrInsertSemicolonAfterNonExpression())
return null(); return null();
ParseNode* node = BinaryNode* node =
handler.newImportDeclaration(importSpecSet, moduleSpec, TokenPos(begin, pos().end)); handler.newImportDeclaration(importSpecSet, moduleSpec, TokenPos(begin, pos().end));
if (!node || !pc->sc()->asModuleContext()->builder.processImport(node)) if (!node || !pc->sc()->asModuleContext()->builder.processImport(node))
return null(); return null();
@ -5182,7 +5187,7 @@ Parser<FullParseHandler>::importDeclaration()
} }
template<> template<>
SyntaxParseHandler::Node SyntaxParseHandler::BinaryNodeType
Parser<SyntaxParseHandler>::importDeclaration() Parser<SyntaxParseHandler>::importDeclaration()
{ {
JS_ALWAYS_FALSE(abortIfSyntaxParser()); JS_ALWAYS_FALSE(abortIfSyntaxParser());
@ -5226,7 +5231,7 @@ Parser<FullParseHandler>::checkExportedNamesForArrayBinding(ListNode* array)
if (node->isKind(PNK_SPREAD)) if (node->isKind(PNK_SPREAD))
binding = node->pn_kid; binding = node->pn_kid;
else if (node->isKind(PNK_ASSIGN)) else if (node->isKind(PNK_ASSIGN))
binding = node->pn_left; binding = node->as<AssignmentNode>().left();
else else
binding = node; binding = node;
@ -5264,10 +5269,10 @@ Parser<FullParseHandler>::checkExportedNamesForObjectBinding(ListNode* obj)
if (node->isKind(PNK_MUTATEPROTO)) if (node->isKind(PNK_MUTATEPROTO))
target = node->pn_kid; target = node->pn_kid;
else else
target = node->pn_right; target = node->as<BinaryNode>().right();
if (target->isKind(PNK_ASSIGN)) if (target->isKind(PNK_ASSIGN))
target = target->pn_left; target = target->as<AssignmentNode>().left();
} }
if (!checkExportedNamesForDeclaration(target)) if (!checkExportedNamesForDeclaration(target))
@ -5318,7 +5323,7 @@ Parser<FullParseHandler>::checkExportedNamesForDeclarationList(ListNode* node)
{ {
for (ParseNode* binding : node->contents()) { for (ParseNode* binding : node->contents()) {
if (binding->isKind(PNK_ASSIGN)) if (binding->isKind(PNK_ASSIGN))
binding = binding->pn_left; binding = binding->as<AssignmentNode>().left();
else else
MOZ_ASSERT(binding->isKind(PNK_NAME)); MOZ_ASSERT(binding->isKind(PNK_NAME));
@ -5400,21 +5405,21 @@ Parser<SyntaxParseHandler>::processExport(Node node)
template<> template<>
bool bool
Parser<FullParseHandler>::processExportFrom(ParseNode* node) Parser<FullParseHandler>::processExportFrom(BinaryNodeType node)
{ {
return pc->sc()->asModuleContext()->builder.processExportFrom(node); return pc->sc()->asModuleContext()->builder.processExportFrom(node);
} }
template<> template<>
bool bool
Parser<SyntaxParseHandler>::processExportFrom(Node node) Parser<SyntaxParseHandler>::processExportFrom(BinaryNodeType node)
{ {
MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
return false; return false;
} }
template <typename ParseHandler> template <typename ParseHandler>
typename ParseHandler::Node typename ParseHandler::BinaryNodeType
Parser<ParseHandler>::exportFrom(uint32_t begin, Node specList) Parser<ParseHandler>::exportFrom(uint32_t begin, Node specList)
{ {
if (!abortIfSyntaxParser()) if (!abortIfSyntaxParser())
@ -5434,7 +5439,7 @@ Parser<ParseHandler>::exportFrom(uint32_t begin, Node specList)
if (!matchOrInsertSemicolonAfterNonExpression()) if (!matchOrInsertSemicolonAfterNonExpression())
return null(); return null();
Node node = handler.newExportFromDeclaration(begin, specList, moduleSpec); BinaryNodeType node = handler.newExportFromDeclaration(begin, specList, moduleSpec);
if (!node) if (!node)
return null(); return null();
@ -5445,7 +5450,7 @@ Parser<ParseHandler>::exportFrom(uint32_t begin, Node specList)
} }
template <typename ParseHandler> template <typename ParseHandler>
typename ParseHandler::Node typename ParseHandler::BinaryNodeType
Parser<ParseHandler>::exportBatch(uint32_t begin) Parser<ParseHandler>::exportBatch(uint32_t begin)
{ {
if (!abortIfSyntaxParser()) if (!abortIfSyntaxParser())
@ -5476,7 +5481,7 @@ Parser<FullParseHandler>::checkLocalExportNames(ListNode* node)
{ {
// ES 2017 draft 15.2.3.1. // ES 2017 draft 15.2.3.1.
for (ParseNode* next : node->contents()) { for (ParseNode* next : node->contents()) {
ParseNode* name = next->pn_left; ParseNode* name = next->as<BinaryNode>().left();
MOZ_ASSERT(name->isKind(PNK_NAME)); MOZ_ASSERT(name->isKind(PNK_NAME));
RootedPropertyName ident(context, name->pn_atom->asPropertyName()); RootedPropertyName ident(context, name->pn_atom->asPropertyName());
@ -5540,7 +5545,7 @@ Parser<ParseHandler>::exportClause(uint32_t begin)
if (!checkExportedNameForClause(exportName)) if (!checkExportedNameForClause(exportName))
return null(); return null();
Node exportSpec = handler.newBinary(PNK_EXPORT_SPEC, bindingName, exportName); BinaryNodeType exportSpec = handler.newBinary(PNK_EXPORT_SPEC, bindingName, exportName);
if (!exportSpec) if (!exportSpec)
return null(); return null();
@ -5702,7 +5707,7 @@ Parser<ParseHandler>::exportLexicalDeclaration(uint32_t begin, DeclarationKind k
} }
template <typename ParseHandler> template <typename ParseHandler>
typename ParseHandler::Node typename ParseHandler::BinaryNodeType
Parser<ParseHandler>::exportDefaultFunctionDeclaration(uint32_t begin, Parser<ParseHandler>::exportDefaultFunctionDeclaration(uint32_t begin,
FunctionAsyncKind asyncKind FunctionAsyncKind asyncKind
/* = SyncFunction */) /* = SyncFunction */)
@ -5716,7 +5721,7 @@ Parser<ParseHandler>::exportDefaultFunctionDeclaration(uint32_t begin,
if (!kid) if (!kid)
return null(); return null();
Node node = handler.newExportDefaultDeclaration(kid, null(), TokenPos(begin, pos().end)); BinaryNodeType node = handler.newExportDefaultDeclaration(kid, null(), TokenPos(begin, pos().end));
if (!node) if (!node)
return null(); return null();
@ -5727,7 +5732,7 @@ Parser<ParseHandler>::exportDefaultFunctionDeclaration(uint32_t begin,
} }
template <typename ParseHandler> template <typename ParseHandler>
typename ParseHandler::Node typename ParseHandler::BinaryNodeType
Parser<ParseHandler>::exportDefaultClassDeclaration(uint32_t begin) Parser<ParseHandler>::exportDefaultClassDeclaration(uint32_t begin)
{ {
if (!abortIfSyntaxParser()) if (!abortIfSyntaxParser())
@ -5739,7 +5744,7 @@ Parser<ParseHandler>::exportDefaultClassDeclaration(uint32_t begin)
if (!kid) if (!kid)
return null(); return null();
Node node = handler.newExportDefaultDeclaration(kid, null(), TokenPos(begin, pos().end)); BinaryNodeType node = handler.newExportDefaultDeclaration(kid, null(), TokenPos(begin, pos().end));
if (!node) if (!node)
return null(); return null();
@ -5750,7 +5755,7 @@ Parser<ParseHandler>::exportDefaultClassDeclaration(uint32_t begin)
} }
template <typename ParseHandler> template <typename ParseHandler>
typename ParseHandler::Node typename ParseHandler::BinaryNodeType
Parser<ParseHandler>::exportDefaultAssignExpr(uint32_t begin) Parser<ParseHandler>::exportDefaultAssignExpr(uint32_t begin)
{ {
if (!abortIfSyntaxParser()) if (!abortIfSyntaxParser())
@ -5769,7 +5774,7 @@ Parser<ParseHandler>::exportDefaultAssignExpr(uint32_t begin)
if (!matchOrInsertSemicolonAfterExpression()) if (!matchOrInsertSemicolonAfterExpression())
return null(); return null();
Node node = handler.newExportDefaultDeclaration(kid, nameNode, TokenPos(begin, pos().end)); BinaryNodeType node = handler.newExportDefaultDeclaration(kid, nameNode, TokenPos(begin, pos().end));
if (!node) if (!node)
return null(); return null();
@ -5780,7 +5785,7 @@ Parser<ParseHandler>::exportDefaultAssignExpr(uint32_t begin)
} }
template <typename ParseHandler> template <typename ParseHandler>
typename ParseHandler::Node typename ParseHandler::BinaryNodeType
Parser<ParseHandler>::exportDefault(uint32_t begin) Parser<ParseHandler>::exportDefault(uint32_t begin)
{ {
if (!abortIfSyntaxParser()) if (!abortIfSyntaxParser())
@ -6027,7 +6032,7 @@ Parser<ParseHandler>::ifStatement(YieldHandling yieldHandling)
} }
template <typename ParseHandler> template <typename ParseHandler>
typename ParseHandler::Node typename ParseHandler::BinaryNodeType
Parser<ParseHandler>::doWhileStatement(YieldHandling yieldHandling) Parser<ParseHandler>::doWhileStatement(YieldHandling yieldHandling)
{ {
uint32_t begin = pos().begin; uint32_t begin = pos().begin;
@ -6053,7 +6058,7 @@ Parser<ParseHandler>::doWhileStatement(YieldHandling yieldHandling)
} }
template <typename ParseHandler> template <typename ParseHandler>
typename ParseHandler::Node typename ParseHandler::BinaryNodeType
Parser<ParseHandler>::whileStatement(YieldHandling yieldHandling) Parser<ParseHandler>::whileStatement(YieldHandling yieldHandling)
{ {
uint32_t begin = pos().begin; uint32_t begin = pos().begin;
@ -6414,7 +6419,7 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
if (!body) if (!body)
return null(); return null();
Node forLoop = handler.newForStatement(begin, forHead, body, iflags); BinaryNodeType forLoop = handler.newForStatement(begin, forHead, body, iflags);
if (!forLoop) if (!forLoop)
return null(); return null();
@ -6425,7 +6430,7 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
} }
template <typename ParseHandler> template <typename ParseHandler>
typename ParseHandler::Node typename ParseHandler::SwitchStatementType
Parser<ParseHandler>::switchStatement(YieldHandling yieldHandling) Parser<ParseHandler>::switchStatement(YieldHandling yieldHandling)
{ {
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_SWITCH)); MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_SWITCH));
@ -6516,10 +6521,10 @@ Parser<ParseHandler>::switchStatement(YieldHandling yieldHandling)
handler.addStatementToList(body, stmt); handler.addStatementToList(body, stmt);
} }
Node casepn = handler.newCaseOrDefault(caseBegin, caseExpr, body); CaseClauseType caseClause = handler.newCaseOrDefault(caseBegin, caseExpr, body);
if (!casepn) if (!caseClause)
return null(); return null();
handler.addCaseStatementToList(caseList, casepn); handler.addCaseStatementToList(caseList, caseClause);
} }
Node lexicalForCaseList = finishLexicalScope(scope, caseList); Node lexicalForCaseList = finishLexicalScope(scope, caseList);
@ -6818,7 +6823,7 @@ Parser<ParseHandler>::yieldExpression(InHandling inHandling)
} }
template <typename ParseHandler> template <typename ParseHandler>
typename ParseHandler::Node typename ParseHandler::BinaryNodeType
Parser<ParseHandler>::withStatement(YieldHandling yieldHandling) Parser<ParseHandler>::withStatement(YieldHandling yieldHandling)
{ {
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_WITH)); MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_WITH));
@ -9181,8 +9186,8 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
if (tt == TOK_NEW) { if (tt == TOK_NEW) {
uint32_t newBegin = pos().begin; uint32_t newBegin = pos().begin;
// Make sure this wasn't a |new.target| in disguise. // Make sure this wasn't a |new.target| in disguise.
Node newTarget; BinaryNodeType newTarget;
if (!tryNewTarget(newTarget)) if (!tryNewTarget(&newTarget))
return null(); return null();
if (newTarget) { if (newTarget) {
lhs = newTarget; lhs = newTarget;
@ -10246,7 +10251,7 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
handler.checkAndSetIsDirectRHSAnonFunction(rhs); handler.checkAndSetIsDirectRHSAnonFunction(rhs);
Node propExpr = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP); BinaryNodeType propExpr = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP);
if (!propExpr) if (!propExpr)
return null(); return null();
@ -10362,11 +10367,11 @@ Parser<ParseHandler>::methodDefinition(uint32_t toStringStart, PropertyType prop
template <typename ParseHandler> template <typename ParseHandler>
bool bool
Parser<ParseHandler>::tryNewTarget(Node &newTarget) Parser<ParseHandler>::tryNewTarget(BinaryNodeType* newTarget)
{ {
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_NEW)); MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_NEW));
newTarget = null(); *newTarget = null();
Node newHolder = handler.newPosHolder(pos()); Node newHolder = handler.newPosHolder(pos());
if (!newHolder) if (!newHolder)
@ -10400,8 +10405,8 @@ Parser<ParseHandler>::tryNewTarget(Node &newTarget)
if (!targetHolder) if (!targetHolder)
return false; return false;
newTarget = handler.newNewTarget(newHolder, targetHolder); *newTarget = handler.newNewTarget(newHolder, targetHolder);
return !!newTarget; return !!*newTarget;
} }
template <typename ParseHandler> template <typename ParseHandler>

View file

@ -1198,8 +1198,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
Node blockStatement(YieldHandling yieldHandling, Node blockStatement(YieldHandling yieldHandling,
unsigned errorNumber = JSMSG_CURLY_IN_COMPOUND); unsigned errorNumber = JSMSG_CURLY_IN_COMPOUND);
Node doWhileStatement(YieldHandling yieldHandling); BinaryNodeType doWhileStatement(YieldHandling yieldHandling);
Node whileStatement(YieldHandling yieldHandling); BinaryNodeType whileStatement(YieldHandling yieldHandling);
Node forStatement(YieldHandling yieldHandling); Node forStatement(YieldHandling yieldHandling);
bool forHeadStart(YieldHandling yieldHandling, bool forHeadStart(YieldHandling yieldHandling,
@ -1210,11 +1210,11 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
Node* forInOrOfExpression); Node* forInOrOfExpression);
Node expressionAfterForInOrOf(ParseNodeKind forHeadKind, YieldHandling yieldHandling); Node expressionAfterForInOrOf(ParseNodeKind forHeadKind, YieldHandling yieldHandling);
Node switchStatement(YieldHandling yieldHandling); SwitchStatementType switchStatement(YieldHandling yieldHandling);
Node continueStatement(YieldHandling yieldHandling); Node continueStatement(YieldHandling yieldHandling);
Node breakStatement(YieldHandling yieldHandling); Node breakStatement(YieldHandling yieldHandling);
Node returnStatement(YieldHandling yieldHandling); Node returnStatement(YieldHandling yieldHandling);
Node withStatement(YieldHandling yieldHandling); BinaryNodeType withStatement(YieldHandling yieldHandling);
Node throwStatement(YieldHandling yieldHandling); Node throwStatement(YieldHandling yieldHandling);
TernaryNodeType tryStatement(YieldHandling yieldHandling); TernaryNodeType tryStatement(YieldHandling yieldHandling);
Node catchBlockStatement(YieldHandling yieldHandling, ParseContext::Scope& catchParamScope); Node catchBlockStatement(YieldHandling yieldHandling, ParseContext::Scope& catchParamScope);
@ -1235,24 +1235,24 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
ListNodeType lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind); ListNodeType lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind);
Node importDeclaration(); inline BinaryNodeType importDeclaration();
bool processExport(Node node); bool processExport(Node node);
bool processExportFrom(Node node); bool processExportFrom(BinaryNodeType node);
Node exportFrom(uint32_t begin, Node specList); BinaryNodeType exportFrom(uint32_t begin, Node specList);
Node exportBatch(uint32_t begin); BinaryNodeType exportBatch(uint32_t begin);
bool checkLocalExportNames(ListNodeType node); bool checkLocalExportNames(ListNodeType node);
Node exportClause(uint32_t begin); Node exportClause(uint32_t begin);
Node exportFunctionDeclaration(uint32_t begin); Node exportFunctionDeclaration(uint32_t begin);
Node exportVariableStatement(uint32_t begin); Node exportVariableStatement(uint32_t begin);
Node exportClassDeclaration(uint32_t begin); Node exportClassDeclaration(uint32_t begin);
Node exportLexicalDeclaration(uint32_t begin, DeclarationKind kind); Node exportLexicalDeclaration(uint32_t begin, DeclarationKind kind);
Node exportDefaultFunctionDeclaration(uint32_t begin, BinaryNodeType exportDefaultFunctionDeclaration(uint32_t begin,
FunctionAsyncKind asyncKind = SyncFunction); FunctionAsyncKind asyncKind = SyncFunction);
Node exportDefaultClassDeclaration(uint32_t begin); BinaryNodeType exportDefaultClassDeclaration(uint32_t begin);
Node exportDefaultAssignExpr(uint32_t begin); BinaryNodeType exportDefaultAssignExpr(uint32_t begin);
Node exportDefault(uint32_t begin); BinaryNodeType exportDefault(uint32_t begin);
Node exportDeclaration(); Node exportDeclaration();
Node expressionStatement(YieldHandling yieldHandling, Node expressionStatement(YieldHandling yieldHandling,
@ -1343,7 +1343,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
Node exprInParens(InHandling inHandling, YieldHandling yieldHandling, Node exprInParens(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling, PossibleError* possibleError = nullptr); TripledotHandling tripledotHandling, PossibleError* possibleError = nullptr);
bool tryNewTarget(Node& newTarget); bool tryNewTarget(BinaryNodeType* newTarget);
bool checkAndMarkSuperScope(); bool checkAndMarkSuperScope();
Node methodDefinition(uint32_t toStringStart, PropertyType propType, HandleAtom funName); Node methodDefinition(uint32_t toStringStart, PropertyType propType, HandleAtom funName);
@ -1526,7 +1526,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
ListNodeType objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError); ListNodeType objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError);
Node bindingInitializer(Node lhs, DeclarationKind kind, YieldHandling yieldHandling); BinaryNodeType bindingInitializer(Node lhs, DeclarationKind kind, YieldHandling yieldHandling);
Node bindingIdentifier(DeclarationKind kind, YieldHandling yieldHandling); Node bindingIdentifier(DeclarationKind kind, YieldHandling yieldHandling);
Node bindingIdentifierOrPattern(DeclarationKind kind, YieldHandling yieldHandling, Node bindingIdentifierOrPattern(DeclarationKind kind, YieldHandling yieldHandling,
TokenKind tt); TokenKind tt);

View file

@ -304,19 +304,19 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
MOZ_MUST_USE bool addSpreadElement(ListNodeType literal, uint32_t begin, Node inner) { return true; } MOZ_MUST_USE bool addSpreadElement(ListNodeType literal, uint32_t begin, Node inner) { return true; }
void addArrayElement(ListNodeType literal, Node element) { } void addArrayElement(ListNodeType literal, Node element) { }
Node newCall(Node callee, Node args) { return NodeFunctionCall; } BinaryNodeType newCall(Node callee, Node args) { return NodeFunctionCall; }
Node newOptionalCall(Node callee, Node args) { return NodeOptionalFunctionCall; } BinaryNodeType newOptionalCall(Node callee, Node args) { return NodeOptionalFunctionCall; }
ListNodeType newArguments(const TokenPos& pos) { return NodeGeneric; } ListNodeType newArguments(const TokenPos& pos) { return NodeGeneric; }
Node newSuperCall(Node callee, Node args) { return NodeGeneric; } BinaryNodeType newSuperCall(Node callee, Node args) { return NodeGeneric; }
Node newTaggedTemplate(Node callee, Node args) { return NodeGeneric; } BinaryNodeType newTaggedTemplate(Node callee, Node args) { return NodeGeneric; }
Node newGenExp(Node callee, Node args) { return NodeGeneric; } Node newGenExp(Node callee, Node args) { return NodeGeneric; }
ListNodeType newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; } ListNodeType newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; }
ListNodeType newClassMethodList(uint32_t begin) { return NodeGeneric; } ListNodeType newClassMethodList(uint32_t begin) { return NodeGeneric; }
Node newClassNames(Node outer, Node inner, const TokenPos& pos) { return NodeGeneric; } ClassNamesType newClassNames(Node outer, Node inner, const TokenPos& pos) { return NodeGeneric; }
ClassNodeType newClass(Node name, Node heritage, Node methodBlock, const TokenPos& pos) { return NodeGeneric; } ClassNodeType newClass(Node name, Node heritage, Node methodBlock, const TokenPos& pos) { return NodeGeneric; }
Node newNewTarget(Node newHolder, Node targetHolder) { return NodeGeneric; } BinaryNodeType newNewTarget(Node newHolder, Node targetHolder) { return NodeGeneric; }
Node newPosHolder(const TokenPos& pos) { return NodeGeneric; } Node newPosHolder(const TokenPos& pos) { return NodeGeneric; }
Node newSuperBase(Node thisName, const TokenPos& pos) { return NodeSuperBase; } Node newSuperBase(Node thisName, const TokenPos& pos) { return NodeSuperBase; }
@ -335,21 +335,21 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
ListNodeType newStatementList(const TokenPos& pos) { return NodeGeneric; } ListNodeType newStatementList(const TokenPos& pos) { return NodeGeneric; }
void addStatementToList(ListNodeType list, Node stmt) {} void addStatementToList(ListNodeType list, Node stmt) {}
void addCaseStatementToList(ListNodeType list, Node caseClause) {} void addCaseStatementToList(ListNodeType list, CaseClauseType caseClause) {}
MOZ_MUST_USE bool prependInitialYield(ListNodeType stmtList, Node genName) { return true; } MOZ_MUST_USE bool prependInitialYield(ListNodeType stmtList, Node genName) { return true; }
Node newEmptyStatement(const TokenPos& pos) { return NodeEmptyStatement; } Node newEmptyStatement(const TokenPos& pos) { return NodeEmptyStatement; }
Node newExportDeclaration(Node kid, const TokenPos& pos) { Node newExportDeclaration(Node kid, const TokenPos& pos) {
return NodeGeneric; return NodeGeneric;
} }
Node newExportFromDeclaration(uint32_t begin, Node exportSpecSet, Node moduleSpec) { BinaryNodeType newExportFromDeclaration(uint32_t begin, Node exportSpecSet, Node moduleSpec) {
return NodeGeneric; return NodeGeneric;
} }
Node newExportDefaultDeclaration(Node kid, Node maybeBinding, const TokenPos& pos) { BinaryNodeType newExportDefaultDeclaration(Node kid, Node maybeBinding, const TokenPos& pos) {
return NodeGeneric; return NodeGeneric;
} }
Node newSetThis(Node thisName, Node value) { return value; } BinaryNodeType newSetThis(Node thisName, Node value) { return value; }
Node newExprStatement(Node expr, uint32_t end) { Node newExprStatement(Node expr, uint32_t end) {
return expr == NodeUnparenthesizedString ? NodeStringExprStatement : NodeGeneric; return expr == NodeUnparenthesizedString ? NodeStringExprStatement : NodeGeneric;
@ -358,17 +358,17 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
TernaryNodeType newIfStatement(uint32_t begin, Node cond, Node thenBranch, Node elseBranch) { TernaryNodeType newIfStatement(uint32_t begin, Node cond, Node thenBranch, Node elseBranch) {
return NodeGeneric; return NodeGeneric;
} }
Node newDoWhileStatement(Node body, Node cond, const TokenPos& pos) { return NodeGeneric; } BinaryNodeType newDoWhileStatement(Node body, Node cond, const TokenPos& pos) { return NodeGeneric; }
Node newWhileStatement(uint32_t begin, Node cond, Node body) { return NodeGeneric; } BinaryNodeType newWhileStatement(uint32_t begin, Node cond, Node body) { return NodeGeneric; }
Node newSwitchStatement(uint32_t begin, Node discriminant, Node lexicalForCaseList, bool hasDefault) SwitchStatementType newSwitchStatement(uint32_t begin, Node discriminant, Node lexicalForCaseList, bool hasDefault)
{ {
return NodeGeneric; return NodeGeneric;
} }
Node newCaseOrDefault(uint32_t begin, Node expr, Node body) { return NodeGeneric; } CaseClauseType newCaseOrDefault(uint32_t begin, Node expr, Node body) { return NodeGeneric; }
Node newContinueStatement(PropertyName* label, const TokenPos& pos) { return NodeGeneric; } Node newContinueStatement(PropertyName* label, const TokenPos& pos) { return NodeGeneric; }
Node newBreakStatement(PropertyName* label, const TokenPos& pos) { return NodeBreak; } Node newBreakStatement(PropertyName* label, const TokenPos& pos) { return NodeBreak; }
Node newReturnStatement(Node expr, const TokenPos& pos) { return NodeReturn; } Node newReturnStatement(Node expr, const TokenPos& pos) { return NodeReturn; }
Node newWithStatement(uint32_t begin, Node expr, Node body) { return NodeGeneric; } BinaryNodeType newWithStatement(uint32_t begin, Node expr, Node body) { return NodeGeneric; }
Node newLabeledStatement(PropertyName* label, Node stmt, uint32_t begin) { Node newLabeledStatement(PropertyName* label, Node stmt, uint32_t begin) {
return NodeGeneric; return NodeGeneric;
@ -385,7 +385,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return NodeGeneric; return NodeGeneric;
} }
Node newPropertyAccess(Node expr, Node key) { PropertyAccessType newPropertyAccess(Node expr, Node key) {
return NodeDottedProperty; return NodeDottedProperty;
} }
@ -393,7 +393,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return NodeOptionalDottedProperty; return NodeOptionalDottedProperty;
} }
Node newPropertyByValue(Node pn, Node kid, uint32_t end) { return NodeElement; } PropertyByValueType newPropertyByValue(Node lhs, Node index, uint32_t end) { return NodeElement; }
Node newOptionalPropertyByValue(Node pn, Node kid, uint32_t end) { return NodeOptionalElement; } Node newOptionalPropertyByValue(Node pn, Node kid, uint32_t end) { return NodeOptionalElement; }
@ -414,7 +414,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
void setFunctionBox(Node pn, FunctionBox* funbox) {} void setFunctionBox(Node pn, FunctionBox* funbox) {}
void addFunctionFormalParameter(Node pn, Node argpn) {} void addFunctionFormalParameter(Node pn, Node argpn) {}
Node newForStatement(uint32_t begin, TernaryNodeType forHead, Node body, unsigned iflags) { ForNodeType newForStatement(uint32_t begin, TernaryNodeType forHead, Node body, unsigned iflags) {
return NodeGeneric; return NodeGeneric;
} }
@ -518,11 +518,11 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
} }
Node newNewExpression(uint32_t begin, Node ctor, Node args) { BinaryNodeType newNewExpression(uint32_t begin, Node ctor, Node args) {
return NodeGeneric; return NodeGeneric;
} }
Node newAssignment(ParseNodeKind kind, Node lhs, Node rhs, JSOp op) { AssignmentNodeType newAssignment(ParseNodeKind kind, Node lhs, Node rhs, JSOp op) {
if (kind == PNK_ASSIGN) if (kind == PNK_ASSIGN)
return NodeUnparenthesizedAssignment; return NodeUnparenthesizedAssignment;
return newBinary(kind, lhs, rhs, op); return newBinary(kind, lhs, rhs, op);

View file

@ -408,15 +408,13 @@ UnaryKid(ParseNode* pn)
static inline ParseNode* static inline ParseNode*
BinaryRight(ParseNode* pn) BinaryRight(ParseNode* pn)
{ {
MOZ_ASSERT(pn->isArity(PN_BINARY)); return pn->as<BinaryNode>().right();
return pn->pn_right;
} }
static inline ParseNode* static inline ParseNode*
BinaryLeft(ParseNode* pn) BinaryLeft(ParseNode* pn)
{ {
MOZ_ASSERT(pn->isArity(PN_BINARY)); return pn->as<BinaryNode>().left();
return pn->pn_left;
} }
static inline ParseNode* static inline ParseNode*
@ -634,31 +632,25 @@ NumberNodeHasFrac(ParseNode* pn)
static ParseNode* static ParseNode*
DotBase(ParseNode* pn) DotBase(ParseNode* pn)
{ {
MOZ_ASSERT(pn->isKind(PNK_DOT)); return &pn->as<PropertyAccess>().expression();
MOZ_ASSERT(pn->isArity(PN_BINARY));
return pn->pn_left;
} }
static PropertyName* static PropertyName*
DotMember(ParseNode* pn) DotMember(ParseNode* pn)
{ {
MOZ_ASSERT(pn->isKind(PNK_DOT)); return &pn->as<PropertyAccess>().name();
MOZ_ASSERT(pn->isArity(PN_BINARY));
return pn->pn_right->pn_atom->asPropertyName();
} }
static ParseNode* static ParseNode*
ElemBase(ParseNode* pn) ElemBase(ParseNode* pn)
{ {
MOZ_ASSERT(pn->isKind(PNK_ELEM)); return &pn->as<PropertyByValueBase>().expression();
return BinaryLeft(pn);
} }
static ParseNode* static ParseNode*
ElemIndex(ParseNode* pn) ElemIndex(ParseNode* pn)
{ {
MOZ_ASSERT(pn->isKind(PNK_ELEM)); return &pn->as<PropertyByValueBase>().key();
return BinaryRight(pn);
} }
static inline JSFunction* static inline JSFunction*