Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(777)

Side by Side Diff: src/preparser.h

Issue 491053002: Add back the duplicate property checker (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | test/cctest/test-parsing.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | test/cctest/test-parsing.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698