Index: src/parsing/parser-base.h |
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h |
index cde95076a598852d1853db5714eda550ed173b8c..3a0dbc8cf65307750c90c91f756474a8a9d56e8a 100644 |
--- a/src/parsing/parser-base.h |
+++ b/src/parsing/parser-base.h |
@@ -36,6 +36,10 @@ enum class ParseFunctionFlags { |
kIsDefault = 4 |
}; |
+enum class FunctionBody { Normal, SingleExpression }; |
+ |
+enum class FunctionParsePhase { Unknown, FormalParameters, FunctionBody }; |
+ |
static inline ParseFunctionFlags operator|(ParseFunctionFlags lhs, |
ParseFunctionFlags rhs) { |
typedef unsigned char T; |
@@ -313,14 +317,26 @@ class ParserBase : public Traits { |
bool is_generator() const { return IsGeneratorFunction(kind_); } |
bool is_async_function() const { return IsAsyncFunction(kind_); } |
+ bool is_resumable() const { return is_generator() || is_async_function(); } |
FunctionKind kind() const { return kind_; } |
FunctionState* outer() const { return outer_function_state_; } |
+ bool is_async_function_body() const { |
+ return is_async_function() && |
+ parse_phase() == FunctionParsePhase::FunctionBody; |
+ } |
+ |
+ FunctionParsePhase parse_phase() const { return parse_phase_; } |
+ |
+ void set_parse_phase(FunctionParsePhase parse_phase) { |
+ parse_phase_ = parse_phase; |
+ } |
+ |
void set_generator_object_variable( |
typename Traits::Type::GeneratorVariable* variable) { |
DCHECK(variable != NULL); |
- DCHECK(is_generator()); |
+ DCHECK(is_resumable()); |
generator_object_variable_ = variable; |
} |
typename Traits::Type::GeneratorVariable* generator_object_variable() |
@@ -426,6 +442,8 @@ class ParserBase : public Traits { |
// to this function. Filled in by constructor. |
bool this_function_is_parenthesized_; |
+ FunctionParsePhase parse_phase_ = FunctionParsePhase::Unknown; |
+ |
friend class ParserTraits; |
friend class PreParserTraits; |
friend class Checkpoint; |
@@ -721,6 +739,7 @@ class ParserBase : public Traits { |
bool is_async_function() const { |
return function_state_->is_async_function(); |
} |
+ bool is_resumable() const { return function_state_->is_resumable(); } |
// Report syntax errors. |
void ReportMessage(MessageTemplate::Template message, const char* arg = NULL, |
@@ -2174,8 +2193,9 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
ValidateFormalParameterInitializer(&arrow_formals_classifier, ok); |
Scanner::Location loc(lhs_beg_pos, scanner()->location().end_pos); |
- Scope* scope = |
- this->NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction); |
+ Scope* scope = this->NewScope(scope_, FUNCTION_SCOPE, |
+ is_async ? FunctionKind::kAsyncArrowFunction |
+ : FunctionKind::kArrowFunction); |
// Because the arrow's parameters were parsed in the outer scope, any |
// usage flags that might have been triggered there need to be copied |
// to the arrow scope. |
@@ -2610,10 +2630,14 @@ ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier, |
Consume(Token::AWAIT); |
ExpressionT value = ParseUnaryExpression(classifier, CHECK_OK); |
- classifier->RecordFormalParameterInitializerError( |
- Scanner::Location(beg_pos, scanner()->location().end_pos), |
- MessageTemplate::kAwaitExpressionFormalParameter); |
- |
+ if (!function_state_->is_async_function_body()) { |
+ // Not currently parsing function body --- must have occurred within |
+ // formal parameter parsing. |
+ ReportMessageAt(Scanner::Location(beg_pos, scanner()->location().end_pos), |
+ MessageTemplate::kAwaitExpressionFormalParameter); |
+ *ok = false; |
+ return this->EmptyExpression(); |
+ } |
return Traits::RewriteAwaitExpression(value, beg_pos); |
} else { |
return this->ParsePostfixExpression(classifier, ok); |
@@ -3211,11 +3235,12 @@ ParserBase<Traits>::ParseArrowFunctionLiteral( |
int expected_property_count = -1; |
Scanner::Location super_loc; |
+ FunctionKind arrow_kind = is_async ? kAsyncArrowFunction : kArrowFunction; |
{ |
typename Traits::Type::Factory function_factory(ast_value_factory()); |
- FunctionState function_state( |
- &function_state_, &scope_, formal_parameters.scope, |
- is_async ? kAsyncArrowFunction : kArrowFunction, &function_factory); |
+ FunctionState function_state(&function_state_, &scope_, |
+ formal_parameters.scope, arrow_kind, |
+ &function_factory); |
function_state.SkipMaterializedLiterals( |
formal_parameters.materialized_literals_count); |
@@ -3223,6 +3248,7 @@ ParserBase<Traits>::ParseArrowFunctionLiteral( |
this->ReindexLiterals(formal_parameters); |
Expect(Token::ARROW, CHECK_OK); |
+ function_state.set_parse_phase(FunctionParsePhase::FunctionBody); |
if (peek() == Token::LBRACE) { |
// Multiple statement body |
@@ -3240,7 +3266,7 @@ ParserBase<Traits>::ParseArrowFunctionLiteral( |
} else { |
body = this->ParseEagerFunctionBody( |
this->EmptyIdentifier(), RelocInfo::kNoPosition, formal_parameters, |
- kArrowFunction, FunctionLiteral::kAnonymousExpression, CHECK_OK); |
+ arrow_kind, FunctionLiteral::kAnonymousExpression, CHECK_OK); |
materialized_literal_count = |
function_state.materialized_literal_count(); |
expected_property_count = function_state.expected_property_count(); |
@@ -3253,18 +3279,25 @@ ParserBase<Traits>::ParseArrowFunctionLiteral( |
function_state_->return_expr_context()); |
ReturnExprScope allow_tail_calls( |
function_state_, ReturnExprContext::kInsideValidReturnStatement); |
- ExpressionT expression = |
- ParseAssignmentExpression(accept_IN, &classifier, CHECK_OK); |
- Traits::RewriteNonPattern(&classifier, CHECK_OK); |
body = this->NewStatementList(1, zone()); |
- this->AddParameterInitializationBlock(formal_parameters, body, CHECK_OK); |
- body->Add(factory()->NewReturnStatement(expression, pos), zone()); |
+ this->AddParameterInitializationBlock(formal_parameters, body, is_async, |
+ CHECK_OK); |
+ if (is_async) { |
+ this->ParseAsyncArrowSingleExpressionBody(body, accept_IN, &classifier, |
+ pos, CHECK_OK); |
+ Traits::RewriteNonPattern(&classifier, CHECK_OK); |
+ } else { |
+ ExpressionT expression = |
+ ParseAssignmentExpression(accept_IN, &classifier, CHECK_OK); |
+ Traits::RewriteNonPattern(&classifier, CHECK_OK); |
+ body->Add(factory()->NewReturnStatement(expression, pos), zone()); |
+ if (allow_tailcalls() && !is_sloppy(language_mode())) { |
+ // ES6 14.6.1 Static Semantics: IsInTailPosition |
+ this->MarkTailPosition(expression); |
+ } |
+ } |
materialized_literal_count = function_state.materialized_literal_count(); |
expected_property_count = function_state.expected_property_count(); |
- if (allow_tailcalls() && !is_sloppy(language_mode())) { |
- // ES6 14.6.1 Static Semantics: IsInTailPosition |
- this->MarkTailPosition(expression); |
- } |
this->MarkCollectedTailCallExpressions(); |
} |
super_loc = function_state.super_location(); |
@@ -3294,7 +3327,7 @@ ParserBase<Traits>::ParseArrowFunctionLiteral( |
materialized_literal_count, expected_property_count, num_parameters, |
FunctionLiteral::kNoDuplicateParameters, |
FunctionLiteral::kAnonymousExpression, |
- FunctionLiteral::kShouldLazyCompile, FunctionKind::kArrowFunction, |
+ FunctionLiteral::kShouldLazyCompile, arrow_kind, |
formal_parameters.scope->start_position()); |
function_literal->set_function_token_position( |