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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 kAllowEvalOrArguments, | 123 kAllowEvalOrArguments, |
124 kDontAllowEvalOrArguments | 124 kDontAllowEvalOrArguments |
125 }; | 125 }; |
126 | 126 |
127 enum Mode { | 127 enum Mode { |
128 PARSE_LAZILY, | 128 PARSE_LAZILY, |
129 PARSE_EAGERLY | 129 PARSE_EAGERLY |
130 }; | 130 }; |
131 | 131 |
132 class ParserCheckpoint; | 132 class ParserCheckpoint; |
| 133 class ObjectLiteralChecker; |
133 | 134 |
134 // --------------------------------------------------------------------------- | 135 // --------------------------------------------------------------------------- |
135 // FunctionState and BlockState together implement the parser's scope stack. | 136 // FunctionState and BlockState together implement the parser's scope stack. |
136 // The parser's current scope is in scope_. BlockState and FunctionState | 137 // The parser's current scope is in scope_. BlockState and FunctionState |
137 // constructors push on the scope stack and the destructors pop. They are also | 138 // constructors push on the scope stack and the destructors pop. They are also |
138 // used to hold the parser's per-function and per-block state. | 139 // used to hold the parser's per-function and per-block state. |
139 class BlockState BASE_EMBEDDED { | 140 class BlockState BASE_EMBEDDED { |
140 public: | 141 public: |
141 BlockState(typename Traits::Type::Scope** scope_stack, | 142 BlockState(typename Traits::Type::Scope** scope_stack, |
142 typename Traits::Type::Scope* scope) | 143 typename Traits::Type::Scope* scope) |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, | 470 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, |
470 bool* is_set, | 471 bool* is_set, |
471 bool* ok); | 472 bool* ok); |
472 | 473 |
473 ExpressionT ParseRegExpLiteral(bool seen_equal, bool* ok); | 474 ExpressionT ParseRegExpLiteral(bool seen_equal, bool* ok); |
474 | 475 |
475 ExpressionT ParsePrimaryExpression(bool* ok); | 476 ExpressionT ParsePrimaryExpression(bool* ok); |
476 ExpressionT ParseExpression(bool accept_IN, bool* ok); | 477 ExpressionT ParseExpression(bool accept_IN, bool* ok); |
477 ExpressionT ParseArrayLiteral(bool* ok); | 478 ExpressionT ParseArrayLiteral(bool* ok); |
478 ExpressionT ParseObjectLiteral(bool* ok); | 479 ExpressionT ParseObjectLiteral(bool* ok); |
479 ObjectLiteralPropertyT ParsePropertyDefinition(bool* ok); | 480 ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker, |
| 481 bool* ok); |
480 typename Traits::Type::ExpressionList ParseArguments(bool* ok); | 482 typename Traits::Type::ExpressionList ParseArguments(bool* ok); |
481 ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok); | 483 ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok); |
482 ExpressionT ParseYieldExpression(bool* ok); | 484 ExpressionT ParseYieldExpression(bool* ok); |
483 ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok); | 485 ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok); |
484 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok); | 486 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok); |
485 ExpressionT ParseUnaryExpression(bool* ok); | 487 ExpressionT ParseUnaryExpression(bool* ok); |
486 ExpressionT ParsePostfixExpression(bool* ok); | 488 ExpressionT ParsePostfixExpression(bool* ok); |
487 ExpressionT ParseLeftHandSideExpression(bool* ok); | 489 ExpressionT ParseLeftHandSideExpression(bool* ok); |
488 ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok); | 490 ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok); |
489 ExpressionT ParseMemberExpression(bool* ok); | 491 ExpressionT ParseMemberExpression(bool* ok); |
490 ExpressionT ParseMemberExpressionContinuation(ExpressionT expression, | 492 ExpressionT ParseMemberExpressionContinuation(ExpressionT expression, |
491 bool* ok); | 493 bool* ok); |
492 ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast, | 494 ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast, |
493 bool* ok); | 495 bool* ok); |
494 | 496 |
495 // Checks if the expression is a valid reference expression (e.g., on the | 497 // Checks if the expression is a valid reference expression (e.g., on the |
496 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 498 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
497 // we allow calls for web compatibility and rewrite them to a runtime throw. | 499 // we allow calls for web compatibility and rewrite them to a runtime throw. |
498 ExpressionT CheckAndRewriteReferenceExpression( | 500 ExpressionT CheckAndRewriteReferenceExpression( |
499 ExpressionT expression, | 501 ExpressionT expression, |
500 Scanner::Location location, const char* message, bool* ok); | 502 Scanner::Location location, const char* message, bool* ok); |
501 | 503 |
| 504 // Used to detect duplicates in object literals. Each of the values |
| 505 // kGetterProperty, kSetterProperty and kValueProperty represents |
| 506 // a type of object literal property. When parsing a property, its |
| 507 // type value is stored in the DuplicateFinder for the property name. |
| 508 // Values are chosen so that having intersection bits means the there is |
| 509 // an incompatibility. |
| 510 // I.e., you can add a getter to a property that already has a setter, since |
| 511 // kGetterProperty and kSetterProperty doesn't intersect, but not if it |
| 512 // already has a getter or a value. Adding the getter to an existing |
| 513 // setter will store the value (kGetterProperty | kSetterProperty), which |
| 514 // is incompatible with adding any further properties. |
| 515 enum PropertyKind { |
| 516 kNone = 0, |
| 517 // Bit patterns representing different object literal property types. |
| 518 kGetterProperty = 1, |
| 519 kSetterProperty = 2, |
| 520 kValueProperty = 7, |
| 521 // Helper constants. |
| 522 kValueFlag = 4 |
| 523 }; |
| 524 |
| 525 // Validation per ECMA 262 - 11.1.5 "Object Initializer". |
| 526 class ObjectLiteralChecker { |
| 527 public: |
| 528 ObjectLiteralChecker(ParserBase* parser, StrictMode strict_mode) |
| 529 : parser_(parser), |
| 530 finder_(scanner()->unicode_cache()), |
| 531 strict_mode_(strict_mode) {} |
| 532 |
| 533 void CheckProperty(Token::Value property, PropertyKind type, bool* ok); |
| 534 |
| 535 private: |
| 536 ParserBase* parser() const { return parser_; } |
| 537 Scanner* scanner() const { return parser_->scanner(); } |
| 538 |
| 539 // Checks the type of conflict based on values coming from PropertyType. |
| 540 bool HasConflict(PropertyKind type1, PropertyKind type2) { |
| 541 return (type1 & type2) != 0; |
| 542 } |
| 543 bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) { |
| 544 return ((type1 & type2) & kValueFlag) != 0; |
| 545 } |
| 546 bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) { |
| 547 return ((type1 ^ type2) & kValueFlag) != 0; |
| 548 } |
| 549 bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) { |
| 550 return ((type1 | type2) & kValueFlag) == 0; |
| 551 } |
| 552 |
| 553 ParserBase* parser_; |
| 554 DuplicateFinder finder_; |
| 555 StrictMode strict_mode_; |
| 556 }; |
| 557 |
502 // If true, the next (and immediately following) function literal is | 558 // If true, the next (and immediately following) function literal is |
503 // preceded by a parenthesis. | 559 // preceded by a parenthesis. |
504 // Heuristically that means that the function will be called immediately, | 560 // Heuristically that means that the function will be called immediately, |
505 // so never lazily compile it. | 561 // so never lazily compile it. |
506 bool parenthesized_function_; | 562 bool parenthesized_function_; |
507 | 563 |
508 typename Traits::Type::Scope* scope_; // Scope stack. | 564 typename Traits::Type::Scope* scope_; // Scope stack. |
509 FunctionState* function_state_; // Function state stack. | 565 FunctionState* function_state_; // Function state stack. |
510 v8::Extension* extension_; | 566 v8::Extension* extension_; |
511 FuncNameInferrer* fni_; | 567 FuncNameInferrer* fni_; |
(...skipping 1282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1794 Expect(Token::RBRACK, CHECK_OK); | 1850 Expect(Token::RBRACK, CHECK_OK); |
1795 | 1851 |
1796 // Update the scope information before the pre-parsing bailout. | 1852 // Update the scope information before the pre-parsing bailout. |
1797 int literal_index = function_state_->NextMaterializedLiteralIndex(); | 1853 int literal_index = function_state_->NextMaterializedLiteralIndex(); |
1798 | 1854 |
1799 return factory()->NewArrayLiteral(values, literal_index, pos); | 1855 return factory()->NewArrayLiteral(values, literal_index, pos); |
1800 } | 1856 } |
1801 | 1857 |
1802 | 1858 |
1803 template <class Traits> | 1859 template <class Traits> |
1804 typename ParserBase<Traits>::ObjectLiteralPropertyT | 1860 typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase< |
1805 ParserBase<Traits>::ParsePropertyDefinition(bool* ok) { | 1861 Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, bool* ok) { |
1806 LiteralT key = this->EmptyLiteral(); | 1862 LiteralT key = this->EmptyLiteral(); |
1807 Token::Value next = peek(); | 1863 Token::Value next = peek(); |
1808 int next_pos = peek_position(); | 1864 int next_pos = peek_position(); |
1809 | 1865 |
1810 switch (next) { | 1866 switch (next) { |
1811 case Token::STRING: { | 1867 case Token::STRING: { |
1812 Consume(Token::STRING); | 1868 Consume(Token::STRING); |
1813 IdentifierT string = this->GetSymbol(scanner_); | 1869 IdentifierT string = this->GetSymbol(scanner_); |
1814 if (fni_ != NULL) this->PushLiteralName(fni_, string); | 1870 if (fni_ != NULL) this->PushLiteralName(fni_, string); |
1815 uint32_t index; | 1871 uint32_t index; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1847 Consume(Token::NUMBER); | 1903 Consume(Token::NUMBER); |
1848 // TODO(arv): Fix issue with numeric keys. get 1.0() should be | 1904 // TODO(arv): Fix issue with numeric keys. get 1.0() should be |
1849 // treated as if the key was '1' | 1905 // treated as if the key was '1' |
1850 // https://code.google.com/p/v8/issues/detail?id=3507 | 1906 // https://code.google.com/p/v8/issues/detail?id=3507 |
1851 name = this->GetSymbol(scanner_); | 1907 name = this->GetSymbol(scanner_); |
1852 break; | 1908 break; |
1853 default: | 1909 default: |
1854 name = ParseIdentifierName( | 1910 name = ParseIdentifierName( |
1855 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1911 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1856 } | 1912 } |
| 1913 // Validate the property. |
| 1914 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; |
| 1915 checker->CheckProperty(next, type, |
| 1916 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1857 typename Traits::Type::FunctionLiteral value = | 1917 typename Traits::Type::FunctionLiteral value = |
1858 this->ParseFunctionLiteral( | 1918 this->ParseFunctionLiteral( |
1859 name, scanner()->location(), | 1919 name, scanner()->location(), |
1860 false, // reserved words are allowed here | 1920 false, // reserved words are allowed here |
1861 false, // not a generator | 1921 false, // not a generator |
1862 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, | 1922 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, |
1863 is_getter ? FunctionLiteral::GETTER_ARITY | 1923 is_getter ? FunctionLiteral::GETTER_ARITY |
1864 : FunctionLiteral::SETTER_ARITY, | 1924 : FunctionLiteral::SETTER_ARITY, |
1865 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1925 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1866 return factory()->NewObjectLiteralProperty(is_getter, value, next_pos); | 1926 return factory()->NewObjectLiteralProperty(is_getter, value, next_pos); |
1867 } | 1927 } |
1868 // Failed to parse as get/set property, so it's just a normal property | 1928 // Failed to parse as get/set property, so it's just a normal property |
1869 // (which might be called "get" or "set" or something else). | 1929 // (which might be called "get" or "set" or something else). |
1870 key = factory()->NewStringLiteral(id, next_pos); | 1930 key = factory()->NewStringLiteral(id, next_pos); |
1871 } | 1931 } |
1872 } | 1932 } |
1873 | 1933 |
| 1934 // Validate the property |
| 1935 checker->CheckProperty(next, kValueProperty, |
| 1936 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| 1937 |
1874 Expect(Token::COLON, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1938 Expect(Token::COLON, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1875 ExpressionT value = this->ParseAssignmentExpression( | 1939 ExpressionT value = this->ParseAssignmentExpression( |
1876 true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1940 true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
1877 | 1941 |
1878 return factory()->NewObjectLiteralProperty(key, value); | 1942 return factory()->NewObjectLiteralProperty(key, value); |
1879 } | 1943 } |
1880 | 1944 |
1881 | 1945 |
1882 template <class Traits> | 1946 template <class Traits> |
1883 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral( | 1947 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral( |
1884 bool* ok) { | 1948 bool* ok) { |
1885 // ObjectLiteral :: | 1949 // ObjectLiteral :: |
1886 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' | 1950 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' |
1887 | 1951 |
1888 int pos = peek_position(); | 1952 int pos = peek_position(); |
1889 typename Traits::Type::PropertyList properties = | 1953 typename Traits::Type::PropertyList properties = |
1890 this->NewPropertyList(4, zone_); | 1954 this->NewPropertyList(4, zone_); |
1891 int number_of_boilerplate_properties = 0; | 1955 int number_of_boilerplate_properties = 0; |
1892 bool has_function = false; | 1956 bool has_function = false; |
1893 | 1957 |
| 1958 ObjectLiteralChecker checker(this, strict_mode()); |
| 1959 |
1894 Expect(Token::LBRACE, CHECK_OK); | 1960 Expect(Token::LBRACE, CHECK_OK); |
1895 | 1961 |
1896 while (peek() != Token::RBRACE) { | 1962 while (peek() != Token::RBRACE) { |
1897 if (fni_ != NULL) fni_->Enter(); | 1963 if (fni_ != NULL) fni_->Enter(); |
1898 | 1964 |
1899 ObjectLiteralPropertyT property = this->ParsePropertyDefinition(CHECK_OK); | 1965 ObjectLiteralPropertyT property = |
| 1966 this->ParsePropertyDefinition(&checker, CHECK_OK); |
1900 | 1967 |
1901 // Mark top-level object literals that contain function literals and | 1968 // Mark top-level object literals that contain function literals and |
1902 // pretenure the literal so it can be added as a constant function | 1969 // pretenure the literal so it can be added as a constant function |
1903 // property. (Parser only.) | 1970 // property. (Parser only.) |
1904 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, property, | 1971 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, property, |
1905 &has_function); | 1972 &has_function); |
1906 | 1973 |
1907 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | 1974 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
1908 if (this->IsBoilerplateProperty(property)) { | 1975 if (this->IsBoilerplateProperty(property)) { |
1909 number_of_boilerplate_properties++; | 1976 number_of_boilerplate_properties++; |
(...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2573 *ok = false; | 2640 *ok = false; |
2574 return this->EmptyExpression(); | 2641 return this->EmptyExpression(); |
2575 } | 2642 } |
2576 } | 2643 } |
2577 | 2644 |
2578 | 2645 |
2579 #undef CHECK_OK | 2646 #undef CHECK_OK |
2580 #undef CHECK_OK_CUSTOM | 2647 #undef CHECK_OK_CUSTOM |
2581 | 2648 |
2582 | 2649 |
| 2650 template <typename Traits> |
| 2651 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( |
| 2652 Token::Value property, PropertyKind type, bool* ok) { |
| 2653 int old; |
| 2654 if (property == Token::NUMBER) { |
| 2655 old = scanner()->FindNumber(&finder_, type); |
| 2656 } else { |
| 2657 old = scanner()->FindSymbol(&finder_, type); |
| 2658 } |
| 2659 PropertyKind old_type = static_cast<PropertyKind>(old); |
| 2660 if (HasConflict(old_type, type)) { |
| 2661 if (IsDataDataConflict(old_type, type)) { |
| 2662 // Both are data properties. |
| 2663 if (strict_mode_ == SLOPPY) return; |
| 2664 parser()->ReportMessage("strict_duplicate_property"); |
| 2665 } else if (IsDataAccessorConflict(old_type, type)) { |
| 2666 // Both a data and an accessor property with the same name. |
| 2667 parser()->ReportMessage("accessor_data_property"); |
| 2668 } else { |
| 2669 DCHECK(IsAccessorAccessorConflict(old_type, type)); |
| 2670 // Both accessors of the same type. |
| 2671 parser()->ReportMessage("accessor_get_set"); |
| 2672 } |
| 2673 *ok = false; |
| 2674 } |
| 2675 } |
2583 } } // v8::internal | 2676 } } // v8::internal |
2584 | 2677 |
2585 #endif // V8_PREPARSER_H | 2678 #endif // V8_PREPARSER_H |
OLD | NEW |