Chromium Code Reviews| Index: src/preparser.h |
| diff --git a/src/preparser.h b/src/preparser.h |
| index b378f47f6576f2739bd9bcad36da634dcff9c752..a2170541fee007738177df008ac5fe6b76bf05d7 100644 |
| --- a/src/preparser.h |
| +++ b/src/preparser.h |
| @@ -87,6 +87,7 @@ class ParserBase : public Traits { |
| allow_harmony_arrow_functions_(false), |
| allow_harmony_object_literals_(false), |
| allow_harmony_sloppy_(false), |
| + allow_harmony_computed_property_names_(false), |
| zone_(zone) {} |
| // Getters that indicate whether certain syntactical constructs are |
| @@ -108,6 +109,9 @@ class ParserBase : public Traits { |
| bool allow_harmony_templates() const { return scanner()->HarmonyTemplates(); } |
| bool allow_harmony_sloppy() const { return allow_harmony_sloppy_; } |
| bool allow_harmony_unicode() const { return scanner()->HarmonyUnicode(); } |
| + bool allow_harmony_computed_property_names() const { |
| + return allow_harmony_computed_property_names_; |
| + } |
| // Setters that determine whether certain syntactical constructs are |
| // allowed to be parsed by this instance of the parser. |
| @@ -140,6 +144,9 @@ class ParserBase : public Traits { |
| void set_allow_harmony_unicode(bool allow) { |
| scanner()->SetHarmonyUnicode(allow); |
| } |
| + void set_allow_harmony_computed_property_names(bool allow) { |
| + allow_harmony_computed_property_names_ = allow; |
| + } |
| protected: |
| enum AllowEvalOrArgumentsAsIdentifier { |
| @@ -490,11 +497,13 @@ 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, |
| + ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, |
| + bool* is_static, bool* is_computed_name, |
| bool* ok); |
| ExpressionT ParseObjectLiteral(bool* ok); |
| ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker, |
| bool in_class, bool is_static, |
| + bool* is_computed_name, |
| bool* has_seen_constructor, |
| bool* ok); |
| typename Traits::Type::ExpressionList ParseArguments(bool* ok); |
| @@ -598,6 +607,7 @@ class ParserBase : public Traits { |
| bool allow_harmony_arrow_functions_; |
| bool allow_harmony_object_literals_; |
| bool allow_harmony_sloppy_; |
| + bool allow_harmony_computed_property_names_; |
| typename Traits::Type::Zone* zone_; // Only used by Parser. |
| }; |
| @@ -1019,13 +1029,16 @@ class PreParserFactory { |
| return PreParserExpression::Default(); |
| } |
| PreParserExpression NewObjectLiteralProperty(bool is_getter, |
| + PreParserExpression key, |
| PreParserExpression value, |
| - int pos, bool is_static) { |
| + int pos, bool is_static, |
| + bool is_computed_name) { |
| return PreParserExpression::Default(); |
| } |
| PreParserExpression NewObjectLiteralProperty(PreParserExpression key, |
| PreParserExpression value, |
| - bool is_static) { |
| + bool is_static, |
| + bool is_computed_name) { |
| return PreParserExpression::Default(); |
| } |
| PreParserExpression NewObjectLiteral(PreParserExpressionList properties, |
| @@ -1211,11 +1224,20 @@ class PreParserTraits { |
| // PreParser should not use FuncNameInferrer. |
| UNREACHABLE(); |
| } |
| + static void PushLiteralName(FuncNameInferrer* fni, |
| + PreParserExpression expression) { |
| + // PreParser should not use FuncNameInferrer. |
| + UNREACHABLE(); |
| + } |
| static void PushPropertyName(FuncNameInferrer* fni, |
| PreParserExpression expression) { |
| // PreParser should not use FuncNameInferrer. |
| UNREACHABLE(); |
| } |
| + static void PushVariableName(FuncNameInferrer* fni, PreParserIdentifier id) { |
| + // PreParser should not use FuncNameInferrer. |
| + UNREACHABLE(); |
| + } |
| static void InferFunctionName(FuncNameInferrer* fni, |
| PreParserExpression expression) { |
| // PreParser should not use FuncNameInferrer. |
| @@ -1815,12 +1837,14 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) { |
| // Using eval or arguments in this context is OK even in strict mode. |
| IdentifierT name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| result = this->ExpressionFromIdentifier(name, pos, scope_, factory()); |
| + if (fni_ != NULL) this->PushVariableName(fni_, name); |
| break; |
| } |
| case Token::STRING: { |
| Consume(Token::STRING); |
| result = this->ExpressionFromString(pos, scanner(), factory()); |
| + if (fni_ != NULL) this->PushLiteralName(fni_, result); |
| break; |
| } |
| @@ -1955,24 +1979,55 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral( |
| template <class Traits> |
| -typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParsePropertyName( |
| - bool* is_get, bool* is_set, bool* is_static, bool* ok) { |
| - Token::Value next = peek(); |
| - switch (next) { |
| +typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName( |
| + IdentifierT* name, bool* is_get, bool* is_set, bool* is_static, |
| + bool* is_computed_name, bool* ok) { |
| + Token::Value token = peek(); |
| + int pos = peek_position(); |
| + |
| + // For non computed property names we normalize the name a bit: |
| + // |
| + // "12" -> 12 |
| + // 12.3 -> "12.3" |
| + // 12.30 -> "12.3" |
| + // identifier -> "identifier" |
| + // |
| + // This is important because we use the property name as a key in a hash |
| + // table when we computed constant properties. |
| + switch (token) { |
| case Token::STRING: |
| Consume(Token::STRING); |
| - return this->GetSymbol(scanner_); |
| + *name = this->GetSymbol(scanner()); |
| + break; |
| + |
| case Token::NUMBER: |
| Consume(Token::NUMBER); |
| - return this->GetNumberAsSymbol(scanner_); |
| + *name = this->GetNumberAsSymbol(scanner()); |
| + break; |
| + |
| + case Token::LBRACK: |
| + if (allow_harmony_computed_property_names_) { |
| + *is_computed_name = true; |
| + Consume(Token::LBRACK); |
| + ExpressionT expression = ParseAssignmentExpression(true, CHECK_OK); |
| + Consume(Token::RBRACK); |
| + return expression; |
| + } |
| + |
| + // Fall through. |
| case Token::STATIC: |
| *is_static = true; |
| - // Fall through. |
| + |
| + // Fall through. |
| default: |
| - return ParseIdentifierNameOrGetOrSet(is_get, is_set, ok); |
| + *name = ParseIdentifierNameOrGetOrSet(is_get, is_set, CHECK_OK); |
| + break; |
| } |
| - UNREACHABLE(); |
| - return this->EmptyIdentifier(); |
| + |
| + uint32_t index; |
| + return this->IsArrayIndex(*name, &index) |
| + ? factory()->NewNumberLiteral(index, pos) |
| + : factory()->NewStringLiteral(*name, pos); |
| } |
| @@ -1980,9 +2035,11 @@ template <class Traits> |
| typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase< |
| Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, |
| bool in_class, bool is_static, |
| + bool* is_computed_name, |
| bool* has_seen_constructor, bool* ok) { |
| DCHECK(!in_class || is_static || has_seen_constructor != NULL); |
| ExpressionT value = this->EmptyExpression(); |
| + IdentifierT name = this->EmptyIdentifier(); |
| bool is_get = false; |
| bool is_set = false; |
| bool name_is_static = false; |
| @@ -1990,15 +2047,17 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase< |
| Token::Value name_token = peek(); |
| int next_pos = peek_position(); |
| - IdentifierT name = |
| - ParsePropertyName(&is_get, &is_set, &name_is_static, |
| - CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| + ExpressionT name_expression = ParsePropertyName( |
| + &name, &is_get, &is_set, &name_is_static, is_computed_name, |
| + CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| - if (fni_ != NULL) this->PushLiteralName(fni_, name); |
| + if (!*is_computed_name && fni_ != NULL) { |
|
arv (Not doing code reviews)
2014/12/10 23:38:13
if (fni_ != NULL) {
since name is empty string fo
arv (Not doing code reviews)
2014/12/11 23:10:33
This one is needed.
|
| + this->PushLiteralName(fni_, name); |
| + } |
| if (!in_class && !is_generator && peek() == Token::COLON) { |
| // PropertyDefinition : PropertyName ':' AssignmentExpression |
| - if (checker != NULL) { |
| + if (!*is_computed_name && checker != NULL) { |
|
arv (Not doing code reviews)
2014/12/10 23:38:13
maybe same here... need to check
arv (Not doing code reviews)
2014/12/11 23:10:33
This one is needed too.
|
| checker->CheckProperty(name_token, kValueProperty, |
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| } |
| @@ -2036,7 +2095,7 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase< |
| kind = FunctionKind::kNormalFunction; |
| } |
| - if (checker != NULL) { |
| + if (!*is_computed_name && checker != NULL) { |
| checker->CheckProperty(name_token, kValueProperty, |
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| } |
| @@ -2050,17 +2109,21 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase< |
| } else if (in_class && name_is_static && !is_static) { |
| // static MethodDefinition |
| - return ParsePropertyDefinition(checker, true, true, NULL, ok); |
| + return ParsePropertyDefinition(checker, true, true, is_computed_name, NULL, |
| + ok); |
| } else if (is_get || is_set) { |
| // Accessor |
| + name = this->EmptyIdentifier(); |
| bool dont_care = false; |
| name_token = peek(); |
| - name = ParsePropertyName(&dont_care, &dont_care, &dont_care, |
| - CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| + |
| + name_expression = ParsePropertyName( |
| + &name, &dont_care, &dont_care, &dont_care, is_computed_name, |
| + CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| // Validate the property. |
| - if (is_static && this->IsPrototype(name)) { |
| + if (is_static && !*is_computed_name && this->IsPrototype(name)) { |
|
arv (Not doing code reviews)
2014/12/11 23:10:34
this one is not needed because IsPrototype will be
|
| ReportMessageAt(scanner()->location(), "static_prototype"); |
| *ok = false; |
| return this->EmptyObjectLiteralProperty(); |
| @@ -2069,7 +2132,7 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase< |
| *ok = false; |
| return this->EmptyObjectLiteralProperty(); |
| } |
| - if (checker != NULL) { |
| + if (!*is_computed_name && checker != NULL) { |
| checker->CheckProperty(name_token, |
| is_get ? kGetterProperty : kSetterProperty, |
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| @@ -2082,8 +2145,9 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase< |
| FunctionLiteral::ANONYMOUS_EXPRESSION, |
| is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY, |
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| - return factory()->NewObjectLiteralProperty(is_get, value, next_pos, |
| - is_static); |
| + |
| + return factory()->NewObjectLiteralProperty( |
| + is_get, name_expression, value, next_pos, is_static, *is_computed_name); |
| } else if (!in_class && allow_harmony_object_literals_ && |
| Token::IsIdentifier(name_token, strict_mode(), |
| @@ -2097,12 +2161,8 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase< |
| return this->EmptyObjectLiteralProperty(); |
| } |
| - uint32_t index; |
| - LiteralT key = this->IsArrayIndex(name, &index) |
| - ? factory()->NewNumberLiteral(index, next_pos) |
| - : factory()->NewStringLiteral(name, next_pos); |
| - |
| - return factory()->NewObjectLiteralProperty(key, value, is_static); |
| + return factory()->NewObjectLiteralProperty(name_expression, value, is_static, |
| + *is_computed_name); |
| } |
| @@ -2117,6 +2177,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral( |
| this->NewPropertyList(4, zone_); |
| int number_of_boilerplate_properties = 0; |
| bool has_function = false; |
| + bool has_computed_names = false; |
| ObjectLiteralChecker checker(this, strict_mode()); |
| @@ -2127,8 +2188,13 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral( |
| const bool in_class = false; |
| const bool is_static = false; |
| + bool is_computed_name = false; |
| ObjectLiteralPropertyT property = this->ParsePropertyDefinition( |
| - &checker, in_class, is_static, NULL, CHECK_OK); |
| + &checker, in_class, is_static, &is_computed_name, NULL, CHECK_OK); |
| + |
| + if (is_computed_name) { |
| + has_computed_names = true; |
| + } |
| // Mark top-level object literals that contain function literals and |
| // pretenure the literal so it can be added as a constant function |
| @@ -2137,7 +2203,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral( |
| &has_function); |
| // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
| - if (this->IsBoilerplateProperty(property)) { |
| + if (!has_computed_names && this->IsBoilerplateProperty(property)) { |
| number_of_boilerplate_properties++; |
| } |
| properties->Add(property, zone()); |