Chromium Code Reviews| Index: src/parsing/parser-base.h |
| diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h |
| index 484d4b977e04c66bd26d3b42d860e00195fd6802..5ea3e43d91eaab6cbd35a08da5a246374cf44557 100644 |
| --- a/src/parsing/parser-base.h |
| +++ b/src/parsing/parser-base.h |
| @@ -29,6 +29,32 @@ enum AllowLabelledFunctionStatement { |
| kDisallowLabelledFunctionStatement, |
| }; |
| +enum class ParseFunctionFlags { |
|
Dan Ehrenberg
2016/05/05 01:14:40
Cute overloading idiom. We could do this elsewhere
|
| + kIsNormal = 0, |
| + kIsGenerator = 1, |
| + kIsAsync = 2, |
| + kIsDefault = 4 |
| +}; |
| + |
| +static inline ParseFunctionFlags operator|(ParseFunctionFlags lhs, |
| + ParseFunctionFlags rhs) { |
| + typedef unsigned char T; |
| + return static_cast<ParseFunctionFlags>(static_cast<T>(lhs) | |
| + static_cast<T>(rhs)); |
| +} |
| + |
| +static inline ParseFunctionFlags& operator|=(ParseFunctionFlags& lhs, |
| + const ParseFunctionFlags& rhs) { |
| + lhs = lhs | rhs; |
| + return lhs; |
| +} |
| + |
| +static inline bool operator&(ParseFunctionFlags bitfield, |
| + ParseFunctionFlags mask) { |
| + typedef unsigned char T; |
| + return static_cast<T>(bitfield) & static_cast<T>(mask); |
| +} |
| + |
| struct FormalParametersBase { |
| explicit FormalParametersBase(Scope* scope) : scope(scope) {} |
| Scope* scope; |
| @@ -117,7 +143,8 @@ class ParserBase : public Traits { |
| allow_harmony_do_expressions_(false), |
| allow_harmony_for_in_(false), |
| allow_harmony_function_name_(false), |
| - allow_harmony_function_sent_(false) {} |
| + allow_harmony_function_sent_(false), |
| + allow_harmony_async_await_(false) {} |
| #define ALLOW_ACCESSORS(name) \ |
| bool allow_##name() const { return allow_##name##_; } \ |
| @@ -137,6 +164,7 @@ class ParserBase : public Traits { |
| ALLOW_ACCESSORS(harmony_for_in); |
| ALLOW_ACCESSORS(harmony_function_name); |
| ALLOW_ACCESSORS(harmony_function_sent); |
| + ALLOW_ACCESSORS(harmony_async_await); |
| SCANNER_ACCESSORS(harmony_exponentiation_operator); |
| #undef SCANNER_ACCESSORS |
| @@ -272,6 +300,7 @@ class ParserBase : public Traits { |
| } |
| bool is_generator() const { return IsGeneratorFunction(kind_); } |
| + bool is_async_function() const { return IsAsyncFunction(kind_); } |
| FunctionKind kind() const { return kind_; } |
| FunctionState* outer() const { return outer_function_state_; } |
| @@ -579,6 +608,11 @@ class ParserBase : public Traits { |
| scanner()->is_next_contextual_keyword(keyword); |
| } |
| + bool PeekAheadContextualKeyword(Vector<const char> keyword) { |
| + return PeekAhead() == Token::IDENTIFIER && |
| + scanner()->is_next_next_contextual_keyword(keyword); |
| + } |
| + |
| void ExpectMetaProperty(Vector<const char> property_name, |
| const char* full_name, int pos, bool* ok); |
| @@ -669,6 +703,9 @@ class ParserBase : public Traits { |
| LanguageMode language_mode() { return scope_->language_mode(); } |
| bool is_generator() const { return function_state_->is_generator(); } |
| + bool is_async_function() const { |
| + return function_state_->is_async_function(); |
| + } |
| // Report syntax errors. |
| void ReportMessage(MessageTemplate::Template message, const char* arg = NULL, |
| @@ -755,7 +792,8 @@ class ParserBase : public Traits { |
| void ValidateArrowFormalParameters(const ExpressionClassifier* classifier, |
| ExpressionT expr, |
| - bool parenthesized_formals, bool* ok) { |
| + bool parenthesized_formals, bool is_async, |
| + bool* ok) { |
| if (classifier->is_valid_binding_pattern()) { |
| // A simple arrow formal parameter: IDENTIFIER => BODY. |
| if (!this->IsIdentifier(expr)) { |
| @@ -775,6 +813,12 @@ class ParserBase : public Traits { |
| ReportClassifierError(error); |
| *ok = false; |
| } |
| + if (is_async && !classifier->is_valid_async_arrow_formal_parameters()) { |
| + const typename ExpressionClassifier::Error& error = |
| + classifier->async_arrow_formal_parameters_error(); |
| + ReportClassifierError(error); |
| + *ok = false; |
| + } |
| } |
| void ValidateLetPattern(const ExpressionClassifier* classifier, bool* ok) { |
| @@ -848,13 +892,18 @@ class ParserBase : public Traits { |
| ExpressionClassifier* classifier, bool* ok); |
| ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, |
| - bool* ok); |
| + bool* is_async, bool* ok); |
| + ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, |
| + bool* ok) { |
| + bool is_async; |
| + return ParsePrimaryExpression(classifier, &is_async, ok); |
| + } |
| ExpressionT ParseExpression(bool accept_IN, bool* ok); |
| ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, |
| bool* ok); |
| ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); |
| ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, |
| - bool* is_computed_name, |
| + bool* is_await, bool* is_computed_name, |
| ExpressionClassifier* classifier, bool* ok); |
| ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok); |
| ObjectLiteralPropertyT ParsePropertyDefinition( |
| @@ -862,8 +911,13 @@ class ParserBase : public Traits { |
| bool is_static, bool* is_computed_name, bool* has_seen_constructor, |
| ExpressionClassifier* classifier, IdentifierT* name, bool* ok); |
| typename Traits::Type::ExpressionList ParseArguments( |
| + Scanner::Location* first_spread_pos, bool maybe_arrow, |
| + ExpressionClassifier* classifier, bool* ok); |
| + typename Traits::Type::ExpressionList ParseArguments( |
| Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, |
| - bool* ok); |
| + bool* ok) { |
| + return ParseArguments(first_spread_pos, false, classifier, ok); |
| + } |
| ExpressionT ParseAssignmentExpression(bool accept_IN, |
| ExpressionClassifier* classifier, |
| @@ -883,12 +937,15 @@ class ParserBase : public Traits { |
| ExpressionT ParseLeftHandSideExpression(ExpressionClassifier* classifier, |
| bool* ok); |
| ExpressionT ParseMemberWithNewPrefixesExpression( |
| - ExpressionClassifier* classifier, bool* ok); |
| - ExpressionT ParseMemberExpression(ExpressionClassifier* classifier, bool* ok); |
| + ExpressionClassifier* classifier, bool* is_async, bool* ok); |
| + ExpressionT ParseMemberExpression(ExpressionClassifier* classifier, |
| + bool* is_async, bool* ok); |
| ExpressionT ParseMemberExpressionContinuation( |
| - ExpressionT expression, ExpressionClassifier* classifier, bool* ok); |
| + ExpressionT expression, bool* is_async, ExpressionClassifier* classifier, |
| + bool* ok); |
| ExpressionT ParseArrowFunctionLiteral(bool accept_IN, |
| const FormalParametersT& parameters, |
| + bool is_async, |
| const ExpressionClassifier& classifier, |
| bool* ok); |
| ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, |
| @@ -1031,6 +1088,7 @@ class ParserBase : public Traits { |
| bool allow_harmony_for_in_; |
| bool allow_harmony_function_name_; |
| bool allow_harmony_function_sent_; |
| + bool allow_harmony_async_await_; |
| }; |
| template <class Traits> |
| @@ -1191,6 +1249,14 @@ ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier, |
| scanner()->location(), MessageTemplate::kStrictEvalArguments); |
| } |
| } |
| + if (this->IsAwait(name)) { |
| + if (is_async_function()) { |
| + classifier->RecordPatternError( |
| + scanner()->location(), MessageTemplate::kAwaitBindingIdentifier); |
| + } |
| + classifier->RecordAsyncArrowFormalParametersError( |
| + scanner()->location(), MessageTemplate::kAwaitBindingIdentifier); |
|
Dan Ehrenberg
2016/05/05 01:14:40
"await is only treated as a FutureReservedWord whe
caitp (gmail)
2016/05/05 01:36:57
Ideally we'd have a variety of versions of this me
|
| + } |
| if (classifier->duplicate_finder() != nullptr && |
| scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { |
| @@ -1243,6 +1309,7 @@ ParserBase<Traits>::ParseIdentifierOrStrictReservedWord( |
| IdentifierT name = this->GetSymbol(scanner()); |
| if (this->IsArguments(name)) scope_->RecordArgumentsUsage(); |
| + |
|
Dan Ehrenberg
2016/05/05 01:14:40
Spurious whitespace change.
caitp (gmail)
2016/05/05 01:36:57
Acknowledged.
|
| return name; |
| } |
| @@ -1306,11 +1373,10 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral( |
| #define DUMMY ) // to make indentation work |
| #undef DUMMY |
| - |
|
Dan Ehrenberg
2016/05/05 01:14:40
Spurious whitespace change.
|
| template <class Traits> |
| typename ParserBase<Traits>::ExpressionT |
| ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
| - bool* ok) { |
| + bool* is_async, bool* ok) { |
| // PrimaryExpression :: |
| // 'this' |
| // 'null' |
| @@ -1326,6 +1392,7 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
| // '(' Expression ')' |
| // TemplateLiteral |
| // do Block |
| + // AsyncFunctionExpression |
| int beg_pos = peek_position(); |
| switch (peek()) { |
| @@ -1346,6 +1413,17 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
| return this->ExpressionFromLiteral(Next(), beg_pos, scanner(), factory()); |
| case Token::IDENTIFIER: |
| + if (allow_harmony_async_await() && |
| + PeekContextualKeyword(CStrVector("async")) && |
| + !scanner()->HasAnyLineTerminatorAfterNext()) { |
| + if (PeekAhead() == Token::FUNCTION) { |
| + Consume(Token::IDENTIFIER); |
| + return this->ParseAsyncFunctionExpression(CHECK_OK); |
| + } |
| + // CoverCallExpressionAndAsyncArrowHead |
| + *is_async = true; |
| + } |
| + /* Falls through */ |
| case Token::LET: |
| case Token::STATIC: |
| case Token::YIELD: |
| @@ -1616,11 +1694,10 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral( |
| return result; |
| } |
| - |
| template <class Traits> |
| typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName( |
| - IdentifierT* name, bool* is_get, bool* is_set, bool* is_computed_name, |
| - ExpressionClassifier* classifier, bool* ok) { |
| + IdentifierT* name, bool* is_get, bool* is_set, bool* is_await, |
| + bool* is_computed_name, ExpressionClassifier* classifier, bool* ok) { |
| Token::Value token = peek(); |
| int pos = peek_position(); |
| @@ -1665,6 +1742,9 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName( |
| default: |
| *name = ParseIdentifierName(CHECK_OK); |
| scanner()->IsGetOrSet(is_get, is_set); |
| + if (this->IsAwait(*name)) { |
| + *is_await = true; |
| + } |
| break; |
| } |
| @@ -1685,14 +1765,22 @@ ParserBase<Traits>::ParsePropertyDefinition( |
| ExpressionT value = this->EmptyExpression(); |
| bool is_get = false; |
| bool is_set = false; |
| + bool is_await = false; |
| bool is_generator = Check(Token::MUL); |
| Token::Value name_token = peek(); |
| + |
| + bool is_async = allow_harmony_async_await() && !is_generator && |
| + name_token == Token::IDENTIFIER && |
| + PeekContextualKeyword(CStrVector("async")) && |
| + !scanner()->HasAnyLineTerminatorAfterNext() && |
| + PeekAhead() != Token::LPAREN; |
| + |
| int next_beg_pos = scanner()->peek_location().beg_pos; |
| int next_end_pos = scanner()->peek_location().end_pos; |
| - ExpressionT name_expression = |
| - ParsePropertyName(name, &is_get, &is_set, is_computed_name, classifier, |
| - CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| + ExpressionT name_expression = ParsePropertyName( |
| + name, &is_get, &is_set, &is_await, is_computed_name, classifier, |
| + CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| if (fni_ != nullptr && !*is_computed_name) { |
| this->PushLiteralName(fni_, *name); |
| @@ -1737,7 +1825,11 @@ ParserBase<Traits>::ParsePropertyDefinition( |
| classifier->RecordLetPatternError( |
| scanner()->location(), MessageTemplate::kLetInLexicalBinding); |
| } |
| - |
| + if (is_await && is_async_function()) { |
| + classifier->RecordPatternError( |
| + Scanner::Location(next_beg_pos, next_end_pos), |
| + MessageTemplate::kAwaitBindingIdentifier); |
| + } |
| ExpressionT lhs = this->ExpressionFromIdentifier( |
| *name, next_beg_pos, next_end_pos, scope_, factory()); |
| CheckDestructuringElement(lhs, classifier, next_beg_pos, next_end_pos); |
| @@ -1775,6 +1867,16 @@ ParserBase<Traits>::ParsePropertyDefinition( |
| Scanner::Location(next_beg_pos, scanner()->location().end_pos), |
| MessageTemplate::kInvalidDestructuringTarget); |
| + if (is_async) { |
| + DCHECK(!is_generator); |
| + DCHECK(!is_get); |
| + DCHECK(!is_set); |
| + bool dont_care; |
| + name_expression = ParsePropertyName( |
| + name, &dont_care, &dont_care, &dont_care, is_computed_name, classifier, |
| + CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| + } |
| + |
| if (is_generator || peek() == Token::LPAREN) { |
| // MethodDefinition |
| // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' |
| @@ -1785,8 +1887,10 @@ ParserBase<Traits>::ParsePropertyDefinition( |
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| } |
| - FunctionKind kind = is_generator ? FunctionKind::kConciseGeneratorMethod |
| - : FunctionKind::kConciseMethod; |
| + FunctionKind kind = is_generator |
| + ? FunctionKind::kConciseGeneratorMethod |
| + : is_async ? FunctionKind::kAsyncConciseMethod |
| + : FunctionKind::kConciseMethod; |
| if (in_class && !is_static && this->IsConstructor(*name)) { |
| *has_seen_constructor = true; |
| @@ -1824,7 +1928,7 @@ ParserBase<Traits>::ParsePropertyDefinition( |
| name_token = peek(); |
| name_expression = ParsePropertyName( |
| - name, &dont_care, &dont_care, is_computed_name, classifier, |
| + name, &dont_care, &dont_care, &dont_care, is_computed_name, classifier, |
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| if (!*is_computed_name) { |
| @@ -1919,11 +2023,10 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral( |
| pos); |
| } |
| - |
| template <class Traits> |
| typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments( |
| - Scanner::Location* first_spread_arg_loc, ExpressionClassifier* classifier, |
| - bool* ok) { |
| + Scanner::Location* first_spread_arg_loc, bool maybe_arrow, |
| + ExpressionClassifier* classifier, bool* ok) { |
| // Arguments :: |
| // '(' (AssignmentExpression)*[','] ')' |
| @@ -1979,7 +2082,7 @@ typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments( |
| } |
| *first_spread_arg_loc = spread_arg; |
| - if (spread_arg.IsValid()) { |
| + if ((!maybe_arrow || peek() != Token::ARROW) && spread_arg.IsValid()) { |
| // Unspread parameter sequences are translated into array literals in the |
| // parser. Ensure that the number of materialized literals matches between |
| // the parser and preparser |
| @@ -2011,18 +2114,32 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| ParserBase<Traits>::Checkpoint checkpoint(this); |
| ExpressionClassifier arrow_formals_classifier(this, |
| classifier->duplicate_finder()); |
| + |
| + bool is_async = allow_harmony_async_await() && peek() == Token::IDENTIFIER && |
| + PeekContextualKeyword(CStrVector("async")) && |
| + !scanner()->HasAnyLineTerminatorAfterNext(); |
| + |
| bool parenthesized_formals = peek() == Token::LPAREN; |
| - if (!parenthesized_formals) { |
| + if (!is_async && !parenthesized_formals) { |
| ArrowFormalParametersUnexpectedToken(&arrow_formals_classifier); |
| } |
| ExpressionT expression = this->ParseConditionalExpression( |
| accept_IN, &arrow_formals_classifier, CHECK_OK); |
| + |
| + if (is_async && peek_any_identifier() && PeekAhead() == Token::ARROW) { |
| + // async Identifier => AsyncConciseBody |
| + IdentifierT name = |
| + ParseAndClassifyIdentifier(&arrow_formals_classifier, CHECK_OK); |
| + expression = this->ExpressionFromIdentifier( |
| + name, position(), scanner()->location().end_pos, scope_, factory()); |
| + } |
| + |
| if (peek() == Token::ARROW) { |
| classifier->RecordPatternError(scanner()->peek_location(), |
| MessageTemplate::kUnexpectedToken, |
| Token::String(Token::ARROW)); |
| ValidateArrowFormalParameters(&arrow_formals_classifier, expression, |
| - parenthesized_formals, CHECK_OK); |
| + parenthesized_formals, is_async, CHECK_OK); |
| // This reads strangely, but is correct: it checks whether any |
| // sub-expression of the parameter list failed to be a valid formal |
| // parameter initializer. Since YieldExpressions are banned anywhere |
| @@ -2030,6 +2147,7 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| // TODO(adamk): Rename "FormalParameterInitializerError" to refer to |
| // "YieldExpression", which is its only use. |
| ValidateFormalParameterInitializer(&arrow_formals_classifier, ok); |
| + |
| Scanner::Location loc(lhs_beg_pos, scanner()->location().end_pos); |
| Scope* scope = |
| this->NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction); |
| @@ -2054,7 +2172,7 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| duplicate_loc); |
| } |
| expression = this->ParseArrowFunctionLiteral( |
| - accept_IN, parameters, arrow_formals_classifier, CHECK_OK); |
| + accept_IN, parameters, is_async, arrow_formals_classifier, CHECK_OK); |
| if (fni_ != nullptr) fni_->Infer(); |
| @@ -2071,8 +2189,9 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| classifier->Accumulate( |
| &arrow_formals_classifier, |
| ExpressionClassifier::StandardProductions | |
| - ExpressionClassifier::FormalParametersProductions | |
| - ExpressionClassifier::CoverInitializedNameProduction, |
| + ExpressionClassifier::FormalParametersProductions | |
| + ExpressionClassifier::CoverInitializedNameProduction | |
| + ExpressionClassifier::AsyncArrowFormalParametersProduction, |
| false); |
| if (!Token::IsAssignmentOp(peek())) { |
| @@ -2375,6 +2494,7 @@ ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier, |
| // '-' UnaryExpression |
| // '~' UnaryExpression |
| // '!' UnaryExpression |
| + // [+Await] AwaitExpression[?Yield] |
| Token::Value op = peek(); |
| if (Token::IsUnaryOp(op)) { |
| @@ -2422,6 +2542,16 @@ ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier, |
| expression, |
| position()); |
| + } else if (is_async_function() && peek() == Token::AWAIT) { |
| + int beg_pos = peek_position(); |
| + Consume(Token::AWAIT); |
| + ExpressionT value = ParseUnaryExpression(classifier, CHECK_OK); |
| + |
| + classifier->RecordFormalParameterInitializerError( |
| + Scanner::Location(beg_pos, scanner()->location().end_pos), |
| + MessageTemplate::kAwaitExpressionFormalParameter); |
| + |
| + return Traits::RewriteAwaitExpression(value, beg_pos); |
| } else { |
| return this->ParsePostfixExpression(classifier, ok); |
| } |
| @@ -2471,8 +2601,9 @@ ParserBase<Traits>::ParseLeftHandSideExpression( |
| return this->ParseTailCallExpression(classifier, ok); |
| } |
| - ExpressionT result = |
| - this->ParseMemberWithNewPrefixesExpression(classifier, CHECK_OK); |
| + bool is_async = false; |
| + ExpressionT result = this->ParseMemberWithNewPrefixesExpression( |
| + classifier, &is_async, CHECK_OK); |
| while (true) { |
| switch (peek()) { |
| @@ -2492,11 +2623,9 @@ ParserBase<Traits>::ParseLeftHandSideExpression( |
| case Token::LPAREN: { |
| CheckNoTailCallExpressions(classifier, CHECK_OK); |
| + int pos; |
| Traits::RewriteNonPattern(classifier, CHECK_OK); |
| BindingPatternUnexpectedToken(classifier); |
| - ArrowFormalParametersUnexpectedToken(classifier); |
| - |
| - int pos; |
| if (scanner()->current_token() == Token::IDENTIFIER || |
| scanner()->current_token() == Token::SUPER) { |
| // For call of an identifier we want to report position of |
| @@ -2518,7 +2647,18 @@ ParserBase<Traits>::ParseLeftHandSideExpression( |
| } |
| Scanner::Location spread_pos; |
| typename Traits::Type::ExpressionList args = |
| - ParseArguments(&spread_pos, classifier, CHECK_OK); |
| + ParseArguments(&spread_pos, is_async, classifier, CHECK_OK); |
| + |
| + if (V8_UNLIKELY(is_async && peek() == Token::ARROW)) { |
| + if (args->length()) { |
| + // async ( Arguments ) => ... |
| + return Traits::ExpressionListToExpression(args); |
| + } |
| + // async () => ... |
| + return factory()->NewEmptyParentheses(pos); |
| + } |
| + |
| + ArrowFormalParametersUnexpectedToken(classifier); |
| // Keep track of eval() calls since they disable all local variable |
| // optimizations. |
| @@ -2579,11 +2719,10 @@ ParserBase<Traits>::ParseLeftHandSideExpression( |
| } |
| } |
| - |
| template <class Traits> |
| typename ParserBase<Traits>::ExpressionT |
| ParserBase<Traits>::ParseMemberWithNewPrefixesExpression( |
| - ExpressionClassifier* classifier, bool* ok) { |
| + ExpressionClassifier* classifier, bool* is_async, bool* ok) { |
| // NewExpression :: |
| // ('new')+ MemberExpression |
| // |
| @@ -2616,7 +2755,8 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression( |
| } else if (peek() == Token::PERIOD) { |
| return ParseNewTargetExpression(CHECK_OK); |
| } else { |
| - result = this->ParseMemberWithNewPrefixesExpression(classifier, CHECK_OK); |
| + result = this->ParseMemberWithNewPrefixesExpression(classifier, is_async, |
| + CHECK_OK); |
| } |
| Traits::RewriteNonPattern(classifier, CHECK_OK); |
| if (peek() == Token::LPAREN) { |
| @@ -2632,8 +2772,8 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression( |
| result = factory()->NewCallNew(result, args, new_pos); |
| } |
| // The expression can still continue with . or [ after the arguments. |
| - result = |
| - this->ParseMemberExpressionContinuation(result, classifier, CHECK_OK); |
| + result = this->ParseMemberExpressionContinuation(result, is_async, |
| + classifier, CHECK_OK); |
| return result; |
| } |
| // NewExpression without arguments. |
| @@ -2641,14 +2781,13 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression( |
| new_pos); |
| } |
| // No 'new' or 'super' keyword. |
| - return this->ParseMemberExpression(classifier, ok); |
| + return this->ParseMemberExpression(classifier, is_async, ok); |
| } |
| - |
| template <class Traits> |
| typename ParserBase<Traits>::ExpressionT |
| ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier, |
| - bool* ok) { |
| + bool* is_async, bool* ok) { |
| // MemberExpression :: |
| // (PrimaryExpression | FunctionLiteral | ClassLiteral) |
| // ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)* |
| @@ -2705,10 +2844,11 @@ ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier, |
| const bool is_new = false; |
| result = ParseSuperExpression(is_new, classifier, CHECK_OK); |
| } else { |
| - result = ParsePrimaryExpression(classifier, CHECK_OK); |
| + result = ParsePrimaryExpression(classifier, is_async, CHECK_OK); |
| } |
| - result = ParseMemberExpressionContinuation(result, classifier, CHECK_OK); |
| + result = |
| + ParseMemberExpressionContinuation(result, is_async, classifier, CHECK_OK); |
| return result; |
| } |
| @@ -2775,16 +2915,17 @@ ParserBase<Traits>::ParseNewTargetExpression(bool* ok) { |
| return this->NewTargetExpression(scope_, factory(), pos); |
| } |
| - |
| template <class Traits> |
| typename ParserBase<Traits>::ExpressionT |
| ParserBase<Traits>::ParseMemberExpressionContinuation( |
| - ExpressionT expression, ExpressionClassifier* classifier, bool* ok) { |
| + ExpressionT expression, bool* is_async, ExpressionClassifier* classifier, |
| + bool* ok) { |
| // Parses this part of MemberExpression: |
| // ('[' Expression ']' | '.' Identifier | TemplateLiteral)* |
| while (true) { |
| switch (peek()) { |
| case Token::LBRACK: { |
| + *is_async = false; |
| Traits::RewriteNonPattern(classifier, CHECK_OK); |
| BindingPatternUnexpectedToken(classifier); |
| ArrowFormalParametersUnexpectedToken(classifier); |
| @@ -2801,6 +2942,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation( |
| break; |
| } |
| case Token::PERIOD: { |
| + *is_async = false; |
| Traits::RewriteNonPattern(classifier, CHECK_OK); |
| BindingPatternUnexpectedToken(classifier); |
| ArrowFormalParametersUnexpectedToken(classifier); |
| @@ -2817,6 +2959,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation( |
| } |
| case Token::TEMPLATE_SPAN: |
| case Token::TEMPLATE_TAIL: { |
| + *is_async = false; |
| Traits::RewriteNonPattern(classifier, CHECK_OK); |
| BindingPatternUnexpectedToken(classifier); |
| ArrowFormalParametersUnexpectedToken(classifier); |
| @@ -2985,11 +3128,10 @@ bool ParserBase<Traits>::IsNextLetKeyword() { |
| } |
| } |
| - |
| template <class Traits> |
| typename ParserBase<Traits>::ExpressionT |
| ParserBase<Traits>::ParseArrowFunctionLiteral( |
| - bool accept_IN, const FormalParametersT& formal_parameters, |
| + bool accept_IN, const FormalParametersT& formal_parameters, bool is_async, |
| const ExpressionClassifier& formals_classifier, bool* ok) { |
| if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) { |
| // ASI inserts `;` after arrow parameters if a line terminator is found. |
| @@ -3008,9 +3150,9 @@ ParserBase<Traits>::ParseArrowFunctionLiteral( |
| { |
| typename Traits::Type::Factory function_factory(ast_value_factory()); |
| - FunctionState function_state(&function_state_, &scope_, |
| - formal_parameters.scope, kArrowFunction, |
| - &function_factory); |
| + FunctionState function_state( |
| + &function_state_, &scope_, formal_parameters.scope, |
| + is_async ? kAsyncArrowFunction : kArrowFunction, &function_factory); |
| function_state.SkipMaterializedLiterals( |
| formal_parameters.materialized_literals_count); |