| Index: src/parsing/parser-base.h
|
| diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
|
| index 1036ac942962ec93e2d37089f460bbf880366821..cde95076a598852d1853db5714eda550ed173b8c 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
|
| @@ -284,6 +312,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_; }
|
| @@ -594,6 +623,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);
|
|
|
| @@ -684,6 +718,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,
|
| @@ -740,8 +777,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;
|
| }
|
| }
|
| @@ -770,7 +815,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)) {
|
| @@ -790,6 +836,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) {
|
| @@ -863,22 +915,32 @@ 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(
|
| ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends,
|
| - bool is_static, bool* is_computed_name, bool* has_seen_constructor,
|
| + MethodKind kind, 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,
|
| @@ -898,12 +960,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,
|
| @@ -975,7 +1040,7 @@ class ParserBase : public Traits {
|
| explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {}
|
|
|
| virtual void CheckProperty(Token::Value property, PropertyKind type,
|
| - bool is_static, bool is_generator, bool* ok) = 0;
|
| + MethodKind method_type, bool* ok) = 0;
|
|
|
| virtual ~ObjectLiteralCheckerBase() {}
|
|
|
| @@ -993,8 +1058,8 @@ class ParserBase : public Traits {
|
| explicit ObjectLiteralChecker(ParserBase* parser)
|
| : ObjectLiteralCheckerBase(parser), has_seen_proto_(false) {}
|
|
|
| - void CheckProperty(Token::Value property, PropertyKind type, bool is_static,
|
| - bool is_generator, bool* ok) override;
|
| + void CheckProperty(Token::Value property, PropertyKind type,
|
| + MethodKind method_type, bool* ok) override;
|
|
|
| private:
|
| bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); }
|
| @@ -1008,8 +1073,8 @@ class ParserBase : public Traits {
|
| explicit ClassLiteralChecker(ParserBase* parser)
|
| : ObjectLiteralCheckerBase(parser), has_seen_constructor_(false) {}
|
|
|
| - void CheckProperty(Token::Value property, PropertyKind type, bool is_static,
|
| - bool is_generator, bool* ok) override;
|
| + void CheckProperty(Token::Value property, PropertyKind type,
|
| + MethodKind method_type, bool* ok) override;
|
|
|
| private:
|
| bool IsConstructor() {
|
| @@ -1046,6 +1111,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>
|
| @@ -1206,6 +1272,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) {
|
| @@ -1321,11 +1395,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'
|
| @@ -1341,6 +1414,7 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
|
| // '(' Expression ')'
|
| // TemplateLiteral
|
| // do Block
|
| + // AsyncFunctionExpression
|
|
|
| int beg_pos = peek_position();
|
| switch (peek()) {
|
| @@ -1361,6 +1435,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:
|
| @@ -1631,11 +1716,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();
|
|
|
| @@ -1680,6 +1764,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;
|
| }
|
|
|
| @@ -1689,38 +1776,51 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName(
|
| : factory()->NewStringLiteral(*name, pos);
|
| }
|
|
|
| -
|
| template <class Traits>
|
| typename ParserBase<Traits>::ObjectLiteralPropertyT
|
| ParserBase<Traits>::ParsePropertyDefinition(
|
| ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends,
|
| - bool is_static, bool* is_computed_name, bool* has_seen_constructor,
|
| + MethodKind method_kind, bool* is_computed_name, bool* has_seen_constructor,
|
| ExpressionClassifier* classifier, IdentifierT* name, bool* ok) {
|
| - DCHECK(!in_class || is_static || has_seen_constructor != nullptr);
|
| + DCHECK(!in_class || IsStaticMethod(method_kind) ||
|
| + has_seen_constructor != nullptr);
|
| ExpressionT value = this->EmptyExpression();
|
| bool is_get = false;
|
| bool is_set = false;
|
| + bool is_await = false;
|
| bool is_generator = Check(Token::MUL);
|
| + bool is_async = false;
|
|
|
| Token::Value name_token = peek();
|
| +
|
| + if (is_generator) {
|
| + method_kind |= MethodKind::Generator;
|
| + } else if (allow_harmony_async_await() &&
|
| + PeekContextualKeyword(CStrVector("async")) &&
|
| + !scanner()->HasAnyLineTerminatorAfterNext() &&
|
| + PeekAhead() != Token::LPAREN) {
|
| + method_kind |= MethodKind::Async;
|
| + is_async = true;
|
| + }
|
| +
|
| 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);
|
| }
|
|
|
| if (!in_class && !is_generator) {
|
| - DCHECK(!is_static);
|
| + DCHECK(!IsStaticMethod(method_kind));
|
|
|
| if (peek() == Token::COLON) {
|
| // PropertyDefinition
|
| // PropertyName ':' AssignmentExpression
|
| if (!*is_computed_name) {
|
| - checker->CheckProperty(name_token, kValueProperty, false, false,
|
| + checker->CheckProperty(name_token, kValueProperty, MethodKind::None,
|
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
| }
|
| Consume(Token::COLON);
|
| @@ -1730,8 +1830,8 @@ ParserBase<Traits>::ParsePropertyDefinition(
|
| CheckDestructuringElement(value, classifier, beg_pos,
|
| scanner()->location().end_pos);
|
|
|
| - return factory()->NewObjectLiteralProperty(name_expression, value, false,
|
| - *is_computed_name);
|
| + return factory()->NewObjectLiteralProperty(
|
| + name_expression, value, MethodKind::None, *is_computed_name);
|
| }
|
|
|
| if (Token::IsIdentifier(name_token, language_mode(), this->is_generator(),
|
| @@ -1752,7 +1852,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);
|
| @@ -1780,8 +1884,8 @@ ParserBase<Traits>::ParsePropertyDefinition(
|
| }
|
|
|
| return factory()->NewObjectLiteralProperty(
|
| - name_expression, value, ObjectLiteralProperty::COMPUTED, false,
|
| - false);
|
| + name_expression, value, ObjectLiteralProperty::COMPUTED,
|
| + MethodKind::None, false);
|
| }
|
| }
|
|
|
| @@ -1790,20 +1894,32 @@ ParserBase<Traits>::ParsePropertyDefinition(
|
| Scanner::Location(next_beg_pos, scanner()->location().end_pos),
|
| MessageTemplate::kInvalidDestructuringTarget);
|
|
|
| + if (IsAsyncMethod(method_kind)) {
|
| + DCHECK(!IsGeneratorMethod(method_kind));
|
| + 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 '}'
|
| // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
|
| if (!*is_computed_name) {
|
| - checker->CheckProperty(name_token, kMethodProperty, is_static,
|
| - is_generator,
|
| + checker->CheckProperty(name_token, kMethodProperty, method_kind,
|
| 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)) {
|
| + if (in_class && !IsStaticMethod(method_kind) &&
|
| + this->IsConstructor(*name)) {
|
| *has_seen_constructor = true;
|
| kind = has_extends ? FunctionKind::kSubclassConstructor
|
| : FunctionKind::kBaseConstructor;
|
| @@ -1816,16 +1932,16 @@ ParserBase<Traits>::ParsePropertyDefinition(
|
|
|
| return factory()->NewObjectLiteralProperty(name_expression, value,
|
| ObjectLiteralProperty::COMPUTED,
|
| - is_static, *is_computed_name);
|
| + method_kind, *is_computed_name);
|
| }
|
|
|
| - if (in_class && name_token == Token::STATIC && !is_static) {
|
| + if (in_class && name_token == Token::STATIC && !IsMethod(method_kind)) {
|
| // ClassElement (static)
|
| // 'static' MethodDefinition
|
| *name = this->EmptyIdentifier();
|
| ObjectLiteralPropertyT property = ParsePropertyDefinition(
|
| - checker, true, has_extends, true, is_computed_name, nullptr, classifier,
|
| - name, ok);
|
| + checker, true, has_extends, MethodKind::Static, is_computed_name,
|
| + nullptr, classifier, name, ok);
|
| Traits::RewriteNonPattern(classifier, ok);
|
| return property;
|
| }
|
| @@ -1839,12 +1955,11 @@ 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) {
|
| - checker->CheckProperty(name_token, kAccessorProperty, is_static,
|
| - is_generator,
|
| + checker->CheckProperty(name_token, kAccessorProperty, method_kind,
|
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
| }
|
|
|
| @@ -1865,7 +1980,7 @@ ParserBase<Traits>::ParsePropertyDefinition(
|
| return factory()->NewObjectLiteralProperty(
|
| name_expression, value,
|
| is_get ? ObjectLiteralProperty::GETTER : ObjectLiteralProperty::SETTER,
|
| - is_static, *is_computed_name);
|
| + method_kind, *is_computed_name);
|
| }
|
|
|
| Token::Value next = Next();
|
| @@ -1894,13 +2009,12 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
|
| FuncNameInferrer::State fni_state(fni_);
|
|
|
| const bool in_class = false;
|
| - const bool is_static = false;
|
| const bool has_extends = false;
|
| bool is_computed_name = false;
|
| IdentifierT name = this->EmptyIdentifier();
|
| ObjectLiteralPropertyT property = this->ParsePropertyDefinition(
|
| - &checker, in_class, has_extends, is_static, &is_computed_name, NULL,
|
| - classifier, &name, CHECK_OK);
|
| + &checker, in_class, has_extends, MethodKind::None, &is_computed_name,
|
| + NULL, classifier, &name, CHECK_OK);
|
|
|
| if (is_computed_name) {
|
| has_computed_names = true;
|
| @@ -1934,11 +2048,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)*[','] ')'
|
|
|
| @@ -1994,7 +2107,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
|
| @@ -2026,18 +2139,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
|
| @@ -2045,6 +2172,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);
|
| @@ -2069,7 +2197,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();
|
|
|
| @@ -2086,8 +2214,10 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
|
| classifier->Accumulate(
|
| &arrow_formals_classifier,
|
| ExpressionClassifier::StandardProductions |
|
| - ExpressionClassifier::FormalParametersProductions |
|
| - ExpressionClassifier::CoverInitializedNameProduction,
|
| + ExpressionClassifier::FormalParametersProductions |
|
| + ExpressionClassifier::CoverInitializedNameProduction |
|
| + ExpressionClassifier::AsyncArrowFormalParametersProduction |
|
| + ExpressionClassifier::AsyncBindingPatternProduction,
|
| false);
|
|
|
| if (!Token::IsAssignmentOp(peek())) {
|
| @@ -2129,8 +2259,10 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
|
| CheckNoTailCallExpressions(&rhs_classifier, CHECK_OK);
|
| Traits::RewriteNonPattern(&rhs_classifier, CHECK_OK);
|
| classifier->Accumulate(
|
| - &rhs_classifier, ExpressionClassifier::ExpressionProductions |
|
| - ExpressionClassifier::CoverInitializedNameProduction);
|
| + &rhs_classifier,
|
| + ExpressionClassifier::ExpressionProductions |
|
| + ExpressionClassifier::CoverInitializedNameProduction |
|
| + ExpressionClassifier::AsyncArrowFormalParametersProduction);
|
|
|
| // TODO(1231235): We try to estimate the set of properties set by
|
| // constructors. We define a new property whenever there is an
|
| @@ -2401,6 +2533,7 @@ ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier,
|
| // '-' UnaryExpression
|
| // '~' UnaryExpression
|
| // '!' UnaryExpression
|
| + // [+Await] AwaitExpression[?Yield]
|
|
|
| Token::Value op = peek();
|
| if (Token::IsUnaryOp(op)) {
|
| @@ -2448,6 +2581,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);
|
| }
|
| @@ -2497,8 +2664,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()) {
|
| @@ -2518,11 +2686,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
|
| @@ -2544,7 +2710,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.
|
| @@ -2605,11 +2782,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
|
| //
|
| @@ -2642,7 +2818,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) {
|
| @@ -2658,8 +2835,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.
|
| @@ -2667,14 +2844,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)*
|
| @@ -2731,10 +2907,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;
|
| }
|
|
|
| @@ -2801,16 +2978,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);
|
| @@ -2827,6 +3005,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(
|
| break;
|
| }
|
| case Token::PERIOD: {
|
| + *is_async = false;
|
| Traits::RewriteNonPattern(classifier, CHECK_OK);
|
| BindingPatternUnexpectedToken(classifier);
|
| ArrowFormalParametersUnexpectedToken(classifier);
|
| @@ -2843,6 +3022,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(
|
| }
|
| case Token::TEMPLATE_SPAN:
|
| case Token::TEMPLATE_TAIL: {
|
| + *is_async = false;
|
| Traits::RewriteNonPattern(classifier, CHECK_OK);
|
| BindingPatternUnexpectedToken(classifier);
|
| ArrowFormalParametersUnexpectedToken(classifier);
|
| @@ -3011,11 +3191,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.
|
| @@ -3034,9 +3213,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);
|
| @@ -3284,13 +3463,12 @@ void ParserBase<Traits>::CheckDestructuringElement(
|
| #undef CHECK_OK
|
| #undef CHECK_OK_CUSTOM
|
|
|
| -
|
| template <typename Traits>
|
| void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
|
| - Token::Value property, PropertyKind type, bool is_static, bool is_generator,
|
| + Token::Value property, PropertyKind type, MethodKind method_type,
|
| bool* ok) {
|
| - DCHECK(!is_static);
|
| - DCHECK(!is_generator || type == kMethodProperty);
|
| + DCHECK(!IsStaticMethod(method_type));
|
| + DCHECK(!IsMethod(method_type) || type == kMethodProperty);
|
|
|
| if (property == Token::SMI || property == Token::NUMBER) return;
|
|
|
| @@ -3305,26 +3483,28 @@ void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
|
| }
|
| }
|
|
|
| -
|
| template <typename Traits>
|
| void ParserBase<Traits>::ClassLiteralChecker::CheckProperty(
|
| - Token::Value property, PropertyKind type, bool is_static, bool is_generator,
|
| + Token::Value property, PropertyKind type, MethodKind method_type,
|
| bool* ok) {
|
| DCHECK(type == kMethodProperty || type == kAccessorProperty);
|
|
|
| if (property == Token::SMI || property == Token::NUMBER) return;
|
|
|
| - if (is_static) {
|
| + if (IsStaticMethod(method_type)) {
|
| if (IsPrototype()) {
|
| this->parser()->ReportMessage(MessageTemplate::kStaticPrototype);
|
| *ok = false;
|
| return;
|
| }
|
| } else if (IsConstructor()) {
|
| - if (is_generator || type == kAccessorProperty) {
|
| + const bool is_generator = IsGeneratorMethod(method_type);
|
| + const bool is_async = IsAsyncMethod(method_type);
|
| + if (is_generator || is_async || type == kAccessorProperty) {
|
| MessageTemplate::Template msg =
|
| is_generator ? MessageTemplate::kConstructorIsGenerator
|
| - : MessageTemplate::kConstructorIsAccessor;
|
| + : is_async ? MessageTemplate::kConstructorIsAsync
|
| + : MessageTemplate::kConstructorIsAccessor;
|
| this->parser()->ReportMessage(msg);
|
| *ok = false;
|
| return;
|
|
|