| Index: src/parsing/parser-base.h
|
| diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
|
| index 2d669cff1d3812edde56b5161e3bcec4b23b8cf2..f00364750994ff42a7fb81274f61a39cecc8575a 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(STRICT);
|
| + 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;
|
|
|