Index: src/preparser.h |
diff --git a/src/preparser.h b/src/preparser.h |
index cdfceea2608f19a6d6f93bc7804d7288e318fc61..ac3683124e7c101bc50976f3d73424207240384d 100644 |
--- a/src/preparser.h |
+++ b/src/preparser.h |
@@ -119,7 +119,8 @@ class ParserBase : public Traits { |
allow_harmony_new_target_(false), |
allow_strong_mode_(false), |
allow_legacy_const_(true), |
- allow_harmony_do_expressions_(false) {} |
+ allow_harmony_do_expressions_(false), |
+ allow_harmony_async_await_(false) {} |
#define ALLOW_ACCESSORS(name) \ |
bool allow_##name() const { return allow_##name##_; } \ |
@@ -139,6 +140,7 @@ class ParserBase : public Traits { |
ALLOW_ACCESSORS(strong_mode); |
ALLOW_ACCESSORS(legacy_const); |
ALLOW_ACCESSORS(harmony_do_expressions); |
+ ALLOW_ACCESSORS(harmony_async_await); |
#undef ALLOW_ACCESSORS |
uintptr_t stack_limit() const { return stack_limit_; } |
@@ -216,6 +218,7 @@ class ParserBase : public Traits { |
} |
bool is_generator() const { return IsGeneratorFunction(kind_); } |
+ bool is_async() const { return IsAsyncFunction(kind_); } |
FunctionKind kind() const { return kind_; } |
FunctionState* outer() const { return outer_function_state_; } |
@@ -402,7 +405,8 @@ class ParserBase : public Traits { |
Token::Value next = peek(); |
return next == Token::IDENTIFIER || next == Token::FUTURE_RESERVED_WORD || |
next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET || |
- next == Token::STATIC || next == Token::YIELD; |
+ next == Token::STATIC || next == Token::YIELD || |
+ next == Token::ASYNC; |
} |
bool CheckContextualKeyword(Vector<const char> keyword) { |
@@ -509,6 +513,7 @@ class ParserBase : public Traits { |
LanguageMode language_mode() { return scope_->language_mode(); } |
bool is_generator() const { return function_state_->is_generator(); } |
+ bool is_async() const { return function_state_->is_async(); } |
bool allow_const() { |
return is_strict(language_mode()) || allow_harmony_sloppy() || |
@@ -743,6 +748,7 @@ class ParserBase : public Traits { |
bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok); |
bool IsNextLetKeyword(); |
+ bool IsNextAsyncFunctionKeyword(); |
// Checks if the expression is a valid reference expression (e.g., on the |
// left-hand side of assignments). Although ruled out by ECMA as early errors, |
@@ -848,6 +854,7 @@ class ParserBase : public Traits { |
bool allow_strong_mode_; |
bool allow_legacy_const_; |
bool allow_harmony_do_expressions_; |
+ bool allow_harmony_async_await_; |
}; |
@@ -881,6 +888,9 @@ class PreParserIdentifier { |
static PreParserIdentifier Yield() { |
return PreParserIdentifier(kYieldIdentifier); |
} |
+ static PreParserIdentifier Async() { |
+ return PreParserIdentifier(kAsyncIdentifier); |
+ } |
static PreParserIdentifier Prototype() { |
return PreParserIdentifier(kPrototypeIdentifier); |
} |
@@ -894,6 +904,7 @@ class PreParserIdentifier { |
bool IsLet() const { return type_ == kLetIdentifier; } |
bool IsStatic() const { return type_ == kStaticIdentifier; } |
bool IsYield() const { return type_ == kYieldIdentifier; } |
+ bool IsAsync() const { return type_ == kAsyncIdentifier; } |
bool IsPrototype() const { return type_ == kPrototypeIdentifier; } |
bool IsConstructor() const { return type_ == kConstructorIdentifier; } |
bool IsFutureReserved() const { return type_ == kFutureReservedIdentifier; } |
@@ -919,6 +930,7 @@ class PreParserIdentifier { |
kLetIdentifier, |
kStaticIdentifier, |
kYieldIdentifier, |
+ kAsyncIdentifier, |
kEvalIdentifier, |
kArgumentsIdentifier, |
kUndefinedIdentifier, |
@@ -1997,6 +2009,7 @@ void ParserBase<Traits>::GetUnexpectedTokenMessage( |
case Token::LET: |
case Token::STATIC: |
case Token::YIELD: |
+ case Token::ASYNC: |
case Token::FUTURE_STRICT_RESERVED_WORD: |
*message = is_strict(language_mode()) |
? MessageTemplate::kUnexpectedStrictReserved |
@@ -2108,6 +2121,7 @@ ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier, |
} else if (is_sloppy(language_mode()) && |
(next == Token::FUTURE_STRICT_RESERVED_WORD || |
next == Token::LET || next == Token::STATIC || |
+ next == Token::ASYNC || |
(next == Token::YIELD && !is_generator()))) { |
classifier->RecordStrictModeFormalParameterError( |
scanner()->location(), MessageTemplate::kUnexpectedStrictReserved); |
@@ -2116,6 +2130,10 @@ ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier, |
MessageTemplate::kLetInLexicalBinding); |
} |
return this->GetSymbol(scanner()); |
+ } else if (next == Token::ASYNC) { |
+ // Async token is special because it's allowed in any mode |
+ // as identifier name |
+ return this->GetSymbol(scanner()); |
} else { |
this->ReportUnexpectedToken(next); |
*ok = false; |
@@ -2129,7 +2147,8 @@ typename ParserBase<Traits>::IdentifierT ParserBase< |
Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, |
bool* ok) { |
Token::Value next = Next(); |
- if (next == Token::IDENTIFIER) { |
+ // Async is allowed as an identifier |
+ if (next == Token::IDENTIFIER || next == Token::ASYNC) { |
*is_strict_reserved = false; |
} else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET || |
next == Token::STATIC || |
@@ -2153,7 +2172,8 @@ ParserBase<Traits>::ParseIdentifierName(bool* ok) { |
Token::Value next = Next(); |
if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD && |
next != Token::LET && next != Token::STATIC && next != Token::YIELD && |
- next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) { |
+ next != Token::ASYNC && next != Token::FUTURE_STRICT_RESERVED_WORD && |
+ !Token::IsKeyword(next)) { |
this->ReportUnexpectedToken(next); |
*ok = false; |
return Traits::EmptyIdentifier(); |
@@ -2280,6 +2300,7 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
case Token::LET: |
case Token::STATIC: |
case Token::YIELD: |
+ case Token::ASYNC: |
case Token::FUTURE_STRICT_RESERVED_WORD: { |
// Using eval or arguments in this context is OK even in strict mode. |
IdentifierT name = ParseAndClassifyIdentifier(classifier, CHECK_OK); |
@@ -3448,7 +3469,7 @@ typename ParserBase<Traits>::ExpressionT |
ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier, |
bool* ok) { |
// MemberExpression :: |
- // (PrimaryExpression | FunctionLiteral | ClassLiteral) |
+ // (PrimaryExpression | FunctionLiteral | AsyncLiteral | ClassLiteral) |
// ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)* |
// The '[' Expression ']' and '.' Identifier parts are parsed by |
@@ -3457,13 +3478,17 @@ ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier, |
// Parse the initial primary or function expression. |
ExpressionT result = this->EmptyExpression(); |
- if (peek() == Token::FUNCTION) { |
+ Token::Value token = peek(); |
+ if (token == Token::FUNCTION || |
+ (allow_harmony_async_await() && token == Token::ASYNC && |
+ IsNextAsyncFunctionKeyword())) { |
+ bool is_async = Check(Token::ASYNC); |
BindingPatternUnexpectedToken(classifier); |
ArrowFormalParametersUnexpectedToken(classifier); |
Consume(Token::FUNCTION); |
int function_token_position = position(); |
- bool is_generator = Check(Token::MUL); |
+ bool is_generator = is_async ? false : Check(Token::MUL); |
IdentifierT name = this->EmptyIdentifier(); |
bool is_strict_reserved_name = false; |
Scanner::Location function_name_location = Scanner::Location::invalid(); |
@@ -3475,14 +3500,20 @@ ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier, |
function_name_location = scanner()->location(); |
function_type = FunctionLiteral::NAMED_EXPRESSION; |
} |
+ |
+ FunctionKind kind = FunctionKind::kNormalFunction; |
+ if (is_generator) { |
+ kind = FunctionKind::kGeneratorFunction; |
+ } else if (is_async) { |
+ kind = FunctionKind::kAsyncFunction; |
+ } |
+ |
result = this->ParseFunctionLiteral( |
name, function_name_location, |
is_strict_reserved_name ? kFunctionNameIsStrictReserved |
: kFunctionNameValidityUnknown, |
- is_generator ? FunctionKind::kGeneratorFunction |
- : FunctionKind::kNormalFunction, |
- function_token_position, function_type, FunctionLiteral::NORMAL_ARITY, |
- language_mode(), CHECK_OK); |
+ kind, function_token_position, function_type, |
+ FunctionLiteral::NORMAL_ARITY, language_mode(), CHECK_OK); |
} else if (peek() == Token::SUPER) { |
const bool is_new = false; |
result = ParseSuperExpression(is_new, classifier, CHECK_OK); |
@@ -3900,6 +3931,7 @@ bool ParserBase<Traits>::IsNextLetKeyword() { |
case Token::STATIC: |
case Token::LET: // Yes, you can do let let = ... in sloppy mode |
case Token::YIELD: |
+ case Token::ASYNC: |
return true; |
default: |
return false; |
@@ -3908,6 +3940,15 @@ bool ParserBase<Traits>::IsNextLetKeyword() { |
template <class Traits> |
+bool ParserBase<Traits>::IsNextAsyncFunctionKeyword() { |
+ DCHECK(peek() == Token::ASYNC); |
+ Token::Value next_next = PeekAhead(); |
+ return next_next == Token::FUNCTION && |
+ !scanner()->HasAnyLineTerminatorBeforeNext(); |
+} |
+ |
+ |
+template <class Traits> |
typename ParserBase<Traits>::ExpressionT |
ParserBase<Traits>::ParseArrowFunctionLiteral( |
bool accept_IN, const FormalParametersT& formal_parameters, |