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 |