Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(573)

Unified Diff: src/parsing/parser-base.h

Issue 1841543003: [esnext] implement frontend changes for async/await proposal (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: A bunch more tests, some fixes, ExpressionClassifier gets fatter :( Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/parsing/parser-base.h
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
index 484d4b977e04c66bd26d3b42d860e00195fd6802..715e68a3f89aaf862f4a3bc37e3f63ed5a962176 100644
--- a/src/parsing/parser-base.h
+++ b/src/parsing/parser-base.h
@@ -29,6 +29,32 @@ enum AllowLabelledFunctionStatement {
kDisallowLabelledFunctionStatement,
};
+enum class ParseFunctionFlags {
+ 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,
@@ -725,8 +762,16 @@ class ParserBase : public Traits {
void ValidateBindingPattern(const ExpressionClassifier* classifier,
bool* ok) {
- if (!classifier->is_valid_binding_pattern()) {
- ReportClassifierError(classifier->binding_pattern_error());
+ if (!classifier->is_valid_binding_pattern() ||
+ !classifier->is_valid_async_binding_pattern()) {
+ const Scanner::Location& a = classifier->binding_pattern_error().location;
+ const Scanner::Location& b =
+ classifier->async_binding_pattern_error().location;
+ if (a.beg_pos < 0 || (b.beg_pos >= 0 && a.beg_pos > b.beg_pos)) {
+ ReportClassifierError(classifier->async_binding_pattern_error());
+ } else {
+ ReportClassifierError(classifier->binding_pattern_error());
+ }
*ok = false;
}
}
@@ -755,7 +800,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 +821,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 +900,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 +919,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 +945,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 +1096,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 +1257,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);
+ }
if (classifier->duplicate_finder() != nullptr &&
scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) {
@@ -1306,11 +1380,10 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral(
#define DUMMY ) // to make indentation work
#undef DUMMY
-
template <class Traits>
typename ParserBase<Traits>::ExpressionT
ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
- bool* ok) {
+ bool* is_async, bool* ok) {
// PrimaryExpression ::
// 'this'
// 'null'
@@ -1326,6 +1399,7 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
// '(' Expression ')'
// TemplateLiteral
// do Block
+ // AsyncFunctionExpression
int beg_pos = peek_position();
switch (peek()) {
@@ -1346,6 +1420,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 +1701,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 +1749,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 +1772,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 +1832,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 +1874,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 +1894,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 +1935,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 +2030,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 +2089,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 +2121,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 +2154,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 +2179,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 +2196,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 +2501,7 @@ ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier,
// '-' UnaryExpression
// '~' UnaryExpression
// '!' UnaryExpression
+ // [+Await] AwaitExpression[?Yield]
Token::Value op = peek();
if (Token::IsUnaryOp(op)) {
@@ -2422,6 +2549,40 @@ ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier,
expression,
position());
+ } else if (is_async_function() && peek() == Token::AWAIT) {
+ int beg_pos = peek_position();
+ switch (PeekAhead()) {
+ case Token::RPAREN:
+ case Token::RBRACK:
+ case Token::RBRACE:
+ case Token::ASSIGN:
+ case Token::COMMA: {
+ Next();
+ IdentifierT name = this->GetSymbol(scanner());
+
+ // Possibly async arrow formals --- record ExpressionError just in case.
+ ExpressionUnexpectedToken(classifier);
+ classifier->RecordAsyncBindingPatternError(
+ Scanner::Location(beg_pos, scanner()->location().end_pos),
+ MessageTemplate::kAwaitBindingIdentifier);
+ classifier->RecordAsyncArrowFormalParametersError(
+ Scanner::Location(beg_pos, scanner()->location().end_pos),
+ MessageTemplate::kAwaitBindingIdentifier);
+
+ return this->ExpressionFromIdentifier(
+ name, beg_pos, scanner()->location().end_pos, scope_, factory());
+ }
+ default:
+ break;
+ }
+ 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 +2632,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 +2654,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 +2678,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 +2750,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 +2786,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 +2803,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 +2812,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 +2875,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 +2946,17 @@ ParserBase<Traits>::ParseNewTargetExpression(bool* ok) {
return this->NewTargetExpression(scope_, factory(), pos);
}
-
Dan Ehrenberg 2016/05/06 00:08:56 Add back irrelevant blank line removals.
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 +2973,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(
break;
}
case Token::PERIOD: {
+ *is_async = false;
Traits::RewriteNonPattern(classifier, CHECK_OK);
BindingPatternUnexpectedToken(classifier);
ArrowFormalParametersUnexpectedToken(classifier);
@@ -2817,6 +2990,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 +3159,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 +3181,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);

Powered by Google App Engine
This is Rietveld 408576698