From 57a8b65fc0c4bd12149855d972aea05828e4d6e7 Mon Sep 17 00:00:00 2001 From: Gaming4JC Date: Sun, 9 Jun 2019 22:30:59 -0400 Subject: 1339963 - Part 1: Split Parser::exportDeclaration. --- js/src/frontend/Parser.cpp | 659 ++++++++++++++++++++++++----------- js/src/frontend/Parser.h | 23 +- js/src/frontend/SyntaxParseHandler.h | 14 + 3 files changed, 486 insertions(+), 210 deletions(-) (limited to 'js/src') diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index fc4b0e965..16d4a377a 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -4692,8 +4692,10 @@ Parser::declarationList(YieldHandling yieldHandling, template typename ParseHandler::Node -Parser::lexicalDeclaration(YieldHandling yieldHandling, bool isConst) +Parser::lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind) { + MOZ_ASSERT(kind == DeclarationKind::Const || kind == DeclarationKind::Let); + /* * Parse body-level lets without a new block object. ES6 specs * that an execution environment's initial lexical environment @@ -4705,7 +4707,8 @@ Parser::lexicalDeclaration(YieldHandling yieldHandling, bool isCon * * See 8.1.1.1.6 and the note in 13.2.1. */ - Node decl = declarationList(yieldHandling, isConst ? PNK_CONST : PNK_LET); + Node decl = declarationList(yieldHandling, + kind == DeclarationKind::Const ? PNK_CONST : PNK_LET); if (!decl || !matchOrInsertSemicolonAfterExpression()) return null(); @@ -4994,279 +4997,517 @@ Parser::checkExportedNamesForDeclaration(Node node) } template<> -ParseNode* -Parser::exportDeclaration() +bool +Parser::checkExportedNameForClause(ParseNode* node) { - MOZ_ASSERT(tokenStream.currentToken().type == TOK_EXPORT); + return checkExportedName(node->pn_atom); +} - if (!pc->atModuleLevel()) { - error(JSMSG_EXPORT_DECL_AT_TOP_LEVEL); +template<> +bool +Parser::checkExportedNameForClause(Node node) +{ + MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); + return false; +} + +template<> +bool +Parser::checkExportedNameForFunction(ParseNode* node) +{ + return checkExportedName(node->pn_funbox->function()->explicitName()); +} + +template<> +bool +Parser::checkExportedNameForFunction(Node node) +{ + MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); + return false; +} + +template<> +bool +Parser::checkExportedNameForClass(ParseNode* node) +{ + const ClassNode& cls = node->as(); + MOZ_ASSERT(cls.names()); + return checkExportedName(cls.names()->innerBinding()->pn_atom); +} + +template<> +bool +Parser::checkExportedNameForClass(Node node) +{ + MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); + return false; +} + +template<> +bool +Parser::processExport(ParseNode* node) +{ + return pc->sc()->asModuleContext()->builder.processExport(node); +} + +template<> +bool +Parser::processExport(Node node) +{ + MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); + return false; +} + +template<> +bool +Parser::processExportFrom(ParseNode* node) +{ + return pc->sc()->asModuleContext()->builder.processExportFrom(node); +} + +template<> +bool +Parser::processExportFrom(Node node) +{ + MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); + return false; +} + +template +typename ParseHandler::Node +Parser::exportFrom(uint32_t begin, Node specList) +{ + if (!abortIfSyntaxParser()) return null(); - } - uint32_t begin = pos().begin; + MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FROM)); - Node kid; - TokenKind tt; - if (!tokenStream.getToken(&tt)) + if (!abortIfSyntaxParser()) return null(); - switch (tt) { - case TOK_LC: { - kid = handler.newList(PNK_EXPORT_SPEC_LIST); - if (!kid) - return null(); - while (true) { - // Handle the forms |export {}| and |export { ..., }| (where ... - // is non empty), by escaping the loop early if the next token - // is }. - if (!tokenStream.getToken(&tt)) - return null(); + MUST_MATCH_TOKEN(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM); - if (tt == TOK_RC) - break; + Node moduleSpec = stringLiteral(); + if (!moduleSpec) + return null(); - if (!TokenKindIsPossibleIdentifierName(tt)) { - error(JSMSG_NO_BINDING_NAME); - return null(); - } + if (!matchOrInsertSemicolonAfterNonExpression()) + return null(); - Node bindingName = newName(tokenStream.currentName()); - if (!bindingName) - return null(); + Node node = handler.newExportFromDeclaration(begin, specList, moduleSpec); + if (!node) + return null(); - bool foundAs; - if (!tokenStream.matchToken(&foundAs, TOK_AS)) - return null(); - if (foundAs) - MUST_MATCH_TOKEN_FUNC(TokenKindIsPossibleIdentifierName, JSMSG_NO_EXPORT_NAME); + if (!processExportFrom(node)) + return null(); - Node exportName = newName(tokenStream.currentName()); - if (!exportName) - return null(); + return node; +} - if (!checkExportedName(exportName->pn_atom)) - return null(); +template +typename ParseHandler::Node +Parser::exportBatch(uint32_t begin) +{ + if (!abortIfSyntaxParser()) + return null(); - Node exportSpec = handler.newBinary(PNK_EXPORT_SPEC, bindingName, exportName); - if (!exportSpec) - return null(); + MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_MUL)); - handler.addList(kid, exportSpec); + Node kid = handler.newList(PNK_EXPORT_SPEC_LIST); + if (!kid) + return null(); - TokenKind next; - if (!tokenStream.getToken(&next)) - return null(); + // Handle the form |export *| by adding a special export batch + // specifier to the list. + Node exportSpec = handler.newNullary(PNK_EXPORT_BATCH_SPEC, JSOP_NOP, pos()); + if (!exportSpec) + return null(); - if (next == TOK_RC) - break; + handler.addList(kid, exportSpec); - if (next != TOK_COMMA) { - error(JSMSG_RC_AFTER_EXPORT_SPEC_LIST); - return null(); - } - } + TokenKind tt; + if (!tokenStream.getToken(&tt)) + return null(); + if (tt != TOK_FROM) { + error(JSMSG_FROM_AFTER_EXPORT_STAR); + return null(); + } - // Careful! If |from| follows, even on a new line, it must start a - // FromClause: - // - // export { x } - // from "foo"; // a single ExportDeclaration - // - // But if it doesn't, we might have an ASI opportunity in Operand - // context: - // - // export { x } // ExportDeclaration, terminated by ASI - // fro\u006D // ExpressionStatement, the name "from" - // - // In that case let matchOrInsertSemicolonAfterNonExpression sort out - // ASI or any necessary error. - bool matched; - if (!tokenStream.matchToken(&matched, TOK_FROM, TokenStream::Operand)) - return null(); + return exportFrom(begin, kid); +} - if (matched) { - MUST_MATCH_TOKEN(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM); +template +typename ParseHandler::Node +Parser::exportClause(uint32_t begin) +{ + if (!abortIfSyntaxParser()) + return null(); - Node moduleSpec = stringLiteral(); - if (!moduleSpec) - return null(); + MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC)); - if (!matchOrInsertSemicolonAfterNonExpression()) - return null(); + Node kid = handler.newList(PNK_EXPORT_SPEC_LIST); + if (!kid) + return null(); - ParseNode* node = handler.newExportFromDeclaration(begin, kid, moduleSpec); - if (!node || !pc->sc()->asModuleContext()->builder.processExportFrom(node)) - return null(); + TokenKind tt; + while (true) { + // Handle the forms |export {}| and |export { ..., }| (where ... is non + // empty), by escaping the loop early if the next token is }. + if (!tokenStream.getToken(&tt)) + return null(); + + if (tt == TOK_RC) + break; - return node; + if (!TokenKindIsPossibleIdentifierName(tt)) { + error(JSMSG_NO_BINDING_NAME); + return null(); } - if (!matchOrInsertSemicolonAfterNonExpression()) + Node bindingName = newName(tokenStream.currentName()); + if (!bindingName) return null(); - break; - } - case TOK_MUL: { - kid = handler.newList(PNK_EXPORT_SPEC_LIST); - if (!kid) + bool foundAs; + if (!tokenStream.matchToken(&foundAs, TOK_AS)) + return null(); + if (foundAs) + MUST_MATCH_TOKEN_FUNC(TokenKindIsPossibleIdentifierName, JSMSG_NO_EXPORT_NAME); + + Node exportName = newName(tokenStream.currentName()); + if (!exportName) return null(); - // Handle the form |export *| by adding a special export batch - // specifier to the list. - Node exportSpec = handler.newNullary(PNK_EXPORT_BATCH_SPEC, JSOP_NOP, pos()); + if (!checkExportedNameForClause(exportName)) + return null(); + + Node exportSpec = handler.newBinary(PNK_EXPORT_SPEC, bindingName, exportName); if (!exportSpec) return null(); handler.addList(kid, exportSpec); - if (!tokenStream.getToken(&tt)) + TokenKind next; + if (!tokenStream.getToken(&next)) return null(); - if (tt != TOK_FROM) { - error(JSMSG_FROM_AFTER_EXPORT_STAR); + + if (next == TOK_RC) + break; + + if (next != TOK_COMMA) { + error(JSMSG_RC_AFTER_EXPORT_SPEC_LIST); return null(); } + } - MUST_MATCH_TOKEN(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM); + // Careful! If |from| follows, even on a new line, it must start a + // FromClause: + // + // export { x } + // from "foo"; // a single ExportDeclaration + // + // But if it doesn't, we might have an ASI opportunity in Operand context: + // + // export { x } // ExportDeclaration, terminated by ASI + // fro\u006D // ExpressionStatement, the name "from" + // + // In that case let matchOrInsertSemicolonAfterNonExpression sort out ASI + // or any necessary error. + bool matched; + if (!tokenStream.matchToken(&matched, TOK_FROM, TokenStream::Operand)) + return null(); - Node moduleSpec = stringLiteral(); - if (!moduleSpec) - return null(); + if (matched) + return exportFrom(begin, kid); - if (!matchOrInsertSemicolonAfterNonExpression()) - return null(); + if (!matchOrInsertSemicolonAfterNonExpression()) + return null(); - ParseNode* node = handler.newExportFromDeclaration(begin, kid, moduleSpec); - if (!node || !pc->sc()->asModuleContext()->builder.processExportFrom(node)) - return null(); + Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); + if (!node) + return null(); - return node; + if (!processExport(node)) + return null(); - } + return node; +} + +template +typename ParseHandler::Node +Parser::exportVariableStatement(uint32_t begin) +{ + if (!abortIfSyntaxParser()) + return null(); + + MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_VAR)); + + Node kid = declarationList(YieldIsName, PNK_VAR); + if (!kid) + return null(); + if (!matchOrInsertSemicolonAfterExpression()) + return null(); + if (!checkExportedNamesForDeclaration(kid)) + return null(); + + Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); + if (!node) + return null(); + + if (!processExport(node)) + return null(); + + return node; +} + +template +typename ParseHandler::Node +Parser::exportFunctionDeclaration(uint32_t begin) +{ + if (!abortIfSyntaxParser()) + return null(); + + MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION)); + + Node kid = functionStmt(pos().begin, YieldIsKeyword, NameRequired); + if (!kid) + return null(); + + if (!checkExportedNameForFunction(kid)) + return null(); + + Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); + if (!node) + return null(); + + if (!processExport(node)) + return null(); + + return node; +} + +template +typename ParseHandler::Node +Parser::exportClassDeclaration(uint32_t begin) +{ + if (!abortIfSyntaxParser()) + return null(); + + MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_CLASS)); + + Node kid = classDefinition(YieldIsKeyword, ClassStatement, NameRequired); + if (!kid) + return null(); + + if (!checkExportedNameForClass(kid)) + return null(); + + Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); + if (!node) + return null(); + + if (!processExport(node)) + return null(); + + return node; +} + +template +typename ParseHandler::Node +Parser::exportLexicalDeclaration(uint32_t begin, DeclarationKind kind) +{ + if (!abortIfSyntaxParser()) + return null(); + + MOZ_ASSERT(kind == DeclarationKind::Const || kind == DeclarationKind::Let); + 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); + if (!kid) + return null(); + if (!checkExportedNamesForDeclaration(kid)) + return null(); + + Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); + if (!node) + return null(); + + if (!processExport(node)) + return null(); + + return node; +} + +template +typename ParseHandler::Node +Parser::exportDefaultFunctionDeclaration(uint32_t begin, + FunctionAsyncKind asyncKind + /* = SyncFunction */) +{ + if (!abortIfSyntaxParser()) + return null(); + + MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION)); + + Node kid = functionStmt(pos().begin, YieldIsKeyword, AllowDefaultName, asyncKind); + if (!kid) + return null(); + + Node node = handler.newExportDefaultDeclaration(kid, null(), TokenPos(begin, pos().end)); + if (!node) + return null(); + + if (!processExport(node)) + return null(); + + return node; +} + +template +typename ParseHandler::Node +Parser::exportDefaultClassDeclaration(uint32_t begin) +{ + if (!abortIfSyntaxParser()) + return null(); + + MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_CLASS)); + + Node kid = classDefinition(YieldIsKeyword, ClassStatement, AllowDefaultName); + if (!kid) + return null(); + + Node node = handler.newExportDefaultDeclaration(kid, null(), TokenPos(begin, pos().end)); + if (!node) + return null(); + + if (!processExport(node)) + return null(); + + return node; +} + +template +typename ParseHandler::Node +Parser::exportDefaultAssignExpr(uint32_t begin) +{ + if (!abortIfSyntaxParser()) + return null(); + + RootedPropertyName name(context, context->names().starDefaultStar); + Node nameNode = newName(name); + if (!nameNode) + return null(); + if (!noteDeclaredName(name, DeclarationKind::Const, pos())) + return null(); + + Node kid = assignExpr(InAllowed, YieldIsKeyword, TripledotProhibited); + if (!kid) + return null(); + if (!matchOrInsertSemicolonAfterExpression()) + return null(); + + Node node = handler.newExportDefaultDeclaration(kid, nameNode, TokenPos(begin, pos().end)); + if (!node) + return null(); + + if (!processExport(node)) + return null(); + + return node; +} + +template +typename ParseHandler::Node +Parser::exportDefault(uint32_t begin) +{ + if (!abortIfSyntaxParser()) + return null(); + + MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_DEFAULT)); + + TokenKind tt; + if (!tokenStream.getToken(&tt, TokenStream::Operand)) + return null(); + + if (!checkExportedName(context->names().default_)) + return null(); + switch (tt) { case TOK_FUNCTION: - kid = functionStmt(pos().begin, YieldIsKeyword, NameRequired); - if (!kid) - return null(); + return exportDefaultFunctionDeclaration(begin); - if (!checkExportedName(kid->pn_funbox->function()->explicitName())) + case TOK_ASYNC: { + TokenKind nextSameLine = TOK_EOF; + if (!tokenStream.peekTokenSameLine(&nextSameLine)) return null(); - break; - case TOK_CLASS: { - kid = classDefinition(YieldIsKeyword, ClassStatement, NameRequired); - if (!kid) - return null(); + if (nextSameLine == TOK_FUNCTION) { + tokenStream.consumeKnownToken(TOK_FUNCTION); + return exportDefaultFunctionDeclaration(begin, AsyncFunction); + } - const ClassNode& cls = kid->as(); - MOZ_ASSERT(cls.names()); - if (!checkExportedName(cls.names()->innerBinding()->pn_atom)) - return null(); - break; + tokenStream.ungetToken(); + return exportDefaultAssignExpr(begin); } - case TOK_VAR: - kid = declarationList(YieldIsName, PNK_VAR); - if (!kid) - return null(); - if (!matchOrInsertSemicolonAfterExpression()) - return null(); - if (!checkExportedNamesForDeclaration(kid)) - return null(); - break; + case TOK_CLASS: + return exportDefaultClassDeclaration(begin); - case TOK_DEFAULT: { - if (!tokenStream.getToken(&tt, TokenStream::Operand)) - return null(); + default: + tokenStream.ungetToken(); + return exportDefaultAssignExpr(begin); + } +} - if (!checkExportedName(context->names().default_)) - return null(); +template +typename ParseHandler::Node +Parser::exportDeclaration() +{ + if (!abortIfSyntaxParser()) + return null(); - ParseNode* nameNode = nullptr; - switch (tt) { - case TOK_FUNCTION: - kid = functionStmt(pos().begin, YieldIsKeyword, AllowDefaultName); - if (!kid) - return null(); - break; - case TOK_CLASS: - kid = classDefinition(YieldIsKeyword, ClassStatement, AllowDefaultName); - if (!kid) - return null(); - break; - default: { - if (tt == TOK_ASYNC) { - TokenKind nextSameLine = TOK_EOF; - if (!tokenStream.peekTokenSameLine(&nextSameLine)) - return null(); + MOZ_ASSERT(tokenStream.currentToken().type == TOK_EXPORT); - if (nextSameLine == TOK_FUNCTION) { - tokenStream.consumeKnownToken(nextSameLine); - kid = functionStmt(pos().begin, YieldIsName, AllowDefaultName, AsyncFunction); - if (!kid) - return null(); - break; - } - } + if (!pc->atModuleLevel()) { + error(JSMSG_EXPORT_DECL_AT_TOP_LEVEL); + return null(); + } - tokenStream.ungetToken(); - RootedPropertyName name(context, context->names().starDefaultStar); - nameNode = newName(name); - if (!nameNode) - return null(); - if (!noteDeclaredName(name, DeclarationKind::Const, pos())) - return null(); - kid = assignExpr(InAllowed, YieldIsKeyword, TripledotProhibited); - if (!kid) - return null(); - if (!matchOrInsertSemicolonAfterExpression()) - return null(); - break; - } - } + uint32_t begin = pos().begin; - ParseNode* node = handler.newExportDefaultDeclaration(kid, nameNode, - TokenPos(begin, pos().end)); - if (!node || !pc->sc()->asModuleContext()->builder.processExport(node)) - return null(); + TokenKind tt; + if (!tokenStream.getToken(&tt)) + return null(); + switch (tt) { + case TOK_MUL: + return exportBatch(begin); - return node; - } + case TOK_LC: + return exportClause(begin); + + case TOK_VAR: + return exportVariableStatement(begin); + + case TOK_FUNCTION: + return exportFunctionDeclaration(begin); + + case TOK_CLASS: + return exportClassDeclaration(begin); case TOK_CONST: - kid = lexicalDeclaration(YieldIsName, /* isConst = */ true); - if (!kid) - return null(); - if (!checkExportedNamesForDeclaration(kid)) - return null(); - break; + return exportLexicalDeclaration(begin, DeclarationKind::Const); case TOK_LET: - kid = lexicalDeclaration(YieldIsName, /* isConst = */ false); - if (!kid) - return null(); - if (!checkExportedNamesForDeclaration(kid)) - return null(); - break; + return exportLexicalDeclaration(begin, DeclarationKind::Let); + + case TOK_DEFAULT: + return exportDefault(begin); default: error(JSMSG_DECLARATION_AFTER_EXPORT); return null(); } - - ParseNode* node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); - if (!node || !pc->sc()->asModuleContext()->builder.processExport(node)) - return null(); - - return node; -} - -template<> -SyntaxParseHandler::Node -Parser::exportDeclaration() -{ - JS_ALWAYS_FALSE(abortIfSyntaxParser()); - return SyntaxParseHandler::NodeFailure; } template @@ -7132,7 +7373,7 @@ Parser::statementListItem(YieldHandling yieldHandling, return null(); if (tt == TOK_LET && nextTokenContinuesLetDeclaration(next, yieldHandling)) - return lexicalDeclaration(yieldHandling, /* isConst = */ false); + return lexicalDeclaration(yieldHandling, DeclarationKind::Let); if (tt == TOK_ASYNC) { TokenKind nextSameLine = TOK_EOF; @@ -7228,7 +7469,7 @@ Parser::statementListItem(YieldHandling yieldHandling, case TOK_CONST: // [In] is the default behavior, because for-loops specially parse // their heads to handle |in| in this situation. - return lexicalDeclaration(yieldHandling, /* isConst = */ true); + return lexicalDeclaration(yieldHandling, DeclarationKind::Const); // ImportDeclaration (only inside modules) case TOK_IMPORT: diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 4eb0f5a39..e322a4b26 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -1193,9 +1193,26 @@ class Parser final : public ParserBase, private JS::AutoGCRooter // continues a LexicalDeclaration. bool nextTokenContinuesLetDeclaration(TokenKind next, YieldHandling yieldHandling); - Node lexicalDeclaration(YieldHandling yieldHandling, bool isConst); + Node lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind); Node importDeclaration(); + + bool processExport(Node node); + bool processExportFrom(Node node); + + Node exportFrom(uint32_t begin, Node specList); + Node exportBatch(uint32_t begin); + Node exportClause(uint32_t begin); + Node exportFunctionDeclaration(uint32_t begin); + Node exportVariableStatement(uint32_t begin); + Node exportClassDeclaration(uint32_t begin); + Node exportLexicalDeclaration(uint32_t begin, DeclarationKind kind); + Node exportDefaultFunctionDeclaration(uint32_t begin, + FunctionAsyncKind asyncKind = SyncFunction); + Node exportDefaultClassDeclaration(uint32_t begin); + Node exportDefaultAssignExpr(uint32_t begin); + Node exportDefault(uint32_t begin); + Node exportDeclaration(); Node expressionStatement(YieldHandling yieldHandling, InvokedPrediction invoked = PredictUninvoked); @@ -1327,6 +1344,10 @@ class Parser final : public ParserBase, private JS::AutoGCRooter bool checkExportedName(JSAtom* exportName); bool checkExportedNamesForDeclaration(Node node); + bool checkExportedNameForClause(Node node); + bool checkExportedNameForFunction(Node node); + bool checkExportedNameForClass(Node node); + enum ClassContext { ClassStatement, ClassExpression }; Node classDefinition(YieldHandling yieldHandling, ClassContext classContext, DefaultHandling defaultHandling); diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index aa85a631e..f492bab66 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -241,6 +241,10 @@ class SyntaxParseHandler return NodeUnparenthesizedUnary; } + Node newNullary(ParseNodeKind kind, JSOp op, const TokenPos& pos) { + return NodeGeneric; + } + Node newUnary(ParseNodeKind kind, JSOp op, uint32_t begin, Node kid) { return NodeUnparenthesizedUnary; } @@ -308,6 +312,16 @@ class SyntaxParseHandler MOZ_MUST_USE bool prependInitialYield(Node stmtList, Node gen) { return true; } Node newEmptyStatement(const TokenPos& pos) { return NodeEmptyStatement; } + Node newExportDeclaration(Node kid, const TokenPos& pos) { + return NodeGeneric; + } + Node newExportFromDeclaration(uint32_t begin, Node exportSpecSet, Node moduleSpec) { + return NodeGeneric; + } + Node newExportDefaultDeclaration(Node kid, Node maybeBinding, const TokenPos& pos) { + return NodeGeneric; + } + Node newSetThis(Node thisName, Node value) { return value; } Node newExprStatement(Node expr, uint32_t end) { -- cgit v1.2.3