OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_PREPARSER_H | 5 #ifndef V8_PREPARSER_H |
6 #define V8_PREPARSER_H | 6 #define V8_PREPARSER_H |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/bailout-reason.h" | 10 #include "src/bailout-reason.h" |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
154 kAllowEvalOrArguments, | 154 kAllowEvalOrArguments, |
155 kDontAllowEvalOrArguments | 155 kDontAllowEvalOrArguments |
156 }; | 156 }; |
157 | 157 |
158 enum Mode { | 158 enum Mode { |
159 PARSE_LAZILY, | 159 PARSE_LAZILY, |
160 PARSE_EAGERLY | 160 PARSE_EAGERLY |
161 }; | 161 }; |
162 | 162 |
163 class Checkpoint; | 163 class Checkpoint; |
164 class ObjectLiteralChecker; | 164 class ObjectLiteralCheckerBase; |
165 | 165 |
166 // --------------------------------------------------------------------------- | 166 // --------------------------------------------------------------------------- |
167 // FunctionState and BlockState together implement the parser's scope stack. | 167 // FunctionState and BlockState together implement the parser's scope stack. |
168 // The parser's current scope is in scope_. BlockState and FunctionState | 168 // The parser's current scope is in scope_. BlockState and FunctionState |
169 // constructors push on the scope stack and the destructors pop. They are also | 169 // constructors push on the scope stack and the destructors pop. They are also |
170 // used to hold the parser's per-function and per-block state. | 170 // used to hold the parser's per-function and per-block state. |
171 class BlockState BASE_EMBEDDED { | 171 class BlockState BASE_EMBEDDED { |
172 public: | 172 public: |
173 BlockState(typename Traits::Type::Scope** scope_stack, | 173 BlockState(typename Traits::Type::Scope** scope_stack, |
174 typename Traits::Type::Scope* scope) | 174 typename Traits::Type::Scope* scope) |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
505 | 505 |
506 ExpressionT ParseRegExpLiteral(bool seen_equal, bool* ok); | 506 ExpressionT ParseRegExpLiteral(bool seen_equal, bool* ok); |
507 | 507 |
508 ExpressionT ParsePrimaryExpression(bool* ok); | 508 ExpressionT ParsePrimaryExpression(bool* ok); |
509 ExpressionT ParseExpression(bool accept_IN, bool* ok); | 509 ExpressionT ParseExpression(bool accept_IN, bool* ok); |
510 ExpressionT ParseArrayLiteral(bool* ok); | 510 ExpressionT ParseArrayLiteral(bool* ok); |
511 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, | 511 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, |
512 bool* is_static, bool* is_computed_name, | 512 bool* is_static, bool* is_computed_name, |
513 bool* ok); | 513 bool* ok); |
514 ExpressionT ParseObjectLiteral(bool* ok); | 514 ExpressionT ParseObjectLiteral(bool* ok); |
515 ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker, | 515 ObjectLiteralPropertyT ParsePropertyDefinition( |
516 bool in_class, bool is_static, | 516 ObjectLiteralCheckerBase* checker, bool in_class, bool is_static, |
517 bool* is_computed_name, | 517 bool* is_computed_name, bool* has_seen_constructor, bool* ok); |
518 bool* has_seen_constructor, | |
519 bool* ok); | |
520 typename Traits::Type::ExpressionList ParseArguments(bool* ok); | 518 typename Traits::Type::ExpressionList ParseArguments(bool* ok); |
521 ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok); | 519 ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok); |
522 ExpressionT ParseYieldExpression(bool* ok); | 520 ExpressionT ParseYieldExpression(bool* ok); |
523 ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok); | 521 ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok); |
524 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok); | 522 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok); |
525 ExpressionT ParseUnaryExpression(bool* ok); | 523 ExpressionT ParseUnaryExpression(bool* ok); |
526 ExpressionT ParsePostfixExpression(bool* ok); | 524 ExpressionT ParsePostfixExpression(bool* ok); |
527 ExpressionT ParseLeftHandSideExpression(bool* ok); | 525 ExpressionT ParseLeftHandSideExpression(bool* ok); |
528 ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok); | 526 ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok); |
529 ExpressionT ParseMemberExpression(bool* ok); | 527 ExpressionT ParseMemberExpression(bool* ok); |
530 ExpressionT ParseMemberExpressionContinuation(ExpressionT expression, | 528 ExpressionT ParseMemberExpressionContinuation(ExpressionT expression, |
531 bool* ok); | 529 bool* ok); |
532 ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast, | 530 ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast, |
533 bool* ok); | 531 bool* ok); |
534 ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok); | 532 ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok); |
535 void AddTemplateExpression(ExpressionT); | 533 void AddTemplateExpression(ExpressionT); |
536 | 534 |
537 // Checks if the expression is a valid reference expression (e.g., on the | 535 // Checks if the expression is a valid reference expression (e.g., on the |
538 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 536 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
539 // we allow calls for web compatibility and rewrite them to a runtime throw. | 537 // we allow calls for web compatibility and rewrite them to a runtime throw. |
540 ExpressionT CheckAndRewriteReferenceExpression( | 538 ExpressionT CheckAndRewriteReferenceExpression( |
541 ExpressionT expression, | 539 ExpressionT expression, |
542 Scanner::Location location, const char* message, bool* ok); | 540 Scanner::Location location, const char* message, bool* ok); |
543 | 541 |
544 // Used to detect duplicates in object literals. Each of the values | 542 // Used to validate property names in object literals and class literals |
545 // kGetterProperty, kSetterProperty and kValueProperty represents | |
546 // a type of object literal property. When parsing a property, its | |
547 // type value is stored in the DuplicateFinder for the property name. | |
548 // Values are chosen so that having intersection bits means the there is | |
549 // an incompatibility. | |
550 // I.e., you can add a getter to a property that already has a setter, since | |
551 // kGetterProperty and kSetterProperty doesn't intersect, but not if it | |
552 // already has a getter or a value. Adding the getter to an existing | |
553 // setter will store the value (kGetterProperty | kSetterProperty), which | |
554 // is incompatible with adding any further properties. | |
555 enum PropertyKind { | 543 enum PropertyKind { |
556 kNone = 0, | 544 kAccessorProperty = 1, |
557 // Bit patterns representing different object literal property types. | 545 kValueProperty = 2, |
558 kGetterProperty = 1, | 546 kMethodProperty = 3 |
adamk
2015/01/27 20:05:48
Given that these are no longer bit patterns, you s
arv (Not doing code reviews)
2015/01/28 02:37:15
Done.
| |
559 kSetterProperty = 2, | |
560 kValueProperty = 7, | |
561 // Helper constants. | |
562 kValueFlag = 4 | |
563 }; | 547 }; |
564 | 548 |
565 // Validation per ECMA 262 - 11.1.5 "Object Initializer". | 549 class ObjectLiteralCheckerBase { |
566 class ObjectLiteralChecker { | |
567 public: | 550 public: |
568 ObjectLiteralChecker(ParserBase* parser, StrictMode strict_mode) | 551 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {} |
569 : parser_(parser), | |
570 finder_(scanner()->unicode_cache()), | |
571 strict_mode_(strict_mode) {} | |
572 | 552 |
573 void CheckProperty(Token::Value property, PropertyKind type, bool* ok); | 553 virtual void CheckProperty(Token::Value property, PropertyKind type, |
554 bool is_static, bool is_generator, bool* ok) = 0; | |
574 | 555 |
575 private: | 556 protected: |
576 ParserBase* parser() const { return parser_; } | 557 ParserBase* parser() const { return parser_; } |
577 Scanner* scanner() const { return parser_->scanner(); } | 558 Scanner* scanner() const { return parser_->scanner(); } |
578 | 559 |
579 // Checks the type of conflict based on values coming from PropertyType. | 560 private: |
580 bool HasConflict(PropertyKind type1, PropertyKind type2) { | 561 ParserBase* parser_; |
581 return (type1 & type2) != 0; | 562 }; |
563 | |
564 // Validation per ES6 object literals. | |
565 class ObjectLiteralChecker : public ObjectLiteralCheckerBase { | |
566 public: | |
567 explicit ObjectLiteralChecker(ParserBase* parser) | |
568 : ObjectLiteralCheckerBase(parser), has_seen_proto_(false) {} | |
569 | |
570 void CheckProperty(Token::Value property, PropertyKind type, bool is_static, | |
571 bool is_generator, bool* ok) OVERRIDE; | |
572 | |
573 private: | |
574 bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); } | |
575 | |
576 bool has_seen_proto_; | |
577 }; | |
578 | |
579 // Validation per ES6 class literals. | |
580 class ClassLiteralChecker : public ObjectLiteralCheckerBase { | |
581 public: | |
582 explicit ClassLiteralChecker(ParserBase* parser) | |
583 : ObjectLiteralCheckerBase(parser), has_seen_constructor_(false) {} | |
584 | |
585 void CheckProperty(Token::Value property, PropertyKind type, bool is_static, | |
586 bool is_generator, bool* ok) OVERRIDE; | |
587 | |
588 private: | |
589 bool IsConstructor() { | |
590 return this->scanner()->LiteralMatches("constructor", 11); | |
582 } | 591 } |
583 bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) { | 592 bool IsPrototype() { |
584 return ((type1 & type2) & kValueFlag) != 0; | 593 return this->scanner()->LiteralMatches("prototype", 9); |
585 } | |
586 bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) { | |
587 return ((type1 ^ type2) & kValueFlag) != 0; | |
588 } | |
589 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) { | |
590 return ((type1 | type2) & kValueFlag) == 0; | |
591 } | 594 } |
592 | 595 |
593 ParserBase* parser_; | 596 bool has_seen_constructor_; |
594 DuplicateFinder finder_; | |
595 StrictMode strict_mode_; | |
596 }; | 597 }; |
597 | 598 |
599 | |
598 // If true, the next (and immediately following) function literal is | 600 // If true, the next (and immediately following) function literal is |
599 // preceded by a parenthesis. | 601 // preceded by a parenthesis. |
600 // Heuristically that means that the function will be called immediately, | 602 // Heuristically that means that the function will be called immediately, |
601 // so never lazily compile it. | 603 // so never lazily compile it. |
602 bool parenthesized_function_; | 604 bool parenthesized_function_; |
603 | 605 |
604 typename Traits::Type::Scope* scope_; // Scope stack. | 606 typename Traits::Type::Scope* scope_; // Scope stack. |
605 FunctionState* function_state_; // Function state stack. | 607 FunctionState* function_state_; // Function state stack. |
606 v8::Extension* extension_; | 608 v8::Extension* extension_; |
607 FuncNameInferrer* fni_; | 609 FuncNameInferrer* fni_; |
(...skipping 1455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2063 | 2065 |
2064 uint32_t index; | 2066 uint32_t index; |
2065 return this->IsArrayIndex(*name, &index) | 2067 return this->IsArrayIndex(*name, &index) |
2066 ? factory()->NewNumberLiteral(index, pos) | 2068 ? factory()->NewNumberLiteral(index, pos) |
2067 : factory()->NewStringLiteral(*name, pos); | 2069 : factory()->NewStringLiteral(*name, pos); |
2068 } | 2070 } |
2069 | 2071 |
2070 | 2072 |
2071 template <class Traits> | 2073 template <class Traits> |
2072 typename ParserBase<Traits>::ObjectLiteralPropertyT | 2074 typename ParserBase<Traits>::ObjectLiteralPropertyT |
2073 ParserBase<Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, | 2075 ParserBase<Traits>::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker, |
2074 bool in_class, bool is_static, | 2076 bool in_class, bool is_static, |
2075 bool* is_computed_name, | 2077 bool* is_computed_name, |
2076 bool* has_seen_constructor, | 2078 bool* has_seen_constructor, |
2077 bool* ok) { | 2079 bool* ok) { |
2078 DCHECK(!in_class || is_static || has_seen_constructor != NULL); | 2080 DCHECK(!in_class || is_static || has_seen_constructor != nullptr); |
2079 ExpressionT value = this->EmptyExpression(); | 2081 ExpressionT value = this->EmptyExpression(); |
2080 IdentifierT name = this->EmptyIdentifier(); | 2082 IdentifierT name = this->EmptyIdentifier(); |
2081 bool is_get = false; | 2083 bool is_get = false; |
2082 bool is_set = false; | 2084 bool is_set = false; |
2083 bool name_is_static = false; | 2085 bool name_is_static = false; |
2084 bool is_generator = allow_harmony_object_literals_ && Check(Token::MUL); | 2086 bool is_generator = allow_harmony_object_literals_ && Check(Token::MUL); |
2085 | 2087 |
2086 Token::Value name_token = peek(); | 2088 Token::Value name_token = peek(); |
2087 int next_pos = peek_position(); | 2089 int next_pos = peek_position(); |
2088 ExpressionT name_expression = ParsePropertyName( | 2090 ExpressionT name_expression = ParsePropertyName( |
2089 &name, &is_get, &is_set, &name_is_static, is_computed_name, | 2091 &name, &is_get, &is_set, &name_is_static, is_computed_name, |
2090 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2092 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2091 | 2093 |
2092 if (fni_ != NULL && !*is_computed_name) { | 2094 if (fni_ != nullptr && !*is_computed_name) { |
2093 this->PushLiteralName(fni_, name); | 2095 this->PushLiteralName(fni_, name); |
2094 } | 2096 } |
2095 | 2097 |
2096 if (!in_class && !is_generator && peek() == Token::COLON) { | 2098 if (!in_class && !is_generator && peek() == Token::COLON) { |
2097 // PropertyDefinition : PropertyName ':' AssignmentExpression | 2099 // PropertyDefinition : PropertyName ':' AssignmentExpression |
2098 if (!*is_computed_name && checker != NULL) { | 2100 if (!*is_computed_name) { |
2099 checker->CheckProperty(name_token, kValueProperty, | 2101 checker->CheckProperty(name_token, kValueProperty, is_static, |
2102 is_generator, | |
2100 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2103 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2101 } | 2104 } |
2102 Consume(Token::COLON); | 2105 Consume(Token::COLON); |
2103 value = this->ParseAssignmentExpression( | 2106 value = this->ParseAssignmentExpression( |
2104 true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2107 true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2105 | 2108 |
2106 } else if (is_generator || | 2109 } else if (is_generator || |
2107 (allow_harmony_object_literals_ && peek() == Token::LPAREN)) { | 2110 (allow_harmony_object_literals_ && peek() == Token::LPAREN)) { |
2108 // Concise Method | 2111 // Concise Method |
2109 | 2112 if (!*is_computed_name) { |
2110 if (is_static && this->IsPrototype(name)) { | 2113 checker->CheckProperty(name_token, kMethodProperty, is_static, |
2111 ReportMessageAt(scanner()->location(), "static_prototype"); | 2114 is_generator, |
2112 *ok = false; | 2115 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2113 return this->EmptyObjectLiteralProperty(); | |
2114 } | 2116 } |
2115 | 2117 |
2116 FunctionKind kind = is_generator ? FunctionKind::kConciseGeneratorMethod | 2118 FunctionKind kind = is_generator ? FunctionKind::kConciseGeneratorMethod |
2117 : FunctionKind::kConciseMethod; | 2119 : FunctionKind::kConciseMethod; |
2118 | 2120 |
2119 if (in_class && !is_static && this->IsConstructor(name)) { | 2121 if (in_class && !is_static && this->IsConstructor(name)) { |
2120 if (is_generator) { | |
2121 ReportMessageAt(scanner()->location(), "constructor_special_method"); | |
2122 *ok = false; | |
2123 return this->EmptyObjectLiteralProperty(); | |
2124 } | |
2125 | |
2126 if (*has_seen_constructor) { | |
2127 ReportMessageAt(scanner()->location(), "duplicate_constructor"); | |
2128 *ok = false; | |
2129 return this->EmptyObjectLiteralProperty(); | |
2130 } | |
2131 | |
2132 *has_seen_constructor = true; | 2122 *has_seen_constructor = true; |
2133 kind = FunctionKind::kNormalFunction; | 2123 kind = FunctionKind::kNormalFunction; |
2134 } | 2124 } |
2135 | 2125 |
2136 if (!*is_computed_name && checker != NULL) { | |
2137 checker->CheckProperty(name_token, kValueProperty, | |
2138 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2139 } | |
2140 | |
2141 value = this->ParseFunctionLiteral( | 2126 value = this->ParseFunctionLiteral( |
2142 name, scanner()->location(), | 2127 name, scanner()->location(), |
2143 false, // reserved words are allowed here | 2128 false, // reserved words are allowed here |
2144 kind, RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, | 2129 kind, RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, |
2145 FunctionLiteral::NORMAL_ARITY, | 2130 FunctionLiteral::NORMAL_ARITY, |
2146 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2131 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2147 | 2132 |
2148 return factory()->NewObjectLiteralProperty(name_expression, value, | 2133 return factory()->NewObjectLiteralProperty(name_expression, value, |
2149 ObjectLiteralProperty::COMPUTED, | 2134 ObjectLiteralProperty::COMPUTED, |
2150 is_static, *is_computed_name); | 2135 is_static, *is_computed_name); |
2151 | 2136 |
2152 } else if (in_class && name_is_static && !is_static) { | 2137 } else if (in_class && name_is_static && !is_static) { |
2153 // static MethodDefinition | 2138 // static MethodDefinition |
2154 return ParsePropertyDefinition(checker, true, true, is_computed_name, NULL, | 2139 return ParsePropertyDefinition(checker, true, true, is_computed_name, |
2155 ok); | 2140 nullptr, ok); |
2156 | 2141 |
2157 } else if (is_get || is_set) { | 2142 } else if (is_get || is_set) { |
2158 // Accessor | 2143 // Accessor |
2159 name = this->EmptyIdentifier(); | 2144 name = this->EmptyIdentifier(); |
2160 bool dont_care = false; | 2145 bool dont_care = false; |
2161 name_token = peek(); | 2146 name_token = peek(); |
2162 | 2147 |
2163 name_expression = ParsePropertyName( | 2148 name_expression = ParsePropertyName( |
2164 &name, &dont_care, &dont_care, &dont_care, is_computed_name, | 2149 &name, &dont_care, &dont_care, &dont_care, is_computed_name, |
2165 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2150 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2166 | 2151 |
2167 // Validate the property. | 2152 if (!*is_computed_name) { |
2168 if (is_static && this->IsPrototype(name)) { | 2153 checker->CheckProperty(name_token, kAccessorProperty, is_static, |
2169 ReportMessageAt(scanner()->location(), "static_prototype"); | 2154 is_generator, |
2170 *ok = false; | |
2171 return this->EmptyObjectLiteralProperty(); | |
2172 } else if (in_class && !is_static && this->IsConstructor(name)) { | |
2173 ReportMessageAt(scanner()->location(), "constructor_special_method"); | |
2174 *ok = false; | |
2175 return this->EmptyObjectLiteralProperty(); | |
2176 } | |
2177 if (!*is_computed_name && checker != NULL) { | |
2178 checker->CheckProperty(name_token, | |
2179 is_get ? kGetterProperty : kSetterProperty, | |
2180 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2155 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2181 } | 2156 } |
2182 | 2157 |
2183 typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral( | 2158 typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral( |
2184 name, scanner()->location(), | 2159 name, scanner()->location(), |
2185 false, // reserved words are allowed here | 2160 false, // reserved words are allowed here |
2186 FunctionKind::kNormalFunction, RelocInfo::kNoPosition, | 2161 FunctionKind::kNormalFunction, RelocInfo::kNoPosition, |
2187 FunctionLiteral::ANONYMOUS_EXPRESSION, | 2162 FunctionLiteral::ANONYMOUS_EXPRESSION, |
2188 is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY, | 2163 is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY, |
2189 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2164 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2227 bool* ok) { | 2202 bool* ok) { |
2228 // ObjectLiteral :: | 2203 // ObjectLiteral :: |
2229 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' | 2204 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' |
2230 | 2205 |
2231 int pos = peek_position(); | 2206 int pos = peek_position(); |
2232 typename Traits::Type::PropertyList properties = | 2207 typename Traits::Type::PropertyList properties = |
2233 this->NewPropertyList(4, zone_); | 2208 this->NewPropertyList(4, zone_); |
2234 int number_of_boilerplate_properties = 0; | 2209 int number_of_boilerplate_properties = 0; |
2235 bool has_function = false; | 2210 bool has_function = false; |
2236 bool has_computed_names = false; | 2211 bool has_computed_names = false; |
2237 | 2212 ObjectLiteralChecker checker(this); |
2238 ObjectLiteralChecker checker(this, strict_mode()); | |
2239 | 2213 |
2240 Expect(Token::LBRACE, CHECK_OK); | 2214 Expect(Token::LBRACE, CHECK_OK); |
2241 | 2215 |
2242 while (peek() != Token::RBRACE) { | 2216 while (peek() != Token::RBRACE) { |
2243 if (fni_ != NULL) fni_->Enter(); | 2217 if (fni_ != nullptr) fni_->Enter(); |
2244 | 2218 |
2245 const bool in_class = false; | 2219 const bool in_class = false; |
2246 const bool is_static = false; | 2220 const bool is_static = false; |
2247 bool is_computed_name = false; | 2221 bool is_computed_name = false; |
2248 ObjectLiteralPropertyT property = this->ParsePropertyDefinition( | 2222 ObjectLiteralPropertyT property = this->ParsePropertyDefinition( |
2249 &checker, in_class, is_static, &is_computed_name, NULL, CHECK_OK); | 2223 &checker, in_class, is_static, &is_computed_name, nullptr, CHECK_OK); |
2250 | 2224 |
2251 if (is_computed_name) { | 2225 if (is_computed_name) { |
2252 has_computed_names = true; | 2226 has_computed_names = true; |
2253 } | 2227 } |
2254 | 2228 |
2255 // Mark top-level object literals that contain function literals and | 2229 // Mark top-level object literals that contain function literals and |
2256 // pretenure the literal so it can be added as a constant function | 2230 // pretenure the literal so it can be added as a constant function |
2257 // property. (Parser only.) | 2231 // property. (Parser only.) |
2258 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, property, | 2232 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, property, |
2259 &has_function); | 2233 &has_function); |
2260 | 2234 |
2261 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | 2235 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
2262 if (!has_computed_names && this->IsBoilerplateProperty(property)) { | 2236 if (!has_computed_names && this->IsBoilerplateProperty(property)) { |
2263 number_of_boilerplate_properties++; | 2237 number_of_boilerplate_properties++; |
2264 } | 2238 } |
2265 properties->Add(property, zone()); | 2239 properties->Add(property, zone()); |
2266 | 2240 |
2267 if (peek() != Token::RBRACE) { | 2241 if (peek() != Token::RBRACE) { |
2268 // Need {} because of the CHECK_OK macro. | 2242 // Need {} because of the CHECK_OK macro. |
2269 Expect(Token::COMMA, CHECK_OK); | 2243 Expect(Token::COMMA, CHECK_OK); |
2270 } | 2244 } |
2271 | 2245 |
2272 if (fni_ != NULL) { | 2246 if (fni_ != nullptr) { |
2273 fni_->Infer(); | 2247 fni_->Infer(); |
2274 fni_->Leave(); | 2248 fni_->Leave(); |
2275 } | 2249 } |
2276 } | 2250 } |
2277 Expect(Token::RBRACE, CHECK_OK); | 2251 Expect(Token::RBRACE, CHECK_OK); |
2278 | 2252 |
2279 // Computation of literal_index must happen before pre parse bailout. | 2253 // Computation of literal_index must happen before pre parse bailout. |
2280 int literal_index = function_state_->NextMaterializedLiteralIndex(); | 2254 int literal_index = function_state_->NextMaterializedLiteralIndex(); |
2281 | 2255 |
2282 return factory()->NewObjectLiteral(properties, | 2256 return factory()->NewObjectLiteral(properties, |
(...skipping 751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3034 } | 3008 } |
3035 } | 3009 } |
3036 | 3010 |
3037 | 3011 |
3038 #undef CHECK_OK | 3012 #undef CHECK_OK |
3039 #undef CHECK_OK_CUSTOM | 3013 #undef CHECK_OK_CUSTOM |
3040 | 3014 |
3041 | 3015 |
3042 template <typename Traits> | 3016 template <typename Traits> |
3043 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( | 3017 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( |
3044 Token::Value property, PropertyKind type, bool* ok) { | 3018 Token::Value property, PropertyKind type, bool is_static, bool is_generator, |
3045 int old; | 3019 bool* ok) { |
3046 if (property == Token::NUMBER) { | 3020 DCHECK(!is_static); |
3047 old = scanner()->FindNumber(&finder_, type); | 3021 DCHECK(!is_generator || type == kMethodProperty); |
3048 } else { | 3022 |
3049 old = scanner()->FindSymbol(&finder_, type); | 3023 if (property == Token::NUMBER) return; |
3024 | |
3025 if (type == kValueProperty && IsProto()) { | |
3026 if (has_seen_proto_) { | |
3027 this->parser()->ReportMessage("duplicate_proto"); | |
3028 *ok = false; | |
3029 return; | |
3030 } | |
3031 has_seen_proto_ = true; | |
3032 return; | |
3050 } | 3033 } |
3051 PropertyKind old_type = static_cast<PropertyKind>(old); | 3034 } |
3052 if (HasConflict(old_type, type)) { | 3035 |
3053 if (IsDataDataConflict(old_type, type)) { | 3036 |
3054 // Both are data properties. | 3037 template <typename Traits> |
3055 if (strict_mode_ == SLOPPY) return; | 3038 void ParserBase<Traits>::ClassLiteralChecker::CheckProperty( |
3056 parser()->ReportMessage("strict_duplicate_property"); | 3039 Token::Value property, PropertyKind type, bool is_static, bool is_generator, |
adamk
2015/01/27 20:05:48
If this message is now unused, you ought to be abl
arv (Not doing code reviews)
2015/01/28 02:37:15
Done.
| |
3057 } else if (IsDataAccessorConflict(old_type, type)) { | 3040 bool* ok) { |
3058 // Both a data and an accessor property with the same name. | 3041 DCHECK(type == kMethodProperty); |
3059 parser()->ReportMessage("accessor_data_property"); | 3042 |
3060 } else { | 3043 if (property == Token::NUMBER) return; |
3061 DCHECK(IsAccessorAccessorConflict(old_type, type)); | 3044 |
3062 // Both accessors of the same type. | 3045 if (is_static) { |
3063 parser()->ReportMessage("accessor_get_set"); | 3046 if (IsPrototype()) { |
3047 this->parser()->ReportMessage("static_prototype"); | |
3048 *ok = false; | |
3049 return; | |
3064 } | 3050 } |
3065 *ok = false; | 3051 } else if (IsConstructor()) { |
3052 if (is_generator || type == kAccessorProperty) { | |
3053 this->parser()->ReportMessage("constructor_special_method"); | |
3054 *ok = false; | |
3055 return; | |
3056 } | |
3057 if (has_seen_constructor_) { | |
3058 this->parser()->ReportMessage("duplicate_constructor"); | |
3059 *ok = false; | |
3060 return; | |
3061 } | |
3062 has_seen_constructor_ = true; | |
3063 return; | |
3066 } | 3064 } |
3067 } | 3065 } |
3068 } } // v8::internal | 3066 } } // v8::internal |
3069 | 3067 |
3070 #endif // V8_PREPARSER_H | 3068 #endif // V8_PREPARSER_H |
OLD | NEW |