mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-20 14:17:30 +09:00
parent
c02e109b79
commit
9c17ec0533
14 changed files with 1251 additions and 1049 deletions
|
|
@ -1172,7 +1172,7 @@ ModuleBuilder::processImport(frontend::ParseNode* pn)
|
|||
if (!maybeAppendRequestedModule(module))
|
||||
return false;
|
||||
|
||||
for (ParseNode* spec = pn->pn_left->pn_head; spec; spec = spec->pn_next) {
|
||||
for (ParseNode* spec : pn->pn_left->as<ListNode>().contents()) {
|
||||
MOZ_ASSERT(spec->isKind(PNK_IMPORT_SPEC));
|
||||
MOZ_ASSERT(spec->pn_left->isArity(PN_NAME));
|
||||
MOZ_ASSERT(spec->pn_right->isArity(PN_NAME));
|
||||
|
|
@ -1215,7 +1215,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
|
|||
switch (kid->getKind()) {
|
||||
case PNK_EXPORT_SPEC_LIST:
|
||||
MOZ_ASSERT(!isDefault);
|
||||
for (ParseNode* spec = kid->pn_head; spec; spec = spec->pn_next) {
|
||||
for (ParseNode* spec : kid->as<ListNode>().contents()) {
|
||||
MOZ_ASSERT(spec->isKind(PNK_EXPORT_SPEC));
|
||||
RootedAtom localName(cx_, spec->pn_left->pn_atom);
|
||||
RootedAtom exportName(cx_, spec->pn_right->pn_atom);
|
||||
|
|
@ -1238,7 +1238,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
|
|||
case PNK_CONST:
|
||||
case PNK_LET: {
|
||||
MOZ_ASSERT(kid->isArity(PN_LIST));
|
||||
for (ParseNode* binding = kid->pn_head; binding; binding = binding->pn_next) {
|
||||
for (ParseNode* binding : kid->as<ListNode>().contents()) {
|
||||
if (binding->isKind(PNK_ASSIGN))
|
||||
binding = binding->pn_left;
|
||||
else
|
||||
|
|
@ -1250,11 +1250,11 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
|
|||
if (!appendExportEntry(exportName, localName))
|
||||
return false;
|
||||
} else if (binding->isKind(PNK_ARRAY)) {
|
||||
if (!processExportArrayBinding(binding))
|
||||
if (!processExportArrayBinding(&binding->as<ListNode>()))
|
||||
return false;
|
||||
} else {
|
||||
MOZ_ASSERT(binding->isKind(PNK_OBJECT));
|
||||
if (!processExportObjectBinding(binding))
|
||||
if (!processExportObjectBinding(&binding->as<ListNode>()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1288,19 +1288,18 @@ ModuleBuilder::processExportBinding(frontend::ParseNode* binding)
|
|||
}
|
||||
|
||||
if (binding->isKind(PNK_ARRAY))
|
||||
return processExportArrayBinding(binding);
|
||||
return processExportArrayBinding(&binding->as<ListNode>());
|
||||
|
||||
MOZ_ASSERT(binding->isKind(PNK_OBJECT));
|
||||
return processExportObjectBinding(binding);
|
||||
return processExportObjectBinding(&binding->as<ListNode>());
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleBuilder::processExportArrayBinding(frontend::ParseNode* pn)
|
||||
ModuleBuilder::processExportArrayBinding(frontend::ListNode* array)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_ARRAY));
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(array->isKind(PNK_ARRAY));
|
||||
|
||||
for (ParseNode* node = pn->pn_head; node; node = node->pn_next) {
|
||||
for (ParseNode* node : array->contents()) {
|
||||
if (node->isKind(PNK_ELISION))
|
||||
continue;
|
||||
|
||||
|
|
@ -1317,12 +1316,11 @@ ModuleBuilder::processExportArrayBinding(frontend::ParseNode* pn)
|
|||
}
|
||||
|
||||
bool
|
||||
ModuleBuilder::processExportObjectBinding(frontend::ParseNode* pn)
|
||||
ModuleBuilder::processExportObjectBinding(frontend::ListNode* obj)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(obj->isKind(PNK_OBJECT));
|
||||
|
||||
for (ParseNode* node = pn->pn_head; node; node = node->pn_next) {
|
||||
for (ParseNode* node : obj->contents()) {
|
||||
MOZ_ASSERT(node->isKind(PNK_MUTATEPROTO) ||
|
||||
node->isKind(PNK_COLON) ||
|
||||
node->isKind(PNK_SHORTHAND) ||
|
||||
|
|
@ -1360,7 +1358,7 @@ ModuleBuilder::processExportFrom(frontend::ParseNode* pn)
|
|||
if (!maybeAppendRequestedModule(module))
|
||||
return false;
|
||||
|
||||
for (ParseNode* spec = pn->pn_left->pn_head; spec; spec = spec->pn_next) {
|
||||
for (ParseNode* spec : pn->pn_left->as<ListNode>().contents()) {
|
||||
if (spec->isKind(PNK_EXPORT_SPEC)) {
|
||||
RootedAtom bindingName(cx_, spec->pn_left->pn_atom);
|
||||
RootedAtom exportName(cx_, spec->pn_right->pn_atom);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class ModuleEnvironmentObject;
|
|||
class ModuleObject;
|
||||
|
||||
namespace frontend {
|
||||
class ListNode;
|
||||
class ParseNode;
|
||||
class TokenStream;
|
||||
} /* namespace frontend */
|
||||
|
|
@ -353,8 +354,8 @@ class MOZ_STACK_CLASS ModuleBuilder
|
|||
ImportEntryObject* importEntryFor(JSAtom* localName) const;
|
||||
|
||||
bool processExportBinding(frontend::ParseNode* pn);
|
||||
bool processExportArrayBinding(frontend::ParseNode* pn);
|
||||
bool processExportObjectBinding(frontend::ParseNode* pn);
|
||||
bool processExportArrayBinding(frontend::ListNode* pn);
|
||||
bool processExportObjectBinding(frontend::ListNode* pn);
|
||||
|
||||
bool appendExportEntry(HandleAtom exportName, HandleAtom localName,
|
||||
frontend::ParseNode* node = nullptr);
|
||||
|
|
|
|||
|
|
@ -1790,17 +1790,17 @@ class ASTSerializer
|
|||
UnaryOperator unop(ParseNodeKind kind, JSOp op);
|
||||
AssignmentOperator aop(JSOp op);
|
||||
|
||||
bool statements(ParseNode* pn, NodeVector& elts);
|
||||
bool expressions(ParseNode* pn, NodeVector& elts);
|
||||
bool leftAssociate(ParseNode* pn, MutableHandleValue dst);
|
||||
bool rightAssociate(ParseNode* pn, MutableHandleValue dst);
|
||||
bool functionArgs(ParseNode* pn, ParseNode* pnargs,
|
||||
bool statements(ListNode* stmtList, NodeVector& elts);
|
||||
bool expressions(ListNode* exprList, NodeVector& elts);
|
||||
bool leftAssociate(ListNode* node, MutableHandleValue dst);
|
||||
bool rightAssociate(ListNode* node, MutableHandleValue dst);
|
||||
bool functionArgs(ParseNode* pn, ListNode* argsList,
|
||||
NodeVector& args, NodeVector& defaults, MutableHandleValue rest);
|
||||
|
||||
bool sourceElement(ParseNode* pn, MutableHandleValue dst);
|
||||
|
||||
bool declaration(ParseNode* pn, MutableHandleValue dst);
|
||||
bool variableDeclaration(ParseNode* pn, bool lexical, MutableHandleValue dst);
|
||||
bool variableDeclaration(ListNode* declList, bool lexical, MutableHandleValue dst);
|
||||
bool variableDeclarator(ParseNode* pn, MutableHandleValue dst);
|
||||
bool importDeclaration(ParseNode* pn, MutableHandleValue dst);
|
||||
bool importSpecifier(ParseNode* pn, MutableHandleValue dst);
|
||||
|
|
@ -1822,7 +1822,7 @@ class ASTSerializer
|
|||
bool forOf(ParseNode* loop, ParseNode* head, HandleValue var, HandleValue stmt,
|
||||
MutableHandleValue dst);
|
||||
bool statement(ParseNode* pn, MutableHandleValue dst);
|
||||
bool blockStatement(ParseNode* pn, MutableHandleValue dst);
|
||||
bool blockStatement(ListNode* node, MutableHandleValue dst);
|
||||
bool switchStatement(ParseNode* pn, MutableHandleValue dst);
|
||||
bool switchCase(ParseNode* pn, MutableHandleValue dst);
|
||||
bool tryStatement(ParseNode* pn, MutableHandleValue dst);
|
||||
|
|
@ -1864,8 +1864,8 @@ class ASTSerializer
|
|||
}
|
||||
|
||||
bool pattern(ParseNode* pn, MutableHandleValue dst);
|
||||
bool arrayPattern(ParseNode* pn, MutableHandleValue dst);
|
||||
bool objectPattern(ParseNode* pn, MutableHandleValue dst);
|
||||
bool arrayPattern(ListNode* array, MutableHandleValue dst);
|
||||
bool objectPattern(ListNode* obj, MutableHandleValue dst);
|
||||
|
||||
bool function(ParseNode* pn, ASTType type, MutableHandleValue dst);
|
||||
bool functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector& defaults,
|
||||
|
|
@ -1897,7 +1897,7 @@ class ASTSerializer
|
|||
builder.setTokenStream(&p->tokenStream);
|
||||
}
|
||||
|
||||
bool program(ParseNode* pn, MutableHandleValue dst);
|
||||
bool program(ListNode* node, MutableHandleValue dst);
|
||||
};
|
||||
|
||||
} /* anonymous namespace */
|
||||
|
|
@ -2021,19 +2021,18 @@ ASTSerializer::binop(ParseNodeKind kind, JSOp op)
|
|||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::statements(ParseNode* pn, NodeVector& elts)
|
||||
ASTSerializer::statements(ListNode* stmtList, NodeVector& elts)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_STATEMENTLIST));
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(stmtList->isKind(PNK_STATEMENTLIST));
|
||||
|
||||
if (!elts.reserve(pn->pn_count))
|
||||
if (!elts.reserve(stmtList->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
|
||||
for (ParseNode* stmt : stmtList->contents()) {
|
||||
MOZ_ASSERT(stmtList->pn_pos.encloses(stmt->pn_pos));
|
||||
|
||||
RootedValue elt(cx);
|
||||
if (!sourceElement(next, &elt))
|
||||
if (!sourceElement(stmt, &elt))
|
||||
return false;
|
||||
elts.infallibleAppend(elt);
|
||||
}
|
||||
|
|
@ -2042,16 +2041,16 @@ ASTSerializer::statements(ParseNode* pn, NodeVector& elts)
|
|||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::expressions(ParseNode* pn, NodeVector& elts)
|
||||
ASTSerializer::expressions(ListNode* exprList, NodeVector& elts)
|
||||
{
|
||||
if (!elts.reserve(pn->pn_count))
|
||||
if (!elts.reserve(exprList->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
|
||||
for (ParseNode* expr : exprList->contents()) {
|
||||
MOZ_ASSERT(exprList->pn_pos.encloses(expr->pn_pos));
|
||||
|
||||
RootedValue elt(cx);
|
||||
if (!expression(next, &elt))
|
||||
if (!expression(expr, &elt))
|
||||
return false;
|
||||
elts.infallibleAppend(elt);
|
||||
}
|
||||
|
|
@ -2060,23 +2059,23 @@ ASTSerializer::expressions(ParseNode* pn, NodeVector& elts)
|
|||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::blockStatement(ParseNode* pn, MutableHandleValue dst)
|
||||
ASTSerializer::blockStatement(ListNode* node, MutableHandleValue dst)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_STATEMENTLIST));
|
||||
MOZ_ASSERT(node->isKind(PNK_STATEMENTLIST));
|
||||
|
||||
NodeVector stmts(cx);
|
||||
return statements(pn, stmts) &&
|
||||
builder.blockStatement(stmts, &pn->pn_pos, dst);
|
||||
return statements(node, stmts) &&
|
||||
builder.blockStatement(stmts, &node->pn_pos, dst);
|
||||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::program(ParseNode* pn, MutableHandleValue dst)
|
||||
ASTSerializer::program(ListNode* node, MutableHandleValue dst)
|
||||
{
|
||||
MOZ_ASSERT(parser->tokenStream.srcCoords.lineNum(pn->pn_pos.begin) == lineno);
|
||||
MOZ_ASSERT(parser->tokenStream.srcCoords.lineNum(node->pn_pos.begin) == lineno);
|
||||
|
||||
NodeVector stmts(cx);
|
||||
return statements(pn, stmts) &&
|
||||
builder.program(stmts, &pn->pn_pos, dst);
|
||||
return statements(node, stmts) &&
|
||||
builder.program(stmts, &node->pn_pos, dst);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -2099,38 +2098,38 @@ ASTSerializer::declaration(ParseNode* pn, MutableHandleValue dst)
|
|||
return function(pn, AST_FUNC_DECL, dst);
|
||||
|
||||
case PNK_VAR:
|
||||
return variableDeclaration(pn, false, dst);
|
||||
return variableDeclaration(&pn->as<ListNode>(), false, dst);
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(pn->isKind(PNK_LET) || pn->isKind(PNK_CONST));
|
||||
return variableDeclaration(pn, true, dst);
|
||||
return variableDeclaration(&pn->as<ListNode>(), true, dst);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::variableDeclaration(ParseNode* pn, bool lexical, MutableHandleValue dst)
|
||||
ASTSerializer::variableDeclaration(ListNode* declList, bool lexical, MutableHandleValue dst)
|
||||
{
|
||||
MOZ_ASSERT_IF(lexical, pn->isKind(PNK_LET) || pn->isKind(PNK_CONST));
|
||||
MOZ_ASSERT_IF(!lexical, pn->isKind(PNK_VAR));
|
||||
MOZ_ASSERT_IF(lexical, declList->isKind(PNK_LET) || declList->isKind(PNK_CONST));
|
||||
MOZ_ASSERT_IF(!lexical, declList->isKind(PNK_VAR));
|
||||
|
||||
VarDeclKind kind = VARDECL_ERR;
|
||||
// Treat both the toplevel const binding (secretly var-like) and the lexical const
|
||||
// the same way
|
||||
if (lexical)
|
||||
kind = pn->isKind(PNK_LET) ? VARDECL_LET : VARDECL_CONST;
|
||||
kind = declList->isKind(PNK_LET) ? VARDECL_LET : VARDECL_CONST;
|
||||
else
|
||||
kind = pn->isKind(PNK_VAR) ? VARDECL_VAR : VARDECL_CONST;
|
||||
kind = declList->isKind(PNK_VAR) ? VARDECL_VAR : VARDECL_CONST;
|
||||
|
||||
NodeVector dtors(cx);
|
||||
if (!dtors.reserve(pn->pn_count))
|
||||
if (!dtors.reserve(declList->count()))
|
||||
return false;
|
||||
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
|
||||
for (ParseNode* decl : declList->contents()) {
|
||||
RootedValue child(cx);
|
||||
if (!variableDeclarator(next, &child))
|
||||
if (!variableDeclarator(decl, &child))
|
||||
return false;
|
||||
dtors.infallibleAppend(child);
|
||||
}
|
||||
return builder.variableDeclaration(dtors, kind, &pn->pn_pos, dst);
|
||||
return builder.variableDeclaration(dtors, kind, &declList->pn_pos, dst);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -2168,13 +2167,15 @@ ASTSerializer::importDeclaration(ParseNode* pn, MutableHandleValue dst)
|
|||
MOZ_ASSERT(pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST));
|
||||
MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING));
|
||||
|
||||
ListNode* specList = &pn->pn_left->as<ListNode>();
|
||||
|
||||
NodeVector elts(cx);
|
||||
if (!elts.reserve(pn->pn_left->pn_count))
|
||||
if (!elts.reserve(specList->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* next = pn->pn_left->pn_head; next; next = next->pn_next) {
|
||||
for (ParseNode* spec : specList->contents()) {
|
||||
RootedValue elt(cx);
|
||||
if (!importSpecifier(next, &elt))
|
||||
if (!importSpecifier(spec, &elt))
|
||||
return false;
|
||||
elts.infallibleAppend(elt);
|
||||
}
|
||||
|
|
@ -2210,14 +2211,15 @@ ASTSerializer::exportDeclaration(ParseNode* pn, MutableHandleValue dst)
|
|||
|
||||
ParseNode* kid = pn->isKind(PNK_EXPORT) ? pn->pn_kid : pn->pn_left;
|
||||
switch (ParseNodeKind kind = kid->getKind()) {
|
||||
case PNK_EXPORT_SPEC_LIST:
|
||||
if (!elts.reserve(pn->pn_left->pn_count))
|
||||
case PNK_EXPORT_SPEC_LIST: {
|
||||
ListNode* specList = &pn->pn_left->as<ListNode>();
|
||||
if (!elts.reserve(specList->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* next = pn->pn_left->pn_head; next; next = next->pn_next) {
|
||||
for (ParseNode* spec : specList->contents()) {
|
||||
RootedValue elt(cx);
|
||||
if (next->isKind(PNK_EXPORT_SPEC)) {
|
||||
if (!exportSpecifier(next, &elt))
|
||||
if (spec->isKind(PNK_EXPORT_SPEC)) {
|
||||
if (!exportSpecifier(spec, &elt))
|
||||
return false;
|
||||
} else {
|
||||
if (!builder.exportBatchSpecifier(&pn->pn_pos, &elt))
|
||||
|
|
@ -2226,6 +2228,7 @@ ASTSerializer::exportDeclaration(ParseNode* pn, MutableHandleValue dst)
|
|||
elts.infallibleAppend(elt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PNK_FUNCTION:
|
||||
if (!function(kid, AST_FUNC_DECL, &decl))
|
||||
|
|
@ -2240,7 +2243,7 @@ ASTSerializer::exportDeclaration(ParseNode* pn, MutableHandleValue dst)
|
|||
case PNK_VAR:
|
||||
case PNK_CONST:
|
||||
case PNK_LET:
|
||||
if (!variableDeclaration(kid, kind != PNK_VAR, &decl))
|
||||
if (!variableDeclaration(&kid->as<ListNode>(), kind != PNK_VAR, &decl))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
|
@ -2299,29 +2302,22 @@ ASTSerializer::switchStatement(ParseNode* pn, MutableHandleValue dst)
|
|||
if (!expression(pn->pn_left, &disc))
|
||||
return false;
|
||||
|
||||
ParseNode* listNode;
|
||||
bool lexical;
|
||||
|
||||
if (pn->pn_right->isKind(PNK_LEXICALSCOPE)) {
|
||||
listNode = pn->pn_right->pn_expr;
|
||||
lexical = true;
|
||||
} else {
|
||||
listNode = pn->pn_right;
|
||||
lexical = false;
|
||||
}
|
||||
MOZ_ASSERT(pn->pn_right->isKind(PNK_LEXICALSCOPE));
|
||||
ListNode* caseList = &pn->pn_right->scopeBody()->as<ListNode>();
|
||||
|
||||
NodeVector cases(cx);
|
||||
if (!cases.reserve(listNode->pn_count))
|
||||
if (!cases.reserve(caseList->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* next = listNode->pn_head; next; next = next->pn_next) {
|
||||
for (ParseNode* caseNode : caseList->contents()) {
|
||||
RootedValue child(cx);
|
||||
if (!switchCase(next, &child))
|
||||
if (!switchCase(caseNode, &child))
|
||||
return false;
|
||||
cases.infallibleAppend(child);
|
||||
}
|
||||
|
||||
return builder.switchStatement(disc, cases, lexical, &pn->pn_pos, dst);
|
||||
return builder.switchStatement(disc, cases, /* lexical = */ true, &pn->pn_pos, dst);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -2358,11 +2354,11 @@ ASTSerializer::tryStatement(ParseNode* pn, MutableHandleValue dst)
|
|||
NodeVector guarded(cx);
|
||||
RootedValue unguarded(cx, NullValue());
|
||||
|
||||
if (ParseNode* catchList = pn->pn_kid2) {
|
||||
if (!guarded.reserve(catchList->pn_count))
|
||||
if (ListNode* catchList = &pn->pn_kid2->as<ListNode>()) {
|
||||
if (!guarded.reserve(catchList->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* next = catchList->pn_head; next; next = next->pn_next) {
|
||||
for (ParseNode* next : catchList->contents()) {
|
||||
RootedValue clause(cx);
|
||||
bool isGuarded;
|
||||
if (!catchClause(next->pn_expr, &isGuarded, &clause))
|
||||
|
|
@ -2389,7 +2385,7 @@ ASTSerializer::forInit(ParseNode* pn, MutableHandleValue dst)
|
|||
|
||||
bool lexical = pn->isKind(PNK_LET) || pn->isKind(PNK_CONST);
|
||||
return (lexical || pn->isKind(PNK_VAR))
|
||||
? variableDeclaration(pn, lexical, dst)
|
||||
? variableDeclaration(&pn->as<ListNode>(), lexical, dst)
|
||||
: expression(pn, dst);
|
||||
}
|
||||
|
||||
|
|
@ -2467,7 +2463,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
|||
MOZ_FALLTHROUGH;
|
||||
|
||||
case PNK_STATEMENTLIST:
|
||||
return blockStatement(pn, dst);
|
||||
return blockStatement(&pn->as<ListNode>(), dst);
|
||||
|
||||
case PNK_IF:
|
||||
{
|
||||
|
|
@ -2535,7 +2531,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
|||
if (head->isKind(PNK_FORIN) || head->isKind(PNK_FOROF)) {
|
||||
RootedValue var(cx);
|
||||
if (head->pn_kid1->isKind(PNK_LEXICALSCOPE)) {
|
||||
if (!variableDeclaration(head->pn_kid1->pn_expr, true, &var))
|
||||
if (!variableDeclaration(&head->pn_kid1->scopeBody()->as<ListNode>(), true, &var))
|
||||
return false;
|
||||
} else if (!head->pn_kid1->isKind(PNK_VAR) &&
|
||||
!head->pn_kid1->isKind(PNK_LET) &&
|
||||
|
|
@ -2544,7 +2540,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
|||
if (!pattern(head->pn_kid1, &var))
|
||||
return false;
|
||||
} else {
|
||||
if (!variableDeclaration(head->pn_kid1,
|
||||
if (!variableDeclaration(&head->pn_kid1->as<ListNode>(),
|
||||
head->pn_kid1->isKind(PNK_LET) ||
|
||||
head->pn_kid1->isKind(PNK_CONST),
|
||||
&var))
|
||||
|
|
@ -2615,15 +2611,16 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
|||
|
||||
case PNK_CLASSMETHODLIST:
|
||||
{
|
||||
ListNode* methodList = &pn->as<ListNode>();
|
||||
NodeVector methods(cx);
|
||||
if (!methods.reserve(pn->pn_count))
|
||||
if (!methods.reserve(methodList->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
|
||||
for (ParseNode* method : methodList->contents()) {
|
||||
MOZ_ASSERT(methodList->pn_pos.encloses(method->pn_pos));
|
||||
|
||||
RootedValue prop(cx);
|
||||
if (!classMethod(next, &prop))
|
||||
if (!classMethod(method, &prop))
|
||||
return false;
|
||||
methods.infallibleAppend(prop);
|
||||
}
|
||||
|
|
@ -2668,32 +2665,31 @@ ASTSerializer::classMethod(ParseNode* pn, MutableHandleValue dst)
|
|||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::leftAssociate(ParseNode* pn, MutableHandleValue dst)
|
||||
ASTSerializer::leftAssociate(ListNode* node, MutableHandleValue dst)
|
||||
{
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(pn->pn_count >= 1);
|
||||
MOZ_ASSERT(!node->empty());
|
||||
|
||||
ParseNodeKind kind = pn->getKind();
|
||||
ParseNodeKind kind = node->getKind();
|
||||
bool logop = (kind == PNK_COALESCE ||
|
||||
kind == PNK_OR ||
|
||||
kind == PNK_AND);
|
||||
|
||||
ParseNode* head = pn->pn_head;
|
||||
ParseNode* head = node->head();
|
||||
RootedValue left(cx);
|
||||
if (!expression(head, &left))
|
||||
return false;
|
||||
for (ParseNode* next = head->pn_next; next; next = next->pn_next) {
|
||||
for (ParseNode* next : node->contentsFrom(head->pn_next)) {
|
||||
RootedValue right(cx);
|
||||
if (!expression(next, &right))
|
||||
return false;
|
||||
|
||||
TokenPos subpos(pn->pn_pos.begin, next->pn_pos.end);
|
||||
TokenPos subpos(node->pn_pos.begin, next->pn_pos.end);
|
||||
|
||||
if (logop) {
|
||||
if (!builder.logicalExpression(kind, left, right, &subpos, &left))
|
||||
return false;
|
||||
} else {
|
||||
BinaryOperator op = binop(pn->getKind(), pn->getOp());
|
||||
BinaryOperator op = binop(node->getKind(), node->getOp());
|
||||
LOCAL_ASSERT(op > BINOP_ERR && op < BINOP_LIMIT);
|
||||
|
||||
if (!builder.binaryExpression(op, left, right, &subpos, &left))
|
||||
|
|
@ -2706,15 +2702,14 @@ ASTSerializer::leftAssociate(ParseNode* pn, MutableHandleValue dst)
|
|||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::rightAssociate(ParseNode* pn, MutableHandleValue dst)
|
||||
ASTSerializer::rightAssociate(ListNode* node, MutableHandleValue dst)
|
||||
{
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(pn->pn_count >= 1);
|
||||
MOZ_ASSERT(!node->empty());
|
||||
|
||||
// First, we need to reverse the list, so that we can traverse it in the right order.
|
||||
// It's OK to destructively reverse the list, because there are no other consumers.
|
||||
|
||||
ParseNode* head = pn->pn_head;
|
||||
ParseNode* head = node->head();
|
||||
ParseNode* prev = nullptr;
|
||||
ParseNode* current = head;
|
||||
ParseNode* next;
|
||||
|
|
@ -2735,9 +2730,9 @@ ASTSerializer::rightAssociate(ParseNode* pn, MutableHandleValue dst)
|
|||
if (!expression(next, &left))
|
||||
return false;
|
||||
|
||||
TokenPos subpos(pn->pn_pos.begin, next->pn_pos.end);
|
||||
TokenPos subpos(node->pn_pos.begin, next->pn_pos.end);
|
||||
|
||||
BinaryOperator op = binop(pn->getKind(), pn->getOp());
|
||||
BinaryOperator op = binop(node->getKind(), node->getOp());
|
||||
LOCAL_ASSERT(op > BINOP_ERR && op < BINOP_LIMIT);
|
||||
|
||||
if (!builder.binaryExpression(op, left, right, &subpos, &right))
|
||||
|
|
@ -2760,13 +2755,15 @@ ASTSerializer::comprehensionBlock(ParseNode* pn, MutableHandleValue dst)
|
|||
bool isForEach = in->isKind(PNK_FORIN) && (pn->pn_iflags & JSITER_FOREACH);
|
||||
bool isForOf = in->isKind(PNK_FOROF);
|
||||
|
||||
ParseNode* decl = in->pn_kid1;
|
||||
if (decl->isKind(PNK_LEXICALSCOPE))
|
||||
decl = decl->pn_expr;
|
||||
MOZ_ASSERT(decl->pn_count == 1);
|
||||
ListNode* decl;
|
||||
if (in->pn_kid1->isKind(PNK_LEXICALSCOPE))
|
||||
decl = &in->pn_kid1->pn_expr->as<ListNode>();
|
||||
else
|
||||
decl = &in->pn_kid1->as<ListNode>();
|
||||
MOZ_ASSERT(decl->count() == 1);
|
||||
|
||||
RootedValue patt(cx), src(cx);
|
||||
return pattern(decl->pn_head, &patt) &&
|
||||
return pattern(decl->head(), &patt) &&
|
||||
expression(in->pn_kid3, &src) &&
|
||||
builder.comprehensionBlock(patt, src, isForEach, isForOf, &in->pn_pos, dst);
|
||||
}
|
||||
|
|
@ -2885,7 +2882,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
case PNK_COMMA:
|
||||
{
|
||||
NodeVector exprs(cx);
|
||||
return expressions(pn, exprs) &&
|
||||
return expressions(&pn->as<ListNode>(), exprs) &&
|
||||
builder.sequenceExpression(exprs, &pn->pn_pos, dst);
|
||||
}
|
||||
|
||||
|
|
@ -2906,7 +2903,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
case PNK_COALESCE:
|
||||
case PNK_OR:
|
||||
case PNK_AND:
|
||||
return leftAssociate(pn, dst);
|
||||
return leftAssociate(&pn->as<ListNode>(), dst);
|
||||
|
||||
case PNK_PREINCREMENT:
|
||||
case PNK_PREDECREMENT:
|
||||
|
|
@ -2977,10 +2974,10 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
case PNK_BITAND:
|
||||
case PNK_IN:
|
||||
case PNK_INSTANCEOF:
|
||||
return leftAssociate(pn, dst);
|
||||
return leftAssociate(&pn->as<ListNode>(), dst);
|
||||
|
||||
case PNK_POW:
|
||||
return rightAssociate(pn, dst);
|
||||
return rightAssociate(&pn->as<ListNode>(), dst);
|
||||
|
||||
case PNK_DELETENAME:
|
||||
case PNK_DELETEPROP:
|
||||
|
|
@ -3004,8 +3001,19 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
builder.unaryExpression(op, expr, &pn->pn_pos, dst);
|
||||
}
|
||||
|
||||
case PNK_GENEXP:
|
||||
return generatorExpression(pn->generatorExpr(), dst);
|
||||
case PNK_GENEXP: {
|
||||
ParseNode* callee = pn->pn_left;
|
||||
MOZ_ASSERT(callee->isKind(PNK_FUNCTION));
|
||||
|
||||
ListNode* paramsBody = &callee->pn_body->as<ListNode>();
|
||||
MOZ_ASSERT(paramsBody->isKind(PNK_PARAMSBODY));
|
||||
|
||||
ListNode* body = ¶msBody->last()->as<ListNode>();
|
||||
MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST));
|
||||
MOZ_ASSERT(body->last()->isKind(PNK_LEXICALSCOPE) ||
|
||||
body->last()->isKind(PNK_COMPREHENSIONFOR));
|
||||
return generatorExpression(body->last(), dst);
|
||||
}
|
||||
|
||||
case PNK_DELETEOPTCHAIN: {
|
||||
RootedValue expr(cx);
|
||||
|
|
@ -3026,7 +3034,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
case PNK_SUPERCALL:
|
||||
{
|
||||
ParseNode* pn_callee = pn->pn_left;
|
||||
ParseNode* pn_args = pn->pn_right;
|
||||
ListNode* argsList = &pn->pn_right->as<ListNode>();
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn_callee->pn_pos));
|
||||
|
||||
RootedValue callee(cx);
|
||||
|
|
@ -3040,14 +3048,14 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
}
|
||||
|
||||
NodeVector args(cx);
|
||||
if (!args.reserve(pn_args->pn_count))
|
||||
if (!args.reserve(argsList->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* next = pn_args->pn_head; next; next = next->pn_next) {
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
|
||||
for (ParseNode* argNode : argsList->contents()) {
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(argNode->pn_pos));
|
||||
|
||||
RootedValue arg(cx);
|
||||
if (!expression(next, &arg))
|
||||
if (!expression(argNode, &arg))
|
||||
return false;
|
||||
args.infallibleAppend(arg);
|
||||
}
|
||||
|
|
@ -3118,57 +3126,62 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
|
||||
case PNK_CALLSITEOBJ:
|
||||
{
|
||||
CallSiteNode* callSiteObj = &pn->as<CallSiteNode>();
|
||||
ListNode* rawNodes = callSiteObj->rawNodes();
|
||||
NodeVector raw(cx);
|
||||
if (!raw.reserve(pn->pn_head->pn_count))
|
||||
if (!raw.reserve(rawNodes->count()))
|
||||
return false;
|
||||
for (ParseNode* next = pn->pn_head->pn_head; next; next = next->pn_next) {
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
|
||||
for (ParseNode* rawItem : rawNodes->contents()) {
|
||||
MOZ_ASSERT(callSiteObj->pn_pos.encloses(rawItem->pn_pos));
|
||||
|
||||
RootedValue expr(cx);
|
||||
expr.setString(next->pn_atom);
|
||||
expr.setString(rawItem->pn_atom);
|
||||
raw.infallibleAppend(expr);
|
||||
}
|
||||
|
||||
NodeVector cooked(cx);
|
||||
if (!cooked.reserve(pn->pn_count - 1))
|
||||
if (!cooked.reserve(callSiteObj->count() - 1))
|
||||
return false;
|
||||
|
||||
for (ParseNode* next = pn->pn_head->pn_next; next; next = next->pn_next) {
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
|
||||
for (ParseNode* cookedItem = callSiteObj->head()->pn_next;
|
||||
cookedItem;
|
||||
cookedItem = cookedItem->pn_next) {
|
||||
MOZ_ASSERT(callSiteObj->pn_pos.encloses(cookedItem->pn_pos));
|
||||
|
||||
RootedValue expr(cx);
|
||||
if (next->isKind(PNK_RAW_UNDEFINED)) {
|
||||
if (cookedItem->isKind(PNK_RAW_UNDEFINED)) {
|
||||
expr.setUndefined();
|
||||
} else {
|
||||
MOZ_ASSERT(next->isKind(PNK_TEMPLATE_STRING));
|
||||
expr.setString(next->pn_atom);
|
||||
MOZ_ASSERT(cookedItem->isKind(PNK_TEMPLATE_STRING));
|
||||
expr.setString(cookedItem->pn_atom);
|
||||
}
|
||||
cooked.infallibleAppend(expr);
|
||||
}
|
||||
|
||||
return builder.callSiteObj(raw, cooked, &pn->pn_pos, dst);
|
||||
return builder.callSiteObj(raw, cooked, &callSiteObj->pn_pos, dst);
|
||||
}
|
||||
|
||||
case PNK_ARRAY:
|
||||
{
|
||||
ListNode* array = &pn->as<ListNode>();
|
||||
NodeVector elts(cx);
|
||||
if (!elts.reserve(pn->pn_count))
|
||||
if (!elts.reserve(array->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
|
||||
for (ParseNode* item : array->contents()) {
|
||||
MOZ_ASSERT(array->pn_pos.encloses(item->pn_pos));
|
||||
|
||||
if (next->isKind(PNK_ELISION)) {
|
||||
if (item->isKind(PNK_ELISION)) {
|
||||
elts.infallibleAppend(NullValue());
|
||||
} else {
|
||||
RootedValue expr(cx);
|
||||
if (!expression(next, &expr))
|
||||
if (!expression(item, &expr))
|
||||
return false;
|
||||
elts.infallibleAppend(expr);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.arrayExpression(elts, &pn->pn_pos, dst);
|
||||
return builder.arrayExpression(elts, &array->pn_pos, dst);
|
||||
}
|
||||
|
||||
case PNK_SPREAD:
|
||||
|
|
@ -3187,20 +3200,21 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
|
||||
case PNK_OBJECT:
|
||||
{
|
||||
ListNode* obj = &pn->as<ListNode>();
|
||||
NodeVector elts(cx);
|
||||
if (!elts.reserve(pn->pn_count))
|
||||
if (!elts.reserve(obj->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
|
||||
for (ParseNode* item : obj->contents()) {
|
||||
MOZ_ASSERT(obj->pn_pos.encloses(item->pn_pos));
|
||||
|
||||
RootedValue prop(cx);
|
||||
if (!property(next, &prop))
|
||||
if (!property(item, &prop))
|
||||
return false;
|
||||
elts.infallibleAppend(prop);
|
||||
}
|
||||
|
||||
return builder.objectExpression(elts, &pn->pn_pos, dst);
|
||||
return builder.objectExpression(elts, &obj->pn_pos, dst);
|
||||
}
|
||||
|
||||
case PNK_NAME:
|
||||
|
|
@ -3211,20 +3225,21 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
|
||||
case PNK_TEMPLATE_STRING_LIST:
|
||||
{
|
||||
ListNode* list = &pn->as<ListNode>();
|
||||
NodeVector elts(cx);
|
||||
if (!elts.reserve(pn->pn_count))
|
||||
if (!elts.reserve(list->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
|
||||
for (ParseNode* item : list->contents()) {
|
||||
MOZ_ASSERT(list->pn_pos.encloses(item->pn_pos));
|
||||
|
||||
RootedValue expr(cx);
|
||||
if (!expression(next, &expr))
|
||||
if (!expression(item, &expr))
|
||||
return false;
|
||||
elts.infallibleAppend(expr);
|
||||
}
|
||||
|
||||
return builder.templateLiteral(elts, &pn->pn_pos, dst);
|
||||
return builder.templateLiteral(elts, &list->pn_pos, dst);
|
||||
}
|
||||
|
||||
case PNK_TEMPLATE_STRING:
|
||||
|
|
@ -3256,11 +3271,14 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
}
|
||||
|
||||
case PNK_ARRAYCOMP:
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_head->pn_pos));
|
||||
{
|
||||
ListNode* literal = &pn->as<ListNode>();
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(literal->head()->pn_pos));
|
||||
|
||||
/* NB: it's no longer the case that pn_count could be 2. */
|
||||
LOCAL_ASSERT(pn->pn_count == 1);
|
||||
return comprehension(pn->pn_head, dst);
|
||||
LOCAL_ASSERT(literal->count() == 1);
|
||||
return comprehension(literal->head(), dst);
|
||||
}
|
||||
|
||||
case PNK_CLASS:
|
||||
return classDefinition(pn, true, dst);
|
||||
|
|
@ -3397,46 +3415,46 @@ ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst)
|
|||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::arrayPattern(ParseNode* pn, MutableHandleValue dst)
|
||||
ASTSerializer::arrayPattern(ListNode* array, MutableHandleValue dst)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_ARRAY));
|
||||
MOZ_ASSERT(array->isKind(PNK_ARRAY));
|
||||
|
||||
NodeVector elts(cx);
|
||||
if (!elts.reserve(pn->pn_count))
|
||||
if (!elts.reserve(array->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* next = pn->pn_head; next; next = next->pn_next) {
|
||||
if (next->isKind(PNK_ELISION)) {
|
||||
for (ParseNode* item : array->contents()) {
|
||||
if (item->isKind(PNK_ELISION)) {
|
||||
elts.infallibleAppend(NullValue());
|
||||
} else if (next->isKind(PNK_SPREAD)) {
|
||||
} else if (item->isKind(PNK_SPREAD)) {
|
||||
RootedValue target(cx);
|
||||
RootedValue spread(cx);
|
||||
if (!pattern(next->pn_kid, &target))
|
||||
if (!pattern(item->pn_kid, &target))
|
||||
return false;
|
||||
if(!builder.spreadExpression(target, &next->pn_pos, &spread))
|
||||
if(!builder.spreadExpression(target, &item->pn_pos, &spread))
|
||||
return false;
|
||||
elts.infallibleAppend(spread);
|
||||
} else {
|
||||
RootedValue patt(cx);
|
||||
if (!pattern(next, &patt))
|
||||
if (!pattern(item, &patt))
|
||||
return false;
|
||||
elts.infallibleAppend(patt);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.arrayPattern(elts, &pn->pn_pos, dst);
|
||||
return builder.arrayPattern(elts, &array->pn_pos, dst);
|
||||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::objectPattern(ParseNode* pn, MutableHandleValue dst)
|
||||
ASTSerializer::objectPattern(ListNode* obj, MutableHandleValue dst)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(obj->isKind(PNK_OBJECT));
|
||||
|
||||
NodeVector elts(cx);
|
||||
if (!elts.reserve(pn->pn_count))
|
||||
if (!elts.reserve(obj->count()))
|
||||
return false;
|
||||
|
||||
for (ParseNode* propdef = pn->pn_head; propdef; propdef = propdef->pn_next) {
|
||||
for (ParseNode* propdef : obj->contents()) {
|
||||
if (propdef->isKind(PNK_SPREAD)) {
|
||||
RootedValue target(cx);
|
||||
RootedValue spread(cx);
|
||||
|
|
@ -3473,7 +3491,7 @@ ASTSerializer::objectPattern(ParseNode* pn, MutableHandleValue dst)
|
|||
elts.infallibleAppend(prop);
|
||||
}
|
||||
|
||||
return builder.objectPattern(elts, &pn->pn_pos, dst);
|
||||
return builder.objectPattern(elts, &obj->pn_pos, dst);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -3482,10 +3500,10 @@ ASTSerializer::pattern(ParseNode* pn, MutableHandleValue dst)
|
|||
JS_CHECK_RECURSION(cx, return false);
|
||||
switch (pn->getKind()) {
|
||||
case PNK_OBJECT:
|
||||
return objectPattern(pn, dst);
|
||||
return objectPattern(&pn->as<ListNode>(), dst);
|
||||
|
||||
case PNK_ARRAY:
|
||||
return arrayPattern(pn, dst);
|
||||
return arrayPattern(&pn->as<ListNode>(), dst);
|
||||
|
||||
default:
|
||||
return expression(pn, dst);
|
||||
|
|
@ -3547,15 +3565,15 @@ ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector&
|
|||
bool isAsync, bool isExpression,
|
||||
MutableHandleValue body, MutableHandleValue rest)
|
||||
{
|
||||
ParseNode* pnargs;
|
||||
ListNode* argsList;
|
||||
ParseNode* pnbody;
|
||||
|
||||
/* Extract the args and body separately. */
|
||||
if (pn->isKind(PNK_PARAMSBODY)) {
|
||||
pnargs = pn;
|
||||
pnbody = pn->last();
|
||||
argsList = &pn->as<ListNode>();
|
||||
pnbody = argsList->last();
|
||||
} else {
|
||||
pnargs = nullptr;
|
||||
argsList = nullptr;
|
||||
pnbody = pn;
|
||||
}
|
||||
|
||||
|
|
@ -3565,29 +3583,29 @@ ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector&
|
|||
/* Serialize the arguments and body. */
|
||||
switch (pnbody->getKind()) {
|
||||
case PNK_RETURN: /* expression closure, no destructured args */
|
||||
return functionArgs(pn, pnargs, args, defaults, rest) &&
|
||||
return functionArgs(pn, argsList, args, defaults, rest) &&
|
||||
expression(pnbody->pn_kid, body);
|
||||
|
||||
case PNK_STATEMENTLIST: /* statement closure */
|
||||
{
|
||||
ParseNode* pnstart = pnbody->pn_head;
|
||||
ParseNode* firstNode = pnbody->as<ListNode>().head();
|
||||
|
||||
// Skip over initial yield in generator.
|
||||
if (pnstart && pnstart->isKind(PNK_INITIALYIELD)) {
|
||||
MOZ_ASSERT(pnstart->getOp() == JSOP_INITIALYIELD);
|
||||
pnstart = pnstart->pn_next;
|
||||
if (firstNode && firstNode->isKind(PNK_INITIALYIELD)) {
|
||||
MOZ_ASSERT(firstNode->getOp() == JSOP_INITIALYIELD);
|
||||
firstNode = firstNode->pn_next;
|
||||
}
|
||||
|
||||
// Async arrow with expression body is converted into STATEMENTLIST
|
||||
// to insert initial yield.
|
||||
if (isAsync && isExpression) {
|
||||
MOZ_ASSERT(pnstart->getKind() == PNK_RETURN);
|
||||
return functionArgs(pn, pnargs, args, defaults, rest) &&
|
||||
expression(pnstart->pn_kid, body);
|
||||
MOZ_ASSERT(firstNode->getKind() == PNK_RETURN);
|
||||
return functionArgs(pn, argsList, args, defaults, rest) &&
|
||||
expression(firstNode->pn_kid, body);
|
||||
}
|
||||
|
||||
return functionArgs(pn, pnargs, args, defaults, rest) &&
|
||||
functionBody(pnstart, &pnbody->pn_pos, body);
|
||||
return functionArgs(pn, argsList, args, defaults, rest) &&
|
||||
functionBody(firstNode, &pnbody->pn_pos, body);
|
||||
}
|
||||
|
||||
default:
|
||||
|
|
@ -3596,11 +3614,11 @@ ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector&
|
|||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::functionArgs(ParseNode* pn, ParseNode* pnargs,
|
||||
ASTSerializer::functionArgs(ParseNode* pn, ListNode* argsList,
|
||||
NodeVector& args, NodeVector& defaults,
|
||||
MutableHandleValue rest)
|
||||
{
|
||||
if (!pnargs)
|
||||
if (!argsList)
|
||||
return true;
|
||||
|
||||
RootedValue node(cx);
|
||||
|
|
@ -3609,7 +3627,7 @@ ASTSerializer::functionArgs(ParseNode* pn, ParseNode* pnargs,
|
|||
"must be initially empty for it to be proper to clear this "
|
||||
"when there are no defaults");
|
||||
|
||||
for (ParseNode* arg = pnargs->pn_head; arg && arg != pnargs->last(); arg = arg->pn_next) {
|
||||
for (ParseNode* arg : argsList->contentsTo(argsList->last())) {
|
||||
ParseNode* pat;
|
||||
ParseNode* defNode;
|
||||
if (arg->isKind(PNK_NAME) || arg->isKind(PNK_ARRAY) || arg->isKind(PNK_OBJECT)) {
|
||||
|
|
@ -3625,7 +3643,7 @@ ASTSerializer::functionArgs(ParseNode* pn, ParseNode* pnargs,
|
|||
MOZ_ASSERT(pat->isKind(PNK_NAME) || pat->isKind(PNK_ARRAY) || pat->isKind(PNK_OBJECT));
|
||||
if (!pattern(pat, &node))
|
||||
return false;
|
||||
if (rest.isUndefined() && arg->pn_next == pnargs->last()) {
|
||||
if (rest.isUndefined() && arg->pn_next == argsList->last()) {
|
||||
rest.setObject(node.toObject());
|
||||
} else {
|
||||
if (!args.append(node))
|
||||
|
|
@ -3837,7 +3855,7 @@ reflect_parse(JSContext* cx, uint32_t argc, Value* vp)
|
|||
}
|
||||
|
||||
RootedValue val(cx);
|
||||
if (!serialize.program(pn, &val)) {
|
||||
if (!serialize.program(&pn->as<ListNode>(), &val)) {
|
||||
args.rval().setNull();
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -498,9 +498,9 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitAtomOp(JSAtom* atom, JSOp op);
|
||||
MOZ_MUST_USE bool emitAtomOp(uint32_t atomIndex, JSOp op);
|
||||
|
||||
MOZ_MUST_USE bool emitArrayLiteral(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitArray(ParseNode* pn, uint32_t count, JSOp op);
|
||||
MOZ_MUST_USE bool emitArrayComp(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitArrayLiteral(ListNode* array);
|
||||
MOZ_MUST_USE bool emitArray(ParseNode* arrayHead, uint32_t count, JSOp op);
|
||||
MOZ_MUST_USE bool emitArrayComp(ListNode* pn);
|
||||
|
||||
MOZ_MUST_USE bool emitInternedScopeOp(uint32_t index, JSOp op);
|
||||
MOZ_MUST_USE bool emitInternedObjectOp(uint32_t index, JSOp op);
|
||||
|
|
@ -509,13 +509,13 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitRegExp(uint32_t index);
|
||||
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitFunction(ParseNode* pn, bool needsProto = false);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitObject(ParseNode* pn);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitObject(ListNode* objNode);
|
||||
|
||||
MOZ_MUST_USE bool replaceNewInitWithNewObject(JSObject* obj, ptrdiff_t offset);
|
||||
|
||||
MOZ_MUST_USE bool emitHoistedFunctionsInList(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitHoistedFunctionsInList(ListNode* stmtList);
|
||||
|
||||
MOZ_MUST_USE bool emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
|
||||
MOZ_MUST_USE bool emitPropertyList(ListNode* obj, MutableHandlePlainObject objp,
|
||||
PropListType type);
|
||||
|
||||
// To catch accidental misuse, emitUint16Operand/emit3 assert that they are
|
||||
|
|
@ -538,8 +538,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
|
||||
MOZ_MUST_USE bool emitNameIncDec(ParseNode* incDec);
|
||||
|
||||
MOZ_MUST_USE bool emitDeclarationList(ParseNode* decls);
|
||||
MOZ_MUST_USE bool emitSingleDeclaration(ParseNode* decls, ParseNode* decl,
|
||||
MOZ_MUST_USE bool emitDeclarationList(ListNode* declList);
|
||||
MOZ_MUST_USE bool emitSingleDeclaration(ParseNode* declList, ParseNode* decl,
|
||||
ParseNode* initializer);
|
||||
|
||||
MOZ_MUST_USE bool emitNewInit(JSProtoKey key);
|
||||
|
|
@ -624,21 +624,18 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
|
||||
// emitDestructuringObjRestExclusionSet emits the property exclusion set
|
||||
// for the rest-property in an object pattern.
|
||||
MOZ_MUST_USE bool emitDestructuringObjRestExclusionSet(ParseNode* pattern);
|
||||
MOZ_MUST_USE bool emitDestructuringObjRestExclusionSet(ListNode* pattern);
|
||||
|
||||
// emitDestructuringOps assumes the to-be-destructured value has been
|
||||
// pushed on the stack and emits code to destructure each part of a [] or
|
||||
// {} lhs expression.
|
||||
MOZ_MUST_USE bool emitDestructuringOps(ParseNode* pattern, DestructuringFlavor flav);
|
||||
MOZ_MUST_USE bool emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlavor flav);
|
||||
MOZ_MUST_USE bool emitDestructuringOpsObject(ParseNode* pattern, DestructuringFlavor flav);
|
||||
MOZ_MUST_USE bool emitDestructuringOps(ListNode* pattern, DestructuringFlavor flav);
|
||||
MOZ_MUST_USE bool emitDestructuringOpsArray(ListNode* pattern, DestructuringFlavor flav);
|
||||
MOZ_MUST_USE bool emitDestructuringOpsObject(ListNode* pattern, DestructuringFlavor flav);
|
||||
|
||||
typedef bool
|
||||
(*DestructuringDeclEmitter)(BytecodeEmitter* bce, ParseNode* pn);
|
||||
|
||||
template <typename NameEmitter>
|
||||
MOZ_MUST_USE bool emitDestructuringDeclsWithEmitter(ParseNode* pattern, NameEmitter emitName);
|
||||
|
||||
// Throw a TypeError if the value atop the stack isn't convertible to an
|
||||
// object, with no overall effect on the stack.
|
||||
MOZ_MUST_USE bool emitRequireObjectCoercible();
|
||||
|
|
@ -694,13 +691,13 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitInitializer(ParseNode* initializer, ParseNode* pattern);
|
||||
MOZ_MUST_USE bool emitInitializerInBranch(ParseNode* initializer, ParseNode* pattern);
|
||||
|
||||
MOZ_MUST_USE bool emitCallSiteObject(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitTemplateString(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitCallSiteObject(CallSiteNode* callSiteObj);
|
||||
MOZ_MUST_USE bool emitTemplateString(ListNode* templateString);
|
||||
MOZ_MUST_USE bool emitAssignment(ParseNode* lhs, JSOp compoundOp, ParseNode* rhs);
|
||||
|
||||
MOZ_MUST_USE bool emitReturn(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitStatement(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitStatementList(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitStatementList(ListNode* stmtList);
|
||||
|
||||
MOZ_MUST_USE bool emitDeleteName(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitDeleteProperty(ParseNode* pn);
|
||||
|
|
@ -735,10 +732,10 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitTypeof(ParseNode* node, JSOp op);
|
||||
|
||||
MOZ_MUST_USE bool emitUnary(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitRightAssociative(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitLeftAssociative(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitLogical(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSequenceExpr(ParseNode* pn,
|
||||
MOZ_MUST_USE bool emitRightAssociative(ListNode* node);
|
||||
MOZ_MUST_USE bool emitLeftAssociative(ListNode* node);
|
||||
MOZ_MUST_USE bool emitLogical(ListNode* node);
|
||||
MOZ_MUST_USE bool emitSequenceExpr(ListNode* node,
|
||||
ValueUsage valueUsage = ValueUsage::WantValue);
|
||||
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitIncOrDec(ParseNode* pn);
|
||||
|
|
@ -750,8 +747,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitOptimizeSpread(ParseNode* arg0, JumpList* jmp, bool* emitted);
|
||||
|
||||
MOZ_MUST_USE ParseNode* getCoordNode(ParseNode* callNode, ParseNode* calleeNode,
|
||||
ParseNode* firstArgNode);
|
||||
MOZ_MUST_USE bool emitArguments(ParseNode* argsList, bool isCall, bool isSpread,
|
||||
ListNode* argsList);
|
||||
MOZ_MUST_USE bool emitArguments(ListNode* argsList, bool isCall, bool isSpread,
|
||||
CallOrNewEmitter& cone);
|
||||
MOZ_MUST_USE bool emitCallOrNew(ParseNode* pn,
|
||||
ValueUsage valueUsage = ValueUsage::WantValue);
|
||||
|
|
@ -786,8 +783,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitBreak(PropertyName* label);
|
||||
MOZ_MUST_USE bool emitContinue(PropertyName* label);
|
||||
|
||||
MOZ_MUST_USE bool emitFunctionFormalParametersAndBody(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitFunctionFormalParameters(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitFunctionFormalParametersAndBody(ListNode* paramsBody);
|
||||
MOZ_MUST_USE bool emitFunctionFormalParameters(ListNode* paramsBody);
|
||||
MOZ_MUST_USE bool emitInitializeFunctionSpecialNames();
|
||||
MOZ_MUST_USE bool emitFunctionBody(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitLexicalInitialization(ParseNode* pn);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result);
|
|||
static bool
|
||||
ListContainsHoistedDeclaration(ExclusiveContext* cx, ListNode* list, bool* result)
|
||||
{
|
||||
for (ParseNode* node = list->pn_head; node; node = node->pn_next) {
|
||||
for (ParseNode* node : list->contents()) {
|
||||
if (!ContainsHoistedDeclaration(cx, node, result))
|
||||
return false;
|
||||
if (*result)
|
||||
|
|
@ -74,7 +74,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
// Non-global lexical declarations are block-scoped (ergo not hoistable).
|
||||
case PNK_LET:
|
||||
case PNK_CONST:
|
||||
MOZ_ASSERT(node->isArity(PN_LIST));
|
||||
MOZ_ASSERT(node->is<ListNode>());
|
||||
*result = false;
|
||||
return true;
|
||||
|
||||
|
|
@ -202,21 +202,20 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
if (*result)
|
||||
return true;
|
||||
|
||||
if (ParseNode* catchList = node->pn_kid2) {
|
||||
for (ParseNode* lexicalScope = catchList->pn_head;
|
||||
lexicalScope;
|
||||
lexicalScope = lexicalScope->pn_next)
|
||||
{
|
||||
MOZ_ASSERT(lexicalScope->isKind(PNK_LEXICALSCOPE));
|
||||
if (node->pn_kid2) {
|
||||
if (ListNode* catchList = &node->pn_kid2->as<ListNode>()) {
|
||||
for (ParseNode* lexicalScope : catchList->contents()) {
|
||||
MOZ_ASSERT(lexicalScope->isKind(PNK_LEXICALSCOPE));
|
||||
|
||||
ParseNode* catchNode = lexicalScope->pn_expr;
|
||||
MOZ_ASSERT(catchNode->isKind(PNK_CATCH));
|
||||
ParseNode* catchNode = lexicalScope->scopeBody();
|
||||
MOZ_ASSERT(catchNode->isKind(PNK_CATCH));
|
||||
|
||||
ParseNode* catchStatements = catchNode->pn_kid3;
|
||||
if (!ContainsHoistedDeclaration(cx, catchStatements, result))
|
||||
return false;
|
||||
if (*result)
|
||||
return true;
|
||||
ParseNode* catchStatements = catchNode->pn_kid3;
|
||||
if (!ContainsHoistedDeclaration(cx, catchStatements, result))
|
||||
return false;
|
||||
if (*result)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -764,16 +763,15 @@ static bool
|
|||
FoldLogical(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& parser,
|
||||
bool inGenexpLambda)
|
||||
{
|
||||
ParseNode* node = *nodePtr;
|
||||
ListNode* node = &(*nodePtr)->as<ListNode>();
|
||||
|
||||
bool isCoalesceNode = node->isKind(PNK_COALESCE);
|
||||
bool isOrNode = node->isKind(PNK_OR);
|
||||
bool isAndNode = node->isKind(PNK_AND);
|
||||
|
||||
MOZ_ASSERT(isCoalesceNode || isOrNode || isAndNode);
|
||||
MOZ_ASSERT(node->isArity(PN_LIST));
|
||||
|
||||
ParseNode** elem = &node->pn_head;
|
||||
ParseNode** elem = node->unsafeHeadReference();
|
||||
do {
|
||||
if (!Fold(cx, elem, parser, inGenexpLambda))
|
||||
return false;
|
||||
|
|
@ -802,7 +800,7 @@ FoldLogical(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>&
|
|||
for (ParseNode* next = (*elem)->pn_next; next; next = afterNext) {
|
||||
afterNext = next->pn_next;
|
||||
parser.handler.freeTree(next);
|
||||
--node->pn_count;
|
||||
node->unsafeDecrementCount();
|
||||
}
|
||||
|
||||
// Terminate the original and/or list at the known-truthiness
|
||||
|
|
@ -820,7 +818,7 @@ FoldLogical(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>&
|
|||
ParseNode* elt = *elem;
|
||||
*elem = elt->pn_next;
|
||||
parser.handler.freeTree(elt);
|
||||
--node->pn_count;
|
||||
node->unsafeDecrementCount();
|
||||
} else {
|
||||
// Otherwise this node is the result of the overall expression,
|
||||
// so leave it alone. And we're done.
|
||||
|
|
@ -829,16 +827,12 @@ FoldLogical(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>&
|
|||
}
|
||||
} while (*elem);
|
||||
|
||||
// If the last node in the list was replaced, we need to update the
|
||||
// tail pointer in the original and/or node.
|
||||
node->pn_tail = elem;
|
||||
|
||||
node->checkListConsistency();
|
||||
node->unsafeReplaceTail(elem);
|
||||
|
||||
// If we removed nodes, we may have to replace a one-element list with
|
||||
// its element.
|
||||
if (node->pn_count == 1) {
|
||||
ParseNode* first = node->pn_head;
|
||||
if (node->count() == 1) {
|
||||
ParseNode* first = node->head();
|
||||
ReplaceNode(nodePtr, first);
|
||||
|
||||
node->setKind(PNK_NULL);
|
||||
|
|
@ -999,7 +993,7 @@ FoldIf(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& pars
|
|||
parser.prepareNodeForMutation(node);
|
||||
node->setKind(PNK_STATEMENTLIST);
|
||||
node->setArity(PN_LIST);
|
||||
node->makeEmpty();
|
||||
node->as<ListNode>().makeEmpty();
|
||||
} else {
|
||||
// Replacement invalidates |nextNode|, so reset it (if the
|
||||
// replacement requires folding) or clear it (if |alternative|
|
||||
|
|
@ -1013,9 +1007,9 @@ FoldIf(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& pars
|
|||
// any bugs in the preceding logic.
|
||||
node->setKind(PNK_STATEMENTLIST);
|
||||
node->setArity(PN_LIST);
|
||||
node->makeEmpty();
|
||||
node->as<ListNode>().makeEmpty();
|
||||
if (discarded)
|
||||
node->append(discarded);
|
||||
node->as<ListNode>().append(discarded);
|
||||
parser.freeTree(node);
|
||||
}
|
||||
} while (nextNode);
|
||||
|
|
@ -1098,7 +1092,7 @@ FoldModule(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& pars
|
|||
}
|
||||
|
||||
static bool
|
||||
FoldBinaryArithmetic(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
|
||||
FoldBinaryArithmetic(ExclusiveContext* cx, ListNode* node, Parser<FullParseHandler>& parser,
|
||||
bool inGenexpLambda)
|
||||
{
|
||||
MOZ_ASSERT(node->isKind(PNK_SUB) ||
|
||||
|
|
@ -1108,11 +1102,10 @@ FoldBinaryArithmetic(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHand
|
|||
node->isKind(PNK_URSH) ||
|
||||
node->isKind(PNK_DIV) ||
|
||||
node->isKind(PNK_MOD));
|
||||
MOZ_ASSERT(node->isArity(PN_LIST));
|
||||
MOZ_ASSERT(node->pn_count >= 2);
|
||||
MOZ_ASSERT(node->count() >= 2);
|
||||
|
||||
// Fold each operand, ideally into a number.
|
||||
ParseNode** listp = &node->pn_head;
|
||||
ParseNode** listp = node->unsafeHeadReference();
|
||||
for (; *listp; listp = &(*listp)->pn_next) {
|
||||
if (!Fold(cx, listp, parser, inGenexpLambda))
|
||||
return false;
|
||||
|
|
@ -1121,15 +1114,14 @@ FoldBinaryArithmetic(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHand
|
|||
return false;
|
||||
}
|
||||
|
||||
// Repoint the list's tail pointer.
|
||||
node->pn_tail = listp;
|
||||
node->unsafeReplaceTail(listp);
|
||||
|
||||
// Now fold all leading numeric terms together into a single number.
|
||||
// (Trailing terms for the non-shift operations can't be folded together
|
||||
// due to floating point imprecision. For example, if |x === -2**53|,
|
||||
// |x - 1 - 1 === -2**53| but |x - 2 === -2**53 - 2|. Shifts could be
|
||||
// folded, but it doesn't seem worth the effort.)
|
||||
ParseNode* elem = node->pn_head;
|
||||
ParseNode* elem = node->head();
|
||||
ParseNode* next = elem->pn_next;
|
||||
if (elem->isKind(PNK_NUMBER)) {
|
||||
ParseNodeKind kind = node->getKind();
|
||||
|
|
@ -1149,11 +1141,11 @@ FoldBinaryArithmetic(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHand
|
|||
elem->setArity(PN_NULLARY);
|
||||
elem->pn_dval = d;
|
||||
|
||||
node->pn_count--;
|
||||
node->unsafeDecrementCount();
|
||||
}
|
||||
|
||||
if (node->pn_count == 1) {
|
||||
MOZ_ASSERT(node->pn_head == elem);
|
||||
if (node->count() == 1) {
|
||||
MOZ_ASSERT(node->head() == elem);
|
||||
MOZ_ASSERT(elem->isKind(PNK_NUMBER));
|
||||
|
||||
double d = elem->pn_dval;
|
||||
|
|
@ -1170,15 +1162,14 @@ FoldBinaryArithmetic(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHand
|
|||
}
|
||||
|
||||
static bool
|
||||
FoldExponentiation(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
|
||||
FoldExponentiation(ExclusiveContext* cx, ListNode* node, Parser<FullParseHandler>& parser,
|
||||
bool inGenexpLambda)
|
||||
{
|
||||
MOZ_ASSERT(node->isKind(PNK_POW));
|
||||
MOZ_ASSERT(node->isArity(PN_LIST));
|
||||
MOZ_ASSERT(node->pn_count >= 2);
|
||||
MOZ_ASSERT(node->count() >= 2);
|
||||
|
||||
// Fold each operand, ideally into a number.
|
||||
ParseNode** listp = &node->pn_head;
|
||||
ParseNode** listp = node->unsafeHeadReference();
|
||||
for (; *listp; listp = &(*listp)->pn_next) {
|
||||
if (!Fold(cx, listp, parser, inGenexpLambda))
|
||||
return false;
|
||||
|
|
@ -1187,18 +1178,17 @@ FoldExponentiation(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandle
|
|||
return false;
|
||||
}
|
||||
|
||||
// Repoint the list's tail pointer.
|
||||
node->pn_tail = listp;
|
||||
node->unsafeReplaceTail(listp);
|
||||
|
||||
// Unlike all other binary arithmetic operators, ** is right-associative:
|
||||
// 2**3**5 is 2**(3**5), not (2**3)**5. As list nodes singly-link their
|
||||
// children, full constant-folding requires either linear space or dodgy
|
||||
// in-place linked list reversal. So we only fold one exponentiation: it's
|
||||
// easy and addresses common cases like |2**32|.
|
||||
if (node->pn_count > 2)
|
||||
if (node->count() > 2)
|
||||
return true;
|
||||
|
||||
ParseNode* base = node->pn_head;
|
||||
ParseNode* base = node->head();
|
||||
ParseNode* exponent = base->pn_next;
|
||||
if (!base->isKind(PNK_NUMBER) || !exponent->isKind(PNK_NUMBER))
|
||||
return true;
|
||||
|
|
@ -1214,21 +1204,16 @@ FoldExponentiation(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandle
|
|||
}
|
||||
|
||||
static bool
|
||||
FoldList(ExclusiveContext* cx, ParseNode* list, Parser<FullParseHandler>& parser,
|
||||
FoldList(ExclusiveContext* cx, ListNode* list, Parser<FullParseHandler>& parser,
|
||||
bool inGenexpLambda)
|
||||
{
|
||||
MOZ_ASSERT(list->isArity(PN_LIST));
|
||||
|
||||
ParseNode** elem = &list->pn_head;
|
||||
ParseNode** elem = list->unsafeHeadReference();
|
||||
for (; *elem; elem = &(*elem)->pn_next) {
|
||||
if (!Fold(cx, elem, parser, inGenexpLambda))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Repoint the list's tail pointer if the final element was replaced.
|
||||
list->pn_tail = elem;
|
||||
|
||||
list->checkListConsistency();
|
||||
list->unsafeReplaceTail(elem);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1400,11 +1385,10 @@ static bool
|
|||
FoldAdd(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& parser,
|
||||
bool inGenexpLambda)
|
||||
{
|
||||
ParseNode* node = *nodePtr;
|
||||
ListNode* node = &(*nodePtr)->as<ListNode>();
|
||||
|
||||
MOZ_ASSERT(node->isKind(PNK_ADD));
|
||||
MOZ_ASSERT(node->isArity(PN_LIST));
|
||||
MOZ_ASSERT(node->pn_count >= 2);
|
||||
MOZ_ASSERT(node->count() >= 2);
|
||||
|
||||
// Generically fold all operands first.
|
||||
if (!FoldList(cx, node, parser, inGenexpLambda))
|
||||
|
|
@ -1416,7 +1400,7 @@ FoldAdd(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& par
|
|||
//
|
||||
// Don't go past the leading operands: additions after a string are
|
||||
// string concatenations, not additions: ("1" + 2 + 3 === "123").
|
||||
ParseNode* current = node->pn_head;
|
||||
ParseNode* current = node->head();
|
||||
ParseNode* next = current->pn_next;
|
||||
if (current->isKind(PNK_NUMBER)) {
|
||||
do {
|
||||
|
|
@ -1428,8 +1412,7 @@ FoldAdd(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& par
|
|||
parser.freeTree(next);
|
||||
next = current->pn_next;
|
||||
|
||||
MOZ_ASSERT(node->pn_count > 1);
|
||||
node->pn_count--;
|
||||
node->unsafeDecrementCount();
|
||||
} while (next);
|
||||
}
|
||||
|
||||
|
|
@ -1490,8 +1473,7 @@ FoldAdd(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& par
|
|||
parser.freeTree(next);
|
||||
next = current->pn_next;
|
||||
|
||||
MOZ_ASSERT(node->pn_count > 1);
|
||||
node->pn_count--;
|
||||
node->unsafeDecrementCount();
|
||||
} while (next);
|
||||
|
||||
// Replace |current|'s string with the entire combination.
|
||||
|
|
@ -1529,10 +1511,9 @@ FoldAdd(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& par
|
|||
MOZ_ASSERT(!next, "must have considered all nodes here");
|
||||
MOZ_ASSERT(!current->pn_next, "current node must be the last node");
|
||||
|
||||
node->pn_tail = ¤t->pn_next;
|
||||
node->checkListConsistency();
|
||||
node->unsafeReplaceTail(¤t->pn_next);
|
||||
|
||||
if (node->pn_count == 1) {
|
||||
if (node->count() == 1) {
|
||||
// We reduced the list to a constant. Replace the PNK_ADD node
|
||||
// with that constant.
|
||||
ReplaceNode(nodePtr, current);
|
||||
|
|
@ -1583,23 +1564,18 @@ FoldCall(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser
|
|||
}
|
||||
|
||||
static bool
|
||||
FoldArguments(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser,
|
||||
FoldArguments(ExclusiveContext* cx, ListNode* node, Parser<FullParseHandler>& parser,
|
||||
bool inGenexpLambda)
|
||||
{
|
||||
MOZ_ASSERT(node->isKind(PNK_ARGUMENTS));
|
||||
MOZ_ASSERT(node->isArity(PN_LIST));
|
||||
|
||||
ParseNode** listp = &node->pn_head;
|
||||
ParseNode** listp = node->unsafeHeadReference();
|
||||
|
||||
for (; *listp; listp = &(*listp)->pn_next) {
|
||||
if (!Fold(cx, listp, parser, inGenexpLambda))
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the last node in the list was replaced, pn_tail points into the wrong node.
|
||||
node->pn_tail = listp;
|
||||
|
||||
node->checkListConsistency();
|
||||
node->unsafeReplaceTail(listp);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1779,6 +1755,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
case PNK_COALESCE:
|
||||
case PNK_AND:
|
||||
case PNK_OR:
|
||||
MOZ_ASSERT((*pnp)->is<ListNode>());
|
||||
return FoldLogical(cx, pnp, parser, inGenexpLambda);
|
||||
|
||||
case PNK_FUNCTION:
|
||||
|
|
@ -1794,10 +1771,10 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
case PNK_URSH:
|
||||
case PNK_DIV:
|
||||
case PNK_MOD:
|
||||
return FoldBinaryArithmetic(cx, pn, parser, inGenexpLambda);
|
||||
return FoldBinaryArithmetic(cx, &pn->as<ListNode>(), parser, inGenexpLambda);
|
||||
|
||||
case PNK_POW:
|
||||
return FoldExponentiation(cx, pn, parser, inGenexpLambda);
|
||||
return FoldExponentiation(cx, &pn->as<ListNode>(), parser, inGenexpLambda);
|
||||
|
||||
// Various list nodes not requiring care to minimally fold. Some of
|
||||
// these could be further folded/optimized, but we don't make the effort.
|
||||
|
|
@ -1829,7 +1806,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
case PNK_CALLSITEOBJ:
|
||||
case PNK_EXPORT_SPEC_LIST:
|
||||
case PNK_IMPORT_SPEC_LIST:
|
||||
return FoldList(cx, pn, parser, inGenexpLambda);
|
||||
return FoldList(cx, &pn->as<ListNode>(), parser, inGenexpLambda);
|
||||
|
||||
case PNK_INITIALYIELD:
|
||||
MOZ_ASSERT(pn->isArity(PN_UNARY));
|
||||
|
|
@ -1866,6 +1843,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
return FoldElement(cx, pnp, parser, inGenexpLambda);
|
||||
|
||||
case PNK_ADD:
|
||||
MOZ_ASSERT((*pnp)->is<ListNode>());
|
||||
return FoldAdd(cx, pnp, parser, inGenexpLambda);
|
||||
|
||||
case PNK_CALL:
|
||||
|
|
@ -1876,7 +1854,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
return FoldCall(cx, pn, parser, inGenexpLambda);
|
||||
|
||||
case PNK_ARGUMENTS:
|
||||
return FoldArguments(cx, pn, parser, inGenexpLambda);
|
||||
return FoldArguments(cx, &pn->as<ListNode>(), parser, inGenexpLambda);
|
||||
|
||||
case PNK_SWITCH:
|
||||
case PNK_COLON:
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
|
||||
#include <cstddef> // std::nullptr_t
|
||||
#include <string.h>
|
||||
|
||||
#include "frontend/ParseNode.h"
|
||||
|
|
@ -68,7 +69,15 @@ class FullParseHandler
|
|||
/* new_ methods for creating parse nodes. These report OOM on context. */
|
||||
JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline)
|
||||
|
||||
typedef ParseNode* Node;
|
||||
// FIXME: Use ListNode instead of ListNodeType as an alias (bug 1489008).
|
||||
using Node = ParseNode*;
|
||||
|
||||
#define DECLARE_TYPE(typeName, longTypeName, asMethodName) \
|
||||
using longTypeName = typeName*;
|
||||
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
||||
#undef DECLARE_TYPE
|
||||
|
||||
using NullNode = std::nullptr_t;
|
||||
|
||||
bool isPropertyAccess(ParseNode* node) {
|
||||
return node->isKind(PNK_DOT) || node->isKind(PNK_ELEM);
|
||||
|
|
@ -111,7 +120,14 @@ class FullParseHandler
|
|||
syntaxParser(syntaxParser)
|
||||
{}
|
||||
|
||||
static ParseNode* null() { return nullptr; }
|
||||
static NullNode null() { return NullNode(); }
|
||||
|
||||
#define DECLARE_AS(typeName, longTypeName, asMethodName) \
|
||||
static longTypeName asMethodName(Node node) { \
|
||||
return &node->as<typeName>(); \
|
||||
}
|
||||
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
||||
#undef DECLARE_AS
|
||||
|
||||
ParseNode* freeTree(ParseNode* pn) { return allocator.freeTree(pn); }
|
||||
void prepareNodeForMutation(ParseNode* pn) { return allocator.prepareNodeForMutation(pn); }
|
||||
|
|
@ -151,31 +167,32 @@ class FullParseHandler
|
|||
return new_<NullaryNode>(PNK_TEMPLATE_STRING, JSOP_NOP, pos, atom);
|
||||
}
|
||||
|
||||
ParseNode* newCallSiteObject(uint32_t begin) {
|
||||
ParseNode* callSite = new_<CallSiteNode>(begin);
|
||||
if (!callSite)
|
||||
CallSiteNodeType newCallSiteObject(uint32_t begin) {
|
||||
CallSiteNode* callSiteObj = new_<CallSiteNode>(begin);
|
||||
if (!callSiteObj)
|
||||
return null();
|
||||
|
||||
Node propExpr = newArrayLiteral(getPosition(callSite).begin);
|
||||
if (!propExpr)
|
||||
ListNode* rawNodes = newArrayLiteral(callSiteObj->pn_pos.begin);
|
||||
if (!rawNodes)
|
||||
return null();
|
||||
|
||||
addArrayElement(callSite, propExpr);
|
||||
addArrayElement(callSiteObj, rawNodes);
|
||||
|
||||
return callSite;
|
||||
return callSiteObj;
|
||||
}
|
||||
|
||||
void addToCallSiteObject(ParseNode* callSiteObj, ParseNode* rawNode, ParseNode* cookedNode) {
|
||||
void addToCallSiteObject(CallSiteNodeType callSiteObj, ParseNode* rawNode,
|
||||
ParseNode* cookedNode) {
|
||||
MOZ_ASSERT(callSiteObj->isKind(PNK_CALLSITEOBJ));
|
||||
|
||||
addArrayElement(callSiteObj, cookedNode);
|
||||
addArrayElement(callSiteObj->pn_head, rawNode);
|
||||
addArrayElement(callSiteObj->rawNodes(), rawNode);
|
||||
|
||||
/*
|
||||
* We don't know when the last noSubstTemplate will come in, and we
|
||||
* don't want to deal with this outside this method
|
||||
*/
|
||||
setEndPosition(callSiteObj, callSiteObj->pn_head);
|
||||
setEndPosition(callSiteObj, callSiteObj->rawNodes());
|
||||
}
|
||||
|
||||
ParseNode* newThisLiteral(const TokenPos& pos, ParseNode* thisName) {
|
||||
|
|
@ -289,45 +306,37 @@ class FullParseHandler
|
|||
|
||||
// Expressions
|
||||
|
||||
ParseNode* newArrayComprehension(ParseNode* body, const TokenPos& pos) {
|
||||
MOZ_ASSERT(pos.begin <= body->pn_pos.begin);
|
||||
MOZ_ASSERT(body->pn_pos.end <= pos.end);
|
||||
ParseNode* pn = new_<ListNode>(PNK_ARRAYCOMP, pos);
|
||||
if (!pn)
|
||||
return nullptr;
|
||||
pn->append(body);
|
||||
return pn;
|
||||
}
|
||||
|
||||
ParseNode* newArrayLiteral(uint32_t begin) {
|
||||
ParseNode* literal = new_<ListNode>(PNK_ARRAY, TokenPos(begin, begin + 1));
|
||||
ListNodeType newArrayLiteral(uint32_t begin) {
|
||||
ListNode* literal = new_<ListNode>(PNK_ARRAY, TokenPos(begin, begin + 1));
|
||||
// Later in this stack: remove dependency on this opcode.
|
||||
if (literal)
|
||||
literal->setOp(JSOP_NEWINIT);
|
||||
return literal;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool addElision(ParseNode* literal, const TokenPos& pos) {
|
||||
MOZ_MUST_USE bool addElision(ListNodeType literal, const TokenPos& pos) {
|
||||
ParseNode* elision = new_<NullaryNode>(PNK_ELISION, pos);
|
||||
if (!elision)
|
||||
return false;
|
||||
literal->append(elision);
|
||||
literal->pn_xflags |= PNX_ARRAYHOLESPREAD | PNX_NONCONST;
|
||||
literal->setHasArrayHoleOrSpread();
|
||||
literal->setHasNonConstInitializer();
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool addSpreadElement(ParseNode* literal, uint32_t begin, ParseNode* inner) {
|
||||
MOZ_MUST_USE bool addSpreadElement(ListNodeType literal, uint32_t begin, Node inner) {
|
||||
ParseNode* spread = newSpread(begin, inner);
|
||||
if (!spread)
|
||||
return false;
|
||||
literal->append(spread);
|
||||
literal->pn_xflags |= PNX_ARRAYHOLESPREAD | PNX_NONCONST;
|
||||
literal->setHasArrayHoleOrSpread();
|
||||
literal->setHasNonConstInitializer();
|
||||
return true;
|
||||
}
|
||||
|
||||
void addArrayElement(ParseNode* literal, ParseNode* element) {
|
||||
void addArrayElement(ListNodeType literal, Node element) {
|
||||
if (!element->isConstant())
|
||||
literal->pn_xflags |= PNX_NONCONST;
|
||||
literal->setHasNonConstInitializer();
|
||||
literal->append(element);
|
||||
}
|
||||
|
||||
|
|
@ -339,7 +348,7 @@ class FullParseHandler
|
|||
return new_<BinaryNode>(PNK_OPTCALL, JSOP_CALL, callee, args);
|
||||
}
|
||||
|
||||
ParseNode* newArguments(const TokenPos& pos) {
|
||||
ListNodeType newArguments(const TokenPos& pos) {
|
||||
return new_<ListNode>(PNK_ARGUMENTS, JSOP_NOP, pos);
|
||||
}
|
||||
|
||||
|
|
@ -355,8 +364,8 @@ class FullParseHandler
|
|||
return new_<BinaryNode>(PNK_GENEXP, JSOP_CALL, callee, args);
|
||||
}
|
||||
|
||||
ParseNode* newObjectLiteral(uint32_t begin) {
|
||||
ParseNode* literal = new_<ListNode>(PNK_OBJECT, TokenPos(begin, begin + 1));
|
||||
ListNodeType newObjectLiteral(uint32_t begin) {
|
||||
ListNode* literal = new_<ListNode>(PNK_OBJECT, TokenPos(begin, begin + 1));
|
||||
// Later in this stack: remove dependency on this opcode.
|
||||
if (literal)
|
||||
literal->setOp(JSOP_NEWINIT);
|
||||
|
|
@ -368,7 +377,7 @@ class FullParseHandler
|
|||
{
|
||||
return new_<ClassNode>(name, heritage, methodBlock, pos);
|
||||
}
|
||||
ParseNode* newClassMethodList(uint32_t begin) {
|
||||
ListNodeType newClassMethodList(uint32_t begin) {
|
||||
return new_<ListNode>(PNK_CLASSMETHODLIST, TokenPos(begin, begin + 1));
|
||||
}
|
||||
ParseNode* newClassNames(ParseNode* outer, ParseNode* inner, const TokenPos& pos) {
|
||||
|
|
@ -384,10 +393,10 @@ class FullParseHandler
|
|||
return new_<UnaryNode>(PNK_SUPERBASE, JSOP_NOP, pos, thisName);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool addPrototypeMutation(ParseNode* literal, uint32_t begin, ParseNode* expr) {
|
||||
MOZ_MUST_USE bool addPrototypeMutation(ListNodeType literal, uint32_t begin, ParseNode* expr) {
|
||||
// Object literals with mutated [[Prototype]] are non-constant so that
|
||||
// singleton objects will have Object.prototype as their [[Prototype]].
|
||||
setListFlag(literal, PNX_NONCONST);
|
||||
literal->setHasNonConstInitializer();
|
||||
|
||||
ParseNode* mutation = newUnary(PNK_MUTATEPROTO, JSOP_NOP, begin, expr);
|
||||
if (!mutation)
|
||||
|
|
@ -396,9 +405,8 @@ class FullParseHandler
|
|||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool addPropertyDefinition(ParseNode* literal, ParseNode* key, ParseNode* val) {
|
||||
MOZ_MUST_USE bool addPropertyDefinition(ListNodeType literal, ParseNode* key, ParseNode* val) {
|
||||
MOZ_ASSERT(literal->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(literal->isArity(PN_LIST));
|
||||
MOZ_ASSERT(key->isKind(PNK_NUMBER) ||
|
||||
key->isKind(PNK_OBJECT_PROPERTY_NAME) ||
|
||||
key->isKind(PNK_STRING) ||
|
||||
|
|
@ -407,18 +415,21 @@ class FullParseHandler
|
|||
ParseNode* propdef = newBinary(PNK_COLON, key, val, JSOP_INITPROP);
|
||||
if (!propdef)
|
||||
return false;
|
||||
|
||||
if (!val->isConstant()) {
|
||||
literal->setHasNonConstInitializer();
|
||||
}
|
||||
literal->append(propdef);
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool addShorthand(ParseNode* literal, ParseNode* name, ParseNode* expr) {
|
||||
MOZ_MUST_USE bool addShorthand(ListNodeType literal, ParseNode* name, ParseNode* expr) {
|
||||
MOZ_ASSERT(literal->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(literal->isArity(PN_LIST));
|
||||
MOZ_ASSERT(name->isKind(PNK_OBJECT_PROPERTY_NAME));
|
||||
MOZ_ASSERT(expr->isKind(PNK_NAME));
|
||||
MOZ_ASSERT(name->pn_atom == expr->pn_atom);
|
||||
|
||||
setListFlag(literal, PNX_NONCONST);
|
||||
literal->setHasNonConstInitializer();
|
||||
ParseNode* propdef = newBinary(PNK_SHORTHAND, name, expr, JSOP_INITPROP);
|
||||
if (!propdef)
|
||||
return false;
|
||||
|
|
@ -426,11 +437,10 @@ class FullParseHandler
|
|||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool addSpreadProperty(ParseNode* literal, uint32_t begin, ParseNode* inner) {
|
||||
MOZ_MUST_USE bool addSpreadProperty(ListNodeType literal, uint32_t begin, ParseNode* inner) {
|
||||
MOZ_ASSERT(literal->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(literal->isArity(PN_LIST));
|
||||
|
||||
setListFlag(literal, PNX_NONCONST);
|
||||
literal->setHasNonConstInitializer();
|
||||
ParseNode* spread = newSpread(begin, inner);
|
||||
if (!spread)
|
||||
return false;
|
||||
|
|
@ -438,15 +448,14 @@ class FullParseHandler
|
|||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool addObjectMethodDefinition(ParseNode* literal, ParseNode* key, ParseNode* fn,
|
||||
MOZ_MUST_USE bool addObjectMethodDefinition(ListNodeType literal, Node key, Node fn,
|
||||
JSOp op)
|
||||
{
|
||||
MOZ_ASSERT(literal->isArity(PN_LIST));
|
||||
MOZ_ASSERT(key->isKind(PNK_NUMBER) ||
|
||||
key->isKind(PNK_OBJECT_PROPERTY_NAME) ||
|
||||
key->isKind(PNK_STRING) ||
|
||||
key->isKind(PNK_COMPUTED_NAME));
|
||||
literal->pn_xflags |= PNX_NONCONST;
|
||||
literal->setHasNonConstInitializer();
|
||||
|
||||
ParseNode* propdef = newBinary(PNK_COLON, key, fn, op);
|
||||
if (!propdef)
|
||||
|
|
@ -455,7 +464,7 @@ class FullParseHandler
|
|||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool addClassMethodDefinition(ParseNode* methodList, ParseNode* key, ParseNode* fn,
|
||||
MOZ_MUST_USE bool addClassMethodDefinition(ListNodeType methodList, Node key, Node fn,
|
||||
JSOp op, bool isStatic)
|
||||
{
|
||||
MOZ_ASSERT(methodList->isKind(PNK_CLASSMETHODLIST));
|
||||
|
|
@ -498,7 +507,7 @@ class FullParseHandler
|
|||
|
||||
// Statements
|
||||
|
||||
ParseNode* newStatementList(const TokenPos& pos) {
|
||||
ListNodeType newStatementList(const TokenPos& pos) {
|
||||
return new_<ListNode>(PNK_STATEMENTLIST, pos);
|
||||
}
|
||||
|
||||
|
|
@ -508,31 +517,30 @@ class FullParseHandler
|
|||
return stmt->isKind(PNK_FUNCTION);
|
||||
}
|
||||
|
||||
void addStatementToList(ParseNode* list, ParseNode* stmt) {
|
||||
void addStatementToList(ListNodeType list, ParseNode* stmt) {
|
||||
MOZ_ASSERT(list->isKind(PNK_STATEMENTLIST));
|
||||
|
||||
list->append(stmt);
|
||||
|
||||
if (isFunctionStmt(stmt)) {
|
||||
// PNX_FUNCDEFS notifies the emitter that the block contains
|
||||
// body-level function definitions that should be processed
|
||||
// before the rest of nodes.
|
||||
list->pn_xflags |= PNX_FUNCDEFS;
|
||||
// Notify the emitter that the block contains body-level function
|
||||
// definitions that should be processed before the rest of nodes.
|
||||
list->setHasTopLevelFunctionDeclarations();
|
||||
}
|
||||
}
|
||||
|
||||
void addCaseStatementToList(ParseNode* list, ParseNode* casepn) {
|
||||
void addCaseStatementToList(ListNodeType list, ParseNode* caseClause) {
|
||||
MOZ_ASSERT(list->isKind(PNK_STATEMENTLIST));
|
||||
MOZ_ASSERT(casepn->isKind(PNK_CASE));
|
||||
MOZ_ASSERT(casepn->pn_right->isKind(PNK_STATEMENTLIST));
|
||||
MOZ_ASSERT(caseClause->isKind(PNK_CASE));
|
||||
MOZ_ASSERT(caseClause->pn_right->isKind(PNK_STATEMENTLIST));
|
||||
|
||||
list->append(casepn);
|
||||
list->append(caseClause);
|
||||
|
||||
if (casepn->pn_right->pn_xflags & PNX_FUNCDEFS)
|
||||
list->pn_xflags |= PNX_FUNCDEFS;
|
||||
if (caseClause->pn_right->as<ListNode>().hasTopLevelFunctionDeclarations())
|
||||
list->setHasTopLevelFunctionDeclarations();
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool prependInitialYield(ParseNode* stmtList, ParseNode* genName) {
|
||||
MOZ_MUST_USE bool prependInitialYield(ListNodeType stmtList, Node genName) {
|
||||
MOZ_ASSERT(stmtList->isKind(PNK_STATEMENTLIST));
|
||||
|
||||
TokenPos yieldPos(stmtList->pn_pos.begin, stmtList->pn_pos.begin + 1);
|
||||
|
|
@ -699,7 +707,7 @@ class FullParseHandler
|
|||
return new_<UnaryNode>(PNK_THROW, JSOP_THROW, pos, expr);
|
||||
}
|
||||
|
||||
ParseNode* newTryStatement(uint32_t begin, ParseNode* body, ParseNode* catchList,
|
||||
ParseNode* newTryStatement(uint32_t begin, ParseNode* body, ListNodeType catchList,
|
||||
ParseNode* finallyBlock) {
|
||||
TokenPos pos(begin, (finallyBlock ? finallyBlock : catchList)->pn_pos.end);
|
||||
return new_<TernaryNode>(PNK_TRY, JSOP_NOP, body, catchList, finallyBlock, pos);
|
||||
|
|
@ -729,7 +737,7 @@ class FullParseHandler
|
|||
return new_<OptionalPropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool addCatchBlock(ParseNode* catchList, ParseNode* lexicalScope,
|
||||
inline MOZ_MUST_USE bool addCatchBlock(ListNodeType catchList, ParseNode* lexicalScope,
|
||||
ParseNode* catchName, ParseNode* catchGuard,
|
||||
ParseNode* catchBody);
|
||||
|
||||
|
|
@ -772,11 +780,11 @@ class FullParseHandler
|
|||
funbox->functionNode = pn;
|
||||
}
|
||||
void addFunctionFormalParameter(ParseNode* pn, ParseNode* argpn) {
|
||||
pn->pn_body->append(argpn);
|
||||
addList(/* list = */ &pn->pn_body->as<ListNode>(), /* child = */ argpn);
|
||||
}
|
||||
void setFunctionBody(ParseNode* fn, ParseNode* body) {
|
||||
MOZ_ASSERT(fn->pn_body->isKind(PNK_PARAMSBODY));
|
||||
fn->pn_body->append(body);
|
||||
addList(/* list = */ &fn->pn_body->as<ListNode>(), /* child = */ body);
|
||||
}
|
||||
|
||||
ParseNode* newModule() {
|
||||
|
|
@ -869,27 +877,27 @@ class FullParseHandler
|
|||
return kind == PNK_VAR || kind == PNK_LET || kind == PNK_CONST;
|
||||
}
|
||||
|
||||
ParseNode* newList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
ListNodeType newList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(!isDeclarationKind(kind));
|
||||
return new_<ListNode>(kind, op, pos());
|
||||
}
|
||||
|
||||
ParseNode* newList(ParseNodeKind kind, uint32_t begin, JSOp op = JSOP_NOP) {
|
||||
ListNodeType newList(ParseNodeKind kind, uint32_t begin, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(!isDeclarationKind(kind));
|
||||
return new_<ListNode>(kind, op, TokenPos(begin, begin + 1));
|
||||
}
|
||||
|
||||
ParseNode* newList(ParseNodeKind kind, ParseNode* kid, JSOp op = JSOP_NOP) {
|
||||
ListNodeType newList(ParseNodeKind kind, ParseNode* kid, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(!isDeclarationKind(kind));
|
||||
return new_<ListNode>(kind, op, kid);
|
||||
}
|
||||
|
||||
ParseNode* newDeclarationList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
ListNodeType newDeclarationList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(isDeclarationKind(kind));
|
||||
return new_<ListNode>(kind, op, pos());
|
||||
}
|
||||
|
||||
ParseNode* newDeclarationList(ParseNodeKind kind, ParseNode* kid, JSOp op = JSOP_NOP) {
|
||||
ListNodeType newDeclarationList(ParseNodeKind kind, ParseNode* kid, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(isDeclarationKind(kind));
|
||||
return new_<ListNode>(kind, op, kid);
|
||||
}
|
||||
|
|
@ -898,30 +906,29 @@ class FullParseHandler
|
|||
return isDeclarationKind(node->getKind());
|
||||
}
|
||||
|
||||
ParseNode* singleBindingFromDeclaration(ParseNode* decl) {
|
||||
Node singleBindingFromDeclaration(ListNodeType decl) {
|
||||
MOZ_ASSERT(isDeclarationList(decl));
|
||||
MOZ_ASSERT(decl->pn_count == 1);
|
||||
return decl->pn_head;
|
||||
MOZ_ASSERT(decl->count() == 1);
|
||||
return decl->head();
|
||||
}
|
||||
|
||||
ParseNode* newCatchList() {
|
||||
ListNodeType newCatchList() {
|
||||
return new_<ListNode>(PNK_CATCHLIST, JSOP_NOP, pos());
|
||||
}
|
||||
|
||||
ParseNode* newCommaExpressionList(ParseNode* kid) {
|
||||
ListNodeType newCommaExpressionList(Node kid) {
|
||||
return newList(PNK_COMMA, kid, JSOP_NOP);
|
||||
}
|
||||
|
||||
void addList(ParseNode* list, ParseNode* kid) {
|
||||
void addList(ListNodeType list, Node kid) {
|
||||
list->append(kid);
|
||||
}
|
||||
|
||||
void setOp(ParseNode* pn, JSOp op) {
|
||||
pn->setOp(op);
|
||||
}
|
||||
void setListFlag(ParseNode* pn, unsigned flag) {
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
pn->pn_xflags |= flag;
|
||||
void setListHasNonConstInitializer(ListNodeType literal) {
|
||||
literal->setHasNonConstInitializer();
|
||||
}
|
||||
MOZ_MUST_USE ParseNode* parenthesize(ParseNode* pn) {
|
||||
pn->setInParens(true);
|
||||
|
|
@ -1015,7 +1022,7 @@ class FullParseHandler
|
|||
};
|
||||
|
||||
inline bool
|
||||
FullParseHandler::addCatchBlock(ParseNode* catchList, ParseNode* lexicalScope,
|
||||
FullParseHandler::addCatchBlock(ListNodeType catchList, ParseNode* lexicalScope,
|
||||
ParseNode* catchName, ParseNode* catchGuard, ParseNode* catchBody)
|
||||
{
|
||||
ParseNode* catchpn = newTernary(PNK_CATCH, catchName, catchGuard, catchBody);
|
||||
|
|
@ -1029,27 +1036,15 @@ FullParseHandler::addCatchBlock(ParseNode* catchList, ParseNode* lexicalScope,
|
|||
inline bool
|
||||
FullParseHandler::setLastFunctionFormalParameterDefault(ParseNode* funcpn, ParseNode* defaultValue)
|
||||
{
|
||||
ParseNode* arg = funcpn->pn_body->last();
|
||||
ListNode* body = &funcpn->pn_body->as<ListNode>();
|
||||
ParseNode* arg = body->last();
|
||||
ParseNode* pn = newBinary(PNK_ASSIGN, arg, defaultValue, JSOP_NOP);
|
||||
if (!pn)
|
||||
return false;
|
||||
|
||||
checkAndSetIsDirectRHSAnonFunction(defaultValue);
|
||||
|
||||
funcpn->pn_body->pn_pos.end = pn->pn_pos.end;
|
||||
ParseNode* pnchild = funcpn->pn_body->pn_head;
|
||||
ParseNode* pnlast = funcpn->pn_body->last();
|
||||
MOZ_ASSERT(pnchild);
|
||||
if (pnchild == pnlast) {
|
||||
funcpn->pn_body->pn_head = pn;
|
||||
} else {
|
||||
while (pnchild->pn_next != pnlast) {
|
||||
MOZ_ASSERT(pnchild->pn_next);
|
||||
pnchild = pnchild->pn_next;
|
||||
}
|
||||
pnchild->pn_next = pn;
|
||||
}
|
||||
funcpn->pn_body->pn_tail = &pn->pn_next;
|
||||
body->replaceLast(pn);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -284,12 +284,12 @@ class NameResolver
|
|||
* for new variables and then return an anonymous function using this scope.
|
||||
*/
|
||||
bool isDirectCall(int pos, ParseNode* cur) {
|
||||
return pos >= 0 && call(parents[pos]) && parents[pos]->pn_head == cur;
|
||||
return pos >= 0 && call(parents[pos]) && parents[pos]->pn_left == cur;
|
||||
}
|
||||
|
||||
bool resolveTemplateLiteral(ParseNode* node, HandleAtom prefix) {
|
||||
bool resolveTemplateLiteral(ListNode* node, HandleAtom prefix) {
|
||||
MOZ_ASSERT(node->isKind(PNK_TEMPLATE_STRING_LIST));
|
||||
ParseNode* element = node->pn_head;
|
||||
ParseNode* element = node->head();
|
||||
while (true) {
|
||||
MOZ_ASSERT(element->isKind(PNK_TEMPLATE_STRING));
|
||||
|
||||
|
|
@ -317,16 +317,18 @@ class NameResolver
|
|||
// The callsite object node is first. This node only contains
|
||||
// internal strings or undefined and an array -- no user-controlled
|
||||
// expressions.
|
||||
ParseNode* element = node->pn_right->pn_head;
|
||||
CallSiteNode* element = &node->pn_right->as<ListNode>().head()->as<CallSiteNode>();
|
||||
#ifdef DEBUG
|
||||
{
|
||||
MOZ_ASSERT(element->isKind(PNK_CALLSITEOBJ));
|
||||
ParseNode* array = element->pn_head;
|
||||
MOZ_ASSERT(array->isKind(PNK_ARRAY));
|
||||
for (ParseNode* kid = array->pn_head; kid; kid = kid->pn_next)
|
||||
MOZ_ASSERT(kid->isKind(PNK_TEMPLATE_STRING));
|
||||
for (ParseNode* next = array->pn_next; next; next = next->pn_next)
|
||||
MOZ_ASSERT(next->isKind(PNK_TEMPLATE_STRING) || next->isKind(PNK_RAW_UNDEFINED));
|
||||
ListNode* rawNodes = &element->head()->as<ListNode>();
|
||||
MOZ_ASSERT(rawNodes->isKind(PNK_ARRAY));
|
||||
for (ParseNode* raw : rawNodes->contents()) {
|
||||
MOZ_ASSERT(raw->isKind(PNK_TEMPLATE_STRING));
|
||||
}
|
||||
for (ParseNode* cooked : element->contentsFrom(rawNodes->pn_next)) {
|
||||
MOZ_ASSERT(cooked->isKind(PNK_TEMPLATE_STRING) ||
|
||||
cooked->isKind(PNK_RAW_UNDEFINED));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -697,8 +699,7 @@ class NameResolver
|
|||
case PNK_VAR:
|
||||
case PNK_CONST:
|
||||
case PNK_LET:
|
||||
MOZ_ASSERT(cur->isArity(PN_LIST));
|
||||
for (ParseNode* element = cur->pn_head; element; element = element->pn_next) {
|
||||
for (ParseNode* element : cur->as<ListNode>().contents()) {
|
||||
if (!resolve(element, prefix))
|
||||
return false;
|
||||
}
|
||||
|
|
@ -708,19 +709,19 @@ class NameResolver
|
|||
// PNK_COMPREHENSIONFOR for comprehensions, PNK_LEXICALSCOPE for
|
||||
// legacy comprehensions. Probably this should be a non-list
|
||||
// eventually.
|
||||
case PNK_ARRAYCOMP:
|
||||
MOZ_ASSERT(cur->isArity(PN_LIST));
|
||||
MOZ_ASSERT(cur->pn_count == 1);
|
||||
MOZ_ASSERT(cur->pn_head->isKind(PNK_LEXICALSCOPE) ||
|
||||
cur->pn_head->isKind(PNK_COMPREHENSIONFOR));
|
||||
if (!resolve(cur->pn_head, prefix))
|
||||
case PNK_ARRAYCOMP: {
|
||||
ListNode* literal = &cur->as<ListNode>();
|
||||
MOZ_ASSERT(literal->count() == 1);
|
||||
MOZ_ASSERT(literal->head()->isKind(PNK_LEXICALSCOPE) ||
|
||||
literal->head()->isKind(PNK_COMPREHENSIONFOR));
|
||||
if (!resolve(literal->head(), prefix))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
case PNK_OBJECT:
|
||||
case PNK_CLASSMETHODLIST:
|
||||
MOZ_ASSERT(cur->isArity(PN_LIST));
|
||||
for (ParseNode* element = cur->pn_head; element; element = element->pn_next) {
|
||||
for (ParseNode* element : cur->as<ListNode>().contents()) {
|
||||
if (!resolve(element, prefix))
|
||||
return false;
|
||||
}
|
||||
|
|
@ -729,8 +730,7 @@ class NameResolver
|
|||
// A template string list's contents alternate raw template string
|
||||
// contents with expressions interpolated into the overall literal.
|
||||
case PNK_TEMPLATE_STRING_LIST:
|
||||
MOZ_ASSERT(cur->isArity(PN_LIST));
|
||||
if (!resolveTemplateLiteral(cur, prefix))
|
||||
if (!resolveTemplateLiteral(&cur->as<ListNode>(), prefix))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
|
@ -755,8 +755,7 @@ class NameResolver
|
|||
// the Arguments node used by tagged template literals, since that is
|
||||
// special-cased inside of resolveTaggedTemplate.
|
||||
case PNK_ARGUMENTS:
|
||||
MOZ_ASSERT(cur->isArity(PN_LIST));
|
||||
for (ParseNode* element = cur->pn_head; element; element = element->pn_next) {
|
||||
for (ParseNode* element : cur->as<ListNode>().contents()) {
|
||||
if (!resolve(element, prefix))
|
||||
return false;
|
||||
}
|
||||
|
|
@ -767,15 +766,15 @@ class NameResolver
|
|||
// contain a single export batch specifier.
|
||||
case PNK_EXPORT_SPEC_LIST:
|
||||
case PNK_IMPORT_SPEC_LIST: {
|
||||
MOZ_ASSERT(cur->isArity(PN_LIST));
|
||||
#ifdef DEBUG
|
||||
bool isImport = cur->isKind(PNK_IMPORT_SPEC_LIST);
|
||||
ParseNode* item = cur->pn_head;
|
||||
ListNode* list = &cur->as<ListNode>();
|
||||
ParseNode* item = list->head();
|
||||
if (!isImport && item && item->isKind(PNK_EXPORT_BATCH_SPEC)) {
|
||||
MOZ_ASSERT(item->isArity(PN_NULLARY));
|
||||
break;
|
||||
}
|
||||
for (; item; item = item->pn_next) {
|
||||
for (ParseNode* item : list->contents()) {
|
||||
MOZ_ASSERT(item->isKind(isImport ? PNK_IMPORT_SPEC : PNK_EXPORT_SPEC));
|
||||
MOZ_ASSERT(item->isArity(PN_BINARY));
|
||||
MOZ_ASSERT(item->pn_left->isKind(PNK_NAME));
|
||||
|
|
@ -788,8 +787,8 @@ class NameResolver
|
|||
}
|
||||
|
||||
case PNK_CATCHLIST: {
|
||||
MOZ_ASSERT(cur->isArity(PN_LIST));
|
||||
for (ParseNode* catchNode = cur->pn_head; catchNode; catchNode = catchNode->pn_next) {
|
||||
ListNode* catchList = &cur->as<ListNode>();
|
||||
for (ParseNode* catchNode : catchList->contents()) {
|
||||
MOZ_ASSERT(catchNode->isKind(PNK_LEXICALSCOPE));
|
||||
MOZ_ASSERT(catchNode->scopeBody()->isKind(PNK_CATCH));
|
||||
MOZ_ASSERT(catchNode->scopeBody()->isArity(PN_TERNARY));
|
||||
|
|
|
|||
|
|
@ -17,26 +17,24 @@ using mozilla::IsFinite;
|
|||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
ParseNode::checkListConsistency()
|
||||
ListNode::checkConsistency() const
|
||||
{
|
||||
MOZ_ASSERT(isArity(PN_LIST));
|
||||
ParseNode** tail;
|
||||
uint32_t count = 0;
|
||||
if (pn_head) {
|
||||
ParseNode* last = pn_head;
|
||||
ParseNode* pn = last;
|
||||
ParseNode* const* tailNode;
|
||||
uint32_t actualCount = 0;
|
||||
if (const ParseNode* last = head()) {
|
||||
const ParseNode* pn = last;
|
||||
while (pn) {
|
||||
last = pn;
|
||||
pn = pn->pn_next;
|
||||
count++;
|
||||
actualCount++;
|
||||
}
|
||||
|
||||
tail = &last->pn_next;
|
||||
tailNode = &last->pn_next;
|
||||
} else {
|
||||
tail = &pn_head;
|
||||
tailNode = &pn_u.list.head;
|
||||
}
|
||||
MOZ_ASSERT(pn_tail == tail);
|
||||
MOZ_ASSERT(pn_count == count);
|
||||
MOZ_ASSERT(tail() == tailNode);
|
||||
MOZ_ASSERT(count() == actualCount);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -76,10 +74,10 @@ class NodeStack {
|
|||
top = pn;
|
||||
}
|
||||
/* Push the children of the PN_LIST node |pn| on the stack. */
|
||||
void pushList(ParseNode* pn) {
|
||||
void pushList(ListNode* pn) {
|
||||
/* This clobbers pn->pn_head if the list is empty; should be okay. */
|
||||
*pn->pn_tail = top;
|
||||
top = pn->pn_head;
|
||||
pn->unsafeSetTail(top);
|
||||
top = pn->head();
|
||||
}
|
||||
ParseNode* pop() {
|
||||
MOZ_ASSERT(!empty());
|
||||
|
|
@ -148,10 +146,10 @@ PushScopeNodeChildren(ParseNode* node, NodeStack* stack)
|
|||
}
|
||||
|
||||
static PushResult
|
||||
PushListNodeChildren(ParseNode* node, NodeStack* stack)
|
||||
PushListNodeChildren(ListNode* node, NodeStack* stack)
|
||||
{
|
||||
MOZ_ASSERT(node->isArity(PN_LIST));
|
||||
node->checkListConsistency();
|
||||
node->checkConsistency();
|
||||
|
||||
stack->pushList(node);
|
||||
|
||||
|
|
@ -335,7 +333,7 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
|||
MOZ_ASSERT_IF(pn->isKind(PNK_EXPORT_FROM), pn->pn_left->isKind(PNK_EXPORT_SPEC_LIST));
|
||||
MOZ_ASSERT(pn->pn_left->isArity(PN_LIST));
|
||||
MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING));
|
||||
stack->pushList(pn->pn_left);
|
||||
stack->pushList(&pn->pn_left->as<ListNode>());
|
||||
stack->push(pn->pn_right);
|
||||
return PushResult::Recyclable;
|
||||
}
|
||||
|
|
@ -474,20 +472,17 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
|||
case PNK_EXPORT_SPEC_LIST:
|
||||
case PNK_PARAMSBODY:
|
||||
case PNK_CLASSMETHODLIST:
|
||||
return PushListNodeChildren(pn, stack);
|
||||
return PushListNodeChildren(&pn->as<ListNode>(), stack);
|
||||
|
||||
// Array comprehension nodes are lists with a single child:
|
||||
// PNK_COMPREHENSIONFOR for comprehensions, PNK_LEXICALSCOPE for legacy
|
||||
// comprehensions. Probably this should be a non-list eventually.
|
||||
case PNK_ARRAYCOMP: {
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(pn->isKind(PNK_ARRAYCOMP));
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(pn->pn_count == 1);
|
||||
MOZ_ASSERT(pn->pn_head->isKind(PNK_LEXICALSCOPE) ||
|
||||
pn->pn_head->isKind(PNK_COMPREHENSIONFOR));
|
||||
#endif
|
||||
return PushListNodeChildren(pn, stack);
|
||||
ListNode* literal = &pn->as<ListNode>();
|
||||
MOZ_ASSERT(literal->count() == 1);
|
||||
MOZ_ASSERT(literal->head()->isKind(PNK_LEXICALSCOPE) ||
|
||||
literal->head()->isKind(PNK_COMPREHENSIONFOR));
|
||||
return PushListNodeChildren(literal, stack);
|
||||
}
|
||||
|
||||
case PNK_LABEL:
|
||||
|
|
@ -614,7 +609,7 @@ ParseNode::appendOrCreateList(ParseNodeKind kind, JSOp op, ParseNode* left, Pars
|
|||
}
|
||||
}
|
||||
|
||||
ParseNode* list = handler->new_<ListNode>(kind, op, left);
|
||||
ListNode* list = handler->new_<ListNode>(kind, op, left);
|
||||
if (!list)
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -674,7 +669,7 @@ ParseNode::dump(int indent)
|
|||
((CodeNode*) this)->dump(indent);
|
||||
break;
|
||||
case PN_LIST:
|
||||
((ListNode*) this)->dump(indent);
|
||||
as<ListNode>().dump(indent);
|
||||
break;
|
||||
case PN_NAME:
|
||||
((NameNode*) this)->dump(indent);
|
||||
|
|
@ -785,14 +780,12 @@ ListNode::dump(int indent)
|
|||
{
|
||||
const char* name = parseNodeNames[getKind()];
|
||||
fprintf(stderr, "(%s [", name);
|
||||
if (pn_head != nullptr) {
|
||||
if (ParseNode* listHead = head()) {
|
||||
indent += strlen(name) + 3;
|
||||
DumpParseTree(pn_head, indent);
|
||||
ParseNode* pn = pn_head->pn_next;
|
||||
while (pn != nullptr) {
|
||||
DumpParseTree(listHead, indent);
|
||||
for (ParseNode* item : contentsFrom(listHead->pn_next)) {
|
||||
IndentNewLine(indent);
|
||||
DumpParseTree(pn, indent);
|
||||
pn = pn->pn_next;
|
||||
DumpParseTree(item, indent);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "])");
|
||||
|
|
|
|||
|
|
@ -220,8 +220,6 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
}
|
||||
|
||||
/*
|
||||
* Label Variant Members
|
||||
* ----- ------- -------
|
||||
* <Definitions>
|
||||
* PNK_FUNCTION name pn_funbox: ptr to js::FunctionBox holding function
|
||||
* object containing arg and var properties. We
|
||||
|
|
@ -229,27 +227,25 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* time to specialize arg and var bytecodes early.
|
||||
* pn_body: PNK_PARAMSBODY, ordinarily;
|
||||
* PNK_LEXICALSCOPE for implicit function in genexpr
|
||||
* PNK_PARAMSBODY list list of formal parameters with
|
||||
* PNK_NAME node with non-empty name for
|
||||
* SingleNameBinding without Initializer
|
||||
* PNK_ASSIGN node for SingleNameBinding with
|
||||
* Initializer
|
||||
* PNK_NAME node with empty name for destructuring
|
||||
* pn_expr: PNK_ARRAY, PNK_OBJECT, or PNK_ASSIGN
|
||||
* PNK_ARRAY or PNK_OBJECT for BindingPattern
|
||||
* without Initializer
|
||||
* PNK_ASSIGN for BindingPattern with
|
||||
* Initializer
|
||||
* followed by:
|
||||
* PNK_STATEMENTLIST node for function body
|
||||
* statements,
|
||||
* PNK_RETURN for expression closure
|
||||
* pn_count: 1 + number of formal parameters
|
||||
* pn_tree: PNK_PARAMSBODY or PNK_STATEMENTLIST node
|
||||
* PNK_PARAMSBODY (ListNode)
|
||||
* head: list of formal parameters with
|
||||
* * Name node with non-empty name for SingleNameBinding without
|
||||
* Initializer
|
||||
* * Assign node for SingleNameBinding with Initializer
|
||||
* * Name node with empty name for destructuring
|
||||
* pn_expr: Array or Object for BindingPattern without
|
||||
* Initializer, Assign for BindingPattern with
|
||||
* Initializer
|
||||
* followed by either:
|
||||
* * StatementList node for function body statements
|
||||
* * Return for expression closure
|
||||
* count: number of formal parameters + 1
|
||||
* PNK_SPREAD unary pn_kid: expression being spread
|
||||
*
|
||||
* <Statements>
|
||||
* PNK_STATEMENTLIST list pn_head: list of pn_count statements
|
||||
* PNK_STATEMENTLIST (ListNode)
|
||||
* head: list of N statements
|
||||
* count: N >= 0
|
||||
* PNK_IF ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else or null.
|
||||
* In body of a comprehension or desugared generator
|
||||
* expression, pn_kid2 is PNK_YIELD, PNK_ARRAYPUSH,
|
||||
|
|
@ -293,19 +289,21 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* PNK_BREAK name pn_atom: label or null
|
||||
* PNK_CONTINUE name pn_atom: label or null
|
||||
* PNK_WITH binary pn_left: head expr; pn_right: body;
|
||||
* PNK_VAR, list pn_head: list of PNK_NAME or PNK_ASSIGN nodes
|
||||
* PNK_LET, each name node has either
|
||||
* PNK_CONST pn_used: false
|
||||
* pn_atom: variable name
|
||||
* pn_expr: initializer or null
|
||||
* or
|
||||
* pn_used: true
|
||||
* pn_atom: variable name
|
||||
* pn_lexdef: def node
|
||||
* each assignment node has
|
||||
* pn_left: PNK_NAME with pn_used true and
|
||||
* pn_lexdef (NOT pn_expr) set
|
||||
* pn_right: initializer
|
||||
* PNK_VAR, PNK_LET, PNK_CONST (ListNode)
|
||||
* head: list of N Name or Assign nodes
|
||||
* each name node has either
|
||||
* pn_used: false
|
||||
* pn_atom: variable name
|
||||
* pn_expr: initializer or null
|
||||
* or
|
||||
* pn_used: true
|
||||
* pn_atom: variable name
|
||||
* pn_lexdef: def node
|
||||
* each assignment node has
|
||||
* pn_left: Name with pn_used true and
|
||||
* pn_lexdef (NOT pn_expr) set
|
||||
* pn_right: initializer
|
||||
* count: N > 0
|
||||
* PNK_RETURN unary pn_kid: return expr or null
|
||||
* PNK_SEMI unary pn_kid: expr or null statement
|
||||
* pn_prologue: true if Directive Prologue member
|
||||
|
|
@ -314,15 +312,23 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* PNK_LABEL name pn_atom: label, pn_expr: labeled statement
|
||||
* PNK_IMPORT binary pn_left: PNK_IMPORT_SPEC_LIST import specifiers
|
||||
* pn_right: PNK_STRING module specifier
|
||||
* PNK_IMPORT_SPEC_LIST (ListNode)
|
||||
* head: list of N ImportSpec nodes
|
||||
* count: N >= 0 (N = 0 for `import {} from ...`)
|
||||
* PNK_EXPORT unary pn_kid: declaration expression
|
||||
* PNK_EXPORT_FROM binary pn_left: PNK_EXPORT_SPEC_LIST export specifiers
|
||||
* pn_right: PNK_STRING module specifier
|
||||
* PNK_EXPORT_SPEC_LIST (ListNode)
|
||||
* head: list of N ExportSpec nodes
|
||||
* count: N >= 0 (N = 0 for `export {}`)
|
||||
* PNK_EXPORT_DEFAULT unary pn_kid: export default declaration or expression
|
||||
*
|
||||
* <Expressions>
|
||||
* All left-associated binary trees of the same type are optimized into lists
|
||||
* to avoid recursion when processing expression chains.
|
||||
* PNK_COMMA list pn_head: list of pn_count comma-separated exprs
|
||||
* PNK_COMMA (ListNode)
|
||||
* head: list of N comma-separated exprs
|
||||
* count: N >= 2
|
||||
* PNK_ASSIGN binary pn_left: lvalue, pn_right: rvalue
|
||||
* PNK_ADDASSIGN, binary pn_left: lvalue, pn_right: rvalue
|
||||
* PNK_SUBASSIGN, pn_op: JSOP_ADD for +=, etc.
|
||||
|
|
@ -339,29 +345,18 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* PNK_CONDITIONAL ternary (cond ? trueExpr : falseExpr)
|
||||
* pn_kid1: cond, pn_kid2: then, pn_kid3: else
|
||||
* PNK_COALESCE, list pn_head; list of pn_count subexpressions
|
||||
* PNK_OR, All of these operators are left-associative except (**).
|
||||
* PNK_AND
|
||||
* PNK_BITOR,
|
||||
* PNK_BITXOR,
|
||||
* PNK_BITAND,
|
||||
* PNK_EQ,
|
||||
* PNK_NE,
|
||||
* PNK_STRICTEQ,
|
||||
* PNK_STRICTNE,
|
||||
* PNK_LT,
|
||||
* PNK_LE,
|
||||
* PNK_GT,
|
||||
* PNK_GE,
|
||||
* PNK_LSH,
|
||||
* PNK_RSH,
|
||||
* PNK_URSH,
|
||||
* PNK_ADD,
|
||||
* PNK_SUB,
|
||||
* PNK_STAR,
|
||||
* PNK_DIV,
|
||||
* PNK_MOD,
|
||||
* PNK_POW (**) is right-associative, but forms a list
|
||||
* nonetheless. Special hacks everywhere.
|
||||
* PNK_OR, PNK_AND, PNK_BITOR,
|
||||
* PNK_BITXOR, PNK_BITAND, PNK_EQ,
|
||||
* PNK_NE, PNK_STRICTEQ, PNK_STRICTNE,
|
||||
* PNK_LT, PNK_LE, PNK_GT, PNK_GE,
|
||||
* PNK_LSH, PNK_RSH, PNK_URSH,
|
||||
* PNK_ADD, PNK_SUB, PNK_STAR,
|
||||
* PNK_DIV, PNK_MOD, PNK_POW (ListNode)
|
||||
* head: list of N subexpressions
|
||||
* All of these operators are left-associative except Pow which is
|
||||
* right-associative, but still forms a list (see comments in
|
||||
* ParseNode::appendOrCreateList).
|
||||
* count: N >= 2
|
||||
*
|
||||
* PNK_POS, unary pn_kid: UNARY expr
|
||||
* PNK_NEG
|
||||
|
|
@ -420,10 +415,21 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* pn_count: N (where N is number of args)
|
||||
* PNK_GENEXP binary Exactly like PNK_CALL, used for the implicit call
|
||||
* in the desugaring of a generator-expression.
|
||||
* PNK_ARRAY list pn_head: list of pn_count array element exprs
|
||||
* [,,] holes are represented by PNK_ELISION nodes
|
||||
* pn_xflags: PN_ENDCOMMA if extra comma at end
|
||||
* PNK_OBJECT list pn_head: list of pn_count binary PNK_COLON nodes
|
||||
* PNK_ARGUMENTS (ListNode)
|
||||
* head: list of arg1, arg2, ... argN
|
||||
* count: N >= 0
|
||||
* PNK_ARRAY (ListNode)
|
||||
* head: list of N array element expressions
|
||||
* holes ([,,]) are represented by Elision nodes,
|
||||
* spread elements ([...X]) are represented by Spread nodes
|
||||
* count: N >= 0
|
||||
* PNK_OBJECT (ListNode)
|
||||
* head: list of N nodes, each item is one of:
|
||||
* * MutateProto
|
||||
* * Colon
|
||||
* * Shorthand
|
||||
* * Spread
|
||||
* count: N >= 0
|
||||
* PNK_COLON binary key-value pair in object initializer or
|
||||
* destructuring lhs
|
||||
* pn_left: property id, pn_right: value
|
||||
|
|
@ -435,14 +441,21 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* PNK_STRING pn_op: JSOP_GETNAME, JSOP_STRING, or JSOP_OBJECT
|
||||
* If JSOP_GETNAME, pn_op may be JSOP_*ARG or JSOP_*VAR
|
||||
* telling const-ness and static analysis results
|
||||
* PNK_TEMPLATE_STRING_LIST pn_head: list of alternating expr and template strings
|
||||
* list
|
||||
* PNK_TEMPLATE_STRING_LIST (ListNode)
|
||||
* head: list of alternating expr and template strings
|
||||
* TemplateString [, expression, TemplateString]+
|
||||
* there's at least one expression. If the template literal contains
|
||||
* no ${}-delimited expression, it's parsed as a single TemplateString
|
||||
* PNK_TEMPLATE_STRING pn_atom: template string atom
|
||||
nullary pn_op: JSOP_NOP
|
||||
* PNK_TAGGED_TEMPLATE pn_left: tag expression
|
||||
* binary pn_right: Arguments, with the first being the call site object, then arg1, arg2, ... argN
|
||||
* PNK_CALLSITEOBJ list pn_head: a PNK_ARRAY node followed by
|
||||
* list of pn_count - 1 PNK_TEMPLATE_STRING nodes
|
||||
* PNK_CALLSITEOBJ (CallSiteNode)
|
||||
* head: an Array of raw TemplateString, then corresponding cooked
|
||||
* TemplateString nodes
|
||||
* Array [, cooked TemplateString]+
|
||||
* where the Array is
|
||||
* [raw TemplateString]+
|
||||
* PNK_REGEXP nullary pn_objbox: RegExp model object
|
||||
* PNK_NUMBER dval pn_dval: double value of numeric literal
|
||||
* PNK_TRUE, nullary pn_op: JSOp bytecode
|
||||
|
|
@ -483,12 +496,21 @@ enum ParseNodeArity
|
|||
PN_SCOPE /* lexical scope */
|
||||
};
|
||||
|
||||
#define FOR_EACH_PARSENODE_SUBCLASS(macro) \
|
||||
macro(ListNode, ListNodeType, asList) \
|
||||
macro(CallSiteNode, CallSiteNodeType, asCallSite)
|
||||
|
||||
class LoopControlStatement;
|
||||
class BreakStatement;
|
||||
class ContinueStatement;
|
||||
class ConditionalExpression;
|
||||
class PropertyAccess;
|
||||
|
||||
#define DECLARE_CLASS(typeName, longTypeName, asMethodName) \
|
||||
class typeName;
|
||||
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_CLASS)
|
||||
#undef DECLARE_CLASS
|
||||
|
||||
class ParseNode
|
||||
{
|
||||
uint16_t pn_type; /* PNK_* type */
|
||||
|
|
@ -574,10 +596,12 @@ class ParseNode
|
|||
|
||||
union {
|
||||
struct { /* list of next-linked nodes */
|
||||
private:
|
||||
friend class ListNode;
|
||||
ParseNode* head; /* first node in list */
|
||||
ParseNode** tail; /* ptr to ptr to last node in list */
|
||||
ParseNode** tail; /* ptr to last node's pn_next in list */
|
||||
uint32_t count; /* number of nodes in list */
|
||||
uint32_t xflags; /* see PNX_* below */
|
||||
uint32_t xflags; /* see ListNode class */
|
||||
} list;
|
||||
struct { /* ternary: if, for(;;), ?: */
|
||||
ParseNode* kid1; /* condition, discriminant, etc. */
|
||||
|
|
@ -624,10 +648,6 @@ class ParseNode
|
|||
#define pn_objbox pn_u.name.objbox
|
||||
#define pn_funbox pn_u.name.funbox
|
||||
#define pn_body pn_u.name.expr
|
||||
#define pn_head pn_u.list.head
|
||||
#define pn_tail pn_u.list.tail
|
||||
#define pn_count pn_u.list.count
|
||||
#define pn_xflags pn_u.list.xflags
|
||||
#define pn_kid1 pn_u.ternary.kid1
|
||||
#define pn_kid2 pn_u.ternary.kid2
|
||||
#define pn_kid3 pn_u.ternary.kid3
|
||||
|
|
@ -682,13 +702,6 @@ class ParseNode
|
|||
pn_u.scope.body = body;
|
||||
}
|
||||
|
||||
/* PN_LIST pn_xflags bits. */
|
||||
#define PNX_FUNCDEFS 0x01 /* contains top-level function statements */
|
||||
#define PNX_ARRAYHOLESPREAD 0x02 /* one or more of
|
||||
1. array initialiser has holes
|
||||
2. array initializer has spread node */
|
||||
#define PNX_NONCONST 0x04 /* initialiser has non-constants */
|
||||
|
||||
bool functionIsHoisted() const {
|
||||
MOZ_ASSERT(pn_arity == PN_CODE && getKind() == PNK_FUNCTION);
|
||||
MOZ_ASSERT(isOp(JSOP_LAMBDA) || // lambda, genexpr
|
||||
|
|
@ -738,41 +751,7 @@ class ParseNode
|
|||
bool isDirectivePrologueMember() const { return pn_prologue; }
|
||||
|
||||
// True iff this is a for-in/of loop variable declaration (var/let/const).
|
||||
bool isForLoopDeclaration() const {
|
||||
if (isKind(PNK_VAR) || isKind(PNK_LET) || isKind(PNK_CONST)) {
|
||||
MOZ_ASSERT(isArity(PN_LIST));
|
||||
MOZ_ASSERT(pn_count > 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ParseNode* generatorExpr() const {
|
||||
MOZ_ASSERT(isKind(PNK_GENEXP));
|
||||
|
||||
ParseNode* callee = this->pn_left;
|
||||
MOZ_ASSERT(callee->isKind(PNK_FUNCTION));
|
||||
|
||||
ParseNode* paramsBody = callee->pn_body;
|
||||
MOZ_ASSERT(paramsBody->isKind(PNK_PARAMSBODY));
|
||||
|
||||
ParseNode* body = paramsBody->last();
|
||||
MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST));
|
||||
MOZ_ASSERT(body->last()->isKind(PNK_LEXICALSCOPE) ||
|
||||
body->last()->isKind(PNK_COMPREHENSIONFOR));
|
||||
return body->last();
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute a pointer to the last element in a singly-linked list. NB: list
|
||||
* must be non-empty for correct PN_LAST usage -- this is asserted!
|
||||
*/
|
||||
ParseNode* last() const {
|
||||
MOZ_ASSERT(pn_arity == PN_LIST);
|
||||
MOZ_ASSERT(pn_count != 0);
|
||||
return (ParseNode*)(uintptr_t(pn_tail) - offsetof(ParseNode, pn_next));
|
||||
}
|
||||
bool isForLoopDeclaration() const;
|
||||
|
||||
void initNumber(double value, DecimalPoint decimalPoint) {
|
||||
MOZ_ASSERT(pn_arity == PN_NULLARY);
|
||||
|
|
@ -781,49 +760,6 @@ class ParseNode
|
|||
pn_u.number.decimalPoint = decimalPoint;
|
||||
}
|
||||
|
||||
void makeEmpty() {
|
||||
MOZ_ASSERT(pn_arity == PN_LIST);
|
||||
pn_head = nullptr;
|
||||
pn_tail = &pn_head;
|
||||
pn_count = 0;
|
||||
pn_xflags = 0;
|
||||
}
|
||||
|
||||
void initList(ParseNode* pn) {
|
||||
MOZ_ASSERT(pn_arity == PN_LIST);
|
||||
if (pn->pn_pos.begin < pn_pos.begin)
|
||||
pn_pos.begin = pn->pn_pos.begin;
|
||||
pn_pos.end = pn->pn_pos.end;
|
||||
pn_head = pn;
|
||||
pn_tail = &pn->pn_next;
|
||||
pn_count = 1;
|
||||
pn_xflags = 0;
|
||||
}
|
||||
|
||||
void append(ParseNode* pn) {
|
||||
MOZ_ASSERT(pn_arity == PN_LIST);
|
||||
MOZ_ASSERT(pn->pn_pos.begin >= pn_pos.begin);
|
||||
pn_pos.end = pn->pn_pos.end;
|
||||
*pn_tail = pn;
|
||||
pn_tail = &pn->pn_next;
|
||||
pn_count++;
|
||||
}
|
||||
|
||||
void prepend(ParseNode* pn) {
|
||||
MOZ_ASSERT(pn_arity == PN_LIST);
|
||||
pn->pn_next = pn_head;
|
||||
pn_head = pn;
|
||||
if (pn_tail == &pn_head)
|
||||
pn_tail = &pn->pn_next;
|
||||
pn_count++;
|
||||
}
|
||||
|
||||
void checkListConsistency()
|
||||
#ifndef DEBUG
|
||||
{}
|
||||
#endif
|
||||
;
|
||||
|
||||
enum AllowConstantObjects {
|
||||
DontAllowObjects = 0,
|
||||
AllowObjects,
|
||||
|
|
@ -944,8 +880,33 @@ struct TernaryNode : public ParseNode
|
|||
#endif
|
||||
};
|
||||
|
||||
struct ListNode : public ParseNode
|
||||
class ListNode : public ParseNode
|
||||
{
|
||||
private:
|
||||
// xflags bits.
|
||||
|
||||
// Statement list has top-level function statements.
|
||||
static constexpr uint32_t hasTopLevelFunctionDeclarationsBit = 0x01;
|
||||
|
||||
// One or more of
|
||||
// * array has holes
|
||||
// * array has spread node
|
||||
static constexpr uint32_t hasArrayHoleOrSpreadBit = 0x02;
|
||||
|
||||
// Array/Object/Class initializer has non-constants.
|
||||
// * array has holes
|
||||
// * array has spread node
|
||||
// * array has element which is known not to be constant
|
||||
// * array has no element
|
||||
// * object/class has __proto__
|
||||
// * object/class has property which is known not to be constant
|
||||
// * object/class shorthand property
|
||||
// * object/class spread property
|
||||
// * object/class has method
|
||||
// * object/class has computed property
|
||||
static constexpr uint32_t hasNonConstInitializerBit = 0x04;
|
||||
|
||||
public:
|
||||
ListNode(ParseNodeKind kind, const TokenPos& pos)
|
||||
: ParseNode(kind, JSOP_NOP, PN_LIST, pos)
|
||||
{
|
||||
|
|
@ -961,7 +922,15 @@ struct ListNode : public ParseNode
|
|||
ListNode(ParseNodeKind kind, JSOp op, ParseNode* kid)
|
||||
: ParseNode(kind, op, PN_LIST, kid->pn_pos)
|
||||
{
|
||||
initList(kid);
|
||||
if (kid->pn_pos.begin < pn_pos.begin) {
|
||||
pn_pos.begin = kid->pn_pos.begin;
|
||||
}
|
||||
pn_pos.end = kid->pn_pos.end;
|
||||
|
||||
pn_u.list.head = kid;
|
||||
pn_u.list.tail = &kid->pn_next;
|
||||
pn_u.list.count = 1;
|
||||
pn_u.list.xflags = 0;
|
||||
}
|
||||
|
||||
static bool test(const ParseNode& node) {
|
||||
|
|
@ -971,8 +940,278 @@ struct ListNode : public ParseNode
|
|||
#ifdef DEBUG
|
||||
void dump(int indent);
|
||||
#endif
|
||||
|
||||
ParseNode* head() const {
|
||||
return pn_u.list.head;
|
||||
}
|
||||
|
||||
ParseNode** tail() const {
|
||||
return pn_u.list.tail;
|
||||
}
|
||||
|
||||
uint32_t count() const {
|
||||
return pn_u.list.count;
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return count() == 0;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool hasTopLevelFunctionDeclarations() const {
|
||||
MOZ_ASSERT(isKind(PNK_STATEMENTLIST));
|
||||
return pn_u.list.xflags & hasTopLevelFunctionDeclarationsBit;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool hasArrayHoleOrSpread() const {
|
||||
MOZ_ASSERT(isKind(PNK_ARRAY));
|
||||
return pn_u.list.xflags & hasArrayHoleOrSpreadBit;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool hasNonConstInitializer() const {
|
||||
MOZ_ASSERT(isKind(PNK_ARRAY) ||
|
||||
isKind(PNK_OBJECT) ||
|
||||
isKind(PNK_CLASSMETHODLIST));
|
||||
return pn_u.list.xflags & hasNonConstInitializerBit;
|
||||
}
|
||||
|
||||
void setHasTopLevelFunctionDeclarations() {
|
||||
MOZ_ASSERT(isKind(PNK_STATEMENTLIST));
|
||||
pn_u.list.xflags |= hasTopLevelFunctionDeclarationsBit;
|
||||
}
|
||||
|
||||
void setHasArrayHoleOrSpread() {
|
||||
MOZ_ASSERT(isKind(PNK_ARRAY));
|
||||
pn_u.list.xflags |= hasArrayHoleOrSpreadBit;
|
||||
}
|
||||
|
||||
void setHasNonConstInitializer() {
|
||||
MOZ_ASSERT(isKind(PNK_ARRAY) ||
|
||||
isKind(PNK_OBJECT) ||
|
||||
isKind(PNK_CLASSMETHODLIST));
|
||||
pn_u.list.xflags |= hasNonConstInitializerBit;
|
||||
}
|
||||
|
||||
void checkConsistency() const
|
||||
#ifndef DEBUG
|
||||
{}
|
||||
#endif
|
||||
;
|
||||
|
||||
/*
|
||||
* Compute a pointer to the last element in a singly-linked list. NB: list
|
||||
* must be non-empty -- this is asserted!
|
||||
*/
|
||||
ParseNode* last() const {
|
||||
MOZ_ASSERT(!empty());
|
||||
//
|
||||
// ParseNode ParseNode
|
||||
// +-----+---------+-----+ +-----+---------+-----+
|
||||
// | ... | pn_next | ... | +-...->| ... | pn_next | ... |
|
||||
// +-----+---------+-----+ | +-----+---------+-----+
|
||||
// ^ | | ^ ^
|
||||
// | +---------------+ | |
|
||||
// | | tail()
|
||||
// | |
|
||||
// head() last()
|
||||
//
|
||||
return (ParseNode*)(uintptr_t(tail()) - offsetof(ParseNode, pn_next));
|
||||
}
|
||||
|
||||
void replaceLast(ParseNode* node) {
|
||||
MOZ_ASSERT(!empty());
|
||||
pn_pos.end = node->pn_pos.end;
|
||||
|
||||
ParseNode* item = head();
|
||||
ParseNode* lastNode = last();
|
||||
MOZ_ASSERT(item);
|
||||
if (item == lastNode) {
|
||||
pn_u.list.head = node;
|
||||
} else {
|
||||
while (item->pn_next != lastNode) {
|
||||
MOZ_ASSERT(item->pn_next);
|
||||
item = item->pn_next;
|
||||
}
|
||||
item->pn_next = node;
|
||||
}
|
||||
pn_u.list.tail = &node->pn_next;
|
||||
}
|
||||
|
||||
void makeEmpty() {
|
||||
pn_u.list.head = nullptr;
|
||||
pn_u.list.tail = &pn_u.list.head;
|
||||
pn_u.list.count = 0;
|
||||
pn_u.list.xflags = 0;
|
||||
}
|
||||
|
||||
void append(ParseNode* item) {
|
||||
MOZ_ASSERT(item->pn_pos.begin >= pn_pos.begin);
|
||||
pn_pos.end = item->pn_pos.end;
|
||||
*pn_u.list.tail = item;
|
||||
pn_u.list.tail = &item->pn_next;
|
||||
pn_u.list.count++;
|
||||
}
|
||||
|
||||
void prepend(ParseNode* item) {
|
||||
item->pn_next = pn_u.list.head;
|
||||
pn_u.list.head = item;
|
||||
if (pn_u.list.tail == &pn_u.list.head) {
|
||||
pn_u.list.tail = &item->pn_next;
|
||||
}
|
||||
pn_u.list.count++;
|
||||
}
|
||||
|
||||
// Methods used by FoldConstants.cpp.
|
||||
// Caller is responsible for keeping the list consistent.
|
||||
ParseNode** unsafeHeadReference() {
|
||||
return &pn_u.list.head;
|
||||
}
|
||||
|
||||
void unsafeReplaceTail(ParseNode** newTail) {
|
||||
pn_u.list.tail = newTail;
|
||||
checkConsistency();
|
||||
}
|
||||
|
||||
void unsafeSetTail(ParseNode* newTail) {
|
||||
*pn_u.list.tail = newTail;
|
||||
}
|
||||
|
||||
void unsafeDecrementCount() {
|
||||
MOZ_ASSERT(count() > 1);
|
||||
pn_u.list.count--;
|
||||
}
|
||||
|
||||
private:
|
||||
// Classes to iterate over ListNode contents:
|
||||
//
|
||||
// Usage:
|
||||
// ListNode* list;
|
||||
// for (ParseNode* item : list->contents()) {
|
||||
// // item is ParseNode* typed.
|
||||
// }
|
||||
class iterator
|
||||
{
|
||||
private:
|
||||
ParseNode* node_;
|
||||
|
||||
friend class ListNode;
|
||||
explicit iterator(ParseNode* node)
|
||||
: node_(node)
|
||||
{}
|
||||
|
||||
public:
|
||||
bool operator==(const iterator& other) const {
|
||||
return node_ == other.node_;
|
||||
}
|
||||
|
||||
bool operator!=(const iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
iterator& operator++() {
|
||||
node_ = node_->pn_next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ParseNode* operator*() {
|
||||
return node_;
|
||||
}
|
||||
|
||||
const ParseNode* operator*() const {
|
||||
return node_;
|
||||
}
|
||||
};
|
||||
|
||||
class range
|
||||
{
|
||||
private:
|
||||
ParseNode* begin_;
|
||||
ParseNode* end_;
|
||||
|
||||
friend class ListNode;
|
||||
range(ParseNode* begin, ParseNode* end)
|
||||
: begin_(begin),
|
||||
end_(end)
|
||||
{}
|
||||
|
||||
public:
|
||||
iterator begin() {
|
||||
return iterator(begin_);
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return iterator(end_);
|
||||
}
|
||||
|
||||
const iterator begin() const {
|
||||
return iterator(begin_);
|
||||
}
|
||||
|
||||
const iterator end() const {
|
||||
return iterator(end_);
|
||||
}
|
||||
|
||||
const iterator cbegin() const {
|
||||
return begin();
|
||||
}
|
||||
|
||||
const iterator cend() const {
|
||||
return end();
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
MOZ_MUST_USE bool contains(ParseNode* target) const {
|
||||
MOZ_ASSERT(target);
|
||||
for (ParseNode* node : contents()) {
|
||||
if (target == node) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
range contents() {
|
||||
return range(head(), nullptr);
|
||||
}
|
||||
|
||||
const range contents() const {
|
||||
return range(head(), nullptr);
|
||||
}
|
||||
|
||||
range contentsFrom(ParseNode* begin) {
|
||||
MOZ_ASSERT_IF(begin, contains(begin));
|
||||
return range(begin, nullptr);
|
||||
}
|
||||
|
||||
const range contentsFrom(ParseNode* begin) const {
|
||||
MOZ_ASSERT_IF(begin, contains(begin));
|
||||
return range(begin, nullptr);
|
||||
}
|
||||
|
||||
range contentsTo(ParseNode* end) {
|
||||
MOZ_ASSERT_IF(end, contains(end));
|
||||
return range(head(), end);
|
||||
}
|
||||
|
||||
const range contentsTo(ParseNode* end) const {
|
||||
MOZ_ASSERT_IF(end, contains(end));
|
||||
return range(head(), end);
|
||||
}
|
||||
};
|
||||
|
||||
inline bool
|
||||
ParseNode::isForLoopDeclaration() const
|
||||
{
|
||||
if (isKind(PNK_VAR) || isKind(PNK_LET) || isKind(PNK_CONST)) {
|
||||
MOZ_ASSERT(!as<ListNode>().empty());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct CodeNode : public ParseNode
|
||||
{
|
||||
CodeNode(ParseNodeKind kind, JSOp op, const TokenPos& pos)
|
||||
|
|
@ -1066,10 +1305,7 @@ class CaseClause : public BinaryNode
|
|||
|
||||
ParseNode* caseExpression() const { return pn_left; }
|
||||
bool isDefault() const { return !caseExpression(); }
|
||||
ParseNode* statementList() const { return pn_right; }
|
||||
|
||||
// The next CaseClause in the same switch statement.
|
||||
CaseClause* next() const { return pn_next ? &pn_next->as<CaseClause>() : nullptr; }
|
||||
ListNode* statementList() const { return &pn_right->as<ListNode>(); }
|
||||
|
||||
static bool test(const ParseNode& node) {
|
||||
bool match = node.isKind(PNK_CASE);
|
||||
|
|
@ -1363,15 +1599,24 @@ class OptionalPropertyByValue : public PropertyByValueBase {
|
|||
/*
|
||||
* A CallSiteNode represents the implicit call site object argument in a TaggedTemplate.
|
||||
*/
|
||||
struct CallSiteNode : public ListNode {
|
||||
class CallSiteNode : public ListNode
|
||||
{
|
||||
public:
|
||||
explicit CallSiteNode(uint32_t begin): ListNode(PNK_CALLSITEOBJ, TokenPos(begin, begin + 1)) {}
|
||||
|
||||
static bool test(const ParseNode& node) {
|
||||
return node.isKind(PNK_CALLSITEOBJ);
|
||||
bool match = node.isKind(PNK_CALLSITEOBJ);
|
||||
MOZ_ASSERT_IF(match, node.is<ListNode>());
|
||||
return match;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool getRawArrayValue(ExclusiveContext* cx, MutableHandleValue vp) {
|
||||
return pn_head->getConstantValue(cx, AllowObjects, vp);
|
||||
return head()->getConstantValue(cx, AllowObjects, vp);
|
||||
}
|
||||
|
||||
ListNode* rawNodes() const {
|
||||
MOZ_ASSERT(head());
|
||||
return &head()->as<ListNode>();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1412,11 +1657,11 @@ struct SwitchStatement : public BinaryNode {
|
|||
{
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(lexicalForCaseList->isKind(PNK_LEXICALSCOPE));
|
||||
ParseNode* cases = lexicalForCaseList->scopeBody();
|
||||
ListNode* cases = &lexicalForCaseList->scopeBody()->as<ListNode>();
|
||||
MOZ_ASSERT(cases->isKind(PNK_STATEMENTLIST));
|
||||
bool found = false;
|
||||
CaseClause* firstCase = cases->pn_head ? &cases->pn_head->as<CaseClause>() : nullptr;
|
||||
for (CaseClause* caseNode = firstCase; caseNode; caseNode = caseNode->next()) {
|
||||
for (ParseNode* item : cases->contents()) {
|
||||
CaseClause* caseNode = &item->as<CaseClause>();
|
||||
if (caseNode->isDefault()) {
|
||||
found = true;
|
||||
break;
|
||||
|
|
@ -1498,12 +1743,12 @@ struct ClassNode : public TernaryNode {
|
|||
ParseNode* heritage() const {
|
||||
return pn_kid2;
|
||||
}
|
||||
ParseNode* methodList() const {
|
||||
ListNode* methodList() const {
|
||||
if (pn_kid3->isKind(PNK_CLASSMETHODLIST))
|
||||
return pn_kid3;
|
||||
return &pn_kid3->as<ListNode>();
|
||||
|
||||
MOZ_ASSERT(pn_kid3->is<LexicalScopeNode>());
|
||||
ParseNode* list = pn_kid3->scopeBody();
|
||||
ListNode* list = &pn_kid3->scopeBody()->as<ListNode>();
|
||||
MOZ_ASSERT(list->isKind(PNK_CLASSMETHODLIST));
|
||||
return list;
|
||||
}
|
||||
|
|
@ -1550,7 +1795,7 @@ ParseNode::isConstant()
|
|||
case PNK_ARRAY:
|
||||
case PNK_OBJECT:
|
||||
MOZ_ASSERT(isOp(JSOP_NEWINIT));
|
||||
return !(pn_xflags & PNX_NONCONST);
|
||||
return !as<ListNode>().hasNonConstInitializer();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1628,17 +1873,16 @@ static inline ParseNode*
|
|||
FunctionFormalParametersList(ParseNode* fn, unsigned* numFormals)
|
||||
{
|
||||
MOZ_ASSERT(fn->isKind(PNK_FUNCTION));
|
||||
ParseNode* argsBody = fn->pn_body;
|
||||
ListNode* argsBody = &fn->pn_body->as<ListNode>();
|
||||
MOZ_ASSERT(argsBody->isKind(PNK_PARAMSBODY));
|
||||
*numFormals = argsBody->pn_count;
|
||||
*numFormals = argsBody->count();
|
||||
if (*numFormals > 0 &&
|
||||
argsBody->last()->isKind(PNK_LEXICALSCOPE) &&
|
||||
argsBody->last()->scopeBody()->isKind(PNK_STATEMENTLIST))
|
||||
{
|
||||
(*numFormals)--;
|
||||
}
|
||||
MOZ_ASSERT(argsBody->isArity(PN_LIST));
|
||||
return argsBody->pn_head;
|
||||
return argsBody->head();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -969,7 +969,7 @@ MarkParser(JSTracer* trc, AutoGCRooter* parser)
|
|||
* Parse a top-level JS script.
|
||||
*/
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::ListNodeType
|
||||
Parser<ParseHandler>::parse()
|
||||
{
|
||||
MOZ_ASSERT(checkOptionsCalled);
|
||||
|
|
@ -985,8 +985,8 @@ Parser<ParseHandler>::parse()
|
|||
if (!varScope.init(pc))
|
||||
return null();
|
||||
|
||||
Node pn = statementList(YieldIsName);
|
||||
if (!pn)
|
||||
ListNodeType stmtList = statementList(YieldIsName);
|
||||
if (!stmtList)
|
||||
return null();
|
||||
|
||||
TokenKind tt;
|
||||
|
|
@ -997,11 +997,14 @@ Parser<ParseHandler>::parse()
|
|||
return null();
|
||||
}
|
||||
if (foldConstants) {
|
||||
if (!FoldConstants(context, &pn, this))
|
||||
Node node = stmtList;
|
||||
if (!FoldConstants(context, &node, this)) {
|
||||
return null();
|
||||
}
|
||||
stmtList = handler.asList(node);
|
||||
}
|
||||
|
||||
return pn;
|
||||
return stmtList;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2179,7 +2182,7 @@ Parser<FullParseHandler>::evalBody(EvalSharedContext* evalsc)
|
|||
}
|
||||
|
||||
template <>
|
||||
ParseNode*
|
||||
ListNode*
|
||||
Parser<FullParseHandler>::globalBody(GlobalSharedContext* globalsc)
|
||||
{
|
||||
ParseContext globalpc(this, globalsc, /* newDirectives = */ nullptr);
|
||||
|
|
@ -2190,15 +2193,18 @@ Parser<FullParseHandler>::globalBody(GlobalSharedContext* globalsc)
|
|||
if (!varScope.init(pc))
|
||||
return nullptr;
|
||||
|
||||
ParseNode* body = statementList(YieldIsName);
|
||||
ListNode* body = statementList(YieldIsName);
|
||||
if (!body)
|
||||
return nullptr;
|
||||
|
||||
if (!checkStatementsEOF())
|
||||
return nullptr;
|
||||
|
||||
if (!FoldConstants(context, &body, this))
|
||||
return nullptr;
|
||||
ParseNode* node = body;
|
||||
if (!FoldConstants(context, &node, this)) {
|
||||
return null();
|
||||
}
|
||||
body = &node->as<ListNode>();
|
||||
|
||||
Maybe<GlobalScope::Data*> bindings = newGlobalScopeData(pc->varScope());
|
||||
if (!bindings)
|
||||
|
|
@ -2227,12 +2233,13 @@ Parser<FullParseHandler>::moduleBody(ModuleSharedContext* modulesc)
|
|||
return null();
|
||||
|
||||
AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, true);
|
||||
ParseNode* pn = statementList(YieldIsKeyword);
|
||||
if (!pn)
|
||||
ListNode* stmtList = statementList(YieldIsName);
|
||||
if (!stmtList) {
|
||||
return null();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(pn->isKind(PNK_STATEMENTLIST));
|
||||
mn->pn_body = pn;
|
||||
MOZ_ASSERT(stmtList->isKind(PNK_STATEMENTLIST));
|
||||
mn->pn_body = stmtList;
|
||||
|
||||
TokenKind tt;
|
||||
if (!tokenStream.getToken(&tt, TokenStream::Operand))
|
||||
|
|
@ -2264,8 +2271,11 @@ Parser<FullParseHandler>::moduleBody(ModuleSharedContext* modulesc)
|
|||
p->value()->setClosedOver();
|
||||
}
|
||||
|
||||
if (!FoldConstants(context, &pn, this))
|
||||
ParseNode* node = stmtList;
|
||||
if (!FoldConstants(context, &node, this)) {
|
||||
return null();
|
||||
}
|
||||
stmtList = &node->as<ListNode>();
|
||||
|
||||
if (!propagateFreeNamesAndMarkClosedOverBindings(modulepc.varScope()))
|
||||
return null();
|
||||
|
|
@ -2536,7 +2546,7 @@ Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
|
|||
if (!fn)
|
||||
return null();
|
||||
|
||||
ParseNode* argsbody = handler.newList(PNK_PARAMSBODY);
|
||||
ListNodeType argsbody = handler.newList(PNK_PARAMSBODY);
|
||||
if (!argsbody)
|
||||
return null();
|
||||
fn->pn_body = argsbody;
|
||||
|
|
@ -2662,11 +2672,11 @@ Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHan
|
|||
uint32_t startYieldOffset = pc->lastYieldOffset;
|
||||
#endif
|
||||
|
||||
Node pn;
|
||||
Node body;
|
||||
if (type == StatementListBody) {
|
||||
bool inheritedStrict = pc->sc()->strict();
|
||||
pn = statementList(yieldHandling);
|
||||
if (!pn)
|
||||
body = statementList(yieldHandling);
|
||||
if (!body)
|
||||
return null();
|
||||
|
||||
// When we transitioned from non-strict to strict mode, we need to
|
||||
|
|
@ -2687,7 +2697,7 @@ Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHan
|
|||
// Async functions are implemented as star generators, and star
|
||||
// generators are assumed to be statement lists, to prepend initial
|
||||
// `yield`.
|
||||
Node stmtList = null();
|
||||
ListNodeType stmtList = null();
|
||||
if (pc->isAsync()) {
|
||||
stmtList = handler.newStatementList(pos());
|
||||
if (!stmtList)
|
||||
|
|
@ -2698,13 +2708,13 @@ Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHan
|
|||
if (!kid)
|
||||
return null();
|
||||
|
||||
pn = handler.newReturnStatement(kid, handler.getPosition(kid));
|
||||
if (!pn)
|
||||
body = handler.newReturnStatement(kid, handler.getPosition(kid));
|
||||
if (!body)
|
||||
return null();
|
||||
|
||||
if (pc->isAsync()) {
|
||||
handler.addStatementToList(stmtList, pn);
|
||||
pn = stmtList;
|
||||
handler.addStatementToList(stmtList, body);
|
||||
body = stmtList;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2738,7 +2748,7 @@ Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHan
|
|||
Node generator = newDotGeneratorName();
|
||||
if (!generator)
|
||||
return null();
|
||||
if (!handler.prependInitialYield(pn, generator))
|
||||
if (!handler.prependInitialYield(handler.asList(body), generator))
|
||||
return null();
|
||||
}
|
||||
|
||||
|
|
@ -2752,7 +2762,7 @@ Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHan
|
|||
return null();
|
||||
}
|
||||
|
||||
return finishLexicalScope(pc->varScope(), pn);
|
||||
return finishLexicalScope(pc->varScope(), body);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
|
|
@ -3000,7 +3010,7 @@ Parser<ParseHandler>::functionArguments(YieldHandling yieldHandling, FunctionSyn
|
|||
funbox->setStart(tokenStream);
|
||||
}
|
||||
|
||||
Node argsbody = handler.newList(PNK_PARAMSBODY);
|
||||
ListNodeType argsbody = handler.newList(PNK_PARAMSBODY);
|
||||
if (!argsbody)
|
||||
return false;
|
||||
handler.setFunctionFormalParametersAndBody(funcpn, argsbody);
|
||||
|
|
@ -3259,7 +3269,7 @@ Parser<SyntaxParseHandler>::skipLazyInnerFunction(Node pn, uint32_t toStringStar
|
|||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::addExprAndGetNextTemplStrToken(YieldHandling yieldHandling, Node nodeList,
|
||||
Parser<ParseHandler>::addExprAndGetNextTemplStrToken(YieldHandling yieldHandling, ListNodeType nodeList,
|
||||
TokenKind* ttp)
|
||||
{
|
||||
Node pn = expr(InAllowed, yieldHandling, TripledotProhibited);
|
||||
|
|
@ -3280,9 +3290,9 @@ Parser<ParseHandler>::addExprAndGetNextTemplStrToken(YieldHandling yieldHandling
|
|||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::taggedTemplate(YieldHandling yieldHandling, Node tagArgsList, TokenKind tt)
|
||||
Parser<ParseHandler>::taggedTemplate(YieldHandling yieldHandling, ListNodeType tagArgsList, TokenKind tt)
|
||||
{
|
||||
Node callSiteObjNode = handler.newCallSiteObject(pos().begin);
|
||||
CallSiteNodeType callSiteObjNode = handler.newCallSiteObject(pos().begin);
|
||||
if (!callSiteObjNode)
|
||||
return false;
|
||||
handler.addList(tagArgsList, callSiteObjNode);
|
||||
|
|
@ -3301,14 +3311,14 @@ Parser<ParseHandler>::taggedTemplate(YieldHandling yieldHandling, Node tagArgsLi
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::ListNodeType
|
||||
Parser<ParseHandler>::templateLiteral(YieldHandling yieldHandling)
|
||||
{
|
||||
Node pn = noSubstitutionUntaggedTemplate();
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
Node nodeList = handler.newList(PNK_TEMPLATE_STRING_LIST, pn);
|
||||
ListNodeType nodeList = handler.newList(PNK_TEMPLATE_STRING_LIST, pn);
|
||||
if (!nodeList)
|
||||
return null();
|
||||
|
||||
|
|
@ -3543,7 +3553,7 @@ Parser<ParseHandler>::innerFunction(Node pn, ParseContext* outerpc, HandleFuncti
|
|||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::appendToCallSiteObj(Node callSiteObj)
|
||||
Parser<ParseHandler>::appendToCallSiteObj(CallSiteNodeType callSiteObj)
|
||||
{
|
||||
Node cookedNode = noSubstitutionTaggedTemplate();
|
||||
if (!cookedNode)
|
||||
|
|
@ -3914,7 +3924,7 @@ IsEscapeFreeStringLiteral(const TokenPos& pos, JSAtom* str)
|
|||
|
||||
template <>
|
||||
bool
|
||||
Parser<SyntaxParseHandler>::asmJS(Node list)
|
||||
Parser<SyntaxParseHandler>::asmJS(ListNodeType list)
|
||||
{
|
||||
// While asm.js could technically be validated and compiled during syntax
|
||||
// parsing, we have no guarantee that some later JS wouldn't abort the
|
||||
|
|
@ -3928,7 +3938,7 @@ Parser<SyntaxParseHandler>::asmJS(Node list)
|
|||
|
||||
template <>
|
||||
bool
|
||||
Parser<FullParseHandler>::asmJS(Node list)
|
||||
Parser<FullParseHandler>::asmJS(ListNodeType list)
|
||||
{
|
||||
// Disable syntax parsing in anything nested inside the asm.js module.
|
||||
handler.disableSyntaxParser();
|
||||
|
|
@ -3984,7 +3994,7 @@ Parser<FullParseHandler>::asmJS(Node list)
|
|||
*/
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::maybeParseDirective(Node list, Node possibleDirective, bool* cont)
|
||||
Parser<ParseHandler>::maybeParseDirective(ListNodeType list, Node possibleDirective, bool* cont)
|
||||
{
|
||||
TokenPos directivePos;
|
||||
JSAtom* directive = handler.isStringExprStatement(possibleDirective, &directivePos);
|
||||
|
|
@ -4046,13 +4056,13 @@ Parser<ParseHandler>::maybeParseDirective(Node list, Node possibleDirective, boo
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::ListNodeType
|
||||
Parser<ParseHandler>::statementList(YieldHandling yieldHandling)
|
||||
{
|
||||
JS_CHECK_RECURSION(context, return null());
|
||||
|
||||
Node pn = handler.newStatementList(pos());
|
||||
if (!pn)
|
||||
ListNodeType stmtList = handler.newStatementList(pos());
|
||||
if (!stmtList)
|
||||
return null();
|
||||
|
||||
bool canHaveDirectives = pc->atBodyLevel();
|
||||
|
|
@ -4094,14 +4104,14 @@ Parser<ParseHandler>::statementList(YieldHandling yieldHandling)
|
|||
}
|
||||
|
||||
if (canHaveDirectives) {
|
||||
if (!maybeParseDirective(pn, next, &canHaveDirectives))
|
||||
if (!maybeParseDirective(stmtList, next, &canHaveDirectives))
|
||||
return null();
|
||||
}
|
||||
|
||||
handler.addStatementToList(pn, next);
|
||||
handler.addStatementToList(stmtList, next);
|
||||
}
|
||||
|
||||
return pn;
|
||||
return stmtList;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
|
|
@ -4357,7 +4367,7 @@ Parser<ParseHandler>::bindingIdentifierOrPattern(DeclarationKind kind, YieldHand
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::ListNodeType
|
||||
Parser<ParseHandler>::objectBindingPattern(DeclarationKind kind, YieldHandling yieldHandling)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
|
||||
|
|
@ -4365,7 +4375,7 @@ Parser<ParseHandler>::objectBindingPattern(DeclarationKind kind, YieldHandling y
|
|||
JS_CHECK_RECURSION(context, return null());
|
||||
|
||||
uint32_t begin = pos().begin;
|
||||
Node literal = handler.newObjectLiteral(begin);
|
||||
ListNodeType literal = handler.newObjectLiteral(begin);
|
||||
if (!literal)
|
||||
return null();
|
||||
|
||||
|
|
@ -4477,7 +4487,7 @@ Parser<ParseHandler>::objectBindingPattern(DeclarationKind kind, YieldHandling y
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::ListNodeType
|
||||
Parser<ParseHandler>::arrayBindingPattern(DeclarationKind kind, YieldHandling yieldHandling)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LB));
|
||||
|
|
@ -4485,7 +4495,7 @@ Parser<ParseHandler>::arrayBindingPattern(DeclarationKind kind, YieldHandling yi
|
|||
JS_CHECK_RECURSION(context, return null());
|
||||
|
||||
uint32_t begin = pos().begin;
|
||||
Node literal = handler.newArrayLiteral(begin);
|
||||
ListNodeType literal = handler.newArrayLiteral(begin);
|
||||
if (!literal)
|
||||
return null();
|
||||
|
||||
|
|
@ -4611,7 +4621,7 @@ Parser<ParseHandler>::blockStatement(YieldHandling yieldHandling, unsigned error
|
|||
if (!scope.init(pc))
|
||||
return null();
|
||||
|
||||
Node list = statementList(yieldHandling);
|
||||
ListNodeType list = statementList(yieldHandling);
|
||||
if (!list)
|
||||
return null();
|
||||
|
||||
|
|
@ -4871,7 +4881,7 @@ Parser<ParseHandler>::declarationName(Node decl, DeclarationKind declKind, Token
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::ListNodeType
|
||||
Parser<ParseHandler>::declarationList(YieldHandling yieldHandling,
|
||||
ParseNodeKind kind,
|
||||
ParseNodeKind* forHeadKind /* = nullptr */,
|
||||
|
|
@ -4898,7 +4908,7 @@ Parser<ParseHandler>::declarationList(YieldHandling yieldHandling,
|
|||
MOZ_CRASH("Unknown declaration kind");
|
||||
}
|
||||
|
||||
Node decl = handler.newDeclarationList(kind, op);
|
||||
ListNodeType decl = handler.newDeclarationList(kind, op);
|
||||
if (!decl)
|
||||
return null();
|
||||
|
||||
|
|
@ -4935,7 +4945,7 @@ Parser<ParseHandler>::declarationList(YieldHandling yieldHandling,
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::ListNodeType
|
||||
Parser<ParseHandler>::lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind)
|
||||
{
|
||||
MOZ_ASSERT(kind == DeclarationKind::Const || kind == DeclarationKind::Let);
|
||||
|
|
@ -4951,8 +4961,8 @@ Parser<ParseHandler>::lexicalDeclaration(YieldHandling yieldHandling, Declaratio
|
|||
*
|
||||
* See 8.1.1.1.6 and the note in 13.2.1.
|
||||
*/
|
||||
Node decl = declarationList(yieldHandling,
|
||||
kind == DeclarationKind::Const ? PNK_CONST : PNK_LET);
|
||||
ListNodeType decl = declarationList(yieldHandling,
|
||||
kind == DeclarationKind::Const ? PNK_CONST : PNK_LET);
|
||||
if (!decl || !matchOrInsertSemicolonAfterExpression())
|
||||
return null();
|
||||
|
||||
|
|
@ -4961,7 +4971,7 @@ Parser<ParseHandler>::lexicalDeclaration(YieldHandling yieldHandling, Declaratio
|
|||
|
||||
template <>
|
||||
bool
|
||||
Parser<FullParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet)
|
||||
Parser<FullParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, ListNodeType importSpecSet)
|
||||
{
|
||||
if (tt == TOK_LC) {
|
||||
while (true) {
|
||||
|
|
@ -5092,7 +5102,7 @@ Parser<FullParseHandler>::importDeclaration()
|
|||
if (!tokenStream.getToken(&tt))
|
||||
return null();
|
||||
|
||||
Node importSpecSet = handler.newList(PNK_IMPORT_SPEC_LIST);
|
||||
ListNodeType importSpecSet = handler.newList(PNK_IMPORT_SPEC_LIST);
|
||||
if (!importSpecSet)
|
||||
return null();
|
||||
|
||||
|
|
@ -5204,12 +5214,11 @@ Parser<SyntaxParseHandler>::checkExportedName(JSAtom* exportName)
|
|||
|
||||
template<>
|
||||
bool
|
||||
Parser<FullParseHandler>::checkExportedNamesForArrayBinding(ParseNode* pn)
|
||||
Parser<FullParseHandler>::checkExportedNamesForArrayBinding(ListNode* array)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_ARRAY));
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(array->isKind(PNK_ARRAY));
|
||||
|
||||
for (ParseNode* node = pn->pn_head; node; node = node->pn_next) {
|
||||
for (ParseNode* node : array->contents()) {
|
||||
if (node->isKind(PNK_ELISION))
|
||||
continue;
|
||||
|
||||
|
|
@ -5230,7 +5239,7 @@ Parser<FullParseHandler>::checkExportedNamesForArrayBinding(ParseNode* pn)
|
|||
|
||||
template<>
|
||||
inline bool
|
||||
Parser<SyntaxParseHandler>::checkExportedNamesForArrayBinding(Node node)
|
||||
Parser<SyntaxParseHandler>::checkExportedNamesForArrayBinding(ListNodeType array)
|
||||
{
|
||||
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return false;
|
||||
|
|
@ -5238,12 +5247,11 @@ Parser<SyntaxParseHandler>::checkExportedNamesForArrayBinding(Node node)
|
|||
|
||||
template<>
|
||||
bool
|
||||
Parser<FullParseHandler>::checkExportedNamesForObjectBinding(ParseNode* pn)
|
||||
Parser<FullParseHandler>::checkExportedNamesForObjectBinding(ListNode* obj)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(obj->isKind(PNK_OBJECT));
|
||||
|
||||
for (ParseNode* node = pn->pn_head; node; node = node->pn_next) {
|
||||
for (ParseNode* node : obj->contents()) {
|
||||
MOZ_ASSERT(node->isKind(PNK_MUTATEPROTO) ||
|
||||
node->isKind(PNK_COLON) ||
|
||||
node->isKind(PNK_SHORTHAND) ||
|
||||
|
|
@ -5271,7 +5279,7 @@ Parser<FullParseHandler>::checkExportedNamesForObjectBinding(ParseNode* pn)
|
|||
|
||||
template<>
|
||||
inline bool
|
||||
Parser<SyntaxParseHandler>::checkExportedNamesForObjectBinding(Node node)
|
||||
Parser<SyntaxParseHandler>::checkExportedNamesForObjectBinding(ListNodeType obj)
|
||||
{
|
||||
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return false;
|
||||
|
|
@ -5285,11 +5293,11 @@ Parser<FullParseHandler>::checkExportedNamesForDeclaration(ParseNode* node)
|
|||
if (!checkExportedName(node->pn_atom))
|
||||
return false;
|
||||
} else if (node->isKind(PNK_ARRAY)) {
|
||||
if (!checkExportedNamesForArrayBinding(node))
|
||||
if (!checkExportedNamesForArrayBinding(&node->as<ListNode>()))
|
||||
return false;
|
||||
} else {
|
||||
MOZ_ASSERT(node->isKind(PNK_OBJECT));
|
||||
if (!checkExportedNamesForObjectBinding(node))
|
||||
if (!checkExportedNamesForObjectBinding(&node->as<ListNode>()))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -5306,10 +5314,9 @@ Parser<SyntaxParseHandler>::checkExportedNamesForDeclaration(Node node)
|
|||
|
||||
template<>
|
||||
bool
|
||||
Parser<FullParseHandler>::checkExportedNamesForDeclarationList(ParseNode* node)
|
||||
Parser<FullParseHandler>::checkExportedNamesForDeclarationList(ListNode* node)
|
||||
{
|
||||
MOZ_ASSERT(node->isArity(PN_LIST));
|
||||
for (ParseNode* binding = node->pn_head; binding; binding = binding->pn_next) {
|
||||
for (ParseNode* binding : node->contents()) {
|
||||
if (binding->isKind(PNK_ASSIGN))
|
||||
binding = binding->pn_left;
|
||||
else
|
||||
|
|
@ -5324,7 +5331,7 @@ Parser<FullParseHandler>::checkExportedNamesForDeclarationList(ParseNode* node)
|
|||
|
||||
template<>
|
||||
bool
|
||||
Parser<SyntaxParseHandler>::checkExportedNamesForDeclarationList(Node node)
|
||||
Parser<SyntaxParseHandler>::checkExportedNamesForDeclarationList(ListNodeType node)
|
||||
{
|
||||
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return false;
|
||||
|
|
@ -5447,7 +5454,7 @@ Parser<ParseHandler>::exportBatch(uint32_t begin)
|
|||
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_MUL));
|
||||
|
||||
Node kid = handler.newList(PNK_EXPORT_SPEC_LIST);
|
||||
ListNodeType kid = handler.newList(PNK_EXPORT_SPEC_LIST);
|
||||
if (!kid)
|
||||
return null();
|
||||
|
||||
|
|
@ -5466,10 +5473,10 @@ Parser<ParseHandler>::exportBatch(uint32_t begin)
|
|||
|
||||
template<>
|
||||
bool
|
||||
Parser<FullParseHandler>::checkLocalExportNames(ParseNode* node)
|
||||
Parser<FullParseHandler>::checkLocalExportNames(ListNode* node)
|
||||
{
|
||||
// ES 2017 draft 15.2.3.1.
|
||||
for (ParseNode* next = node->pn_head; next; next = next->pn_next) {
|
||||
for (ParseNode* next : node->contents()) {
|
||||
ParseNode* name = next->pn_left;
|
||||
MOZ_ASSERT(name->isKind(PNK_NAME));
|
||||
|
||||
|
|
@ -5483,7 +5490,7 @@ Parser<FullParseHandler>::checkLocalExportNames(ParseNode* node)
|
|||
|
||||
template<>
|
||||
bool
|
||||
Parser<SyntaxParseHandler>::checkLocalExportNames(Node node)
|
||||
Parser<SyntaxParseHandler>::checkLocalExportNames(ListNodeType node)
|
||||
{
|
||||
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return false;
|
||||
|
|
@ -5498,7 +5505,7 @@ Parser<ParseHandler>::exportClause(uint32_t begin)
|
|||
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
|
||||
|
||||
Node kid = handler.newList(PNK_EXPORT_SPEC_LIST);
|
||||
ListNodeType kid = handler.newList(PNK_EXPORT_SPEC_LIST);
|
||||
if (!kid)
|
||||
return null();
|
||||
|
||||
|
|
@ -5598,7 +5605,7 @@ Parser<ParseHandler>::exportVariableStatement(uint32_t begin)
|
|||
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_VAR));
|
||||
|
||||
Node kid = declarationList(YieldIsName, PNK_VAR);
|
||||
ListNodeType kid = declarationList(YieldIsName, PNK_VAR);
|
||||
if (!kid)
|
||||
return null();
|
||||
if (!matchOrInsertSemicolonAfterExpression())
|
||||
|
|
@ -5679,7 +5686,7 @@ Parser<ParseHandler>::exportLexicalDeclaration(uint32_t begin, DeclarationKind k
|
|||
MOZ_ASSERT_IF(kind == DeclarationKind::Const, tokenStream.isCurrentTokenType(TOK_CONST));
|
||||
MOZ_ASSERT_IF(kind == DeclarationKind::Let, tokenStream.isCurrentTokenType(TOK_LET));
|
||||
|
||||
Node kid = lexicalDeclaration(YieldIsName, kind);
|
||||
ListNodeType kid = lexicalDeclaration(YieldIsName, kind);
|
||||
if (!kid)
|
||||
return null();
|
||||
if (!checkExportedNamesForDeclarationList(kid))
|
||||
|
|
@ -5947,7 +5954,7 @@ Parser<ParseHandler>::consequentOrAlternative(YieldHandling yieldHandling)
|
|||
if (!fun)
|
||||
return null();
|
||||
|
||||
Node block = handler.newStatementList(funcPos);
|
||||
ListNodeType block = handler.newStatementList(funcPos);
|
||||
if (!block)
|
||||
return null();
|
||||
|
||||
|
|
@ -6436,7 +6443,7 @@ Parser<ParseHandler>::switchStatement(YieldHandling yieldHandling)
|
|||
if (!scope.init(pc))
|
||||
return null();
|
||||
|
||||
Node caseList = handler.newStatementList(pos());
|
||||
ListNodeType caseList = handler.newStatementList(pos());
|
||||
if (!caseList)
|
||||
return null();
|
||||
|
||||
|
|
@ -6473,7 +6480,7 @@ Parser<ParseHandler>::switchStatement(YieldHandling yieldHandling)
|
|||
|
||||
MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE);
|
||||
|
||||
Node body = handler.newStatementList(pos());
|
||||
ListNodeType body = handler.newStatementList(pos());
|
||||
if (!body)
|
||||
return null();
|
||||
|
||||
|
|
@ -6513,13 +6520,13 @@ Parser<ParseHandler>::switchStatement(YieldHandling yieldHandling)
|
|||
handler.addCaseStatementToList(caseList, casepn);
|
||||
}
|
||||
|
||||
caseList = finishLexicalScope(scope, caseList);
|
||||
if (!caseList)
|
||||
Node lexicalForCaseList = finishLexicalScope(scope, caseList);
|
||||
if (!lexicalForCaseList)
|
||||
return null();
|
||||
|
||||
handler.setEndPosition(caseList, pos().end);
|
||||
handler.setEndPosition(lexicalForCaseList, pos().end);
|
||||
|
||||
return handler.newSwitchStatement(begin, discriminant, caseList, seenDefault);
|
||||
return handler.newSwitchStatement(begin, discriminant, lexicalForCaseList, seenDefault);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
|
|
@ -6989,7 +6996,7 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
|||
}
|
||||
|
||||
bool hasUnconditionalCatch = false;
|
||||
Node catchList = null();
|
||||
ListNodeType catchList = null();
|
||||
TokenKind tt;
|
||||
if (!tokenStream.getToken(&tt))
|
||||
return null();
|
||||
|
|
@ -7158,7 +7165,7 @@ Parser<ParseHandler>::catchBlockStatement(YieldHandling yieldHandling,
|
|||
if (!scope.addCatchParameters(pc, catchParamScope))
|
||||
return null();
|
||||
|
||||
Node list = statementList(yieldHandling);
|
||||
ListNodeType list = statementList(yieldHandling);
|
||||
if (!list)
|
||||
return null();
|
||||
|
||||
|
|
@ -7281,7 +7288,7 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling,
|
|||
|
||||
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_CLASS);
|
||||
|
||||
Node classMethods = handler.newClassMethodList(pos().begin);
|
||||
ListNodeType classMethods = handler.newClassMethodList(pos().begin);
|
||||
if (!classMethods)
|
||||
return null();
|
||||
|
||||
|
|
@ -7494,7 +7501,7 @@ template <typename ParseHandler>
|
|||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::variableStatement(YieldHandling yieldHandling)
|
||||
{
|
||||
Node vars = declarationList(yieldHandling, PNK_VAR);
|
||||
ListNodeType vars = declarationList(yieldHandling, PNK_VAR);
|
||||
if (!vars)
|
||||
return null();
|
||||
if (!matchOrInsertSemicolonAfterExpression())
|
||||
|
|
@ -7909,7 +7916,7 @@ Parser<ParseHandler>::expr(InHandling inHandling, YieldHandling yieldHandling,
|
|||
if (!matched)
|
||||
return pn;
|
||||
|
||||
Node seq = handler.newCommaExpressionList(pn);
|
||||
ListNodeType seq = handler.newCommaExpressionList(pn);
|
||||
if (!seq)
|
||||
return null();
|
||||
while (true) {
|
||||
|
|
@ -8815,7 +8822,7 @@ Parser<ParseHandler>::generatorComprehensionLambda(unsigned begin)
|
|||
if (!declareDotGeneratorName())
|
||||
return null();
|
||||
|
||||
Node body = handler.newStatementList(TokenPos(begin, pos().end));
|
||||
ListNodeType body = handler.newStatementList(TokenPos(begin, pos().end));
|
||||
if (!body)
|
||||
return null();
|
||||
|
||||
|
|
@ -9014,7 +9021,7 @@ Parser<ParseHandler>::comprehension(GeneratorKind comprehensionKind)
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::ListNodeType
|
||||
Parser<ParseHandler>::arrayComprehension(uint32_t begin)
|
||||
{
|
||||
Node inner = comprehension(NotGenerator);
|
||||
|
|
@ -9023,7 +9030,7 @@ Parser<ParseHandler>::arrayComprehension(uint32_t begin)
|
|||
|
||||
MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_ARRAY_COMPREHENSION);
|
||||
|
||||
Node comp = handler.newList(PNK_ARRAYCOMP, inner);
|
||||
ListNodeType comp = handler.newList(PNK_ARRAYCOMP, inner);
|
||||
if (!comp)
|
||||
return null();
|
||||
|
||||
|
|
@ -9086,11 +9093,11 @@ Parser<ParseHandler>::assignExprWithoutYieldOrAwait(YieldHandling yieldHandling)
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::ListNodeType
|
||||
Parser<ParseHandler>::argumentList(YieldHandling yieldHandling, bool* isSpread,
|
||||
PossibleError* possibleError /* = nullptr */)
|
||||
{
|
||||
Node argsList = handler.newArguments(pos());
|
||||
ListNodeType argsList = handler.newArguments(pos());
|
||||
if (!argsList)
|
||||
return null();
|
||||
|
||||
|
|
@ -9473,7 +9480,7 @@ Parser<ParseHandler>::memberCall(
|
|||
if (!nextMember)
|
||||
return null();
|
||||
} else {
|
||||
Node args = handler.newArguments(pos());
|
||||
ListNodeType args = handler.newArguments(pos());
|
||||
if (!args)
|
||||
return null();
|
||||
|
||||
|
|
@ -9752,13 +9759,13 @@ Parser<ParseHandler>::checkDestructuringAssignmentElement(Node expr, TokenPos ex
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::ListNodeType
|
||||
Parser<ParseHandler>::arrayInitializer(YieldHandling yieldHandling, PossibleError* possibleError)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LB));
|
||||
|
||||
uint32_t begin = pos().begin;
|
||||
Node literal = handler.newArrayLiteral(begin);
|
||||
ListNodeType literal = handler.newArrayLiteral(begin);
|
||||
if (!literal)
|
||||
return null();
|
||||
|
||||
|
|
@ -9775,7 +9782,7 @@ Parser<ParseHandler>::arrayInitializer(YieldHandling yieldHandling, PossibleErro
|
|||
* Mark empty arrays as non-constant, since we cannot easily
|
||||
* determine their type.
|
||||
*/
|
||||
handler.setListFlag(literal, PNX_NONCONST);
|
||||
handler.setListHasNonConstInitializer(literal);
|
||||
} else {
|
||||
tokenStream.ungetToken();
|
||||
|
||||
|
|
@ -9861,7 +9868,7 @@ DoubleToAtom(ExclusiveContext* cx, double value)
|
|||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::propertyName(YieldHandling yieldHandling,
|
||||
const Maybe<DeclarationKind>& maybeDecl, Node propList,
|
||||
const Maybe<DeclarationKind>& maybeDecl, ListNodeType propList,
|
||||
PropertyType* propType, MutableHandleAtom propAtom)
|
||||
{
|
||||
TokenKind ltok;
|
||||
|
|
@ -10054,7 +10061,7 @@ template <typename ParseHandler>
|
|||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::computedPropertyName(YieldHandling yieldHandling,
|
||||
const Maybe<DeclarationKind>& maybeDecl,
|
||||
Node literal)
|
||||
ListNodeType literal)
|
||||
{
|
||||
uint32_t begin = pos().begin;
|
||||
|
||||
|
|
@ -10062,7 +10069,7 @@ Parser<ParseHandler>::computedPropertyName(YieldHandling yieldHandling,
|
|||
if (*maybeDecl == DeclarationKind::FormalParameter)
|
||||
pc->functionBox()->hasParameterExprs = true;
|
||||
} else {
|
||||
handler.setListFlag(literal, PNX_NONCONST);
|
||||
handler.setListHasNonConstInitializer(literal);
|
||||
}
|
||||
|
||||
Node assignNode = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
|
||||
|
|
@ -10074,14 +10081,14 @@ Parser<ParseHandler>::computedPropertyName(YieldHandling yieldHandling,
|
|||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
typename ParseHandler::ListNodeType
|
||||
Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
|
||||
|
||||
uint32_t openedPos = pos().begin;
|
||||
|
||||
Node literal = handler.newObjectLiteral(pos().begin);
|
||||
ListNodeType literal = handler.newObjectLiteral(pos().begin);
|
||||
if (!literal)
|
||||
return null();
|
||||
|
||||
|
|
@ -10164,7 +10171,7 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
|
|||
return null();
|
||||
} else {
|
||||
if (!handler.isConstant(propExpr))
|
||||
handler.setListFlag(literal, PNX_NONCONST);
|
||||
handler.setListHasNonConstInitializer(literal);
|
||||
|
||||
if (!handler.addPropertyDefinition(literal, propName, propExpr))
|
||||
return null();
|
||||
|
|
|
|||
|
|
@ -903,6 +903,11 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
private:
|
||||
using Node = typename ParseHandler::Node;
|
||||
|
||||
#define DECLARE_TYPE(typeName, longTypeName, asMethodName) \
|
||||
using longTypeName = typename ParseHandler::longTypeName;
|
||||
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
||||
#undef DECLARE_TYPE
|
||||
|
||||
/*
|
||||
* A class for temporarily stashing errors while parsing continues.
|
||||
*
|
||||
|
|
@ -1073,7 +1078,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
/*
|
||||
* Parse a top-level JS script.
|
||||
*/
|
||||
Node parse();
|
||||
ListNodeType parse();
|
||||
|
||||
/*
|
||||
* Allocate a new parsed object or function container from
|
||||
|
|
@ -1103,10 +1108,10 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
Node stringLiteral();
|
||||
Node noSubstitutionTaggedTemplate();
|
||||
Node noSubstitutionUntaggedTemplate();
|
||||
Node templateLiteral(YieldHandling yieldHandling);
|
||||
bool taggedTemplate(YieldHandling yieldHandling, Node nodeList, TokenKind tt);
|
||||
bool appendToCallSiteObj(Node callSiteObj);
|
||||
bool addExprAndGetNextTemplStrToken(YieldHandling yieldHandling, Node nodeList,
|
||||
ListNodeType templateLiteral(YieldHandling yieldHandling);
|
||||
bool taggedTemplate(YieldHandling yieldHandling, ListNodeType tagArgsList, TokenKind tt);
|
||||
bool appendToCallSiteObj(CallSiteNodeType callSiteObj);
|
||||
bool addExprAndGetNextTemplStrToken(YieldHandling yieldHandling, ListNodeType nodeList,
|
||||
TokenKind* ttp);
|
||||
bool checkStatementsEOF();
|
||||
|
||||
|
|
@ -1120,7 +1125,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
Node statement(YieldHandling yieldHandling);
|
||||
Node statementListItem(YieldHandling yieldHandling, bool canHaveDirectives = false);
|
||||
|
||||
bool maybeParseDirective(Node list, Node pn, bool* cont);
|
||||
bool maybeParseDirective(ListNodeType list, Node pn, bool* cont);
|
||||
|
||||
// Parse the body of an eval.
|
||||
//
|
||||
|
|
@ -1130,7 +1135,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
Node evalBody(EvalSharedContext* evalsc);
|
||||
|
||||
// Parse the body of a global script.
|
||||
Node globalBody(GlobalSharedContext* globalsc);
|
||||
ListNodeType globalBody(GlobalSharedContext* globalsc);
|
||||
|
||||
// Parse a module.
|
||||
Node moduleBody(ModuleSharedContext* modulesc);
|
||||
|
|
@ -1189,7 +1194,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
Node functionExpr(uint32_t toStringStart, InvokedPrediction invoked = PredictUninvoked,
|
||||
FunctionAsyncKind asyncKind = SyncFunction);
|
||||
|
||||
Node statementList(YieldHandling yieldHandling);
|
||||
ListNodeType statementList(YieldHandling yieldHandling);
|
||||
|
||||
Node blockStatement(YieldHandling yieldHandling,
|
||||
unsigned errorNumber = JSMSG_CURLY_IN_COMPOUND);
|
||||
|
|
@ -1228,7 +1233,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
// continues a LexicalDeclaration.
|
||||
bool nextTokenContinuesLetDeclaration(TokenKind next, YieldHandling yieldHandling);
|
||||
|
||||
Node lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind);
|
||||
ListNodeType lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind);
|
||||
|
||||
Node importDeclaration();
|
||||
|
||||
|
|
@ -1237,7 +1242,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
|
||||
Node exportFrom(uint32_t begin, Node specList);
|
||||
Node exportBatch(uint32_t begin);
|
||||
bool checkLocalExportNames(Node node);
|
||||
bool checkLocalExportNames(ListNodeType node);
|
||||
Node exportClause(uint32_t begin);
|
||||
Node exportFunctionDeclaration(uint32_t begin);
|
||||
Node exportVariableStatement(uint32_t begin);
|
||||
|
|
@ -1273,10 +1278,10 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
// Otherwise, for for-in/of loops, the next token is the ')' ending the
|
||||
// loop-head. Additionally, the expression that the loop iterates over was
|
||||
// parsed into |*forInOrOfExpression|.
|
||||
Node declarationList(YieldHandling yieldHandling,
|
||||
ParseNodeKind kind,
|
||||
ParseNodeKind* forHeadKind = nullptr,
|
||||
Node* forInOrOfExpression = nullptr);
|
||||
ListNodeType declarationList(YieldHandling yieldHandling,
|
||||
ParseNodeKind kind,
|
||||
ParseNodeKind* forHeadKind = nullptr,
|
||||
Node* forInOrOfExpression = nullptr);
|
||||
|
||||
// The items in a declaration list are either patterns or names, with or
|
||||
// without initializers. These two methods parse a single pattern/name and
|
||||
|
|
@ -1371,22 +1376,22 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
Node comprehensionIf(GeneratorKind comprehensionKind);
|
||||
Node comprehensionTail(GeneratorKind comprehensionKind);
|
||||
Node comprehension(GeneratorKind comprehensionKind);
|
||||
Node arrayComprehension(uint32_t begin);
|
||||
ListNodeType arrayComprehension(uint32_t begin);
|
||||
Node generatorComprehension(uint32_t begin);
|
||||
|
||||
Node argumentList(YieldHandling yieldHandling, bool* isSpread,
|
||||
PossibleError* possibleError = nullptr);
|
||||
ListNodeType argumentList(YieldHandling yieldHandling, bool* isSpread,
|
||||
PossibleError* possibleError = nullptr);
|
||||
Node destructuringDeclaration(DeclarationKind kind, YieldHandling yieldHandling,
|
||||
TokenKind tt);
|
||||
Node destructuringDeclarationWithoutYieldOrAwait(DeclarationKind kind, YieldHandling yieldHandling,
|
||||
TokenKind tt);
|
||||
|
||||
bool namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet);
|
||||
bool namedImportsOrNamespaceImport(TokenKind tt, ListNodeType importSpecSet);
|
||||
bool checkExportedName(JSAtom* exportName);
|
||||
bool checkExportedNamesForArrayBinding(Node node);
|
||||
bool checkExportedNamesForObjectBinding(Node node);
|
||||
bool checkExportedNamesForArrayBinding(ListNodeType array);
|
||||
bool checkExportedNamesForObjectBinding(ListNodeType obj);
|
||||
bool checkExportedNamesForDeclaration(Node node);
|
||||
bool checkExportedNamesForDeclarationList(Node node);
|
||||
bool checkExportedNamesForDeclarationList(ListNodeType node);
|
||||
|
||||
bool checkExportedNameForClause(Node node);
|
||||
bool checkExportedNameForFunction(Node node);
|
||||
|
|
@ -1512,21 +1517,21 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
Node finishLexicalScope(ParseContext::Scope& scope, Node body);
|
||||
|
||||
Node propertyName(YieldHandling yieldHandling,
|
||||
const mozilla::Maybe<DeclarationKind>& maybeDecl, Node propList,
|
||||
const mozilla::Maybe<DeclarationKind>& maybeDecl, ListNodeType propList,
|
||||
PropertyType* propType, MutableHandleAtom propAtom);
|
||||
Node computedPropertyName(YieldHandling yieldHandling,
|
||||
const mozilla::Maybe<DeclarationKind>& maybeDecl, Node literal);
|
||||
Node arrayInitializer(YieldHandling yieldHandling, PossibleError* possibleError);
|
||||
const mozilla::Maybe<DeclarationKind>& maybeDecl, ListNodeType literal);
|
||||
ListNodeType arrayInitializer(YieldHandling yieldHandling, PossibleError* possibleError);
|
||||
Node newRegExp();
|
||||
|
||||
Node objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError);
|
||||
ListNodeType objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError);
|
||||
|
||||
Node bindingInitializer(Node lhs, DeclarationKind kind, YieldHandling yieldHandling);
|
||||
Node bindingIdentifier(DeclarationKind kind, YieldHandling yieldHandling);
|
||||
Node bindingIdentifierOrPattern(DeclarationKind kind, YieldHandling yieldHandling,
|
||||
TokenKind tt);
|
||||
Node objectBindingPattern(DeclarationKind kind, YieldHandling yieldHandling);
|
||||
Node arrayBindingPattern(DeclarationKind kind, YieldHandling yieldHandling);
|
||||
ListNodeType objectBindingPattern(DeclarationKind kind, YieldHandling yieldHandling);
|
||||
ListNodeType arrayBindingPattern(DeclarationKind kind, YieldHandling yieldHandling);
|
||||
|
||||
void checkDestructuringAssignmentTarget(Node expr, TokenPos exprPos,
|
||||
PossibleError* possibleError);
|
||||
|
|
@ -1537,11 +1542,11 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
return handler.newNumber(tok.number(), tok.decimalPoint(), tok.pos);
|
||||
}
|
||||
|
||||
static Node null() { return ParseHandler::null(); }
|
||||
static typename ParseHandler::NullNode null() { return ParseHandler::null(); }
|
||||
|
||||
JSAtom* prefixAccessorName(PropertyType propType, HandleAtom propAtom);
|
||||
|
||||
bool asmJS(Node list);
|
||||
bool asmJS(ListNodeType list);
|
||||
|
||||
enum class OptionalKind {
|
||||
NonOptional = 0,
|
||||
|
|
|
|||
|
|
@ -145,6 +145,13 @@ class SyntaxParseHandler
|
|||
NodeSuperBase
|
||||
};
|
||||
|
||||
#define DECLARE_TYPE(typeName, longTypeName, asMethodName) \
|
||||
using longTypeName = Node;
|
||||
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
||||
#undef DECLARE_TYPE
|
||||
|
||||
using NullNode = Node;
|
||||
|
||||
bool isPropertyAccess(Node node) {
|
||||
return node == NodeDottedProperty || node == NodeElement;
|
||||
}
|
||||
|
|
@ -183,7 +190,14 @@ class SyntaxParseHandler
|
|||
tokenStream(tokenStream)
|
||||
{}
|
||||
|
||||
static Node null() { return NodeFailure; }
|
||||
static NullNode null() { return NodeFailure; }
|
||||
|
||||
#define DECLARE_AS(typeName, longTypeName, asMethodName) \
|
||||
static longTypeName asMethodName(Node node) { \
|
||||
return node; \
|
||||
}
|
||||
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
||||
#undef DECLARE_AS
|
||||
|
||||
void prepareNodeForMutation(Node node) {}
|
||||
void freeTree(Node node) {}
|
||||
|
|
@ -222,11 +236,11 @@ class SyntaxParseHandler
|
|||
return NodeGeneric;
|
||||
}
|
||||
|
||||
Node newCallSiteObject(uint32_t begin) {
|
||||
CallSiteNodeType newCallSiteObject(uint32_t begin) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
void addToCallSiteObject(Node callSiteObj, Node rawNode, Node cookedNode) {}
|
||||
void addToCallSiteObject(CallSiteNodeType callSiteObj, Node rawNode, Node cookedNode) {}
|
||||
|
||||
Node newThisLiteral(const TokenPos& pos, Node thisName) { return NodeGeneric; }
|
||||
Node newNullLiteral(const TokenPos& pos) { return NodeGeneric; }
|
||||
|
|
@ -283,21 +297,20 @@ class SyntaxParseHandler
|
|||
|
||||
// Expressions
|
||||
|
||||
Node newArrayComprehension(Node body, const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newArrayLiteral(uint32_t begin) { return NodeUnparenthesizedArray; }
|
||||
MOZ_MUST_USE bool addElision(Node literal, const TokenPos& pos) { return true; }
|
||||
MOZ_MUST_USE bool addSpreadElement(Node literal, uint32_t begin, Node inner) { return true; }
|
||||
void addArrayElement(Node literal, Node element) { }
|
||||
ListNodeType newArrayLiteral(uint32_t begin) { return NodeUnparenthesizedArray; }
|
||||
MOZ_MUST_USE bool addElision(ListNodeType literal, const TokenPos& pos) { return true; }
|
||||
MOZ_MUST_USE bool addSpreadElement(ListNodeType literal, uint32_t begin, Node inner) { return true; }
|
||||
void addArrayElement(ListNodeType literal, Node element) { }
|
||||
|
||||
Node newCall(Node callee, Node args) { return NodeFunctionCall; }
|
||||
Node newOptionalCall(Node callee, Node args) { return NodeOptionalFunctionCall; }
|
||||
Node newArguments(const TokenPos& pos) { return NodeGeneric; }
|
||||
ListNodeType newArguments(const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newSuperCall(Node callee, Node args) { return NodeGeneric; }
|
||||
Node newTaggedTemplate(Node callee, Node args) { return NodeGeneric; }
|
||||
Node newGenExp(Node callee, Node args) { return NodeGeneric; }
|
||||
|
||||
Node newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; }
|
||||
Node newClassMethodList(uint32_t begin) { return NodeGeneric; }
|
||||
ListNodeType newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; }
|
||||
ListNodeType newClassMethodList(uint32_t begin) { return NodeGeneric; }
|
||||
Node newClassNames(Node outer, Node inner, const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newClass(Node name, Node heritage, Node methodBlock, const TokenPos& pos) { return NodeGeneric; }
|
||||
|
||||
|
|
@ -305,12 +318,12 @@ class SyntaxParseHandler
|
|||
Node newPosHolder(const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newSuperBase(Node thisName, const TokenPos& pos) { return NodeSuperBase; }
|
||||
|
||||
MOZ_MUST_USE bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
|
||||
MOZ_MUST_USE bool addPropertyDefinition(Node literal, Node name, Node expr) { return true; }
|
||||
MOZ_MUST_USE bool addShorthand(Node literal, Node name, Node expr) { return true; }
|
||||
MOZ_MUST_USE bool addSpreadProperty(Node literal, uint32_t begin, Node inner) { return true; }
|
||||
MOZ_MUST_USE bool addObjectMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
|
||||
MOZ_MUST_USE bool addClassMethodDefinition(Node literal, Node name, Node fn, JSOp op, bool isStatic) { return true; }
|
||||
MOZ_MUST_USE bool addPrototypeMutation(ListNodeType literal, uint32_t begin, Node expr) { return true; }
|
||||
MOZ_MUST_USE bool addPropertyDefinition(ListNodeType literal, Node name, Node expr) { return true; }
|
||||
MOZ_MUST_USE bool addShorthand(ListNodeType literal, Node name, Node expr) { return true; }
|
||||
MOZ_MUST_USE bool addSpreadProperty(ListNodeType literal, uint32_t begin, Node inner) { return true; }
|
||||
MOZ_MUST_USE bool addObjectMethodDefinition(ListNodeType literal, Node name, Node fn, JSOp op) { return true; }
|
||||
MOZ_MUST_USE bool addClassMethodDefinition(ListNodeType literal, Node name, Node fn, JSOp op, bool isStatic) { return true; }
|
||||
Node newYieldExpression(uint32_t begin, Node value) { return NodeGeneric; }
|
||||
Node newYieldStarExpression(uint32_t begin, Node value) { return NodeGeneric; }
|
||||
Node newAwaitExpression(uint32_t begin, Node value) { return NodeGeneric; }
|
||||
|
|
@ -318,10 +331,10 @@ class SyntaxParseHandler
|
|||
|
||||
// Statements
|
||||
|
||||
Node newStatementList(const TokenPos& pos) { return NodeGeneric; }
|
||||
void addStatementToList(Node list, Node stmt) {}
|
||||
void addCaseStatementToList(Node list, Node stmt) {}
|
||||
MOZ_MUST_USE bool prependInitialYield(Node stmtList, Node gen) { return true; }
|
||||
ListNodeType newStatementList(const TokenPos& pos) { return NodeGeneric; }
|
||||
void addStatementToList(ListNodeType list, Node stmt) {}
|
||||
void addCaseStatementToList(ListNodeType list, Node caseClause) {}
|
||||
MOZ_MUST_USE bool prependInitialYield(ListNodeType stmtList, Node genName) { return true; }
|
||||
Node newEmptyStatement(const TokenPos& pos) { return NodeEmptyStatement; }
|
||||
|
||||
Node newExportDeclaration(Node kid, const TokenPos& pos) {
|
||||
|
|
@ -358,7 +371,7 @@ class SyntaxParseHandler
|
|||
}
|
||||
|
||||
Node newThrowStatement(Node expr, const TokenPos& pos) { return NodeThrow; }
|
||||
Node newTryStatement(uint32_t begin, Node body, Node catchList, Node finallyBlock) {
|
||||
Node newTryStatement(uint32_t begin, Node body, ListNodeType catchList, Node finallyBlock) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
Node newDebuggerStatement(const TokenPos& pos) { return NodeGeneric; }
|
||||
|
|
@ -380,7 +393,7 @@ class SyntaxParseHandler
|
|||
|
||||
Node newOptionalPropertyByValue(Node pn, Node kid, uint32_t end) { return NodeOptionalElement; }
|
||||
|
||||
MOZ_MUST_USE bool addCatchBlock(Node catchList, Node letBlock, Node catchName,
|
||||
MOZ_MUST_USE bool addCatchBlock(ListNodeType catchList, Node letBlock, Node catchName,
|
||||
Node catchGuard, Node catchBody) { return true; }
|
||||
|
||||
MOZ_MUST_USE bool setLastFunctionFormalParameterDefault(Node funcpn, Node pn) { return true; }
|
||||
|
|
@ -434,26 +447,26 @@ class SyntaxParseHandler
|
|||
return tokenStream.currentToken().pos;
|
||||
}
|
||||
|
||||
Node newList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
ListNodeType newList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(kind != PNK_VAR);
|
||||
MOZ_ASSERT(kind != PNK_LET);
|
||||
MOZ_ASSERT(kind != PNK_CONST);
|
||||
return NodeGeneric;
|
||||
}
|
||||
Node newList(ParseNodeKind kind, uint32_t begin, JSOp op = JSOP_NOP) {
|
||||
ListNodeType newList(ParseNodeKind kind, uint32_t begin, JSOp op = JSOP_NOP) {
|
||||
return newList(kind, op);
|
||||
}
|
||||
Node newList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
|
||||
ListNodeType newList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
|
||||
return newList(kind, op);
|
||||
}
|
||||
|
||||
Node newDeclarationList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
ListNodeType newDeclarationList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
if (kind == PNK_VAR)
|
||||
return NodeVarDeclaration;
|
||||
MOZ_ASSERT(kind == PNK_LET || kind == PNK_CONST);
|
||||
return NodeLexicalDeclaration;
|
||||
}
|
||||
Node newDeclarationList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
|
||||
ListNodeType newDeclarationList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
|
||||
return newDeclarationList(kind, op);
|
||||
}
|
||||
|
||||
|
|
@ -461,7 +474,7 @@ class SyntaxParseHandler
|
|||
return node == NodeVarDeclaration || node == NodeLexicalDeclaration;
|
||||
}
|
||||
|
||||
Node singleBindingFromDeclaration(Node decl) {
|
||||
Node singleBindingFromDeclaration(ListNodeType decl) {
|
||||
MOZ_ASSERT(isDeclarationList(decl));
|
||||
|
||||
// This is, unfortunately, very dodgy. Obviously NodeVarDeclaration
|
||||
|
|
@ -485,11 +498,11 @@ class SyntaxParseHandler
|
|||
return newList(PNK_CATCHLIST, JSOP_NOP);
|
||||
}
|
||||
|
||||
Node newCommaExpressionList(Node kid) {
|
||||
ListNodeType newCommaExpressionList(Node kid) {
|
||||
return NodeUnparenthesizedCommaExpr;
|
||||
}
|
||||
|
||||
void addList(Node list, Node kid) {
|
||||
void addList(ListNodeType list, Node kid) {
|
||||
MOZ_ASSERT(list == NodeGeneric ||
|
||||
list == NodeUnparenthesizedArray ||
|
||||
list == NodeUnparenthesizedObject ||
|
||||
|
|
@ -539,7 +552,7 @@ class SyntaxParseHandler
|
|||
}
|
||||
|
||||
void setOp(Node pn, JSOp op) {}
|
||||
void setListFlag(Node pn, unsigned flag) {}
|
||||
void setListHasNonConstInitializer(ListNodeType literal) {}
|
||||
MOZ_MUST_USE Node parenthesize(Node node) {
|
||||
// A number of nodes have different behavior upon parenthesization, but
|
||||
// only in some circumstances. Convert these nodes to special
|
||||
|
|
|
|||
|
|
@ -450,15 +450,13 @@ TernaryKid3(ParseNode* pn)
|
|||
static inline ParseNode*
|
||||
ListHead(ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
return pn->pn_head;
|
||||
return pn->as<ListNode>().head();
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
ListLength(ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
return pn->pn_count;
|
||||
return pn->as<ListNode>().count();
|
||||
}
|
||||
|
||||
static inline ParseNode*
|
||||
|
|
@ -511,8 +509,7 @@ static inline ParseNode*
|
|||
BinaryOpLeft(ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->isBinaryOperation());
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(pn->pn_count == 2);
|
||||
MOZ_ASSERT(pn->as<ListNode>().count() == 2);
|
||||
return ListHead(pn);
|
||||
}
|
||||
|
||||
|
|
@ -520,8 +517,7 @@ static inline ParseNode*
|
|||
BinaryOpRight(ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->isBinaryOperation());
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(pn->pn_count == 2);
|
||||
MOZ_ASSERT(pn->as<ListNode>().count() == 2);
|
||||
return NextNode(ListHead(pn));
|
||||
}
|
||||
|
||||
|
|
@ -688,7 +684,7 @@ static inline ParseNode*
|
|||
FunctionStatementList(ParseNode* fn)
|
||||
{
|
||||
MOZ_ASSERT(fn->pn_body->isKind(PNK_PARAMSBODY));
|
||||
ParseNode* last = fn->pn_body->last();
|
||||
ParseNode* last = fn->pn_body->as<ListNode>().last();
|
||||
MOZ_ASSERT(last->isKind(PNK_LEXICALSCOPE));
|
||||
MOZ_ASSERT(last->isEmptyScope());
|
||||
ParseNode* body = last->scopeBody();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue