Chromium Code Reviews| Index: src/preparser.h |
| diff --git a/src/preparser.h b/src/preparser.h |
| index 15887bae08234a65b024940f0942750840630075..c1355ab984a7709797675ba73f6dbefb4b1872fc 100644 |
| --- a/src/preparser.h |
| +++ b/src/preparser.h |
| @@ -46,6 +46,7 @@ namespace internal { |
| // typedef Identifier; |
| // typedef Expression; |
| // typedef FunctionLiteral; |
| +// typedef ClassLiteral; |
| // typedef ObjectLiteralProperty; |
| // typedef Literal; |
| // typedef ExpressionList; |
| @@ -63,6 +64,7 @@ class ParserBase : public Traits { |
| typedef typename Traits::Type::Expression ExpressionT; |
| typedef typename Traits::Type::Identifier IdentifierT; |
| typedef typename Traits::Type::FunctionLiteral FunctionLiteralT; |
| + typedef typename Traits::Type::ClassLiteral ClassLiteralT; |
| typedef typename Traits::Type::Literal LiteralT; |
| typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT; |
| @@ -483,10 +485,12 @@ class ParserBase : public Traits { |
| ExpressionT ParsePrimaryExpression(bool* ok); |
| ExpressionT ParseExpression(bool accept_IN, bool* ok); |
| ExpressionT ParseArrayLiteral(bool* ok); |
| + IdentifierT ParsePropertyName(bool* is_get, bool* is_set, bool* is_static, |
| + bool* ok); |
| ExpressionT ParseObjectLiteral(bool* ok); |
| ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker, |
| + bool in_class, bool is_static, |
| bool* ok); |
| - IdentifierT ParsePropertyName(bool* is_getter, bool* is_setter, bool* ok); |
| typename Traits::Type::ExpressionList ParseArguments(bool* ok); |
| ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok); |
| ExpressionT ParseYieldExpression(bool* ok); |
| @@ -501,6 +505,10 @@ class ParserBase : public Traits { |
| bool* ok); |
| ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast, |
| bool* ok); |
| + ClassLiteralT ParseClassLiteral(IdentifierT name, |
| + Scanner::Location function_name_location, |
| + bool name_is_strict_reserved, int pos, |
| + bool* ok); |
| // 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, |
| @@ -616,10 +624,18 @@ class PreParserIdentifier { |
| static PreParserIdentifier Yield() { |
| return PreParserIdentifier(kYieldIdentifier); |
| } |
| + static PreParserIdentifier Prototype() { |
| + return PreParserIdentifier(kPrototypeIdentifier); |
| + } |
| + static PreParserIdentifier Constructor() { |
| + return PreParserIdentifier(kConstructorIdentifier); |
| + } |
| bool IsEval() const { return type_ == kEvalIdentifier; } |
| bool IsArguments() const { return type_ == kArgumentsIdentifier; } |
| bool IsEvalOrArguments() const { return type_ >= kEvalIdentifier; } |
|
marja
2014/09/11 09:40:58
This looks incorrect now, because you're adding mo
arv (Not doing code reviews)
2014/09/11 18:24:42
Oops.
|
| bool IsYield() const { return type_ == kYieldIdentifier; } |
| + bool IsPrototype() const { return type_ >= kPrototypeIdentifier; } |
|
marja
2014/09/11 09:40:58
Why >= ? And in case somebody adds new enum values
arv (Not doing code reviews)
2014/09/11 18:24:42
Ooops here too.
|
| + bool IsConstructor() const { return type_ >= kConstructorIdentifier; } |
| bool IsFutureReserved() const { return type_ == kFutureReservedIdentifier; } |
| bool IsFutureStrictReserved() const { |
| return type_ == kFutureStrictReservedIdentifier; |
| @@ -642,7 +658,9 @@ class PreParserIdentifier { |
| kLetIdentifier, |
| kYieldIdentifier, |
| kEvalIdentifier, |
| - kArgumentsIdentifier |
| + kArgumentsIdentifier, |
| + kPrototypeIdentifier, |
| + kConstructorIdentifier |
| }; |
| explicit PreParserIdentifier(Type type) : type_(type) {} |
| Type type_; |
| @@ -869,6 +887,10 @@ class PreParserStatement { |
| return PreParserStatement(kFunctionDeclaration); |
| } |
| + static PreParserStatement ClassDeclaration() { |
| + return PreParserStatement(kClassDeclaration); |
| + } |
| + |
| // Creates expression statement from expression. |
| // Preserves being an unparenthesized string literal, possibly |
| // "use strict". |
| @@ -895,12 +917,15 @@ class PreParserStatement { |
| return code_ == kFunctionDeclaration; |
| } |
| + bool IsClassDeclaration() { return code_ == kClassDeclaration; } |
| + |
| private: |
| enum Type { |
| kUnknownStatement, |
| kStringLiteralExpressionStatement, |
| kUseStrictExpressionStatement, |
| - kFunctionDeclaration |
| + kFunctionDeclaration, |
| + kClassDeclaration |
| }; |
| explicit PreParserStatement(Type code) : code_(code) {} |
| @@ -975,11 +1000,12 @@ class PreParserFactory { |
| } |
| PreParserExpression NewObjectLiteralProperty(bool is_getter, |
| PreParserExpression value, |
| - int pos) { |
| + int pos, bool is_static) { |
| return PreParserExpression::Default(); |
| } |
| PreParserExpression NewObjectLiteralProperty(PreParserExpression key, |
| - PreParserExpression value) { |
| + PreParserExpression value, |
| + bool is_static) { |
| return PreParserExpression::Default(); |
| } |
| PreParserExpression NewObjectLiteral(PreParserExpressionList properties, |
| @@ -1065,6 +1091,13 @@ class PreParserFactory { |
| int position) { |
| return PreParserExpression::Default(); |
| } |
| + PreParserExpression NewClassLiteral(PreParserIdentifier name, |
| + PreParserExpression extends, |
| + PreParserExpressionList properties, |
| + AstValueFactory* ast_value_factory, |
| + int position) { |
| + return PreParserExpression::Default(); |
| + } |
| // Return the object itself as AstVisitor and implement the needed |
| // dummy method right in this class. |
| @@ -1103,6 +1136,7 @@ class PreParserTraits { |
| typedef PreParserExpression Expression; |
| typedef PreParserExpression YieldExpression; |
| typedef PreParserExpression FunctionLiteral; |
| + typedef PreParserExpression ClassLiteral; |
| typedef PreParserExpression ObjectLiteralProperty; |
| typedef PreParserExpression Literal; |
| typedef PreParserExpressionList ExpressionList; |
| @@ -1129,6 +1163,14 @@ class PreParserTraits { |
| return identifier.IsEvalOrArguments(); |
| } |
| + static bool IsPrototype(PreParserIdentifier identifier) { |
| + return identifier.IsPrototype(); |
| + } |
| + |
| + static bool IsConstructor(PreParserIdentifier identifier) { |
| + return identifier.IsConstructor(); |
| + } |
| + |
| // Returns true if the expression is of type "this.foo". |
| static bool IsThisProperty(PreParserExpression expression) { |
| return expression.IsThisProperty(); |
| @@ -1249,6 +1291,9 @@ class PreParserTraits { |
| static PreParserExpression EmptyObjectLiteralProperty() { |
| return PreParserExpression::Default(); |
| } |
| + static PreParserExpression EmptyClassLiteral() { |
| + return PreParserExpression::Default(); |
| + } |
| static PreParserExpressionList NullExpressionList() { |
| return PreParserExpressionList(); |
| } |
| @@ -1439,6 +1484,7 @@ class PreParser : public ParserBase<PreParserTraits> { |
| SourceElements ParseSourceElements(int end_token, bool* ok); |
| Statement ParseStatement(bool* ok); |
| Statement ParseFunctionDeclaration(bool* ok); |
| + Statement ParseClassDeclaration(bool* ok); |
| Statement ParseBlock(bool* ok); |
| Statement ParseVariableStatement(VariableDeclarationContext var_context, |
| bool* ok); |
| @@ -1712,6 +1758,7 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) { |
| // ArrayLiteral |
| // ObjectLiteral |
| // RegExpLiteral |
| + // ClassLiteral |
| // '(' Expression ')' |
| int pos = peek_position(); |
| @@ -1782,6 +1829,23 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) { |
| } |
| break; |
| + case Token::CLASS: { |
| + Consume(Token::CLASS); |
| + int class_token_position = position(); |
| + IdentifierT name = this->EmptyIdentifier(); |
| + bool is_strict_reserved_name = false; |
| + Scanner::Location class_name_location = Scanner::Location::invalid(); |
| + if (peek_any_identifier()) { |
| + name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, |
| + CHECK_OK); |
| + class_name_location = scanner()->location(); |
| + } |
| + result = this->ParseClassLiteral(name, class_name_location, |
| + is_strict_reserved_name, |
| + class_token_position, CHECK_OK); |
| + break; |
| + } |
| + |
| case Token::MOD: |
| if (allow_natives_syntax() || extension_ != NULL) { |
| result = this->ParseV8Intrinsic(CHECK_OK); |
| @@ -1852,36 +1916,48 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral( |
| template <class Traits> |
| typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParsePropertyName( |
| - bool* is_getter, bool* is_setter, bool* ok) { |
| + bool* is_get, bool* is_set, bool* is_static, bool* ok) { |
| Token::Value next = peek(); |
| switch (next) { |
| case Token::STRING: |
| Consume(Token::STRING); |
| return this->GetSymbol(scanner_); |
| + |
| case Token::NUMBER: |
| Consume(Token::NUMBER); |
| return this->GetNumberAsSymbol(scanner_); |
| + |
| + case Token::STATIC: |
| + *is_static = true; |
| + // Fall through. |
| + |
| default: |
| - return ParseIdentifierNameOrGetOrSet(is_getter, is_setter, |
| - CHECK_OK_CUSTOM(EmptyIdentifier)); |
| + return ParseIdentifierNameOrGetOrSet(is_get, is_set, ok); |
| } |
| + |
| + UNREACHABLE(); |
| + return this->EmptyIdentifier(); |
| } |
| template <class Traits> |
| typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase< |
| - Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, bool* ok) { |
| + Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, |
| + bool in_class, bool is_static, bool* ok) { |
| // TODO(arv): Add support for concise generator methods. |
| ExpressionT value = this->EmptyExpression(); |
| - bool is_getter = false; |
| - bool is_setter = false; |
| + bool is_get = false; |
| + bool is_set = false; |
| + bool name_is_static = false; |
| Token::Value name_token = peek(); |
| int next_pos = peek_position(); |
| - IdentifierT name = ParsePropertyName( |
| - &is_getter, &is_setter, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| + IdentifierT name = |
| + ParsePropertyName(&is_get, &is_set, &name_is_static, |
| + CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| + |
| if (fni_ != NULL) this->PushLiteralName(fni_, name); |
| - if (peek() == Token::COLON) { |
| + if (!in_class && peek() == Token::COLON) { |
| // PropertyDefinition : PropertyName ':' AssignmentExpression |
| checker->CheckProperty(name_token, kValueProperty, |
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| @@ -1891,6 +1967,13 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase< |
| } else if (allow_harmony_object_literals_ && peek() == Token::LPAREN) { |
| // Concise Method |
| + |
| + if (is_static && this->IsPrototype(name)) { |
| + ReportMessageAt(scanner()->location(), "static_prototype"); |
| + *ok = false; |
| + return this->EmptyObjectLiteralProperty(); |
| + } |
| + |
| checker->CheckProperty(name_token, kValueProperty, |
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| value = this->ParseFunctionLiteral( |
| @@ -1900,25 +1983,40 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase< |
| FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::NORMAL_ARITY, |
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| - } else if (is_getter || is_setter) { |
| + } else if (in_class && name_is_static && !is_static) { |
| + // static MethodDefinition |
| + return ParsePropertyDefinition(checker, true, true, ok); |
| + |
| + } else if (is_get || is_set) { |
| // Accessor |
| bool dont_care = false; |
| name_token = peek(); |
| - name = ParsePropertyName(&dont_care, &dont_care, |
| + name = ParsePropertyName(&dont_care, &dont_care, &dont_care, |
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| + |
| // Validate the property. |
| + if (is_static && this->IsPrototype(name)) { |
| + ReportMessageAt(scanner()->location(), "static_prototype"); |
| + *ok = false; |
| + return this->EmptyObjectLiteralProperty(); |
| + } else if (this->IsConstructor(name)) { |
| + ReportMessageAt(scanner()->location(), "constructor_special_method"); |
| + *ok = false; |
| + return this->EmptyObjectLiteralProperty(); |
| + } |
| checker->CheckProperty(name_token, |
| - is_getter ? kGetterProperty : kSetterProperty, |
| + is_get ? kGetterProperty : kSetterProperty, |
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| + |
| typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral( |
| name, scanner()->location(), |
| false, // reserved words are allowed here |
| FunctionKind::kNormalFunction, RelocInfo::kNoPosition, |
| FunctionLiteral::ANONYMOUS_EXPRESSION, |
| - is_getter ? FunctionLiteral::GETTER_ARITY |
| - : FunctionLiteral::SETTER_ARITY, |
| + is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY, |
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| - return factory()->NewObjectLiteralProperty(is_getter, value, next_pos); |
| + return factory()->NewObjectLiteralProperty(is_get, value, next_pos, |
| + is_static); |
| } else { |
| Token::Value next = Next(); |
| ReportUnexpectedToken(next); |
| @@ -1931,7 +2029,7 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase< |
| ? factory()->NewNumberLiteral(index, next_pos) |
| : factory()->NewStringLiteral(name, next_pos); |
| - return factory()->NewObjectLiteralProperty(key, value); |
| + return factory()->NewObjectLiteralProperty(key, value, is_static); |
| } |
| @@ -1951,11 +2049,13 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral( |
| Expect(Token::LBRACE, CHECK_OK); |
| + const bool in_class = false; |
| + const bool is_static = false; |
| while (peek() != Token::RBRACE) { |
| if (fni_ != NULL) fni_->Enter(); |
| ObjectLiteralPropertyT property = |
| - this->ParsePropertyDefinition(&checker, CHECK_OK); |
| + this->ParsePropertyDefinition(&checker, in_class, is_static, CHECK_OK); |
| // Mark top-level object literals that contain function literals and |
| // pretenure the literal so it can be added as a constant function |
| @@ -2404,7 +2504,7 @@ template <class Traits> |
| typename ParserBase<Traits>::ExpressionT |
| ParserBase<Traits>::ParseMemberExpression(bool* ok) { |
| // MemberExpression :: |
| - // (PrimaryExpression | FunctionLiteral) |
| + // (PrimaryExpression | FunctionLiteral | ClassLiteral) |
| // ('[' Expression ']' | '.' Identifier | Arguments)* |
| // The '[' Expression ']' and '.' Identifier parts are parsed by |
| @@ -2607,6 +2707,57 @@ typename ParserBase<Traits>::ExpressionT ParserBase< |
| } |
| +template <class Traits> |
| +typename ParserBase<Traits>::ClassLiteralT |
| +ParserBase<Traits>::ParseClassLiteral(IdentifierT name, |
| + Scanner::Location class_name_location, |
| + bool name_is_strict_reserved, int pos, |
| + bool* ok) { |
| + // Classes are always strict. |
| + if (name_is_strict_reserved) { |
| + ReportMessageAt(class_name_location, "unexpected_strict_reserved"); |
| + *ok = false; |
| + return this->EmptyClassLiteral(); |
| + } |
| + if (this->IsEvalOrArguments(name)) { |
| + ReportMessageAt(class_name_location, "strict_eval_arguments"); |
| + *ok = false; |
| + return this->EmptyClassLiteral(); |
| + } |
| + |
| + ExpressionT extends = this->EmptyExpression(); |
| + if (Check(Token::EXTENDS)) { |
| + extends = |
| + this->ParseLeftHandSideExpression(CHECK_OK_CUSTOM(EmptyClassLiteral)); |
| + } |
| + |
| + ObjectLiteralChecker checker(this, strict_mode()); |
| + const bool in_class = true; |
| + const bool is_static = false; |
| + typename Traits::Type::PropertyList properties = |
| + this->NewPropertyList(4, zone_); |
| + |
| + Expect(Token::LBRACE, CHECK_OK_CUSTOM(EmptyClassLiteral)); |
| + while (peek() != Token::RBRACE) { |
| + if (Check(Token::SEMICOLON)) continue; |
| + if (fni_ != NULL) fni_->Enter(); |
| + |
| + ObjectLiteralPropertyT property = this->ParsePropertyDefinition( |
| + &checker, in_class, is_static, CHECK_OK_CUSTOM(EmptyClassLiteral)); |
| + properties->Add(property, zone()); |
| + |
| + if (fni_ != NULL) { |
| + fni_->Infer(); |
| + fni_->Leave(); |
| + } |
| + } |
| + Expect(Token::RBRACE, CHECK_OK_CUSTOM(EmptyClassLiteral)); |
| + |
| + return factory()->NewClassLiteral(name, extends, properties, |
| + this->ast_value_factory(), pos); |
| +} |
| + |
| + |
| template <typename Traits> |
| typename ParserBase<Traits>::ExpressionT |
| ParserBase<Traits>::CheckAndRewriteReferenceExpression( |