| 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/func-name-inferrer.h" | 10 #include "src/func-name-inferrer.h" |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 enum PropertyKind { | 464 enum PropertyKind { |
| 465 kNone = 0, | 465 kNone = 0, |
| 466 // Bit patterns representing different object literal property types. | 466 // Bit patterns representing different object literal property types. |
| 467 kGetterProperty = 1, | 467 kGetterProperty = 1, |
| 468 kSetterProperty = 2, | 468 kSetterProperty = 2, |
| 469 kValueProperty = 7, | 469 kValueProperty = 7, |
| 470 // Helper constants. | 470 // Helper constants. |
| 471 kValueFlag = 4 | 471 kValueFlag = 4 |
| 472 }; | 472 }; |
| 473 | 473 |
| 474 // Validation per ECMA 262 - 11.1.5 "Object Initialiser". | |
| 475 class ObjectLiteralChecker { | |
| 476 public: | |
| 477 ObjectLiteralChecker(ParserBase* parser, StrictMode strict_mode) | |
| 478 : parser_(parser), | |
| 479 finder_(scanner()->unicode_cache()), | |
| 480 strict_mode_(strict_mode) { } | |
| 481 | |
| 482 void CheckProperty(Token::Value property, PropertyKind type, bool* ok); | |
| 483 | |
| 484 private: | |
| 485 ParserBase* parser() const { return parser_; } | |
| 486 Scanner* scanner() const { return parser_->scanner(); } | |
| 487 | |
| 488 // Checks the type of conflict based on values coming from PropertyType. | |
| 489 bool HasConflict(PropertyKind type1, PropertyKind type2) { | |
| 490 return (type1 & type2) != 0; | |
| 491 } | |
| 492 bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) { | |
| 493 return ((type1 & type2) & kValueFlag) != 0; | |
| 494 } | |
| 495 bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) { | |
| 496 return ((type1 ^ type2) & kValueFlag) != 0; | |
| 497 } | |
| 498 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) { | |
| 499 return ((type1 | type2) & kValueFlag) == 0; | |
| 500 } | |
| 501 | |
| 502 ParserBase* parser_; | |
| 503 DuplicateFinder finder_; | |
| 504 StrictMode strict_mode_; | |
| 505 }; | |
| 506 | |
| 507 // If true, the next (and immediately following) function literal is | 474 // If true, the next (and immediately following) function literal is |
| 508 // preceded by a parenthesis. | 475 // preceded by a parenthesis. |
| 509 // Heuristically that means that the function will be called immediately, | 476 // Heuristically that means that the function will be called immediately, |
| 510 // so never lazily compile it. | 477 // so never lazily compile it. |
| 511 bool parenthesized_function_; | 478 bool parenthesized_function_; |
| 512 | 479 |
| 513 typename Traits::Type::Scope* scope_; // Scope stack. | 480 typename Traits::Type::Scope* scope_; // Scope stack. |
| 514 FunctionState* function_state_; // Function state stack. | 481 FunctionState* function_state_; // Function state stack. |
| 515 v8::Extension* extension_; | 482 v8::Extension* extension_; |
| 516 FuncNameInferrer* fni_; | 483 FuncNameInferrer* fni_; |
| (...skipping 1027 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1544 // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) | 1511 // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) |
| 1545 // ) ',')* '}' | 1512 // ) ',')* '}' |
| 1546 // (Except that the trailing comma is not required.) | 1513 // (Except that the trailing comma is not required.) |
| 1547 | 1514 |
| 1548 int pos = peek_position(); | 1515 int pos = peek_position(); |
| 1549 typename Traits::Type::PropertyList properties = | 1516 typename Traits::Type::PropertyList properties = |
| 1550 this->NewPropertyList(4, zone_); | 1517 this->NewPropertyList(4, zone_); |
| 1551 int number_of_boilerplate_properties = 0; | 1518 int number_of_boilerplate_properties = 0; |
| 1552 bool has_function = false; | 1519 bool has_function = false; |
| 1553 | 1520 |
| 1554 ObjectLiteralChecker checker(this, strict_mode()); | |
| 1555 | |
| 1556 Expect(Token::LBRACE, CHECK_OK); | 1521 Expect(Token::LBRACE, CHECK_OK); |
| 1557 | 1522 |
| 1558 while (peek() != Token::RBRACE) { | 1523 while (peek() != Token::RBRACE) { |
| 1559 if (fni_ != NULL) fni_->Enter(); | 1524 if (fni_ != NULL) fni_->Enter(); |
| 1560 | 1525 |
| 1561 typename Traits::Type::Literal key = this->EmptyLiteral(); | 1526 typename Traits::Type::Literal key = this->EmptyLiteral(); |
| 1562 Token::Value next = peek(); | 1527 Token::Value next = peek(); |
| 1563 int next_pos = peek_position(); | 1528 int next_pos = peek_position(); |
| 1564 | 1529 |
| 1565 switch (next) { | 1530 switch (next) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1580 if (next != i::Token::IDENTIFIER && | 1545 if (next != i::Token::IDENTIFIER && |
| 1581 next != i::Token::FUTURE_RESERVED_WORD && | 1546 next != i::Token::FUTURE_RESERVED_WORD && |
| 1582 next != i::Token::FUTURE_STRICT_RESERVED_WORD && | 1547 next != i::Token::FUTURE_STRICT_RESERVED_WORD && |
| 1583 next != i::Token::NUMBER && | 1548 next != i::Token::NUMBER && |
| 1584 next != i::Token::STRING && | 1549 next != i::Token::STRING && |
| 1585 !Token::IsKeyword(next)) { | 1550 !Token::IsKeyword(next)) { |
| 1586 ReportUnexpectedToken(next); | 1551 ReportUnexpectedToken(next); |
| 1587 *ok = false; | 1552 *ok = false; |
| 1588 return this->EmptyLiteral(); | 1553 return this->EmptyLiteral(); |
| 1589 } | 1554 } |
| 1590 // Validate the property. | |
| 1591 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; | |
| 1592 checker.CheckProperty(next, type, CHECK_OK); | |
| 1593 IdentifierT name = this->GetSymbol(scanner_); | 1555 IdentifierT name = this->GetSymbol(scanner_); |
| 1594 typename Traits::Type::FunctionLiteral value = | 1556 typename Traits::Type::FunctionLiteral value = |
| 1595 this->ParseFunctionLiteral( | 1557 this->ParseFunctionLiteral( |
| 1596 name, scanner()->location(), | 1558 name, scanner()->location(), |
| 1597 false, // reserved words are allowed here | 1559 false, // reserved words are allowed here |
| 1598 false, // not a generator | 1560 false, // not a generator |
| 1599 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, | 1561 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, |
| 1600 is_getter ? FunctionLiteral::GETTER_ARITY | 1562 is_getter ? FunctionLiteral::GETTER_ARITY |
| 1601 : FunctionLiteral::SETTER_ARITY, | 1563 : FunctionLiteral::SETTER_ARITY, |
| 1602 CHECK_OK); | 1564 CHECK_OK); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1646 IdentifierT string = this->GetSymbol(scanner_); | 1608 IdentifierT string = this->GetSymbol(scanner_); |
| 1647 key = factory()->NewStringLiteral(string, next_pos); | 1609 key = factory()->NewStringLiteral(string, next_pos); |
| 1648 } else { | 1610 } else { |
| 1649 Token::Value next = Next(); | 1611 Token::Value next = Next(); |
| 1650 ReportUnexpectedToken(next); | 1612 ReportUnexpectedToken(next); |
| 1651 *ok = false; | 1613 *ok = false; |
| 1652 return this->EmptyLiteral(); | 1614 return this->EmptyLiteral(); |
| 1653 } | 1615 } |
| 1654 } | 1616 } |
| 1655 | 1617 |
| 1656 // Validate the property | |
| 1657 checker.CheckProperty(next, kValueProperty, CHECK_OK); | |
| 1658 | |
| 1659 Expect(Token::COLON, CHECK_OK); | 1618 Expect(Token::COLON, CHECK_OK); |
| 1660 ExpressionT value = this->ParseAssignmentExpression(true, CHECK_OK); | 1619 ExpressionT value = this->ParseAssignmentExpression(true, CHECK_OK); |
| 1661 | 1620 |
| 1662 typename Traits::Type::ObjectLiteralProperty property = | 1621 typename Traits::Type::ObjectLiteralProperty property = |
| 1663 factory()->NewObjectLiteralProperty(key, value); | 1622 factory()->NewObjectLiteralProperty(key, value); |
| 1664 | 1623 |
| 1665 // Mark top-level object literals that contain function literals and | 1624 // Mark top-level object literals that contain function literals and |
| 1666 // pretenure the literal so it can be added as a constant function | 1625 // pretenure the literal so it can be added as a constant function |
| 1667 // property. (Parser only.) | 1626 // property. (Parser only.) |
| 1668 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value, | 1627 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value, |
| (...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2173 *ok = false; | 2132 *ok = false; |
| 2174 return this->EmptyExpression(); | 2133 return this->EmptyExpression(); |
| 2175 } | 2134 } |
| 2176 } | 2135 } |
| 2177 | 2136 |
| 2178 | 2137 |
| 2179 #undef CHECK_OK | 2138 #undef CHECK_OK |
| 2180 #undef CHECK_OK_CUSTOM | 2139 #undef CHECK_OK_CUSTOM |
| 2181 | 2140 |
| 2182 | 2141 |
| 2183 template <typename Traits> | |
| 2184 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( | |
| 2185 Token::Value property, | |
| 2186 PropertyKind type, | |
| 2187 bool* ok) { | |
| 2188 int old; | |
| 2189 if (property == Token::NUMBER) { | |
| 2190 old = scanner()->FindNumber(&finder_, type); | |
| 2191 } else { | |
| 2192 old = scanner()->FindSymbol(&finder_, type); | |
| 2193 } | |
| 2194 PropertyKind old_type = static_cast<PropertyKind>(old); | |
| 2195 if (HasConflict(old_type, type)) { | |
| 2196 if (IsDataDataConflict(old_type, type)) { | |
| 2197 // Both are data properties. | |
| 2198 if (strict_mode_ == SLOPPY) return; | |
| 2199 parser()->ReportMessage("strict_duplicate_property"); | |
| 2200 } else if (IsDataAccessorConflict(old_type, type)) { | |
| 2201 // Both a data and an accessor property with the same name. | |
| 2202 parser()->ReportMessage("accessor_data_property"); | |
| 2203 } else { | |
| 2204 ASSERT(IsAccessorAccessorConflict(old_type, type)); | |
| 2205 // Both accessors of the same type. | |
| 2206 parser()->ReportMessage("accessor_get_set"); | |
| 2207 } | |
| 2208 *ok = false; | |
| 2209 } | |
| 2210 } | |
| 2211 | |
| 2212 | |
| 2213 } } // v8::internal | 2142 } } // v8::internal |
| 2214 | 2143 |
| 2215 #endif // V8_PREPARSER_H | 2144 #endif // V8_PREPARSER_H |
| OLD | NEW |