| 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 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast, | 485 ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast, |
| 486 bool* ok); | 486 bool* ok); |
| 487 | 487 |
| 488 // Checks if the expression is a valid reference expression (e.g., on the | 488 // Checks if the expression is a valid reference expression (e.g., on the |
| 489 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 489 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
| 490 // we allow calls for web compatibility and rewrite them to a runtime throw. | 490 // we allow calls for web compatibility and rewrite them to a runtime throw. |
| 491 ExpressionT CheckAndRewriteReferenceExpression( | 491 ExpressionT CheckAndRewriteReferenceExpression( |
| 492 ExpressionT expression, | 492 ExpressionT expression, |
| 493 Scanner::Location location, const char* message, bool* ok); | 493 Scanner::Location location, const char* message, bool* ok); |
| 494 | 494 |
| 495 // Used to detect duplicates in object literals. Each of the values | |
| 496 // kGetterProperty, kSetterProperty and kValueProperty represents | |
| 497 // a type of object literal property. When parsing a property, its | |
| 498 // type value is stored in the DuplicateFinder for the property name. | |
| 499 // Values are chosen so that having intersection bits means the there is | |
| 500 // an incompatibility. | |
| 501 // I.e., you can add a getter to a property that already has a setter, since | |
| 502 // kGetterProperty and kSetterProperty doesn't intersect, but not if it | |
| 503 // already has a getter or a value. Adding the getter to an existing | |
| 504 // setter will store the value (kGetterProperty | kSetterProperty), which | |
| 505 // is incompatible with adding any further properties. | |
| 506 enum PropertyKind { | |
| 507 kNone = 0, | |
| 508 // Bit patterns representing different object literal property types. | |
| 509 kGetterProperty = 1, | |
| 510 kSetterProperty = 2, | |
| 511 kValueProperty = 7, | |
| 512 // Helper constants. | |
| 513 kValueFlag = 4 | |
| 514 }; | |
| 515 | |
| 516 // Validation per ECMA 262 - 11.1.5 "Object Initialiser". | |
| 517 class ObjectLiteralChecker { | |
| 518 public: | |
| 519 ObjectLiteralChecker(ParserBase* parser, StrictMode strict_mode) | |
| 520 : parser_(parser), | |
| 521 finder_(scanner()->unicode_cache()), | |
| 522 strict_mode_(strict_mode) { } | |
| 523 | |
| 524 void CheckProperty(Token::Value property, PropertyKind type, bool* ok); | |
| 525 | |
| 526 private: | |
| 527 ParserBase* parser() const { return parser_; } | |
| 528 Scanner* scanner() const { return parser_->scanner(); } | |
| 529 | |
| 530 // Checks the type of conflict based on values coming from PropertyType. | |
| 531 bool HasConflict(PropertyKind type1, PropertyKind type2) { | |
| 532 return (type1 & type2) != 0; | |
| 533 } | |
| 534 bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) { | |
| 535 return ((type1 & type2) & kValueFlag) != 0; | |
| 536 } | |
| 537 bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) { | |
| 538 return ((type1 ^ type2) & kValueFlag) != 0; | |
| 539 } | |
| 540 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) { | |
| 541 return ((type1 | type2) & kValueFlag) == 0; | |
| 542 } | |
| 543 | |
| 544 ParserBase* parser_; | |
| 545 DuplicateFinder finder_; | |
| 546 StrictMode strict_mode_; | |
| 547 }; | |
| 548 | |
| 549 // If true, the next (and immediately following) function literal is | 495 // If true, the next (and immediately following) function literal is |
| 550 // preceded by a parenthesis. | 496 // preceded by a parenthesis. |
| 551 // Heuristically that means that the function will be called immediately, | 497 // Heuristically that means that the function will be called immediately, |
| 552 // so never lazily compile it. | 498 // so never lazily compile it. |
| 553 bool parenthesized_function_; | 499 bool parenthesized_function_; |
| 554 | 500 |
| 555 typename Traits::Type::Scope* scope_; // Scope stack. | 501 typename Traits::Type::Scope* scope_; // Scope stack. |
| 556 FunctionState* function_state_; // Function state stack. | 502 FunctionState* function_state_; // Function state stack. |
| 557 v8::Extension* extension_; | 503 v8::Extension* extension_; |
| 558 FuncNameInferrer* fni_; | 504 FuncNameInferrer* fni_; |
| (...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1842 // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) | 1788 // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) |
| 1843 // ) ',')* '}' | 1789 // ) ',')* '}' |
| 1844 // (Except that the trailing comma is not required.) | 1790 // (Except that the trailing comma is not required.) |
| 1845 | 1791 |
| 1846 int pos = peek_position(); | 1792 int pos = peek_position(); |
| 1847 typename Traits::Type::PropertyList properties = | 1793 typename Traits::Type::PropertyList properties = |
| 1848 this->NewPropertyList(4, zone_); | 1794 this->NewPropertyList(4, zone_); |
| 1849 int number_of_boilerplate_properties = 0; | 1795 int number_of_boilerplate_properties = 0; |
| 1850 bool has_function = false; | 1796 bool has_function = false; |
| 1851 | 1797 |
| 1852 ObjectLiteralChecker checker(this, strict_mode()); | |
| 1853 | |
| 1854 Expect(Token::LBRACE, CHECK_OK); | 1798 Expect(Token::LBRACE, CHECK_OK); |
| 1855 | 1799 |
| 1856 while (peek() != Token::RBRACE) { | 1800 while (peek() != Token::RBRACE) { |
| 1857 if (fni_ != NULL) fni_->Enter(); | 1801 if (fni_ != NULL) fni_->Enter(); |
| 1858 | 1802 |
| 1859 typename Traits::Type::Literal key = this->EmptyLiteral(); | 1803 typename Traits::Type::Literal key = this->EmptyLiteral(); |
| 1860 Token::Value next = peek(); | 1804 Token::Value next = peek(); |
| 1861 int next_pos = peek_position(); | 1805 int next_pos = peek_position(); |
| 1862 | 1806 |
| 1863 switch (next) { | 1807 switch (next) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1882 next != i::Token::FUTURE_STRICT_RESERVED_WORD && | 1826 next != i::Token::FUTURE_STRICT_RESERVED_WORD && |
| 1883 next != i::Token::LET && | 1827 next != i::Token::LET && |
| 1884 next != i::Token::YIELD && | 1828 next != i::Token::YIELD && |
| 1885 next != i::Token::NUMBER && | 1829 next != i::Token::NUMBER && |
| 1886 next != i::Token::STRING && | 1830 next != i::Token::STRING && |
| 1887 !Token::IsKeyword(next)) { | 1831 !Token::IsKeyword(next)) { |
| 1888 ReportUnexpectedToken(next); | 1832 ReportUnexpectedToken(next); |
| 1889 *ok = false; | 1833 *ok = false; |
| 1890 return this->EmptyLiteral(); | 1834 return this->EmptyLiteral(); |
| 1891 } | 1835 } |
| 1892 // Validate the property. | |
| 1893 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; | |
| 1894 checker.CheckProperty(next, type, CHECK_OK); | |
| 1895 IdentifierT name = this->GetSymbol(scanner_); | 1836 IdentifierT name = this->GetSymbol(scanner_); |
| 1896 typename Traits::Type::FunctionLiteral value = | 1837 typename Traits::Type::FunctionLiteral value = |
| 1897 this->ParseFunctionLiteral( | 1838 this->ParseFunctionLiteral( |
| 1898 name, scanner()->location(), | 1839 name, scanner()->location(), |
| 1899 false, // reserved words are allowed here | 1840 false, // reserved words are allowed here |
| 1900 false, // not a generator | 1841 false, // not a generator |
| 1901 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, | 1842 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, |
| 1902 is_getter ? FunctionLiteral::GETTER_ARITY | 1843 is_getter ? FunctionLiteral::GETTER_ARITY |
| 1903 : FunctionLiteral::SETTER_ARITY, | 1844 : FunctionLiteral::SETTER_ARITY, |
| 1904 CHECK_OK); | 1845 CHECK_OK); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1948 IdentifierT string = this->GetSymbol(scanner_); | 1889 IdentifierT string = this->GetSymbol(scanner_); |
| 1949 key = factory()->NewStringLiteral(string, next_pos); | 1890 key = factory()->NewStringLiteral(string, next_pos); |
| 1950 } else { | 1891 } else { |
| 1951 Token::Value next = Next(); | 1892 Token::Value next = Next(); |
| 1952 ReportUnexpectedToken(next); | 1893 ReportUnexpectedToken(next); |
| 1953 *ok = false; | 1894 *ok = false; |
| 1954 return this->EmptyLiteral(); | 1895 return this->EmptyLiteral(); |
| 1955 } | 1896 } |
| 1956 } | 1897 } |
| 1957 | 1898 |
| 1958 // Validate the property | |
| 1959 checker.CheckProperty(next, kValueProperty, CHECK_OK); | |
| 1960 | |
| 1961 Expect(Token::COLON, CHECK_OK); | 1899 Expect(Token::COLON, CHECK_OK); |
| 1962 ExpressionT value = this->ParseAssignmentExpression(true, CHECK_OK); | 1900 ExpressionT value = this->ParseAssignmentExpression(true, CHECK_OK); |
| 1963 | 1901 |
| 1964 typename Traits::Type::ObjectLiteralProperty property = | 1902 typename Traits::Type::ObjectLiteralProperty property = |
| 1965 factory()->NewObjectLiteralProperty(key, value); | 1903 factory()->NewObjectLiteralProperty(key, value); |
| 1966 | 1904 |
| 1967 // Mark top-level object literals that contain function literals and | 1905 // Mark top-level object literals that contain function literals and |
| 1968 // pretenure the literal so it can be added as a constant function | 1906 // pretenure the literal so it can be added as a constant function |
| 1969 // property. (Parser only.) | 1907 // property. (Parser only.) |
| 1970 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value, | 1908 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value, |
| (...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2621 *ok = false; | 2559 *ok = false; |
| 2622 return this->EmptyExpression(); | 2560 return this->EmptyExpression(); |
| 2623 } | 2561 } |
| 2624 } | 2562 } |
| 2625 | 2563 |
| 2626 | 2564 |
| 2627 #undef CHECK_OK | 2565 #undef CHECK_OK |
| 2628 #undef CHECK_OK_CUSTOM | 2566 #undef CHECK_OK_CUSTOM |
| 2629 | 2567 |
| 2630 | 2568 |
| 2631 template <typename Traits> | |
| 2632 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( | |
| 2633 Token::Value property, | |
| 2634 PropertyKind type, | |
| 2635 bool* ok) { | |
| 2636 int old; | |
| 2637 if (property == Token::NUMBER) { | |
| 2638 old = scanner()->FindNumber(&finder_, type); | |
| 2639 } else { | |
| 2640 old = scanner()->FindSymbol(&finder_, type); | |
| 2641 } | |
| 2642 PropertyKind old_type = static_cast<PropertyKind>(old); | |
| 2643 if (HasConflict(old_type, type)) { | |
| 2644 if (IsDataDataConflict(old_type, type)) { | |
| 2645 // Both are data properties. | |
| 2646 if (strict_mode_ == SLOPPY) return; | |
| 2647 parser()->ReportMessage("strict_duplicate_property"); | |
| 2648 } else if (IsDataAccessorConflict(old_type, type)) { | |
| 2649 // Both a data and an accessor property with the same name. | |
| 2650 parser()->ReportMessage("accessor_data_property"); | |
| 2651 } else { | |
| 2652 DCHECK(IsAccessorAccessorConflict(old_type, type)); | |
| 2653 // Both accessors of the same type. | |
| 2654 parser()->ReportMessage("accessor_get_set"); | |
| 2655 } | |
| 2656 *ok = false; | |
| 2657 } | |
| 2658 } | |
| 2659 | |
| 2660 | |
| 2661 } } // v8::internal | 2569 } } // v8::internal |
| 2662 | 2570 |
| 2663 #endif // V8_PREPARSER_H | 2571 #endif // V8_PREPARSER_H |
| OLD | NEW |