Chromium Code Reviews| Index: src/parsing/parser-base.h |
| diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h |
| index 2d669cff1d3812edde56b5161e3bcec4b23b8cf2..1112abcaea84d8ab0c2b80a040f3ac93bb3d09d5 100644 |
| --- a/src/parsing/parser-base.h |
| +++ b/src/parsing/parser-base.h |
| @@ -197,7 +197,8 @@ class ParserBase { |
| allow_harmony_function_sent_(false), |
| allow_harmony_async_await_(false), |
| allow_harmony_restrictive_generators_(false), |
| - allow_harmony_trailing_commas_(false) {} |
| + allow_harmony_trailing_commas_(false), |
| + allow_harmony_class_fields_(false) {} |
| #define ALLOW_ACCESSORS(name) \ |
| bool allow_##name() const { return allow_##name##_; } \ |
| @@ -213,6 +214,7 @@ class ParserBase { |
| ALLOW_ACCESSORS(harmony_async_await); |
| ALLOW_ACCESSORS(harmony_restrictive_generators); |
| ALLOW_ACCESSORS(harmony_trailing_commas); |
| + ALLOW_ACCESSORS(harmony_class_fields); |
| #undef ALLOW_ACCESSORS |
| @@ -1092,6 +1094,7 @@ class ParserBase { |
| kValueProperty, |
| kShorthandProperty, |
| kMethodProperty, |
| + kClassField, |
| kNotSet |
| }; |
| @@ -1104,6 +1107,8 @@ class ParserBase { |
| ClassLiteralPropertyT ParseClassPropertyDefinition( |
| ClassLiteralChecker* checker, bool has_extends, bool* is_computed_name, |
| bool* has_seen_constructor, bool* ok); |
| + FunctionLiteralT ParseClassFieldForInitializer(bool has_initializer, |
| + bool* ok); |
| ObjectLiteralPropertyT ParseObjectPropertyDefinition( |
| ObjectLiteralChecker* checker, bool* is_computed_name, bool* ok); |
| ExpressionListT ParseArguments(Scanner::Location* first_spread_pos, |
| @@ -1335,6 +1340,7 @@ class ParserBase { |
| bool allow_harmony_async_await_; |
| bool allow_harmony_restrictive_generators_; |
| bool allow_harmony_trailing_commas_; |
| + bool allow_harmony_class_fields_; |
| friend class DiscardableZoneScope; |
| }; |
| @@ -1890,6 +1896,10 @@ bool ParserBase<Impl>::SetPropertyKindFromToken(Token::Value token, |
| case Token::LPAREN: |
| *kind = PropertyKind::kMethodProperty; |
| return true; |
| + case Token::MUL: |
| + case Token::SEMICOLON: |
| + *kind = PropertyKind::kClassField; |
| + return true; |
| default: |
| break; |
| } |
| @@ -2027,6 +2037,10 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassLiteralChecker* checker, |
| kind = PropertyKind::kMethodProperty; |
| name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static' |
| name_expression = factory()->NewStringLiteral(name, position()); |
| + } else if (peek() == Token::ASSIGN || peek() == Token::SEMICOLON || |
| + peek() == Token::RBRACE) { |
| + name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static' |
| + name_expression = factory()->NewStringLiteral(name, position()); |
| } else { |
| is_static = true; |
| name_expression = ParsePropertyName( |
| @@ -2040,11 +2054,29 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassLiteralChecker* checker, |
| } |
| switch (kind) { |
| + case PropertyKind::kClassField: |
| + case PropertyKind::kNotSet: // This case is a name followed by a name or |
| + // other property. Here we have to assume |
| + // that's an uninitialized field followed by a |
| + // linebreak followed by a property, with ASI |
| + // adding the semicolon. If not, there will be |
| + // a syntax error after parsing the first name |
| + // as an uninitialized field. |
| case PropertyKind::kShorthandProperty: |
| case PropertyKind::kValueProperty: |
| - ReportUnexpectedToken(Next()); |
| - *ok = false; |
| - return impl()->EmptyClassLiteralProperty(); |
| + if (allow_harmony_class_fields()) { |
| + bool has_initializer = Check(Token::ASSIGN); |
| + ExpressionT function_literal = ParseClassFieldForInitializer( |
| + has_initializer, CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); |
| + ExpectSemicolon(CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); |
| + return factory()->NewClassLiteralProperty( |
| + name_expression, function_literal, ClassLiteralProperty::FIELD, |
| + is_static, *is_computed_name); |
| + } else { |
| + ReportUnexpectedToken(Next()); |
| + *ok = false; |
| + return impl()->EmptyClassLiteralProperty(); |
| + } |
| case PropertyKind::kMethodProperty: { |
| DCHECK(!is_get && !is_set); |
| @@ -2111,17 +2143,49 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassLiteralChecker* checker, |
| is_get ? ClassLiteralProperty::GETTER : ClassLiteralProperty::SETTER, |
| is_static, *is_computed_name); |
| } |
| - |
| - case PropertyKind::kNotSet: |
| - ReportUnexpectedToken(Next()); |
| - *ok = false; |
| - return impl()->EmptyClassLiteralProperty(); |
| } |
| UNREACHABLE(); |
| return impl()->EmptyClassLiteralProperty(); |
| } |
| template <typename Impl> |
| +typename ParserBase<Impl>::FunctionLiteralT |
| +ParserBase<Impl>::ParseClassFieldForInitializer(bool has_initializer, |
| + bool* ok) { |
| + // Makes a concise method which evaluates and returns the initialized value |
| + // (or undefined if absent). |
| + FunctionKind kind = FunctionKind::kConciseMethod; |
| + DeclarationScope* initializer_scope = NewFunctionScope(kind); |
| + initializer_scope->set_start_position(scanner()->location().end_pos); |
| + FunctionState initializer_state(&function_state_, &scope_state_, |
| + initializer_scope, kind); |
| + DCHECK(scope() == initializer_scope); |
| + scope()->SetLanguageMode(static_cast<LanguageMode>(language_mode() | STRICT)); |
|
Dan Ehrenberg
2016/09/09 20:58:15
Nit: Now that we don't have strong mode, I think t
|
| + ExpressionClassifier expression_classifier(this); |
| + ExpressionT value; |
| + if (has_initializer) { |
| + value = this->ParseAssignmentExpression( |
| + true, CHECK_OK_CUSTOM(EmptyFunctionLiteral)); |
| + impl()->RewriteNonPattern(CHECK_OK_CUSTOM(EmptyFunctionLiteral)); |
| + } else { |
| + value = factory()->NewUndefinedLiteral(kNoSourcePosition); |
| + } |
| + initializer_scope->set_end_position(scanner()->location().end_pos); |
| + typename Types::StatementList body = impl()->NewStatementList(1); |
| + body->Add(factory()->NewReturnStatement(value, kNoSourcePosition), zone()); |
| + FunctionLiteralT function_literal = factory()->NewFunctionLiteral( |
| + impl()->EmptyIdentifierString(), initializer_scope, body, |
| + initializer_state.materialized_literal_count(), |
| + initializer_state.expected_property_count(), 0, |
| + FunctionLiteral::kNoDuplicateParameters, |
| + FunctionLiteral::kAnonymousExpression, |
| + FunctionLiteral::kShouldLazyCompile, kind, |
| + initializer_scope->start_position()); |
| + function_literal->set_is_class_field_initializer(true); |
| + return function_literal; |
| +} |
| + |
| +template <typename Impl> |
| typename ParserBase<Impl>::ObjectLiteralPropertyT |
| ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker, |
| bool* is_computed_name, |
| @@ -2291,6 +2355,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker, |
| *is_computed_name); |
| } |
| + case PropertyKind::kClassField: |
| case PropertyKind::kNotSet: |
| ReportUnexpectedToken(Next()); |
| *ok = false; |