| 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 |