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

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

Issue 2302643002: Split the AST representation of class properties from object properties (Closed)
Patch Set: remove spurious classliteralproperty typedef 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
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 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
OLDNEW
« src/parsing/parser.cc ('K') | « src/parsing/parser.cc ('k') | src/parsing/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698