summaryrefslogtreecommitdiffstats
path: root/js/src/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/frontend')
-rw-r--r--js/src/frontend/Parser.cpp659
-rw-r--r--js/src/frontend/Parser.h23
-rw-r--r--js/src/frontend/SyntaxParseHandler.h14
3 files changed, 486 insertions, 210 deletions
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<ParseHandler>::declarationList(YieldHandling yieldHandling,
template <typename ParseHandler>
typename ParseHandler::Node
-Parser<ParseHandler>::lexicalDeclaration(YieldHandling yieldHandling, bool isConst)
+Parser<ParseHandler>::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<ParseHandler>::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<SyntaxParseHandler>::checkExportedNamesForDeclaration(Node node)
}
template<>
-ParseNode*
-Parser<FullParseHandler>::exportDeclaration()
+bool
+Parser<FullParseHandler>::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<SyntaxParseHandler>::checkExportedNameForClause(Node node)
+{
+ MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
+ return false;
+}
+
+template<>
+bool
+Parser<FullParseHandler>::checkExportedNameForFunction(ParseNode* node)
+{
+ return checkExportedName(node->pn_funbox->function()->explicitName());
+}
+
+template<>
+bool
+Parser<SyntaxParseHandler>::checkExportedNameForFunction(Node node)
+{
+ MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
+ return false;
+}
+
+template<>
+bool
+Parser<FullParseHandler>::checkExportedNameForClass(ParseNode* node)
+{
+ const ClassNode& cls = node->as<ClassNode>();
+ MOZ_ASSERT(cls.names());
+ return checkExportedName(cls.names()->innerBinding()->pn_atom);
+}
+
+template<>
+bool
+Parser<SyntaxParseHandler>::checkExportedNameForClass(Node node)
+{
+ MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
+ return false;
+}
+
+template<>
+bool
+Parser<FullParseHandler>::processExport(ParseNode* node)
+{
+ return pc->sc()->asModuleContext()->builder.processExport(node);
+}
+
+template<>
+bool
+Parser<SyntaxParseHandler>::processExport(Node node)
+{
+ MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
+ return false;
+}
+
+template<>
+bool
+Parser<FullParseHandler>::processExportFrom(ParseNode* node)
+{
+ return pc->sc()->asModuleContext()->builder.processExportFrom(node);
+}
+
+template<>
+bool
+Parser<SyntaxParseHandler>::processExportFrom(Node node)
+{
+ MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
+ return false;
+}
+
+template <typename ParseHandler>
+typename ParseHandler::Node
+Parser<ParseHandler>::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>
+typename ParseHandler::Node
+Parser<ParseHandler>::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>
+typename ParseHandler::Node
+Parser<ParseHandler>::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>
+typename ParseHandler::Node
+Parser<ParseHandler>::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>
+typename ParseHandler::Node
+Parser<ParseHandler>::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>
+typename ParseHandler::Node
+Parser<ParseHandler>::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>
+typename ParseHandler::Node
+Parser<ParseHandler>::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>
+typename ParseHandler::Node
+Parser<ParseHandler>::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>
+typename ParseHandler::Node
+Parser<ParseHandler>::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>
+typename ParseHandler::Node
+Parser<ParseHandler>::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>
+typename ParseHandler::Node
+Parser<ParseHandler>::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<ClassNode>();
- 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>
+typename ParseHandler::Node
+Parser<ParseHandler>::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<SyntaxParseHandler>::exportDeclaration()
-{
- JS_ALWAYS_FALSE(abortIfSyntaxParser());
- return SyntaxParseHandler::NodeFailure;
}
template <typename ParseHandler>
@@ -7132,7 +7373,7 @@ Parser<ParseHandler>::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<ParseHandler>::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) {