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

Side by Side Diff: src/parsing/parser-base.h

Issue 2278153004: Refactor object/class literal property name parsing (Closed)
Patch Set: address comments Created 4 years, 3 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
« no previous file with comments | « src/parsing/parser.cc ('k') | src/parsing/preparser.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_PARSING_PARSER_BASE_H 5 #ifndef V8_PARSING_PARSER_BASE_H
6 #define V8_PARSING_PARSER_BASE_H 6 #define V8_PARSING_PARSER_BASE_H
7 7
8 #include "src/ast/scopes.h" 8 #include "src/ast/scopes.h"
9 #include "src/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/base/hashmap.h" 10 #include "src/base/hashmap.h"
(...skipping 1056 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 bool* is_async, bool* ok); 1067 bool* is_async, bool* ok);
1068 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, 1068 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier,
1069 bool* ok) { 1069 bool* ok) {
1070 bool is_async; 1070 bool is_async;
1071 return ParsePrimaryExpression(classifier, &is_async, ok); 1071 return ParsePrimaryExpression(classifier, &is_async, ok);
1072 } 1072 }
1073 ExpressionT ParseExpression(bool accept_IN, bool* ok); 1073 ExpressionT ParseExpression(bool accept_IN, bool* ok);
1074 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, 1074 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier,
1075 bool* ok); 1075 bool* ok);
1076 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); 1076 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok);
1077 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, 1077
1078 enum class PropertyKind {
1079 kAccessorProperty,
1080 kValueProperty,
1081 kShorthandProperty,
1082 kMethodProperty
1083 };
1084
1085 bool SetPropertyKindFromToken(Token::Value token, PropertyKind* kind);
1086 ExpressionT ParsePropertyName(IdentifierT* name, PropertyKind* kind,
1087 bool in_class, bool* is_generator, bool* is_get,
1088 bool* is_set, bool* is_async, bool* is_static,
1078 bool* is_computed_name, 1089 bool* is_computed_name,
1079 ExpressionClassifier* classifier, bool* ok); 1090 ExpressionClassifier* classifier, bool* ok);
1080 ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok); 1091 ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok);
1081 ObjectLiteralPropertyT ParsePropertyDefinition( 1092 ObjectLiteralPropertyT ParsePropertyDefinition(
1082 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, 1093 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends,
1083 MethodKind kind, bool* is_computed_name, bool* has_seen_constructor, 1094 bool* is_computed_name, bool* has_seen_constructor,
1084 ExpressionClassifier* classifier, IdentifierT* name, bool* ok); 1095 ExpressionClassifier* classifier, IdentifierT* name, bool* ok);
1085 typename Types::ExpressionList ParseArguments( 1096 typename Types::ExpressionList ParseArguments(
1086 Scanner::Location* first_spread_pos, bool maybe_arrow, 1097 Scanner::Location* first_spread_pos, bool maybe_arrow,
1087 ExpressionClassifier* classifier, bool* ok); 1098 ExpressionClassifier* classifier, bool* ok);
1088 typename Types::ExpressionList ParseArguments( 1099 typename Types::ExpressionList ParseArguments(
1089 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, 1100 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier,
1090 bool* ok) { 1101 bool* ok) {
1091 return ParseArguments(first_spread_pos, false, classifier, ok); 1102 return ParseArguments(first_spread_pos, false, classifier, ok);
1092 } 1103 }
1093 1104
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1172 if (is_sloppy(scope->language_mode())) { 1183 if (is_sloppy(scope->language_mode())) {
1173 // For sloppy scopes we also have to record the call at function level, 1184 // For sloppy scopes we also have to record the call at function level,
1174 // in case it includes declarations that will be hoisted. 1185 // in case it includes declarations that will be hoisted.
1175 scope->GetDeclarationScope()->RecordEvalCall(); 1186 scope->GetDeclarationScope()->RecordEvalCall();
1176 } 1187 }
1177 return Call::IS_POSSIBLY_EVAL; 1188 return Call::IS_POSSIBLY_EVAL;
1178 } 1189 }
1179 return Call::NOT_EVAL; 1190 return Call::NOT_EVAL;
1180 } 1191 }
1181 1192
1182 // Used to validate property names in object literals and class literals
1183 enum PropertyKind {
1184 kAccessorProperty,
1185 kValueProperty,
1186 kMethodProperty
1187 };
1188
1189 class ObjectLiteralCheckerBase { 1193 class ObjectLiteralCheckerBase {
1190 public: 1194 public:
1191 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {} 1195 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {}
1192 1196
1193 virtual void CheckProperty(Token::Value property, PropertyKind type, 1197 virtual void CheckProperty(Token::Value property, PropertyKind type,
1194 MethodKind method_type, 1198 MethodKind method_type,
1195 ExpressionClassifier* classifier, bool* ok) = 0; 1199 ExpressionClassifier* classifier, bool* ok) = 0;
1196 1200
1197 virtual ~ObjectLiteralCheckerBase() {} 1201 virtual ~ObjectLiteralCheckerBase() {}
1198 1202
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after
1855 // to change. Also, this error message will never appear while pre- 1859 // to change. Also, this error message will never appear while pre-
1856 // parsing (this is OK, as it is an implementation limitation). 1860 // parsing (this is OK, as it is an implementation limitation).
1857 ReportMessage(MessageTemplate::kTooManySpreads); 1861 ReportMessage(MessageTemplate::kTooManySpreads);
1858 return impl()->EmptyExpression(); 1862 return impl()->EmptyExpression();
1859 } 1863 }
1860 } 1864 }
1861 return result; 1865 return result;
1862 } 1866 }
1863 1867
1864 template <class Impl> 1868 template <class Impl>
1869 bool ParserBase<Impl>::SetPropertyKindFromToken(Token::Value token,
1870 PropertyKind* kind) {
1871 switch (token) {
1872 case Token::COLON:
1873 *kind = PropertyKind::kValueProperty;
1874 return true;
1875 case Token::COMMA:
1876 case Token::RBRACE:
1877 case Token::ASSIGN:
1878 *kind = PropertyKind::kShorthandProperty;
1879 return true;
1880 case Token::LPAREN:
1881 *kind = PropertyKind::kMethodProperty;
1882 return true;
1883 default:
1884 break;
1885 }
1886 return false;
1887 }
1888
1889 template <class Impl>
1865 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName( 1890 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
1866 IdentifierT* name, bool* is_get, bool* is_set, bool* is_computed_name, 1891 IdentifierT* name, PropertyKind* kind, bool in_class, bool* is_generator,
1867 ExpressionClassifier* classifier, bool* ok) { 1892 bool* is_get, bool* is_set, bool* is_async, bool* is_static,
1893 bool* is_computed_name, ExpressionClassifier* classifier, bool* ok) {
1894 *is_generator = Check(Token::MUL);
1895
1868 Token::Value token = peek(); 1896 Token::Value token = peek();
1869 int pos = peek_position(); 1897 int pos = peek_position();
1870 1898
1899 if (in_class && !*is_generator && token == Token::STATIC) {
1900 Consume(Token::STATIC);
1901 *kind = PropertyKind::kMethodProperty;
1902 if (peek() == Token::LPAREN) {
1903 *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static'
1904 return factory()->NewStringLiteral(*name, pos);
1905 }
1906 *is_generator = Check(Token::MUL);
1907 *is_static = true;
1908 token = peek();
1909 pos = peek_position();
1910 }
1911
1912 if (allow_harmony_async_await() && !*is_generator && token == Token::ASYNC &&
1913 !scanner()->HasAnyLineTerminatorAfterNext()) {
1914 Consume(Token::ASYNC);
1915 token = peek();
1916 if (SetPropertyKindFromToken(token, kind)) {
1917 *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'async'
1918 if (fni_ != nullptr) {
1919 impl()->PushLiteralName(fni_, *name);
1920 }
1921 return factory()->NewStringLiteral(*name, pos);
1922 }
1923 *kind = PropertyKind::kMethodProperty;
1924 *is_async = true;
1925 pos = peek_position();
1926 }
1927
1928 if (token == Token::IDENTIFIER && !*is_generator && !*is_async) {
1929 Consume(Token::IDENTIFIER);
1930 token = peek();
1931 if (SetPropertyKindFromToken(token, kind)) {
1932 *name = impl()->GetSymbol();
1933 if (fni_ != nullptr) {
1934 impl()->PushLiteralName(fni_, *name);
1935 }
1936 return factory()->NewStringLiteral(*name, pos);
1937 }
1938 scanner()->IsGetOrSet(is_get, is_set);
1939 if (!*is_get && !*is_set) { // TODO(bakkot) have IsGetOrSet return a bool
1940 Token::Value next = Next();
1941 ReportUnexpectedToken(next);
1942 *ok = false;
1943 return impl()->EmptyExpression();
1944 }
1945 *kind = PropertyKind::kAccessorProperty;
1946 pos = peek_position();
1947 }
1948
1871 // For non computed property names we normalize the name a bit: 1949 // For non computed property names we normalize the name a bit:
1872 // 1950 //
1873 // "12" -> 12 1951 // "12" -> 12
1874 // 12.3 -> "12.3" 1952 // 12.3 -> "12.3"
1875 // 12.30 -> "12.3" 1953 // 12.30 -> "12.3"
1876 // identifier -> "identifier" 1954 // identifier -> "identifier"
1877 // 1955 //
1878 // This is important because we use the property name as a key in a hash 1956 // This is important because we use the property name as a key in a hash
1879 // table when we compute constant properties. 1957 // table when we compute constant properties.
1958 ExpressionT expression;
1880 switch (token) { 1959 switch (token) {
1881 case Token::STRING: 1960 case Token::STRING:
1882 Consume(Token::STRING); 1961 Consume(Token::STRING);
1883 *name = impl()->GetSymbol(); 1962 *name = impl()->GetSymbol();
1884 break; 1963 break;
1885 1964
1886 case Token::SMI: 1965 case Token::SMI:
1887 Consume(Token::SMI); 1966 Consume(Token::SMI);
1888 *name = impl()->GetNumberAsSymbol(); 1967 *name = impl()->GetNumberAsSymbol();
1889 break; 1968 break;
1890 1969
1891 case Token::NUMBER: 1970 case Token::NUMBER:
1892 Consume(Token::NUMBER); 1971 Consume(Token::NUMBER);
1893 *name = impl()->GetNumberAsSymbol(); 1972 *name = impl()->GetNumberAsSymbol();
1894 break; 1973 break;
1895 1974
1896 case Token::LBRACK: { 1975 case Token::LBRACK: {
1976 *name = impl()->EmptyIdentifier();
1897 *is_computed_name = true; 1977 *is_computed_name = true;
1898 Consume(Token::LBRACK); 1978 Consume(Token::LBRACK);
1899 ExpressionClassifier computed_name_classifier(this); 1979 ExpressionClassifier computed_name_classifier(this);
1900 ExpressionT expression = 1980 expression =
1901 ParseAssignmentExpression(true, &computed_name_classifier, CHECK_OK); 1981 ParseAssignmentExpression(true, &computed_name_classifier, CHECK_OK);
1902 impl()->RewriteNonPattern(&computed_name_classifier, CHECK_OK); 1982 impl()->RewriteNonPattern(&computed_name_classifier, CHECK_OK);
1903 classifier->AccumulateFormalParameterContainmentErrors( 1983 classifier->AccumulateFormalParameterContainmentErrors(
1904 &computed_name_classifier); 1984 &computed_name_classifier);
1905 Expect(Token::RBRACK, CHECK_OK); 1985 Expect(Token::RBRACK, CHECK_OK);
1906 return expression; 1986 break;
1907 } 1987 }
1908 1988
1909 default: 1989 default:
1910 *name = ParseIdentifierName(CHECK_OK); 1990 *name = ParseIdentifierName(CHECK_OK);
1911 scanner()->IsGetOrSet(is_get, is_set);
1912 break; 1991 break;
1913 } 1992 }
1914 1993
1994 if (peek() != Token::COLON && *kind == PropertyKind::kValueProperty) {
marja 2016/08/29 08:07:46 This is still duplicate logic; can this call SetPr
bakkot 2016/08/29 19:54:50 Done. It's a little unpleasant, and strictly speak
1995 switch (peek()) {
1996 case Token::COLON:
1997 UNREACHABLE();
1998 break;
1999 case Token::COMMA:
2000 case Token::RBRACE:
2001 case Token::ASSIGN:
2002 if (!Token::IsIdentifier(token, language_mode(), this->is_generator(),
2003 parsing_module_ || is_async_function())) {
2004 Token::Value next = Next();
2005 ReportUnexpectedToken(next);
2006 *ok = false;
2007 return impl()->EmptyExpression();
2008 }
2009 *kind = PropertyKind::kShorthandProperty;
2010 break;
2011 case Token::LPAREN:
2012 *kind = PropertyKind::kMethodProperty;
2013 break;
2014 default: {
2015 Token::Value next = Next();
2016 ReportUnexpectedToken(next);
2017 *ok = false;
2018 return impl()->EmptyExpression();
2019 }
2020 }
2021 }
2022
2023 if (*is_computed_name) {
2024 return expression;
2025 }
2026
2027 if (fni_ != nullptr) {
2028 impl()->PushLiteralName(fni_, *name);
2029 }
2030
1915 uint32_t index; 2031 uint32_t index;
1916 return impl()->IsArrayIndex(*name, &index) 2032 return impl()->IsArrayIndex(*name, &index)
1917 ? factory()->NewNumberLiteral(index, pos) 2033 ? factory()->NewNumberLiteral(index, pos)
1918 : factory()->NewStringLiteral(*name, pos); 2034 : factory()->NewStringLiteral(*name, pos);
1919 } 2035 }
1920 2036
1921 template <typename Impl> 2037 template <typename Impl>
1922 typename ParserBase<Impl>::ObjectLiteralPropertyT 2038 typename ParserBase<Impl>::ObjectLiteralPropertyT
1923 ParserBase<Impl>::ParsePropertyDefinition( 2039 ParserBase<Impl>::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker,
1924 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, 2040 bool in_class, bool has_extends,
1925 MethodKind method_kind, bool* is_computed_name, bool* has_seen_constructor, 2041 bool* is_computed_name,
1926 ExpressionClassifier* classifier, IdentifierT* name, bool* ok) { 2042 bool* has_seen_constructor,
1927 DCHECK(!in_class || IsStaticMethod(method_kind) || 2043 ExpressionClassifier* classifier,
1928 has_seen_constructor != nullptr); 2044 IdentifierT* name, bool* ok) {
2045 DCHECK(!in_class || has_seen_constructor != nullptr);
1929 bool is_get = false; 2046 bool is_get = false;
1930 bool is_set = false; 2047 bool is_set = false;
1931 bool is_generator = Check(Token::MUL); 2048 bool is_generator = false;
1932 bool is_async = false; 2049 bool is_async = false;
1933 const bool is_static = IsStaticMethod(method_kind); 2050 bool is_static = false;
2051 PropertyKind kind = PropertyKind::kValueProperty;
1934 2052
1935 Token::Value name_token = peek(); 2053 Token::Value name_token = peek();
1936
1937 if (is_generator) {
1938 method_kind |= MethodKind::kGenerator;
1939 } else if (allow_harmony_async_await() && name_token == Token::ASYNC &&
1940 !scanner()->HasAnyLineTerminatorAfterNext() &&
1941 PeekAhead() != Token::LPAREN && PeekAhead()) {
1942 is_async = true;
1943 }
1944
1945 int next_beg_pos = scanner()->peek_location().beg_pos; 2054 int next_beg_pos = scanner()->peek_location().beg_pos;
1946 int next_end_pos = scanner()->peek_location().end_pos; 2055 int next_end_pos = scanner()->peek_location().end_pos;
2056
1947 ExpressionT name_expression = 2057 ExpressionT name_expression =
1948 ParsePropertyName(name, &is_get, &is_set, is_computed_name, classifier, 2058 ParsePropertyName(name, &kind, in_class, &is_generator, &is_get, &is_set,
2059 &is_async, &is_static, is_computed_name, classifier,
1949 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2060 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
1950 2061
1951 if (fni_ != nullptr && !*is_computed_name) { 2062 switch (kind) {
1952 impl()->PushLiteralName(fni_, *name); 2063 case PropertyKind::kValueProperty: {
1953 } 2064 if (in_class) {
2065 Token::Value next = Next();
2066 ReportUnexpectedToken(next);
2067 *ok = false;
2068 return impl()->EmptyObjectLiteralProperty();
2069 }
1954 2070
1955 if (!in_class && !is_generator) { 2071 DCHECK(!is_get && !is_set && !is_generator && !is_async && !is_static);
1956 DCHECK(!IsStaticMethod(method_kind)); 2072
1957 if (peek() == Token::COLON) {
1958 // PropertyDefinition
1959 // PropertyName ':' AssignmentExpression
1960 if (!*is_computed_name) { 2073 if (!*is_computed_name) {
1961 checker->CheckProperty(name_token, kValueProperty, MethodKind::kNormal, 2074 checker->CheckProperty(name_token, PropertyKind::kValueProperty,
1962 classifier, 2075 MethodKind::kNormal, classifier,
1963 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2076 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
1964 } 2077 }
1965 Consume(Token::COLON); 2078 Consume(Token::COLON);
1966 int beg_pos = peek_position(); 2079 int beg_pos = peek_position();
1967 ExpressionT value = ParseAssignmentExpression( 2080 ExpressionT value = ParseAssignmentExpression(
1968 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2081 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
1969 CheckDestructuringElement(value, classifier, beg_pos, 2082 CheckDestructuringElement(value, classifier, beg_pos,
1970 scanner()->location().end_pos); 2083 scanner()->location().end_pos);
1971 2084
1972 return factory()->NewObjectLiteralProperty(name_expression, value, 2085 return factory()->NewObjectLiteralProperty(name_expression, value,
1973 is_static, *is_computed_name); 2086 is_static, *is_computed_name);
1974 } 2087 }
1975 2088
1976 if (Token::IsIdentifier(name_token, language_mode(), this->is_generator(), 2089 case PropertyKind::kShorthandProperty: {
1977 parsing_module_ || is_async_function()) &&
1978 (peek() == Token::COMMA || peek() == Token::RBRACE ||
1979 peek() == Token::ASSIGN)) {
1980 // PropertyDefinition 2090 // PropertyDefinition
1981 // IdentifierReference 2091 // IdentifierReference
1982 // CoverInitializedName 2092 // CoverInitializedName
1983 // 2093 //
1984 // CoverInitializedName 2094 // CoverInitializedName
1985 // IdentifierReference Initializer? 2095 // IdentifierReference Initializer?
2096 if (in_class) {
2097 Token::Value next = Next();
2098 ReportUnexpectedToken(next);
2099 *ok = false;
2100 return impl()->EmptyObjectLiteralProperty();
2101 }
2102
2103 DCHECK(!is_get && !is_set && !is_generator && !is_async && !is_static &&
2104 !*is_computed_name);
2105
1986 if (classifier->duplicate_finder() != nullptr && 2106 if (classifier->duplicate_finder() != nullptr &&
1987 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { 2107 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) {
1988 classifier->RecordDuplicateFormalParameterError(scanner()->location()); 2108 classifier->RecordDuplicateFormalParameterError(scanner()->location());
1989 } 2109 }
1990 2110
1991 if (impl()->IsEvalOrArguments(*name) && is_strict(language_mode())) { 2111 if (impl()->IsEvalOrArguments(*name) && is_strict(language_mode())) {
1992 classifier->RecordBindingPatternError( 2112 classifier->RecordBindingPatternError(
1993 scanner()->location(), MessageTemplate::kStrictEvalArguments); 2113 scanner()->location(), MessageTemplate::kStrictEvalArguments);
1994 } 2114 }
1995 2115
(...skipping 28 matching lines...) Expand all
2024 2144
2025 impl()->SetFunctionNameFromIdentifierRef(rhs, lhs); 2145 impl()->SetFunctionNameFromIdentifierRef(rhs, lhs);
2026 } else { 2146 } else {
2027 value = lhs; 2147 value = lhs;
2028 } 2148 }
2029 2149
2030 return factory()->NewObjectLiteralProperty( 2150 return factory()->NewObjectLiteralProperty(
2031 name_expression, value, ObjectLiteralProperty::COMPUTED, is_static, 2151 name_expression, value, ObjectLiteralProperty::COMPUTED, is_static,
2032 false); 2152 false);
2033 } 2153 }
2034 }
2035 2154
2036 // Method definitions are never valid in patterns. 2155 case PropertyKind::kMethodProperty: {
2037 classifier->RecordPatternError( 2156 DCHECK(!is_get && !is_set);
2038 Scanner::Location(next_beg_pos, scanner()->location().end_pos),
2039 MessageTemplate::kInvalidDestructuringTarget);
2040 2157
2041 if (is_async && !IsSpecialMethod(method_kind)) { 2158 MethodKind method_kind = MethodKind::kNormal;
2042 DCHECK(!is_get); 2159 if (is_generator) {
2043 DCHECK(!is_set); 2160 method_kind |= MethodKind::kGenerator;
2044 bool dont_care; 2161 }
2045 name_expression = ParsePropertyName( 2162 if (is_async) {
2046 name, &dont_care, &dont_care, is_computed_name, classifier, 2163 method_kind |= MethodKind::kAsync;
2047 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2164 }
2048 method_kind |= MethodKind::kAsync; 2165 if (is_static) {
2049 } 2166 method_kind |= MethodKind::kStatic;
2167 }
2050 2168
2051 if (is_generator || peek() == Token::LPAREN) { 2169 // MethodDefinition
2052 // MethodDefinition 2170 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
2053 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' 2171 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
2054 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' 2172
2055 if (!*is_computed_name) { 2173 classifier->RecordPatternError(
2056 checker->CheckProperty(name_token, kMethodProperty, method_kind, 2174 Scanner::Location(next_beg_pos, scanner()->location().end_pos),
2057 classifier, 2175 MessageTemplate::kInvalidDestructuringTarget);
2058 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); 2176
2177 if (!*is_computed_name) {
2178 checker->CheckProperty(name_token, PropertyKind::kMethodProperty,
2179 method_kind, classifier,
2180 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2181 }
2182
2183 FunctionKind kind = is_generator
2184 ? FunctionKind::kConciseGeneratorMethod
2185 : is_async ? FunctionKind::kAsyncConciseMethod
2186 : FunctionKind::kConciseMethod;
2187
2188 if (in_class && !is_static && impl()->IsConstructor(*name)) {
2189 *has_seen_constructor = true;
2190 kind = has_extends ? FunctionKind::kSubclassConstructor
2191 : FunctionKind::kBaseConstructor;
2192 }
2193
2194 ExpressionT value = impl()->ParseFunctionLiteral(
2195 *name, scanner()->location(), kSkipFunctionNameCheck, kind,
2196 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod,
2197 language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2198
2199 return factory()->NewObjectLiteralProperty(
2200 name_expression, value, ObjectLiteralProperty::COMPUTED, is_static,
2201 *is_computed_name);
2059 } 2202 }
2060 2203
2061 FunctionKind kind = is_generator 2204 case PropertyKind::kAccessorProperty: {
2062 ? FunctionKind::kConciseGeneratorMethod 2205 DCHECK((is_get || is_set) && !is_generator && !is_async);
2063 : is_async ? FunctionKind::kAsyncConciseMethod
2064 : FunctionKind::kConciseMethod;
2065 2206
2066 if (in_class && !IsStaticMethod(method_kind) && 2207 MethodKind method_kind = MethodKind::kNormal;
2067 impl()->IsConstructor(*name)) { 2208 if (is_static) {
2068 *has_seen_constructor = true; 2209 DCHECK(in_class);
2069 kind = has_extends ? FunctionKind::kSubclassConstructor 2210 method_kind |= MethodKind::kStatic;
2070 : FunctionKind::kBaseConstructor; 2211 }
2212
2213 classifier->RecordPatternError(
2214 Scanner::Location(next_beg_pos, scanner()->location().end_pos),
2215 MessageTemplate::kInvalidDestructuringTarget);
2216 if (!*is_computed_name) {
2217 checker->CheckProperty(name_token, PropertyKind::kAccessorProperty,
2218 method_kind, classifier,
2219 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2220 }
2221
2222 typename Types::FunctionLiteral value = impl()->ParseFunctionLiteral(
2223 *name, scanner()->location(), kSkipFunctionNameCheck,
2224 is_get ? FunctionKind::kGetterFunction
2225 : FunctionKind::kSetterFunction,
2226 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod,
2227 language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2228
2229 // Make sure the name expression is a string since we need a Name for
2230 // Runtime_DefineAccessorPropertyUnchecked and since we can determine this
2231 // statically we can skip the extra runtime check.
2232 if (!*is_computed_name) {
2233 name_expression =
2234 factory()->NewStringLiteral(*name, name_expression->position());
2235 }
2236
2237 return factory()->NewObjectLiteralProperty(
2238 name_expression, value, is_get ? ObjectLiteralProperty::GETTER
2239 : ObjectLiteralProperty::SETTER,
2240 is_static, *is_computed_name);
2071 } 2241 }
2072
2073 ExpressionT value = impl()->ParseFunctionLiteral(
2074 *name, scanner()->location(), kSkipFunctionNameCheck, kind,
2075 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, language_mode(),
2076 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2077
2078 return factory()->NewObjectLiteralProperty(name_expression, value,
2079 ObjectLiteralProperty::COMPUTED,
2080 is_static, *is_computed_name);
2081 } 2242 }
2082 2243 UNREACHABLE();
2083 if (in_class && name_token == Token::STATIC && IsNormalMethod(method_kind)) {
2084 // ClassElement (static)
2085 // 'static' MethodDefinition
2086 *name = impl()->EmptyIdentifier();
2087 ObjectLiteralPropertyT property = ParsePropertyDefinition(
2088 checker, true, has_extends, MethodKind::kStatic, is_computed_name,
2089 nullptr, classifier, name, ok);
2090 impl()->RewriteNonPattern(classifier, ok);
2091 return property;
2092 }
2093
2094 if (is_get || is_set) {
2095 // MethodDefinition (Accessors)
2096 // get PropertyName '(' ')' '{' FunctionBody '}'
2097 // set PropertyName '(' PropertySetParameterList ')' '{' FunctionBody '}'
2098 *name = impl()->EmptyIdentifier();
2099 bool dont_care = false;
2100 name_token = peek();
2101
2102 name_expression = ParsePropertyName(
2103 name, &dont_care, &dont_care, is_computed_name, classifier,
2104 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2105
2106 if (!*is_computed_name) {
2107 checker->CheckProperty(name_token, kAccessorProperty, method_kind,
2108 classifier,
2109 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2110 }
2111
2112 FunctionLiteralT value = impl()->ParseFunctionLiteral(
2113 *name, scanner()->location(), kSkipFunctionNameCheck,
2114 is_get ? FunctionKind::kGetterFunction : FunctionKind::kSetterFunction,
2115 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, language_mode(),
2116 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
2117
2118 // Make sure the name expression is a string since we need a Name for
2119 // Runtime_DefineAccessorPropertyUnchecked and since we can determine this
2120 // statically we can skip the extra runtime check.
2121 if (!*is_computed_name) {
2122 name_expression =
2123 factory()->NewStringLiteral(*name, name_expression->position());
2124 }
2125
2126 return factory()->NewObjectLiteralProperty(
2127 name_expression, value,
2128 is_get ? ObjectLiteralProperty::GETTER : ObjectLiteralProperty::SETTER,
2129 is_static, *is_computed_name);
2130 }
2131
2132 Token::Value next = Next();
2133 ReportUnexpectedToken(next);
2134 *ok = false;
2135 return impl()->EmptyObjectLiteralProperty(); 2244 return impl()->EmptyObjectLiteralProperty();
2136 } 2245 }
2137 2246
2138 template <typename Impl> 2247 template <typename Impl>
2139 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral( 2248 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral(
2140 ExpressionClassifier* classifier, bool* ok) { 2249 ExpressionClassifier* classifier, bool* ok) {
2141 // ObjectLiteral :: 2250 // ObjectLiteral ::
2142 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' 2251 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}'
2143 2252
2144 int pos = peek_position(); 2253 int pos = peek_position();
2145 typename Types::PropertyList properties = impl()->NewPropertyList(4); 2254 typename Types::PropertyList properties = impl()->NewPropertyList(4);
2146 int number_of_boilerplate_properties = 0; 2255 int number_of_boilerplate_properties = 0;
2147 bool has_computed_names = false; 2256 bool has_computed_names = false;
2148 ObjectLiteralChecker checker(this); 2257 ObjectLiteralChecker checker(this);
2149 2258
2150 Expect(Token::LBRACE, CHECK_OK); 2259 Expect(Token::LBRACE, CHECK_OK);
2151 2260
2152 while (peek() != Token::RBRACE) { 2261 while (peek() != Token::RBRACE) {
2153 FuncNameInferrer::State fni_state(fni_); 2262 FuncNameInferrer::State fni_state(fni_);
2154 2263
2155 const bool in_class = false; 2264 const bool in_class = false;
2156 const bool has_extends = false; 2265 const bool has_extends = false;
2157 bool is_computed_name = false; 2266 bool is_computed_name = false;
2158 IdentifierT name = impl()->EmptyIdentifier(); 2267 IdentifierT name = impl()->EmptyIdentifier();
2159 ObjectLiteralPropertyT property = ParsePropertyDefinition( 2268 ObjectLiteralPropertyT property = ParsePropertyDefinition(
2160 &checker, in_class, has_extends, MethodKind::kNormal, &is_computed_name, 2269 &checker, in_class, has_extends, &is_computed_name, nullptr, classifier,
2161 NULL, classifier, &name, CHECK_OK); 2270 &name, CHECK_OK);
2162 2271
2163 if (is_computed_name) { 2272 if (is_computed_name) {
2164 has_computed_names = true; 2273 has_computed_names = true;
2165 } 2274 }
2166 2275
2167 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. 2276 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
2168 if (!has_computed_names && impl()->IsBoilerplateProperty(property)) { 2277 if (!has_computed_names && impl()->IsBoilerplateProperty(property)) {
2169 number_of_boilerplate_properties++; 2278 number_of_boilerplate_properties++;
2170 } 2279 }
2171 properties->Add(property, zone()); 2280 properties->Add(property, zone());
(...skipping 1462 matching lines...) Expand 10 before | Expand all | Expand 10 after
3634 3743
3635 3744
3636 #undef CHECK_OK 3745 #undef CHECK_OK
3637 #undef CHECK_OK_CUSTOM 3746 #undef CHECK_OK_CUSTOM
3638 3747
3639 template <typename Impl> 3748 template <typename Impl>
3640 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty( 3749 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty(
3641 Token::Value property, PropertyKind type, MethodKind method_type, 3750 Token::Value property, PropertyKind type, MethodKind method_type,
3642 ExpressionClassifier* classifier, bool* ok) { 3751 ExpressionClassifier* classifier, bool* ok) {
3643 DCHECK(!IsStaticMethod(method_type)); 3752 DCHECK(!IsStaticMethod(method_type));
3644 DCHECK(!IsSpecialMethod(method_type) || type == kMethodProperty); 3753 DCHECK(!IsSpecialMethod(method_type) ||
3754 type == PropertyKind::kMethodProperty);
3645 3755
3646 if (property == Token::SMI || property == Token::NUMBER) return; 3756 if (property == Token::SMI || property == Token::NUMBER) return;
3647 3757
3648 if (type == kValueProperty && IsProto()) { 3758 if (type == PropertyKind::kValueProperty && IsProto()) {
3649 if (has_seen_proto_) { 3759 if (has_seen_proto_) {
3650 classifier->RecordExpressionError(this->scanner()->location(), 3760 classifier->RecordExpressionError(this->scanner()->location(),
3651 MessageTemplate::kDuplicateProto); 3761 MessageTemplate::kDuplicateProto);
3652 return; 3762 return;
3653 } 3763 }
3654 has_seen_proto_ = true; 3764 has_seen_proto_ = true;
3655 } 3765 }
3656 } 3766 }
3657 3767
3658 template <typename Impl> 3768 template <typename Impl>
3659 void ParserBase<Impl>::ClassLiteralChecker::CheckProperty( 3769 void ParserBase<Impl>::ClassLiteralChecker::CheckProperty(
3660 Token::Value property, PropertyKind type, MethodKind method_type, 3770 Token::Value property, PropertyKind type, MethodKind method_type,
3661 ExpressionClassifier* classifier, bool* ok) { 3771 ExpressionClassifier* classifier, bool* ok) {
3662 DCHECK(type == kMethodProperty || type == kAccessorProperty); 3772 DCHECK(type == PropertyKind::kMethodProperty ||
3773 type == PropertyKind::kAccessorProperty);
3663 3774
3664 if (property == Token::SMI || property == Token::NUMBER) return; 3775 if (property == Token::SMI || property == Token::NUMBER) return;
3665 3776
3666 if (IsStaticMethod(method_type)) { 3777 if (IsStaticMethod(method_type)) {
3667 if (IsPrototype()) { 3778 if (IsPrototype()) {
3668 this->parser()->ReportMessage(MessageTemplate::kStaticPrototype); 3779 this->parser()->ReportMessage(MessageTemplate::kStaticPrototype);
3669 *ok = false; 3780 *ok = false;
3670 return; 3781 return;
3671 } 3782 }
3672 } else if (IsConstructor()) { 3783 } else if (IsConstructor()) {
3673 const bool is_generator = IsGeneratorMethod(method_type); 3784 const bool is_generator = IsGeneratorMethod(method_type);
3674 const bool is_async = IsAsyncMethod(method_type); 3785 const bool is_async = IsAsyncMethod(method_type);
3675 if (is_generator || is_async || type == kAccessorProperty) { 3786 if (is_generator || is_async || type == PropertyKind::kAccessorProperty) {
3676 MessageTemplate::Template msg = 3787 MessageTemplate::Template msg =
3677 is_generator ? MessageTemplate::kConstructorIsGenerator 3788 is_generator ? MessageTemplate::kConstructorIsGenerator
3678 : is_async ? MessageTemplate::kConstructorIsAsync 3789 : is_async ? MessageTemplate::kConstructorIsAsync
3679 : MessageTemplate::kConstructorIsAccessor; 3790 : MessageTemplate::kConstructorIsAccessor;
3680 this->parser()->ReportMessage(msg); 3791 this->parser()->ReportMessage(msg);
3681 *ok = false; 3792 *ok = false;
3682 return; 3793 return;
3683 } 3794 }
3684 if (has_seen_constructor_) { 3795 if (has_seen_constructor_) {
3685 this->parser()->ReportMessage(MessageTemplate::kDuplicateConstructor); 3796 this->parser()->ReportMessage(MessageTemplate::kDuplicateConstructor);
3686 *ok = false; 3797 *ok = false;
3687 return; 3798 return;
3688 } 3799 }
3689 has_seen_constructor_ = true; 3800 has_seen_constructor_ = true;
3690 return; 3801 return;
3691 } 3802 }
3692 } 3803 }
3693 3804
3694 3805
3695 } // namespace internal 3806 } // namespace internal
3696 } // namespace v8 3807 } // namespace v8
3697 3808
3698 #endif // V8_PARSING_PARSER_BASE_H 3809 #endif // V8_PARSING_PARSER_BASE_H
OLDNEW
« no previous file with comments | « src/parsing/parser.cc ('k') | src/parsing/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698