diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 94f798e754..7a5cef7d78 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -785,7 +785,7 @@ ParserBase::ParserBase(ExclusiveContext* cx, LifoAlloc& alloc, #endif abortedSyntaxParse(false), isUnexpectedEOF_(false), - awaitIsKeyword_(false), + awaitHandling_(AwaitIsName), parseGoal_(uint8_t(parseGoal)) { cx->perThreadData->frontendCollectionPool.addActiveCompilation(); @@ -846,18 +846,18 @@ Parser::~Parser() template <> void -Parser::setAwaitIsKeyword(bool isKeyword) +Parser::setAwaitHandling(AwaitHandling awaitHandling) { - awaitIsKeyword_ = isKeyword; + awaitHandling_ = awaitHandling; } template <> void -Parser::setAwaitIsKeyword(bool isKeyword) +Parser::setAwaitHandling(AwaitHandling awaitHandling) { - awaitIsKeyword_ = isKeyword; + awaitHandling_ = awaitHandling; if (Parser* parser = handler.syntaxParser) - parser->setAwaitIsKeyword(isKeyword); + parser->setAwaitHandling(awaitHandling); } template @@ -2217,7 +2217,7 @@ Parser::moduleBody(ModuleSharedContext* modulesc) if (!moduleNode) return null(); - AutoAwaitIsKeyword awaitIsKeyword(this, true); + AutoAwaitIsKeyword awaitIsKeyword(this, AwaitIsModuleKeyword); ListNode* stmtList = statementList(YieldIsName); if (!stmtList) { return null(); @@ -2490,6 +2490,14 @@ GetYieldHandling(GeneratorKind generatorKind) return YieldIsKeyword; } +static AwaitHandling +GetAwaitHandling(FunctionAsyncKind asyncKind) +{ + if (asyncKind == SyncFunction) + return AwaitIsName; + return AwaitIsKeyword; +} + template <> FunctionNode* Parser::standaloneFunction(HandleFunction fun, @@ -2549,7 +2557,8 @@ Parser::standaloneFunction(HandleFunction fun, funpc.setIsStandaloneFunctionBody(); YieldHandling yieldHandling = GetYieldHandling(generatorKind); - AutoAwaitIsKeyword awaitIsKeyword(this, asyncKind == AsyncFunction); + AwaitHandling awaitHandling = GetAwaitHandling(asyncKind); + AutoAwaitIsKeyword awaitIsKeyword(this, awaitHandling); if (!functionFormalParametersAndBody(InAllowed, yieldHandling, funNode, FunctionSyntaxKind::Statement, parameterListEnd, /* isStandaloneFunction = */ true)) { @@ -3641,9 +3650,11 @@ Parser::functionFormalParametersAndBody(InHandling inHandling, // See below for an explanation why arrow function parameters and arrow // function bodies are parsed with different yield/await settings. { - bool asyncOrArrowInAsync = funbox->isAsync() || - (kind == FunctionSyntaxKind::Arrow && awaitIsKeyword()); - AutoAwaitIsKeyword awaitIsKeyword(this, asyncOrArrowInAsync); + AwaitHandling awaitHandling = funbox->isAsync() || + (kind == FunctionSyntaxKind::Arrow && awaitIsKeyword()) + ? AwaitIsKeyword + : AwaitIsName; + AutoAwaitIsKeyword awaitIsKeyword(this, awaitHandling); if (!functionArguments(yieldHandling, kind, funNode)) return false; } @@ -3713,9 +3724,10 @@ Parser::functionFormalParametersAndBody(InHandling inHandling, // Whereas the |yield| in the function body is always parsed as a name. // The same goes when parsing |await| in arrow functions. YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind()); + AwaitHandling bodyAwaitHandling = GetAwaitHandling(pc->asyncKind()); LexicalScopeNodeType body; { - AutoAwaitIsKeyword awaitIsKeyword(this, funbox->isAsync()); + AutoAwaitIsKeyword awaitIsKeyword(this, bodyAwaitHandling); body = functionBody(inHandling, bodyYieldHandling, kind, bodyType); if (!body) return false; @@ -3873,7 +3885,7 @@ Parser::functionExpr(uint32_t toStringStart, InvokedPrediction inv { MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION)); - AutoAwaitIsKeyword awaitIsKeyword(this, asyncKind == AsyncFunction); + AutoAwaitIsKeyword awaitIsKeyword(this, GetAwaitHandling(asyncKind)); GeneratorKind generatorKind = NotGenerator; TokenKind tt; if (!tokenStream.getToken(&tt)) diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index fce6ead17d..4dd9f64178 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -591,6 +591,7 @@ enum class PropertyType { // we're in a function box -- easier and simpler than passing an extra // parameter everywhere. enum YieldHandling { YieldIsName, YieldIsKeyword }; +enum AwaitHandling : uint8_t { AwaitIsName, AwaitIsKeyword, AwaitIsModuleKeyword }; enum InHandling { InAllowed, InProhibited }; enum DefaultHandling { NameRequired, AllowDefaultName }; enum TripledotHandling { TripledotAllowed, TripledotProhibited }; @@ -800,13 +801,13 @@ class ParserBase : public StrictModeGetter /* Unexpected end of input, i.e. TOK_EOF not at top-level. */ bool isUnexpectedEOF_:1; - bool awaitIsKeyword_:1; + /* AwaitHandling */ uint8_t awaitHandling_:2; uint8_t parseGoal_:1; public: bool awaitIsKeyword() const { - return awaitIsKeyword_; + return awaitHandling_ != AwaitIsName; } ParseGoal parseGoal() const { @@ -1058,7 +1059,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) ~Parser(); friend class AutoAwaitIsKeyword; - void setAwaitIsKeyword(bool isKeyword); + void setAwaitHandling(AwaitHandling awaitHandling); bool checkOptions(); @@ -1643,17 +1644,21 @@ class MOZ_STACK_CLASS AutoAwaitIsKeyword { private: Parser* parser_; - bool oldAwaitIsKeyword_; + AwaitHandling oldAwaitHandling_; public: - AutoAwaitIsKeyword(Parser* parser, bool awaitIsKeyword) { + AutoAwaitIsKeyword(Parser* parser, AwaitHandling awaitHandling) { parser_ = parser; - oldAwaitIsKeyword_ = parser_->awaitIsKeyword_; - parser_->setAwaitIsKeyword(awaitIsKeyword); + oldAwaitHandling_ = static_cast(parser_->awaitHandling_); + + // 'await' is always a keyword in module contexts, so we don't modify + // the state when the original handling is AwaitIsModuleKeyword. + if (oldAwaitHandling_ != AwaitIsModuleKeyword) + parser_->setAwaitHandling(awaitHandling); } ~AutoAwaitIsKeyword() { - parser_->setAwaitIsKeyword(oldAwaitIsKeyword_); + parser_->setAwaitHandling(oldAwaitHandling_); } };