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_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 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
176 // typedef Base; | 176 // typedef Base; |
177 // typedef Impl; | 177 // typedef Impl; |
178 // // TODO(nikolaos): this one will probably go away, as it is | 178 // // TODO(nikolaos): this one will probably go away, as it is |
179 // // not related to pure parsing. | 179 // // not related to pure parsing. |
180 // typedef GeneratorVariable; | 180 // typedef GeneratorVariable; |
181 // // Return types for traversing functions. | 181 // // Return types for traversing functions. |
182 // typedef Identifier; | 182 // typedef Identifier; |
183 // typedef Expression; | 183 // typedef Expression; |
184 // typedef FunctionLiteral; | 184 // typedef FunctionLiteral; |
185 // typedef ObjectLiteralProperty; | 185 // typedef ObjectLiteralProperty; |
186 // typedef ClassLiteralProperty; | |
186 // typedef ExpressionList; | 187 // typedef ExpressionList; |
187 // typedef PropertyList; | 188 // typedef PropertyList; |
188 // typedef FormalParameters; | 189 // typedef FormalParameters; |
189 // typedef StatementList; | 190 // typedef StatementList; |
190 // typedef Block; | 191 // typedef Block; |
191 // // For constructing objects returned by the traversing functions. | 192 // // For constructing objects returned by the traversing functions. |
192 // typedef Factory; | 193 // typedef Factory; |
193 // }; | 194 // }; |
194 | 195 |
195 template <typename Impl> | 196 template <typename Impl> |
196 struct ParserTypes; | 197 struct ParserTypes; |
197 | 198 |
198 template <typename Impl> | 199 template <typename Impl> |
199 class ParserBase { | 200 class ParserBase { |
200 public: | 201 public: |
201 // Shorten type names defined by ParserTypes<Impl>. | 202 // Shorten type names defined by ParserTypes<Impl>. |
202 typedef ParserTypes<Impl> Types; | 203 typedef ParserTypes<Impl> Types; |
203 typedef typename Types::Identifier IdentifierT; | 204 typedef typename Types::Identifier IdentifierT; |
204 typedef typename Types::Expression ExpressionT; | 205 typedef typename Types::Expression ExpressionT; |
205 typedef typename Types::FunctionLiteral FunctionLiteralT; | 206 typedef typename Types::FunctionLiteral FunctionLiteralT; |
206 typedef typename Types::ObjectLiteralProperty ObjectLiteralPropertyT; | 207 typedef typename Types::ObjectLiteralProperty ObjectLiteralPropertyT; |
208 typedef typename Types::ClassLiteralProperty ClassLiteralPropertyT; | |
207 typedef typename Types::ExpressionList ExpressionListT; | 209 typedef typename Types::ExpressionList ExpressionListT; |
208 typedef typename Types::PropertyList PropertyListT; | 210 typedef typename Types::PropertyList PropertyListT; |
209 typedef typename Types::FormalParameters FormalParametersT; | 211 typedef typename Types::FormalParameters FormalParametersT; |
210 typedef typename Types::StatementList StatementListT; | 212 typedef typename Types::StatementList StatementListT; |
211 typedef typename Types::Block BlockT; | 213 typedef typename Types::Block BlockT; |
212 typedef typename v8::internal::ExpressionClassifier<Types> | 214 typedef typename v8::internal::ExpressionClassifier<Types> |
213 ExpressionClassifier; | 215 ExpressionClassifier; |
214 | 216 |
215 // All implementation-specific methods must be called through this. | 217 // All implementation-specific methods must be called through this. |
216 Impl* impl() { return static_cast<Impl*>(this); } | 218 Impl* impl() { return static_cast<Impl*>(this); } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
287 }; | 289 }; |
288 | 290 |
289 enum VariableDeclarationContext { | 291 enum VariableDeclarationContext { |
290 kStatementListItem, | 292 kStatementListItem, |
291 kStatement, | 293 kStatement, |
292 kForStatement | 294 kForStatement |
293 }; | 295 }; |
294 // clang-format on | 296 // clang-format on |
295 | 297 |
296 class Checkpoint; | 298 class Checkpoint; |
297 class ObjectLiteralCheckerBase; | 299 class ClassLiteralChecker; |
300 class ObjectLiteralChecker; | |
298 | 301 |
299 // --------------------------------------------------------------------------- | 302 // --------------------------------------------------------------------------- |
300 // ScopeState and its subclasses implement the parser's scope stack. | 303 // ScopeState and its subclasses implement the parser's scope stack. |
301 // ScopeState keeps track of the current scope, and the outer ScopeState. The | 304 // ScopeState keeps track of the current scope, and the outer ScopeState. The |
302 // parser's scope_state_ points to the top ScopeState. ScopeState's | 305 // parser's scope_state_ points to the top ScopeState. ScopeState's |
303 // constructor push on the scope stack and the destructors pop. BlockState and | 306 // constructor push on the scope stack and the destructors pop. BlockState and |
304 // FunctionState are used to hold additional per-block and per-function state. | 307 // FunctionState are used to hold additional per-block and per-function state. |
305 class ScopeState BASE_EMBEDDED { | 308 class ScopeState BASE_EMBEDDED { |
306 public: | 309 public: |
307 V8_INLINE Scope* scope() const { return scope_; } | 310 V8_INLINE Scope* scope() const { return scope_; } |
(...skipping 817 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1125 enum class PropertyKind { | 1128 enum class PropertyKind { |
1126 kAccessorProperty, | 1129 kAccessorProperty, |
1127 kValueProperty, | 1130 kValueProperty, |
1128 kShorthandProperty, | 1131 kShorthandProperty, |
1129 kMethodProperty, | 1132 kMethodProperty, |
1130 kNotSet | 1133 kNotSet |
1131 }; | 1134 }; |
1132 | 1135 |
1133 bool SetPropertyKindFromToken(Token::Value token, PropertyKind* kind); | 1136 bool SetPropertyKindFromToken(Token::Value token, PropertyKind* kind); |
1134 ExpressionT ParsePropertyName(IdentifierT* name, PropertyKind* kind, | 1137 ExpressionT ParsePropertyName(IdentifierT* name, PropertyKind* kind, |
1135 bool in_class, bool* is_generator, bool* is_get, | 1138 bool* is_generator, bool* is_get, bool* is_set, |
1136 bool* is_set, bool* is_async, bool* is_static, | 1139 bool* is_async, bool* is_computed_name, |
1137 bool* is_computed_name, bool* ok); | 1140 bool* ok); |
1138 | |
1139 ExpressionT ParseObjectLiteral(bool* ok); | 1141 ExpressionT ParseObjectLiteral(bool* ok); |
1140 ObjectLiteralPropertyT ParsePropertyDefinition( | 1142 ClassLiteralPropertyT ParseClassPropertyDefinition( |
1141 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, | 1143 ClassLiteralChecker* checker, bool has_extends, bool* is_computed_name, |
1142 bool* is_computed_name, bool* has_seen_constructor, IdentifierT* name, | 1144 bool* has_seen_constructor, IdentifierT* name, bool* ok); |
1145 ObjectLiteralPropertyT ParseObjectPropertyDefinition( | |
1146 ObjectLiteralChecker* checker, bool* is_computed_name, IdentifierT* name, | |
1143 bool* ok); | 1147 bool* ok); |
1144 ExpressionListT ParseArguments(Scanner::Location* first_spread_pos, | 1148 ExpressionListT ParseArguments(Scanner::Location* first_spread_pos, |
1145 bool maybe_arrow, bool* ok); | 1149 bool maybe_arrow, bool* ok); |
1146 ExpressionListT ParseArguments(Scanner::Location* first_spread_pos, | 1150 ExpressionListT ParseArguments(Scanner::Location* first_spread_pos, |
1147 bool* ok) { | 1151 bool* ok) { |
1148 return ParseArguments(first_spread_pos, false, ok); | 1152 return ParseArguments(first_spread_pos, false, ok); |
1149 } | 1153 } |
1150 | 1154 |
1151 ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok); | 1155 ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok); |
1152 ExpressionT ParseYieldExpression(bool accept_IN, bool* ok); | 1156 ExpressionT ParseYieldExpression(bool accept_IN, bool* ok); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1218 if (is_sloppy(scope->language_mode())) { | 1222 if (is_sloppy(scope->language_mode())) { |
1219 // For sloppy scopes we also have to record the call at function level, | 1223 // For sloppy scopes we also have to record the call at function level, |
1220 // in case it includes declarations that will be hoisted. | 1224 // in case it includes declarations that will be hoisted. |
1221 scope->GetDeclarationScope()->RecordEvalCall(); | 1225 scope->GetDeclarationScope()->RecordEvalCall(); |
1222 } | 1226 } |
1223 return Call::IS_POSSIBLY_EVAL; | 1227 return Call::IS_POSSIBLY_EVAL; |
1224 } | 1228 } |
1225 return Call::NOT_EVAL; | 1229 return Call::NOT_EVAL; |
1226 } | 1230 } |
1227 | 1231 |
1228 class ObjectLiteralCheckerBase { | |
1229 public: | |
1230 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {} | |
1231 | |
1232 virtual void CheckProperty(Token::Value property, PropertyKind type, | |
1233 MethodKind method_type, bool* ok) = 0; | |
1234 | |
1235 virtual ~ObjectLiteralCheckerBase() {} | |
1236 | |
1237 protected: | |
1238 ParserBase* parser() const { return parser_; } | |
1239 Scanner* scanner() const { return parser_->scanner(); } | |
1240 | |
1241 private: | |
1242 ParserBase* parser_; | |
1243 }; | |
1244 | |
1245 // Validation per ES6 object literals. | 1232 // Validation per ES6 object literals. |
1246 class ObjectLiteralChecker : public ObjectLiteralCheckerBase { | 1233 class ObjectLiteralChecker { |
1247 public: | 1234 public: |
1248 explicit ObjectLiteralChecker(ParserBase* parser) | 1235 explicit ObjectLiteralChecker(ParserBase* parser) |
1249 : ObjectLiteralCheckerBase(parser), has_seen_proto_(false) {} | 1236 : parser_(parser), has_seen_proto_(false) {} |
1250 | 1237 |
1251 void CheckProperty(Token::Value property, PropertyKind type, | 1238 void CheckDuplicateProto(Token::Value property); |
1252 MethodKind method_type, bool* ok) override; | |
1253 | 1239 |
1254 private: | 1240 private: |
1255 bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); } | 1241 bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); } |
1256 | 1242 |
1243 ParserBase* parser() const { return parser_; } | |
1244 Scanner* scanner() const { return parser_->scanner(); } | |
1245 | |
1246 ParserBase* parser_; | |
1257 bool has_seen_proto_; | 1247 bool has_seen_proto_; |
1258 }; | 1248 }; |
1259 | 1249 |
1260 // Validation per ES6 class literals. | 1250 // Validation per ES6 class literals. |
1261 class ClassLiteralChecker : public ObjectLiteralCheckerBase { | 1251 class ClassLiteralChecker { |
1262 public: | 1252 public: |
1263 explicit ClassLiteralChecker(ParserBase* parser) | 1253 explicit ClassLiteralChecker(ParserBase* parser) |
1264 : ObjectLiteralCheckerBase(parser), has_seen_constructor_(false) {} | 1254 : parser_(parser), has_seen_constructor_(false) {} |
1265 | 1255 |
1266 void CheckProperty(Token::Value property, PropertyKind type, | 1256 void CheckClassMethodName(Token::Value property, PropertyKind type, |
1267 MethodKind method_type, bool* ok) override; | 1257 MethodKind method_type, bool* ok); |
1268 | 1258 |
1269 private: | 1259 private: |
1270 bool IsConstructor() { | 1260 bool IsConstructor() { |
1271 return this->scanner()->LiteralMatches("constructor", 11); | 1261 return this->scanner()->LiteralMatches("constructor", 11); |
1272 } | 1262 } |
1273 bool IsPrototype() { | 1263 bool IsPrototype() { |
1274 return this->scanner()->LiteralMatches("prototype", 9); | 1264 return this->scanner()->LiteralMatches("prototype", 9); |
1275 } | 1265 } |
1276 | 1266 |
1267 ParserBase* parser() const { return parser_; } | |
1268 Scanner* scanner() const { return parser_->scanner(); } | |
1269 | |
1270 ParserBase* parser_; | |
1277 bool has_seen_constructor_; | 1271 bool has_seen_constructor_; |
1278 }; | 1272 }; |
1279 | 1273 |
1280 ModuleDescriptor* module() const { | 1274 ModuleDescriptor* module() const { |
1281 return scope()->AsModuleScope()->module(); | 1275 return scope()->AsModuleScope()->module(); |
1282 } | 1276 } |
1283 Scope* scope() const { return scope_state_->scope(); } | 1277 Scope* scope() const { return scope_state_->scope(); } |
1284 | 1278 |
1285 // Stack of expression classifiers. | 1279 // Stack of expression classifiers. |
1286 // The top of the stack is always pointed to by classifier(). | 1280 // The top of the stack is always pointed to by classifier(). |
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1909 *kind = PropertyKind::kMethodProperty; | 1903 *kind = PropertyKind::kMethodProperty; |
1910 return true; | 1904 return true; |
1911 default: | 1905 default: |
1912 break; | 1906 break; |
1913 } | 1907 } |
1914 return false; | 1908 return false; |
1915 } | 1909 } |
1916 | 1910 |
1917 template <class Impl> | 1911 template <class Impl> |
1918 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName( | 1912 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName( |
1919 IdentifierT* name, PropertyKind* kind, bool in_class, bool* is_generator, | 1913 IdentifierT* name, PropertyKind* kind, bool* is_generator, bool* is_get, |
1920 bool* is_get, bool* is_set, bool* is_async, bool* is_static, | 1914 bool* is_set, bool* is_async, bool* is_computed_name, bool* ok) { |
1921 bool* is_computed_name, bool* ok) { | 1915 DCHECK(*kind == PropertyKind::kNotSet || |
1922 DCHECK(*kind == PropertyKind::kNotSet); | 1916 *kind == PropertyKind::kMethodProperty); // The second case occurs |
1917 // when parsing static fields | |
1918 // of classes. | |
1923 DCHECK(!*is_generator); | 1919 DCHECK(!*is_generator); |
1924 DCHECK(!*is_get); | 1920 DCHECK(!*is_get); |
1925 DCHECK(!*is_set); | 1921 DCHECK(!*is_set); |
1926 DCHECK(!*is_async); | 1922 DCHECK(!*is_async); |
1927 DCHECK(!*is_static); | |
1928 DCHECK(!*is_computed_name); | 1923 DCHECK(!*is_computed_name); |
1929 | 1924 |
1930 *is_generator = Check(Token::MUL); | 1925 *is_generator = Check(Token::MUL); |
1931 if (*is_generator) { | 1926 if (*is_generator) { |
1932 *kind = PropertyKind::kMethodProperty; | 1927 *kind = PropertyKind::kMethodProperty; |
1933 } | 1928 } |
1934 | 1929 |
1935 Token::Value token = peek(); | 1930 Token::Value token = peek(); |
1936 int pos = peek_position(); | 1931 int pos = peek_position(); |
1937 | 1932 |
1938 if (in_class && !*is_generator && token == Token::STATIC) { | |
1939 Consume(Token::STATIC); | |
1940 *kind = PropertyKind::kMethodProperty; | |
1941 if (peek() == Token::LPAREN) { | |
1942 *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static' | |
1943 return factory()->NewStringLiteral(*name, pos); | |
1944 } | |
1945 *is_generator = Check(Token::MUL); | |
1946 *is_static = true; | |
1947 token = peek(); | |
1948 pos = peek_position(); | |
1949 } | |
1950 | |
1951 if (allow_harmony_async_await() && !*is_generator && token == Token::ASYNC && | 1933 if (allow_harmony_async_await() && !*is_generator && token == Token::ASYNC && |
1952 !scanner()->HasAnyLineTerminatorAfterNext()) { | 1934 !scanner()->HasAnyLineTerminatorAfterNext()) { |
1953 Consume(Token::ASYNC); | 1935 Consume(Token::ASYNC); |
1954 token = peek(); | 1936 token = peek(); |
1955 if (SetPropertyKindFromToken(token, kind)) { | 1937 if (SetPropertyKindFromToken(token, kind)) { |
1956 *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'async' | 1938 *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'async' |
1957 if (fni_ != nullptr) { | 1939 if (fni_ != nullptr) { |
1958 impl()->PushLiteralName(fni_, *name); | 1940 impl()->PushLiteralName(fni_, *name); |
1959 } | 1941 } |
1960 return factory()->NewStringLiteral(*name, pos); | 1942 return factory()->NewStringLiteral(*name, pos); |
1961 } | 1943 } |
1962 *kind = PropertyKind::kMethodProperty; | 1944 *kind = PropertyKind::kMethodProperty; |
1963 *is_async = true; | 1945 *is_async = true; |
1964 pos = peek_position(); | 1946 pos = peek_position(); |
1965 } | 1947 } |
1966 | 1948 |
1967 if (token == Token::IDENTIFIER && !*is_generator && !*is_async) { | 1949 if (token == Token::IDENTIFIER && !*is_generator && !*is_async) { |
1968 // This is checking for 'get' and 'set' in particular. Any other identifier | 1950 // This is checking for 'get' and 'set' in particular. |
1969 // must be the property name, and so SetPropertyKindFromToken will return | |
1970 // true (unless there's a syntax error). | |
1971 Consume(Token::IDENTIFIER); | 1951 Consume(Token::IDENTIFIER); |
1972 token = peek(); | 1952 token = peek(); |
1973 if (SetPropertyKindFromToken(token, kind)) { | 1953 if (SetPropertyKindFromToken(token, kind) || |
1954 !scanner()->IsGetOrSet(is_get, is_set)) { | |
1974 *name = impl()->GetSymbol(); | 1955 *name = impl()->GetSymbol(); |
1975 if (fni_ != nullptr) { | 1956 if (fni_ != nullptr) { |
1976 impl()->PushLiteralName(fni_, *name); | 1957 impl()->PushLiteralName(fni_, *name); |
1977 } | 1958 } |
1978 return factory()->NewStringLiteral(*name, pos); | 1959 return factory()->NewStringLiteral(*name, pos); |
1979 } | 1960 } |
1980 scanner()->IsGetOrSet(is_get, is_set); | |
1981 if (!*is_get && !*is_set) { // TODO(bakkot) have IsGetOrSet return a bool | |
1982 Token::Value next = Next(); | |
1983 ReportUnexpectedToken(next); | |
1984 *ok = false; | |
1985 return impl()->EmptyExpression(); | |
1986 } | |
1987 *kind = PropertyKind::kAccessorProperty; | 1961 *kind = PropertyKind::kAccessorProperty; |
1988 pos = peek_position(); | 1962 pos = peek_position(); |
1989 } | 1963 } |
1990 | 1964 |
1991 // For non computed property names we normalize the name a bit: | 1965 // For non computed property names we normalize the name a bit: |
1992 // | 1966 // |
1993 // "12" -> 12 | 1967 // "12" -> 12 |
1994 // 12.3 -> "12.3" | 1968 // 12.3 -> "12.3" |
1995 // 12.30 -> "12.3" | 1969 // 12.30 -> "12.3" |
1996 // identifier -> "identifier" | 1970 // identifier -> "identifier" |
(...skipping 28 matching lines...) Expand all Loading... | |
2025 Expect(Token::RBRACK, CHECK_OK); | 1999 Expect(Token::RBRACK, CHECK_OK); |
2026 break; | 2000 break; |
2027 } | 2001 } |
2028 | 2002 |
2029 default: | 2003 default: |
2030 *name = ParseIdentifierName(CHECK_OK); | 2004 *name = ParseIdentifierName(CHECK_OK); |
2031 break; | 2005 break; |
2032 } | 2006 } |
2033 | 2007 |
2034 if (*kind == PropertyKind::kNotSet) { | 2008 if (*kind == PropertyKind::kNotSet) { |
2035 if (!SetPropertyKindFromToken(peek(), kind) || | 2009 SetPropertyKindFromToken(peek(), kind); |
2036 (*kind == PropertyKind::kShorthandProperty && | |
2037 !Token::IsIdentifier(token, language_mode(), this->is_generator(), | |
2038 parsing_module_ || is_async_function()))) { | |
2039 Token::Value next = Next(); | |
2040 ReportUnexpectedToken(next); | |
2041 *ok = false; | |
2042 return impl()->EmptyExpression(); | |
2043 } | |
2044 } | 2010 } |
2045 DCHECK(*kind != PropertyKind::kNotSet); | |
2046 | 2011 |
2047 if (*is_computed_name) { | 2012 if (*is_computed_name) { |
2048 return expression; | 2013 return expression; |
2049 } | 2014 } |
2050 | 2015 |
2051 if (fni_ != nullptr) { | 2016 if (fni_ != nullptr) { |
2052 impl()->PushLiteralName(fni_, *name); | 2017 impl()->PushLiteralName(fni_, *name); |
2053 } | 2018 } |
2054 | 2019 |
2055 uint32_t index; | 2020 uint32_t index; |
2056 return impl()->IsArrayIndex(*name, &index) | 2021 return impl()->IsArrayIndex(*name, &index) |
2057 ? factory()->NewNumberLiteral(index, pos) | 2022 ? factory()->NewNumberLiteral(index, pos) |
2058 : factory()->NewStringLiteral(*name, pos); | 2023 : factory()->NewStringLiteral(*name, pos); |
2059 } | 2024 } |
2060 | 2025 |
2061 template <typename Impl> | 2026 template <typename Impl> |
2062 typename ParserBase<Impl>::ObjectLiteralPropertyT | 2027 typename ParserBase<Impl>::ClassLiteralPropertyT |
2063 ParserBase<Impl>::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker, | 2028 ParserBase<Impl>::ParseClassPropertyDefinition(ClassLiteralChecker* checker, |
2064 bool in_class, bool has_extends, | 2029 bool has_extends, |
2065 bool* is_computed_name, | 2030 bool* is_computed_name, |
2066 bool* has_seen_constructor, | 2031 bool* has_seen_constructor, |
2067 IdentifierT* name, bool* ok) { | 2032 IdentifierT* name, bool* ok) { |
2068 DCHECK(!in_class || has_seen_constructor != nullptr); | 2033 DCHECK(has_seen_constructor != nullptr); |
2069 bool is_get = false; | 2034 bool is_get = false; |
2070 bool is_set = false; | 2035 bool is_set = false; |
2071 bool is_generator = false; | 2036 bool is_generator = false; |
2072 bool is_async = false; | 2037 bool is_async = false; |
2073 bool is_static = false; | 2038 bool is_static = false; |
2074 PropertyKind kind = PropertyKind::kNotSet; | 2039 PropertyKind kind = PropertyKind::kNotSet; |
2075 | 2040 |
2076 Token::Value name_token = peek(); | 2041 Token::Value name_token = peek(); |
2042 | |
2043 ExpressionT name_expression; | |
2044 if (name_token == Token::STATIC) { | |
2045 Consume(Token::STATIC); | |
2046 kind = PropertyKind::kMethodProperty; | |
adamk
2016/09/01 21:18:23
If you move this into the LPAREN branch, then you
bakkot
2016/09/01 23:24:31
Done. This was historical, not really intentional.
| |
2047 if (peek() == Token::LPAREN) { | |
2048 *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static' | |
2049 name_expression = factory()->NewStringLiteral(*name, position()); | |
2050 } else { | |
2051 is_static = true; | |
2052 name_expression = ParsePropertyName( | |
2053 name, &kind, &is_generator, &is_get, &is_set, &is_async, | |
2054 is_computed_name, CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); | |
2055 } | |
2056 } else { | |
2057 name_expression = ParsePropertyName( | |
2058 name, &kind, &is_generator, &is_get, &is_set, &is_async, | |
2059 is_computed_name, CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); | |
2060 } | |
2061 | |
2062 switch (kind) { | |
2063 case PropertyKind::kShorthandProperty: | |
2064 case PropertyKind::kValueProperty: { | |
2065 Token::Value next = Next(); | |
adamk
2016/09/01 21:18:23
If you inline the Next() call into the call to Rep
bakkot
2016/09/01 23:24:31
Done.
| |
2066 ReportUnexpectedToken(next); | |
2067 *ok = false; | |
2068 return impl()->EmptyClassLiteralProperty(); | |
2069 } | |
2070 | |
2071 case PropertyKind::kMethodProperty: { | |
2072 DCHECK(!is_get && !is_set); | |
2073 | |
2074 MethodKind method_kind = MethodKind::kNormal; | |
2075 if (is_generator) { | |
2076 method_kind |= MethodKind::kGenerator; | |
adamk
2016/09/01 21:18:23
I'm not sure MethodKind is buying us a whole lot o
bakkot
2016/09/01 23:24:31
Done.
Yeah, that's much better. MethodKind requir
| |
2077 } | |
2078 if (is_async) { | |
2079 method_kind |= MethodKind::kAsync; | |
2080 } | |
2081 if (is_static) { | |
2082 method_kind |= MethodKind::kStatic; | |
2083 } | |
2084 | |
2085 // MethodDefinition | |
2086 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | |
2087 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | |
2088 | |
2089 if (!*is_computed_name) { | |
2090 checker->CheckClassMethodName( | |
2091 name_token, PropertyKind::kMethodProperty, method_kind, | |
2092 CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); | |
2093 } | |
2094 | |
2095 FunctionKind kind = is_generator | |
2096 ? FunctionKind::kConciseGeneratorMethod | |
2097 : is_async ? FunctionKind::kAsyncConciseMethod | |
2098 : FunctionKind::kConciseMethod; | |
2099 | |
2100 if (!is_static && impl()->IsConstructor(*name)) { | |
2101 *has_seen_constructor = true; | |
2102 kind = has_extends ? FunctionKind::kSubclassConstructor | |
2103 : FunctionKind::kBaseConstructor; | |
2104 } | |
2105 | |
2106 ExpressionT value = impl()->ParseFunctionLiteral( | |
2107 *name, scanner()->location(), kSkipFunctionNameCheck, kind, | |
2108 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, | |
2109 language_mode(), CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); | |
2110 | |
2111 return factory()->NewClassLiteralProperty(name_expression, value, | |
2112 ClassLiteralProperty::METHOD, | |
2113 is_static, *is_computed_name); | |
2114 } | |
2115 | |
2116 case PropertyKind::kAccessorProperty: { | |
2117 DCHECK((is_get || is_set) && !is_generator && !is_async); | |
2118 | |
2119 MethodKind method_kind = MethodKind::kNormal; | |
2120 if (is_static) { | |
2121 method_kind |= MethodKind::kStatic; | |
2122 } | |
2123 | |
2124 if (!*is_computed_name) { | |
2125 checker->CheckClassMethodName( | |
2126 name_token, PropertyKind::kAccessorProperty, method_kind, | |
2127 CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); | |
2128 // Make sure the name expression is a string since we need a Name for | |
2129 // Runtime_DefineAccessorPropertyUnchecked and since we can determine | |
2130 // this statically we can skip the extra runtime check. | |
2131 name_expression = | |
2132 factory()->NewStringLiteral(*name, name_expression->position()); | |
2133 } | |
2134 | |
2135 FunctionKind kind = is_get ? FunctionKind::kGetterFunction | |
2136 : FunctionKind::kSetterFunction; | |
2137 | |
2138 ExpressionT value = impl()->ParseFunctionLiteral( | |
2139 *name, scanner()->location(), kSkipFunctionNameCheck, kind, | |
2140 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, | |
2141 language_mode(), CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); | |
2142 | |
2143 return factory()->NewClassLiteralProperty( | |
2144 name_expression, value, | |
2145 is_get ? ClassLiteralProperty::GETTER : ClassLiteralProperty::SETTER, | |
2146 is_static, *is_computed_name); | |
2147 } | |
2148 | |
2149 case PropertyKind::kNotSet: { | |
2150 Token::Value next = Next(); | |
2151 ReportUnexpectedToken(next); | |
2152 *ok = false; | |
2153 return impl()->EmptyClassLiteralProperty(); | |
2154 } | |
2155 } | |
2156 UNREACHABLE(); | |
2157 return impl()->EmptyClassLiteralProperty(); | |
2158 } | |
2159 | |
2160 template <typename Impl> | |
2161 typename ParserBase<Impl>::ObjectLiteralPropertyT | |
2162 ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker, | |
2163 bool* is_computed_name, | |
2164 IdentifierT* name, bool* ok) { | |
2165 bool is_get = false; | |
2166 bool is_set = false; | |
2167 bool is_generator = false; | |
2168 bool is_async = false; | |
2169 PropertyKind kind = PropertyKind::kNotSet; | |
2170 | |
2171 Token::Value name_token = peek(); | |
2077 int next_beg_pos = scanner()->peek_location().beg_pos; | 2172 int next_beg_pos = scanner()->peek_location().beg_pos; |
2078 int next_end_pos = scanner()->peek_location().end_pos; | 2173 int next_end_pos = scanner()->peek_location().end_pos; |
2079 | 2174 |
2080 ExpressionT name_expression = | 2175 ExpressionT name_expression = ParsePropertyName( |
2081 ParsePropertyName(name, &kind, in_class, &is_generator, &is_get, &is_set, | 2176 name, &kind, &is_generator, &is_get, &is_set, &is_async, is_computed_name, |
2082 &is_async, &is_static, is_computed_name, | 2177 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2083 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2084 | 2178 |
2085 switch (kind) { | 2179 switch (kind) { |
2086 case PropertyKind::kValueProperty: { | 2180 case PropertyKind::kValueProperty: { |
2087 if (in_class) { | 2181 DCHECK(!is_get && !is_set && !is_generator && !is_async); |
2088 Token::Value next = Next(); | |
2089 ReportUnexpectedToken(next); | |
2090 *ok = false; | |
2091 return impl()->EmptyObjectLiteralProperty(); | |
2092 } | |
2093 | |
2094 DCHECK(!is_get && !is_set && !is_generator && !is_async && !is_static); | |
2095 | 2182 |
2096 if (!*is_computed_name) { | 2183 if (!*is_computed_name) { |
2097 checker->CheckProperty(name_token, PropertyKind::kValueProperty, | 2184 checker->CheckDuplicateProto(name_token); |
2098 MethodKind::kNormal, | |
2099 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2100 } | 2185 } |
2101 Consume(Token::COLON); | 2186 Consume(Token::COLON); |
2102 int beg_pos = peek_position(); | 2187 int beg_pos = peek_position(); |
2103 ExpressionT value = ParseAssignmentExpression( | 2188 ExpressionT value = ParseAssignmentExpression( |
2104 true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2189 true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2105 CheckDestructuringElement(value, beg_pos, scanner()->location().end_pos); | 2190 CheckDestructuringElement(value, beg_pos, scanner()->location().end_pos); |
2106 | 2191 |
2107 return factory()->NewObjectLiteralProperty(name_expression, value, | 2192 return factory()->NewObjectLiteralProperty(name_expression, value, |
2108 is_static, *is_computed_name); | 2193 *is_computed_name); |
2109 } | 2194 } |
2110 | 2195 |
2111 case PropertyKind::kShorthandProperty: { | 2196 case PropertyKind::kShorthandProperty: { |
2112 // PropertyDefinition | 2197 // PropertyDefinition |
2113 // IdentifierReference | 2198 // IdentifierReference |
2114 // CoverInitializedName | 2199 // CoverInitializedName |
2115 // | 2200 // |
2116 // CoverInitializedName | 2201 // CoverInitializedName |
2117 // IdentifierReference Initializer? | 2202 // IdentifierReference Initializer? |
2118 if (in_class) { | 2203 DCHECK(!is_get && !is_set && !is_generator && !is_async); |
2204 | |
2205 if (!Token::IsIdentifier(name_token, language_mode(), | |
2206 this->is_generator(), | |
2207 parsing_module_ || is_async_function())) { | |
2119 Token::Value next = Next(); | 2208 Token::Value next = Next(); |
2120 ReportUnexpectedToken(next); | 2209 ReportUnexpectedToken(next); |
2121 *ok = false; | 2210 *ok = false; |
2122 return impl()->EmptyObjectLiteralProperty(); | 2211 return impl()->EmptyObjectLiteralProperty(); |
2123 } | 2212 } |
2124 | 2213 |
2125 DCHECK(!is_get && !is_set && !is_generator && !is_async && !is_static && | 2214 DCHECK(!*is_computed_name); |
2126 !*is_computed_name); | |
2127 | 2215 |
2128 if (classifier()->duplicate_finder() != nullptr && | 2216 if (classifier()->duplicate_finder() != nullptr && |
2129 scanner()->FindSymbol(classifier()->duplicate_finder(), 1) != 0) { | 2217 scanner()->FindSymbol(classifier()->duplicate_finder(), 1) != 0) { |
2130 classifier()->RecordDuplicateFormalParameterError( | 2218 classifier()->RecordDuplicateFormalParameterError( |
2131 scanner()->location()); | 2219 scanner()->location()); |
2132 } | 2220 } |
2133 | 2221 |
2134 if (impl()->IsEvalOrArguments(*name) && is_strict(language_mode())) { | 2222 if (impl()->IsEvalOrArguments(*name) && is_strict(language_mode())) { |
2135 classifier()->RecordBindingPatternError( | 2223 classifier()->RecordBindingPatternError( |
2136 scanner()->location(), MessageTemplate::kStrictEvalArguments); | 2224 scanner()->location(), MessageTemplate::kStrictEvalArguments); |
(...skipping 26 matching lines...) Expand all Loading... | |
2163 classifier()->RecordExpressionError( | 2251 classifier()->RecordExpressionError( |
2164 Scanner::Location(next_beg_pos, scanner()->location().end_pos), | 2252 Scanner::Location(next_beg_pos, scanner()->location().end_pos), |
2165 MessageTemplate::kInvalidCoverInitializedName); | 2253 MessageTemplate::kInvalidCoverInitializedName); |
2166 | 2254 |
2167 impl()->SetFunctionNameFromIdentifierRef(rhs, lhs); | 2255 impl()->SetFunctionNameFromIdentifierRef(rhs, lhs); |
2168 } else { | 2256 } else { |
2169 value = lhs; | 2257 value = lhs; |
2170 } | 2258 } |
2171 | 2259 |
2172 return factory()->NewObjectLiteralProperty( | 2260 return factory()->NewObjectLiteralProperty( |
2173 name_expression, value, ObjectLiteralProperty::COMPUTED, is_static, | 2261 name_expression, value, ObjectLiteralProperty::COMPUTED, false); |
2174 false); | |
2175 } | 2262 } |
2176 | 2263 |
2177 case PropertyKind::kMethodProperty: { | 2264 case PropertyKind::kMethodProperty: { |
2178 DCHECK(!is_get && !is_set); | 2265 DCHECK(!is_get && !is_set); |
2179 | 2266 |
2180 MethodKind method_kind = MethodKind::kNormal; | |
2181 if (is_generator) { | |
2182 method_kind |= MethodKind::kGenerator; | |
2183 } | |
2184 if (is_async) { | |
2185 method_kind |= MethodKind::kAsync; | |
2186 } | |
2187 if (is_static) { | |
2188 method_kind |= MethodKind::kStatic; | |
2189 } | |
2190 | |
2191 // MethodDefinition | 2267 // MethodDefinition |
2192 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | 2268 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' |
2193 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | 2269 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' |
2194 | 2270 |
2195 classifier()->RecordPatternError( | 2271 classifier()->RecordPatternError( |
2196 Scanner::Location(next_beg_pos, scanner()->location().end_pos), | 2272 Scanner::Location(next_beg_pos, scanner()->location().end_pos), |
2197 MessageTemplate::kInvalidDestructuringTarget); | 2273 MessageTemplate::kInvalidDestructuringTarget); |
2198 | 2274 |
2199 if (!*is_computed_name) { | |
2200 checker->CheckProperty(name_token, PropertyKind::kMethodProperty, | |
2201 method_kind, | |
2202 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2203 } | |
2204 | |
2205 FunctionKind kind = is_generator | 2275 FunctionKind kind = is_generator |
2206 ? FunctionKind::kConciseGeneratorMethod | 2276 ? FunctionKind::kConciseGeneratorMethod |
2207 : is_async ? FunctionKind::kAsyncConciseMethod | 2277 : is_async ? FunctionKind::kAsyncConciseMethod |
2208 : FunctionKind::kConciseMethod; | 2278 : FunctionKind::kConciseMethod; |
2209 | 2279 |
2210 if (in_class && !is_static && impl()->IsConstructor(*name)) { | |
2211 *has_seen_constructor = true; | |
2212 kind = has_extends ? FunctionKind::kSubclassConstructor | |
2213 : FunctionKind::kBaseConstructor; | |
2214 } | |
2215 | |
2216 ExpressionT value = impl()->ParseFunctionLiteral( | 2280 ExpressionT value = impl()->ParseFunctionLiteral( |
2217 *name, scanner()->location(), kSkipFunctionNameCheck, kind, | 2281 *name, scanner()->location(), kSkipFunctionNameCheck, kind, |
2218 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, | 2282 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, |
2219 language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2283 language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
2220 | 2284 |
2221 return factory()->NewObjectLiteralProperty( | 2285 return factory()->NewObjectLiteralProperty( |
2222 name_expression, value, ObjectLiteralProperty::COMPUTED, is_static, | 2286 name_expression, value, ObjectLiteralProperty::COMPUTED, |
2223 *is_computed_name); | 2287 *is_computed_name); |
2224 } | 2288 } |
2225 | 2289 |
2226 case PropertyKind::kAccessorProperty: { | 2290 case PropertyKind::kAccessorProperty: { |
2227 DCHECK((is_get || is_set) && !is_generator && !is_async); | 2291 DCHECK((is_get || is_set) && !is_generator && !is_async); |
2228 | 2292 |
2229 MethodKind method_kind = MethodKind::kNormal; | |
2230 if (is_static) { | |
2231 DCHECK(in_class); | |
2232 method_kind |= MethodKind::kStatic; | |
2233 } | |
2234 | |
2235 classifier()->RecordPatternError( | 2293 classifier()->RecordPatternError( |
2236 Scanner::Location(next_beg_pos, scanner()->location().end_pos), | 2294 Scanner::Location(next_beg_pos, scanner()->location().end_pos), |
2237 MessageTemplate::kInvalidDestructuringTarget); | 2295 MessageTemplate::kInvalidDestructuringTarget); |
2296 | |
2238 if (!*is_computed_name) { | 2297 if (!*is_computed_name) { |
2239 checker->CheckProperty(name_token, PropertyKind::kAccessorProperty, | 2298 // Make sure the name expression is a string since we need a Name for |
2240 method_kind, | 2299 // Runtime_DefineAccessorPropertyUnchecked and since we can determine |
2241 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 2300 // this statically we can skip the extra runtime check. |
2242 } | |
2243 | |
2244 FunctionLiteralT value = impl()->ParseFunctionLiteral( | |
2245 *name, scanner()->location(), kSkipFunctionNameCheck, | |
2246 is_get ? FunctionKind::kGetterFunction | |
2247 : FunctionKind::kSetterFunction, | |
2248 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, | |
2249 language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2250 | |
2251 // Make sure the name expression is a string since we need a Name for | |
2252 // Runtime_DefineAccessorPropertyUnchecked and since we can determine this | |
2253 // statically we can skip the extra runtime check. | |
2254 if (!*is_computed_name) { | |
2255 name_expression = | 2301 name_expression = |
2256 factory()->NewStringLiteral(*name, name_expression->position()); | 2302 factory()->NewStringLiteral(*name, name_expression->position()); |
2257 } | 2303 } |
2258 | 2304 |
2305 FunctionKind kind = is_get ? FunctionKind::kGetterFunction | |
2306 : FunctionKind::kSetterFunction; | |
2307 | |
2308 ExpressionT value = impl()->ParseFunctionLiteral( | |
2309 *name, scanner()->location(), kSkipFunctionNameCheck, kind, | |
2310 kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, | |
2311 language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2312 | |
2259 return factory()->NewObjectLiteralProperty( | 2313 return factory()->NewObjectLiteralProperty( |
2260 name_expression, value, is_get ? ObjectLiteralProperty::GETTER | 2314 name_expression, value, is_get ? ObjectLiteralProperty::GETTER |
2261 : ObjectLiteralProperty::SETTER, | 2315 : ObjectLiteralProperty::SETTER, |
2262 is_static, *is_computed_name); | 2316 *is_computed_name); |
2263 } | 2317 } |
2264 | 2318 |
2265 case PropertyKind::kNotSet: | 2319 case PropertyKind::kNotSet: { |
adamk
2016/09/01 21:18:23
Can you explain why it's better to have duplicatio
bakkot
2016/09/01 23:24:31
Discussed offline. The real reason is that it make
| |
2266 UNREACHABLE(); | 2320 Token::Value next = Next(); |
2321 ReportUnexpectedToken(next); | |
2322 *ok = false; | |
2323 return impl()->EmptyObjectLiteralProperty(); | |
2324 } | |
2267 } | 2325 } |
2268 UNREACHABLE(); | 2326 UNREACHABLE(); |
2269 return impl()->EmptyObjectLiteralProperty(); | 2327 return impl()->EmptyObjectLiteralProperty(); |
2270 } | 2328 } |
2271 | 2329 |
2272 template <typename Impl> | 2330 template <typename Impl> |
2273 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral( | 2331 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral( |
2274 bool* ok) { | 2332 bool* ok) { |
2275 // ObjectLiteral :: | 2333 // ObjectLiteral :: |
2276 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' | 2334 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' |
2277 | 2335 |
2278 int pos = peek_position(); | 2336 int pos = peek_position(); |
2279 PropertyListT properties = impl()->NewPropertyList(4); | 2337 PropertyListT properties = impl()->NewPropertyList(4); |
2280 int number_of_boilerplate_properties = 0; | 2338 int number_of_boilerplate_properties = 0; |
2281 bool has_computed_names = false; | 2339 bool has_computed_names = false; |
2282 ObjectLiteralChecker checker(this); | 2340 ObjectLiteralChecker checker(this); |
2283 | 2341 |
2284 Expect(Token::LBRACE, CHECK_OK); | 2342 Expect(Token::LBRACE, CHECK_OK); |
2285 | 2343 |
2286 while (peek() != Token::RBRACE) { | 2344 while (peek() != Token::RBRACE) { |
2287 FuncNameInferrer::State fni_state(fni_); | 2345 FuncNameInferrer::State fni_state(fni_); |
2288 | 2346 |
2289 const bool in_class = false; | |
2290 const bool has_extends = false; | |
2291 bool is_computed_name = false; | 2347 bool is_computed_name = false; |
2292 IdentifierT name = impl()->EmptyIdentifier(); | 2348 IdentifierT name = impl()->EmptyIdentifier(); |
2293 ObjectLiteralPropertyT property = | 2349 ObjectLiteralPropertyT property = ParseObjectPropertyDefinition( |
2294 ParsePropertyDefinition(&checker, in_class, has_extends, | 2350 &checker, &is_computed_name, &name, CHECK_OK); |
2295 &is_computed_name, nullptr, &name, CHECK_OK); | |
2296 | 2351 |
2297 if (is_computed_name) { | 2352 if (is_computed_name) { |
2298 has_computed_names = true; | 2353 has_computed_names = true; |
2299 } | 2354 } |
2300 | 2355 |
2301 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | 2356 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
2302 if (!has_computed_names && impl()->IsBoilerplateProperty(property)) { | 2357 if (!has_computed_names && impl()->IsBoilerplateProperty(property)) { |
2303 number_of_boilerplate_properties++; | 2358 number_of_boilerplate_properties++; |
2304 } | 2359 } |
2305 properties->Add(property, zone()); | 2360 properties->Add(property, zone()); |
(...skipping 1604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3910 classifier()->RecordAssignmentPatternError( | 3965 classifier()->RecordAssignmentPatternError( |
3911 Scanner::Location(begin, end), | 3966 Scanner::Location(begin, end), |
3912 MessageTemplate::kInvalidDestructuringTarget); | 3967 MessageTemplate::kInvalidDestructuringTarget); |
3913 } | 3968 } |
3914 } | 3969 } |
3915 | 3970 |
3916 #undef CHECK_OK | 3971 #undef CHECK_OK |
3917 #undef CHECK_OK_CUSTOM | 3972 #undef CHECK_OK_CUSTOM |
3918 | 3973 |
3919 template <typename Impl> | 3974 template <typename Impl> |
3920 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty( | 3975 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( |
3921 Token::Value property, PropertyKind type, MethodKind method_type, | 3976 Token::Value property) { |
3922 bool* ok) { | |
3923 DCHECK(!IsStaticMethod(method_type)); | |
3924 DCHECK(!IsSpecialMethod(method_type) || | |
3925 type == PropertyKind::kMethodProperty); | |
3926 | |
3927 if (property == Token::SMI || property == Token::NUMBER) return; | 3977 if (property == Token::SMI || property == Token::NUMBER) return; |
3928 | 3978 |
3929 if (type == PropertyKind::kValueProperty && IsProto()) { | 3979 if (IsProto()) { |
3930 if (has_seen_proto_) { | 3980 if (has_seen_proto_) { |
3931 this->parser()->classifier()->RecordExpressionError( | 3981 this->parser()->classifier()->RecordExpressionError( |
3932 this->scanner()->location(), MessageTemplate::kDuplicateProto); | 3982 this->scanner()->location(), MessageTemplate::kDuplicateProto); |
3933 return; | 3983 return; |
3934 } | 3984 } |
3935 has_seen_proto_ = true; | 3985 has_seen_proto_ = true; |
3936 } | 3986 } |
3937 } | 3987 } |
3938 | 3988 |
3939 template <typename Impl> | 3989 template <typename Impl> |
3940 void ParserBase<Impl>::ClassLiteralChecker::CheckProperty( | 3990 void ParserBase<Impl>::ClassLiteralChecker::CheckClassMethodName( |
3941 Token::Value property, PropertyKind type, MethodKind method_type, | 3991 Token::Value property, PropertyKind type, MethodKind method_type, |
3942 bool* ok) { | 3992 bool* ok) { |
3943 DCHECK(type == PropertyKind::kMethodProperty || | 3993 DCHECK(type == PropertyKind::kMethodProperty || |
3944 type == PropertyKind::kAccessorProperty); | 3994 type == PropertyKind::kAccessorProperty); |
3945 | 3995 |
3946 if (property == Token::SMI || property == Token::NUMBER) return; | 3996 if (property == Token::SMI || property == Token::NUMBER) return; |
3947 | 3997 |
3948 if (IsStaticMethod(method_type)) { | 3998 if (IsStaticMethod(method_type)) { |
3949 if (IsPrototype()) { | 3999 if (IsPrototype()) { |
3950 this->parser()->ReportMessage(MessageTemplate::kStaticPrototype); | 4000 this->parser()->ReportMessage(MessageTemplate::kStaticPrototype); |
(...skipping 20 matching lines...) Expand all Loading... | |
3971 has_seen_constructor_ = true; | 4021 has_seen_constructor_ = true; |
3972 return; | 4022 return; |
3973 } | 4023 } |
3974 } | 4024 } |
3975 | 4025 |
3976 | 4026 |
3977 } // namespace internal | 4027 } // namespace internal |
3978 } // namespace v8 | 4028 } // namespace v8 |
3979 | 4029 |
3980 #endif // V8_PARSING_PARSER_BASE_H | 4030 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |