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 |