OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef V8_PREPARSER_H | |
6 #define V8_PREPARSER_H | |
7 | |
8 #include "src/bailout-reason.h" | |
9 #include "src/expression-classifier.h" | |
10 #include "src/func-name-inferrer.h" | |
11 #include "src/hashmap.h" | |
12 #include "src/messages.h" | |
13 #include "src/scanner.h" | |
14 #include "src/scopes.h" | |
15 #include "src/token.h" | |
16 | |
17 namespace v8 { | |
18 namespace internal { | |
19 | |
20 | |
21 enum FunctionNameValidity { | |
22 kFunctionNameIsStrictReserved, | |
23 kSkipFunctionNameCheck, | |
24 kFunctionNameValidityUnknown | |
25 }; | |
26 | |
27 | |
28 struct FormalParametersBase { | |
29 explicit FormalParametersBase(Scope* scope) : scope(scope) {} | |
30 Scope* scope; | |
31 bool has_rest = false; | |
32 bool is_simple = true; | |
33 int materialized_literals_count = 0; | |
34 mutable int rest_array_literal_index = -1; | |
35 }; | |
36 | |
37 | |
38 // Common base class shared between parser and pre-parser. Traits encapsulate | |
39 // the differences between Parser and PreParser: | |
40 | |
41 // - Return types: For example, Parser functions return Expression* and | |
42 // PreParser functions return PreParserExpression. | |
43 | |
44 // - Creating parse tree nodes: Parser generates an AST during the recursive | |
45 // descent. PreParser doesn't create a tree. Instead, it passes around minimal | |
46 // data objects (PreParserExpression, PreParserIdentifier etc.) which contain | |
47 // just enough data for the upper layer functions. PreParserFactory is | |
48 // responsible for creating these dummy objects. It provides a similar kind of | |
49 // interface as AstNodeFactory, so ParserBase doesn't need to care which one is | |
50 // used. | |
51 | |
52 // - Miscellaneous other tasks interleaved with the recursive descent. For | |
53 // example, Parser keeps track of which function literals should be marked as | |
54 // pretenured, and PreParser doesn't care. | |
55 | |
56 // The traits are expected to contain the following typedefs: | |
57 // struct Traits { | |
58 // // In particular... | |
59 // struct Type { | |
60 // // Used by FunctionState and BlockState. | |
61 // typedef Scope; | |
62 // typedef GeneratorVariable; | |
63 // // Return types for traversing functions. | |
64 // typedef Identifier; | |
65 // typedef Expression; | |
66 // typedef FunctionLiteral; | |
67 // typedef ClassLiteral; | |
68 // typedef ObjectLiteralProperty; | |
69 // typedef Literal; | |
70 // typedef ExpressionList; | |
71 // typedef PropertyList; | |
72 // typedef FormalParameter; | |
73 // typedef FormalParameters; | |
74 // // For constructing objects returned by the traversing functions. | |
75 // typedef Factory; | |
76 // }; | |
77 // // ... | |
78 // }; | |
79 | |
80 template <typename Traits> | |
81 class ParserBase : public Traits { | |
82 public: | |
83 // Shorten type names defined by Traits. | |
84 typedef typename Traits::Type::Expression ExpressionT; | |
85 typedef typename Traits::Type::Identifier IdentifierT; | |
86 typedef typename Traits::Type::FormalParameter FormalParameterT; | |
87 typedef typename Traits::Type::FormalParameters FormalParametersT; | |
88 typedef typename Traits::Type::FunctionLiteral FunctionLiteralT; | |
89 typedef typename Traits::Type::Literal LiteralT; | |
90 typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT; | |
91 typedef typename Traits::Type::StatementList StatementListT; | |
92 | |
93 ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit, | |
94 v8::Extension* extension, AstValueFactory* ast_value_factory, | |
95 ParserRecorder* log, typename Traits::Type::Parser this_object) | |
96 : Traits(this_object), | |
97 parenthesized_function_(false), | |
98 scope_(NULL), | |
99 function_state_(NULL), | |
100 extension_(extension), | |
101 fni_(NULL), | |
102 ast_value_factory_(ast_value_factory), | |
103 log_(log), | |
104 mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly. | |
105 stack_limit_(stack_limit), | |
106 zone_(zone), | |
107 scanner_(scanner), | |
108 stack_overflow_(false), | |
109 allow_lazy_(false), | |
110 allow_natives_(false), | |
111 allow_harmony_sloppy_(false), | |
112 allow_harmony_sloppy_function_(false), | |
113 allow_harmony_sloppy_let_(false), | |
114 allow_harmony_rest_parameters_(false), | |
115 allow_harmony_default_parameters_(false), | |
116 allow_harmony_destructuring_bind_(false), | |
117 allow_strong_mode_(false), | |
118 allow_legacy_const_(true), | |
119 allow_harmony_do_expressions_(false) {} | |
120 | |
121 #define ALLOW_ACCESSORS(name) \ | |
122 bool allow_##name() const { return allow_##name##_; } \ | |
123 void set_allow_##name(bool allow) { allow_##name##_ = allow; } | |
124 | |
125 ALLOW_ACCESSORS(lazy); | |
126 ALLOW_ACCESSORS(natives); | |
127 ALLOW_ACCESSORS(harmony_sloppy); | |
128 ALLOW_ACCESSORS(harmony_sloppy_function); | |
129 ALLOW_ACCESSORS(harmony_sloppy_let); | |
130 ALLOW_ACCESSORS(harmony_rest_parameters); | |
131 ALLOW_ACCESSORS(harmony_default_parameters); | |
132 ALLOW_ACCESSORS(harmony_destructuring_bind); | |
133 ALLOW_ACCESSORS(strong_mode); | |
134 ALLOW_ACCESSORS(legacy_const); | |
135 ALLOW_ACCESSORS(harmony_do_expressions); | |
136 #undef ALLOW_ACCESSORS | |
137 | |
138 uintptr_t stack_limit() const { return stack_limit_; } | |
139 | |
140 protected: | |
141 enum AllowRestrictedIdentifiers { | |
142 kAllowRestrictedIdentifiers, | |
143 kDontAllowRestrictedIdentifiers | |
144 }; | |
145 | |
146 enum Mode { | |
147 PARSE_LAZILY, | |
148 PARSE_EAGERLY | |
149 }; | |
150 | |
151 enum VariableDeclarationContext { | |
152 kStatementListItem, | |
153 kStatement, | |
154 kForStatement | |
155 }; | |
156 | |
157 class Checkpoint; | |
158 class ObjectLiteralCheckerBase; | |
159 | |
160 // --------------------------------------------------------------------------- | |
161 // FunctionState and BlockState together implement the parser's scope stack. | |
162 // The parser's current scope is in scope_. BlockState and FunctionState | |
163 // constructors push on the scope stack and the destructors pop. They are also | |
164 // used to hold the parser's per-function and per-block state. | |
165 class BlockState BASE_EMBEDDED { | |
166 public: | |
167 BlockState(Scope** scope_stack, Scope* scope) | |
168 : scope_stack_(scope_stack), outer_scope_(*scope_stack) { | |
169 *scope_stack_ = scope; | |
170 } | |
171 ~BlockState() { *scope_stack_ = outer_scope_; } | |
172 | |
173 private: | |
174 Scope** scope_stack_; | |
175 Scope* outer_scope_; | |
176 }; | |
177 | |
178 class FunctionState BASE_EMBEDDED { | |
179 public: | |
180 FunctionState(FunctionState** function_state_stack, Scope** scope_stack, | |
181 Scope* scope, FunctionKind kind, | |
182 typename Traits::Type::Factory* factory); | |
183 ~FunctionState(); | |
184 | |
185 int NextMaterializedLiteralIndex() { | |
186 return next_materialized_literal_index_++; | |
187 } | |
188 int materialized_literal_count() { | |
189 return next_materialized_literal_index_; | |
190 } | |
191 | |
192 void SkipMaterializedLiterals(int count) { | |
193 next_materialized_literal_index_ += count; | |
194 } | |
195 | |
196 void AddProperty() { expected_property_count_++; } | |
197 int expected_property_count() { return expected_property_count_; } | |
198 | |
199 Scanner::Location this_location() const { return this_location_; } | |
200 Scanner::Location super_location() const { return super_location_; } | |
201 Scanner::Location return_location() const { return return_location_; } | |
202 void set_this_location(Scanner::Location location) { | |
203 this_location_ = location; | |
204 } | |
205 void set_super_location(Scanner::Location location) { | |
206 super_location_ = location; | |
207 } | |
208 void set_return_location(Scanner::Location location) { | |
209 return_location_ = location; | |
210 } | |
211 | |
212 bool is_generator() const { return IsGeneratorFunction(kind_); } | |
213 | |
214 FunctionKind kind() const { return kind_; } | |
215 FunctionState* outer() const { return outer_function_state_; } | |
216 | |
217 void set_generator_object_variable( | |
218 typename Traits::Type::GeneratorVariable* variable) { | |
219 DCHECK(variable != NULL); | |
220 DCHECK(is_generator()); | |
221 generator_object_variable_ = variable; | |
222 } | |
223 typename Traits::Type::GeneratorVariable* generator_object_variable() | |
224 const { | |
225 return generator_object_variable_; | |
226 } | |
227 | |
228 typename Traits::Type::Factory* factory() { return factory_; } | |
229 | |
230 private: | |
231 // Used to assign an index to each literal that needs materialization in | |
232 // the function. Includes regexp literals, and boilerplate for object and | |
233 // array literals. | |
234 int next_materialized_literal_index_; | |
235 | |
236 // Properties count estimation. | |
237 int expected_property_count_; | |
238 | |
239 // Location of most recent use of 'this' (invalid if none). | |
240 Scanner::Location this_location_; | |
241 | |
242 // Location of most recent 'return' statement (invalid if none). | |
243 Scanner::Location return_location_; | |
244 | |
245 // Location of call to the "super" constructor (invalid if none). | |
246 Scanner::Location super_location_; | |
247 | |
248 FunctionKind kind_; | |
249 // For generators, this variable may hold the generator object. It variable | |
250 // is used by yield expressions and return statements. It is not necessary | |
251 // for generator functions to have this variable set. | |
252 Variable* generator_object_variable_; | |
253 | |
254 FunctionState** function_state_stack_; | |
255 FunctionState* outer_function_state_; | |
256 Scope** scope_stack_; | |
257 Scope* outer_scope_; | |
258 typename Traits::Type::Factory* factory_; | |
259 | |
260 friend class ParserTraits; | |
261 friend class Checkpoint; | |
262 }; | |
263 | |
264 // Annoyingly, arrow functions first parse as comma expressions, then when we | |
265 // see the => we have to go back and reinterpret the arguments as being formal | |
266 // parameters. To do so we need to reset some of the parser state back to | |
267 // what it was before the arguments were first seen. | |
268 class Checkpoint BASE_EMBEDDED { | |
269 public: | |
270 explicit Checkpoint(ParserBase* parser) { | |
271 function_state_ = parser->function_state_; | |
272 next_materialized_literal_index_ = | |
273 function_state_->next_materialized_literal_index_; | |
274 expected_property_count_ = function_state_->expected_property_count_; | |
275 } | |
276 | |
277 void Restore(int* materialized_literal_index_delta) { | |
278 *materialized_literal_index_delta = | |
279 function_state_->next_materialized_literal_index_ - | |
280 next_materialized_literal_index_; | |
281 function_state_->next_materialized_literal_index_ = | |
282 next_materialized_literal_index_; | |
283 function_state_->expected_property_count_ = expected_property_count_; | |
284 } | |
285 | |
286 private: | |
287 FunctionState* function_state_; | |
288 int next_materialized_literal_index_; | |
289 int expected_property_count_; | |
290 }; | |
291 | |
292 class ParsingModeScope BASE_EMBEDDED { | |
293 public: | |
294 ParsingModeScope(ParserBase* parser, Mode mode) | |
295 : parser_(parser), | |
296 old_mode_(parser->mode()) { | |
297 parser_->mode_ = mode; | |
298 } | |
299 ~ParsingModeScope() { | |
300 parser_->mode_ = old_mode_; | |
301 } | |
302 | |
303 private: | |
304 ParserBase* parser_; | |
305 Mode old_mode_; | |
306 }; | |
307 | |
308 Scope* NewScope(Scope* parent, ScopeType scope_type) { | |
309 // Must always pass the function kind for FUNCTION_SCOPE. | |
310 DCHECK(scope_type != FUNCTION_SCOPE); | |
311 return NewScope(parent, scope_type, kNormalFunction); | |
312 } | |
313 | |
314 Scope* NewScope(Scope* parent, ScopeType scope_type, FunctionKind kind) { | |
315 DCHECK(ast_value_factory()); | |
316 DCHECK(scope_type != MODULE_SCOPE || FLAG_harmony_modules); | |
317 Scope* result = new (zone()) | |
318 Scope(zone(), parent, scope_type, ast_value_factory(), kind); | |
319 result->Initialize(); | |
320 return result; | |
321 } | |
322 | |
323 Scanner* scanner() const { return scanner_; } | |
324 AstValueFactory* ast_value_factory() const { return ast_value_factory_; } | |
325 int position() { return scanner_->location().beg_pos; } | |
326 int peek_position() { return scanner_->peek_location().beg_pos; } | |
327 bool stack_overflow() const { return stack_overflow_; } | |
328 void set_stack_overflow() { stack_overflow_ = true; } | |
329 Mode mode() const { return mode_; } | |
330 Zone* zone() const { return zone_; } | |
331 | |
332 INLINE(Token::Value peek()) { | |
333 if (stack_overflow_) return Token::ILLEGAL; | |
334 return scanner()->peek(); | |
335 } | |
336 | |
337 INLINE(Token::Value PeekAhead()) { | |
338 if (stack_overflow_) return Token::ILLEGAL; | |
339 return scanner()->PeekAhead(); | |
340 } | |
341 | |
342 INLINE(Token::Value Next()) { | |
343 if (stack_overflow_) return Token::ILLEGAL; | |
344 { | |
345 if (GetCurrentStackPosition() < stack_limit_) { | |
346 // Any further calls to Next or peek will return the illegal token. | |
347 // The current call must return the next token, which might already | |
348 // have been peek'ed. | |
349 stack_overflow_ = true; | |
350 } | |
351 } | |
352 return scanner()->Next(); | |
353 } | |
354 | |
355 void Consume(Token::Value token) { | |
356 Token::Value next = Next(); | |
357 USE(next); | |
358 USE(token); | |
359 DCHECK(next == token); | |
360 } | |
361 | |
362 bool Check(Token::Value token) { | |
363 Token::Value next = peek(); | |
364 if (next == token) { | |
365 Consume(next); | |
366 return true; | |
367 } | |
368 return false; | |
369 } | |
370 | |
371 void Expect(Token::Value token, bool* ok) { | |
372 Token::Value next = Next(); | |
373 if (next != token) { | |
374 ReportUnexpectedToken(next); | |
375 *ok = false; | |
376 } | |
377 } | |
378 | |
379 void ExpectSemicolon(bool* ok) { | |
380 // Check for automatic semicolon insertion according to | |
381 // the rules given in ECMA-262, section 7.9, page 21. | |
382 Token::Value tok = peek(); | |
383 if (tok == Token::SEMICOLON) { | |
384 Next(); | |
385 return; | |
386 } | |
387 if (scanner()->HasAnyLineTerminatorBeforeNext() || | |
388 tok == Token::RBRACE || | |
389 tok == Token::EOS) { | |
390 return; | |
391 } | |
392 Expect(Token::SEMICOLON, ok); | |
393 } | |
394 | |
395 bool peek_any_identifier() { | |
396 Token::Value next = peek(); | |
397 return next == Token::IDENTIFIER || next == Token::FUTURE_RESERVED_WORD || | |
398 next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET || | |
399 next == Token::STATIC || next == Token::YIELD; | |
400 } | |
401 | |
402 bool CheckContextualKeyword(Vector<const char> keyword) { | |
403 if (PeekContextualKeyword(keyword)) { | |
404 Consume(Token::IDENTIFIER); | |
405 return true; | |
406 } | |
407 return false; | |
408 } | |
409 | |
410 bool PeekContextualKeyword(Vector<const char> keyword) { | |
411 return peek() == Token::IDENTIFIER && | |
412 scanner()->is_next_contextual_keyword(keyword); | |
413 } | |
414 | |
415 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) { | |
416 Expect(Token::IDENTIFIER, ok); | |
417 if (!*ok) return; | |
418 if (!scanner()->is_literal_contextual_keyword(keyword)) { | |
419 ReportUnexpectedToken(scanner()->current_token()); | |
420 *ok = false; | |
421 } | |
422 } | |
423 | |
424 bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode, bool* ok) { | |
425 if (Check(Token::IN)) { | |
426 if (is_strong(language_mode())) { | |
427 ReportMessageAt(scanner()->location(), MessageTemplate::kStrongForIn); | |
428 *ok = false; | |
429 } else { | |
430 *visit_mode = ForEachStatement::ENUMERATE; | |
431 } | |
432 return true; | |
433 } else if (CheckContextualKeyword(CStrVector("of"))) { | |
434 *visit_mode = ForEachStatement::ITERATE; | |
435 return true; | |
436 } | |
437 return false; | |
438 } | |
439 | |
440 // Checks whether an octal literal was last seen between beg_pos and end_pos. | |
441 // If so, reports an error. Only called for strict mode and template strings. | |
442 void CheckOctalLiteral(int beg_pos, int end_pos, | |
443 MessageTemplate::Template message, bool* ok) { | |
444 Scanner::Location octal = scanner()->octal_position(); | |
445 if (octal.IsValid() && beg_pos <= octal.beg_pos && | |
446 octal.end_pos <= end_pos) { | |
447 ReportMessageAt(octal, message); | |
448 scanner()->clear_octal_position(); | |
449 *ok = false; | |
450 } | |
451 } | |
452 | |
453 inline void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) { | |
454 CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kStrictOctalLiteral, | |
455 ok); | |
456 } | |
457 | |
458 inline void CheckTemplateOctalLiteral(int beg_pos, int end_pos, bool* ok) { | |
459 CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kTemplateOctalLiteral, | |
460 ok); | |
461 } | |
462 | |
463 // Checking the name of a function literal. This has to be done after parsing | |
464 // the function, since the function can declare itself strict. | |
465 void CheckFunctionName(LanguageMode language_mode, IdentifierT function_name, | |
466 FunctionNameValidity function_name_validity, | |
467 const Scanner::Location& function_name_loc, bool* ok) { | |
468 if (function_name_validity == kSkipFunctionNameCheck) return; | |
469 // The function name needs to be checked in strict mode. | |
470 if (is_sloppy(language_mode)) return; | |
471 | |
472 if (this->IsEvalOrArguments(function_name)) { | |
473 Traits::ReportMessageAt(function_name_loc, | |
474 MessageTemplate::kStrictEvalArguments); | |
475 *ok = false; | |
476 return; | |
477 } | |
478 if (function_name_validity == kFunctionNameIsStrictReserved) { | |
479 Traits::ReportMessageAt(function_name_loc, | |
480 MessageTemplate::kUnexpectedStrictReserved); | |
481 *ok = false; | |
482 return; | |
483 } | |
484 if (is_strong(language_mode) && this->IsUndefined(function_name)) { | |
485 Traits::ReportMessageAt(function_name_loc, | |
486 MessageTemplate::kStrongUndefined); | |
487 *ok = false; | |
488 return; | |
489 } | |
490 } | |
491 | |
492 // Determine precedence of given token. | |
493 static int Precedence(Token::Value token, bool accept_IN) { | |
494 if (token == Token::IN && !accept_IN) | |
495 return 0; // 0 precedence will terminate binary expression parsing | |
496 return Token::Precedence(token); | |
497 } | |
498 | |
499 typename Traits::Type::Factory* factory() { | |
500 return function_state_->factory(); | |
501 } | |
502 | |
503 LanguageMode language_mode() { return scope_->language_mode(); } | |
504 bool is_generator() const { return function_state_->is_generator(); } | |
505 | |
506 bool allow_const() { | |
507 return is_strict(language_mode()) || allow_harmony_sloppy() || | |
508 allow_legacy_const(); | |
509 } | |
510 | |
511 bool allow_let() { | |
512 return is_strict(language_mode()) || allow_harmony_sloppy_let(); | |
513 } | |
514 | |
515 // Report syntax errors. | |
516 void ReportMessage(MessageTemplate::Template message, const char* arg = NULL, | |
517 ParseErrorType error_type = kSyntaxError) { | |
518 Scanner::Location source_location = scanner()->location(); | |
519 Traits::ReportMessageAt(source_location, message, arg, error_type); | |
520 } | |
521 | |
522 void ReportMessageAt(Scanner::Location location, | |
523 MessageTemplate::Template message, | |
524 ParseErrorType error_type = kSyntaxError) { | |
525 Traits::ReportMessageAt(location, message, reinterpret_cast<const char*>(0), | |
526 error_type); | |
527 } | |
528 | |
529 void GetUnexpectedTokenMessage( | |
530 Token::Value token, MessageTemplate::Template* message, const char** arg, | |
531 MessageTemplate::Template default_ = MessageTemplate::kUnexpectedToken); | |
532 | |
533 void ReportUnexpectedToken(Token::Value token); | |
534 void ReportUnexpectedTokenAt( | |
535 Scanner::Location location, Token::Value token, | |
536 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken); | |
537 | |
538 | |
539 void ReportClassifierError(const ExpressionClassifier::Error& error) { | |
540 Traits::ReportMessageAt(error.location, error.message, error.arg, | |
541 kSyntaxError); | |
542 } | |
543 | |
544 void ValidateExpression(const ExpressionClassifier* classifier, bool* ok) { | |
545 if (!classifier->is_valid_expression()) { | |
546 ReportClassifierError(classifier->expression_error()); | |
547 *ok = false; | |
548 } | |
549 } | |
550 | |
551 void ValidateFormalParameterInitializer( | |
552 const ExpressionClassifier* classifier, bool* ok) { | |
553 if (!classifier->is_valid_formal_parameter_initializer()) { | |
554 ReportClassifierError(classifier->formal_parameter_initializer_error()); | |
555 *ok = false; | |
556 } | |
557 } | |
558 | |
559 void ValidateBindingPattern(const ExpressionClassifier* classifier, | |
560 bool* ok) { | |
561 if (!classifier->is_valid_binding_pattern()) { | |
562 ReportClassifierError(classifier->binding_pattern_error()); | |
563 *ok = false; | |
564 } | |
565 } | |
566 | |
567 void ValidateAssignmentPattern(const ExpressionClassifier* classifier, | |
568 bool* ok) { | |
569 if (!classifier->is_valid_assignment_pattern()) { | |
570 ReportClassifierError(classifier->assignment_pattern_error()); | |
571 *ok = false; | |
572 } | |
573 } | |
574 | |
575 void ValidateFormalParameters(const ExpressionClassifier* classifier, | |
576 LanguageMode language_mode, | |
577 bool allow_duplicates, bool* ok) { | |
578 if (!allow_duplicates && | |
579 !classifier->is_valid_formal_parameter_list_without_duplicates()) { | |
580 ReportClassifierError(classifier->duplicate_formal_parameter_error()); | |
581 *ok = false; | |
582 } else if (is_strict(language_mode) && | |
583 !classifier->is_valid_strict_mode_formal_parameters()) { | |
584 ReportClassifierError(classifier->strict_mode_formal_parameter_error()); | |
585 *ok = false; | |
586 } else if (is_strong(language_mode) && | |
587 !classifier->is_valid_strong_mode_formal_parameters()) { | |
588 ReportClassifierError(classifier->strong_mode_formal_parameter_error()); | |
589 *ok = false; | |
590 } | |
591 } | |
592 | |
593 void ValidateArrowFormalParameters(const ExpressionClassifier* classifier, | |
594 ExpressionT expr, | |
595 bool parenthesized_formals, bool* ok) { | |
596 if (classifier->is_valid_binding_pattern()) { | |
597 // A simple arrow formal parameter: IDENTIFIER => BODY. | |
598 if (!this->IsIdentifier(expr)) { | |
599 Traits::ReportMessageAt(scanner()->location(), | |
600 MessageTemplate::kUnexpectedToken, | |
601 Token::String(scanner()->current_token())); | |
602 *ok = false; | |
603 } | |
604 } else if (!classifier->is_valid_arrow_formal_parameters()) { | |
605 // If after parsing the expr, we see an error but the expression is | |
606 // neither a valid binding pattern nor a valid parenthesized formal | |
607 // parameter list, show the "arrow formal parameters" error if the formals | |
608 // started with a parenthesis, and the binding pattern error otherwise. | |
609 const ExpressionClassifier::Error& error = | |
610 parenthesized_formals ? classifier->arrow_formal_parameters_error() | |
611 : classifier->binding_pattern_error(); | |
612 ReportClassifierError(error); | |
613 *ok = false; | |
614 } | |
615 } | |
616 | |
617 void ValidateLetPattern(const ExpressionClassifier* classifier, bool* ok) { | |
618 if (!classifier->is_valid_let_pattern()) { | |
619 ReportClassifierError(classifier->let_pattern_error()); | |
620 *ok = false; | |
621 } | |
622 } | |
623 | |
624 void ExpressionUnexpectedToken(ExpressionClassifier* classifier) { | |
625 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken; | |
626 const char* arg; | |
627 GetUnexpectedTokenMessage(peek(), &message, &arg); | |
628 classifier->RecordExpressionError(scanner()->peek_location(), message, arg); | |
629 } | |
630 | |
631 void BindingPatternUnexpectedToken(ExpressionClassifier* classifier) { | |
632 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken; | |
633 const char* arg; | |
634 GetUnexpectedTokenMessage(peek(), &message, &arg); | |
635 classifier->RecordBindingPatternError(scanner()->peek_location(), message, | |
636 arg); | |
637 } | |
638 | |
639 void ArrowFormalParametersUnexpectedToken(ExpressionClassifier* classifier) { | |
640 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken; | |
641 const char* arg; | |
642 GetUnexpectedTokenMessage(peek(), &message, &arg); | |
643 classifier->RecordArrowFormalParametersError(scanner()->peek_location(), | |
644 message, arg); | |
645 } | |
646 | |
647 void FormalParameterInitializerUnexpectedToken( | |
648 ExpressionClassifier* classifier) { | |
649 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken; | |
650 const char* arg; | |
651 GetUnexpectedTokenMessage(peek(), &message, &arg); | |
652 classifier->RecordFormalParameterInitializerError( | |
653 scanner()->peek_location(), message, arg); | |
654 } | |
655 | |
656 // Recursive descent functions: | |
657 | |
658 // Parses an identifier that is valid for the current scope, in particular it | |
659 // fails on strict mode future reserved keywords in a strict scope. If | |
660 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or | |
661 // "arguments" as identifier even in strict mode (this is needed in cases like | |
662 // "var foo = eval;"). | |
663 IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok); | |
664 IdentifierT ParseAndClassifyIdentifier(ExpressionClassifier* classifier, | |
665 bool* ok); | |
666 // Parses an identifier or a strict mode future reserved word, and indicate | |
667 // whether it is strict mode future reserved. Allows passing in is_generator | |
668 // for the case of parsing the identifier in a function expression, where the | |
669 // relevant "is_generator" bit is of the function being parsed, not the | |
670 // containing | |
671 // function. | |
672 IdentifierT ParseIdentifierOrStrictReservedWord(bool is_generator, | |
673 bool* is_strict_reserved, | |
674 bool* ok); | |
675 IdentifierT ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, | |
676 bool* ok) { | |
677 return ParseIdentifierOrStrictReservedWord(this->is_generator(), | |
678 is_strict_reserved, ok); | |
679 } | |
680 | |
681 IdentifierT ParseIdentifierName(bool* ok); | |
682 // Parses an identifier and determines whether or not it is 'get' or 'set'. | |
683 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, bool* is_set, | |
684 bool* ok); | |
685 | |
686 | |
687 ExpressionT ParseRegExpLiteral(bool seen_equal, | |
688 ExpressionClassifier* classifier, bool* ok); | |
689 | |
690 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, | |
691 bool* ok); | |
692 ExpressionT ParseExpression(bool accept_IN, bool* ok); | |
693 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, | |
694 bool* ok); | |
695 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); | |
696 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, | |
697 bool* is_static, bool* is_computed_name, | |
698 bool* is_identifier, bool* is_escaped_keyword, | |
699 ExpressionClassifier* classifier, bool* ok); | |
700 ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok); | |
701 ObjectLiteralPropertyT ParsePropertyDefinition( | |
702 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, | |
703 bool is_static, bool* is_computed_name, bool* has_seen_constructor, | |
704 ExpressionClassifier* classifier, bool* ok); | |
705 typename Traits::Type::ExpressionList ParseArguments( | |
706 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, | |
707 bool* ok); | |
708 ExpressionT ParseAssignmentExpression(bool accept_IN, | |
709 ExpressionClassifier* classifier, | |
710 bool* ok); | |
711 ExpressionT ParseYieldExpression(ExpressionClassifier* classifier, bool* ok); | |
712 ExpressionT ParseConditionalExpression(bool accept_IN, | |
713 ExpressionClassifier* classifier, | |
714 bool* ok); | |
715 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, | |
716 ExpressionClassifier* classifier, bool* ok); | |
717 ExpressionT ParseUnaryExpression(ExpressionClassifier* classifier, bool* ok); | |
718 ExpressionT ParsePostfixExpression(ExpressionClassifier* classifier, | |
719 bool* ok); | |
720 ExpressionT ParseLeftHandSideExpression(ExpressionClassifier* classifier, | |
721 bool* ok); | |
722 ExpressionT ParseMemberWithNewPrefixesExpression( | |
723 ExpressionClassifier* classifier, bool* ok); | |
724 ExpressionT ParseMemberExpression(ExpressionClassifier* classifier, bool* ok); | |
725 ExpressionT ParseMemberExpressionContinuation( | |
726 ExpressionT expression, ExpressionClassifier* classifier, bool* ok); | |
727 ExpressionT ParseArrowFunctionLiteral(bool accept_IN, | |
728 const FormalParametersT& parameters, | |
729 const ExpressionClassifier& classifier, | |
730 bool* ok); | |
731 ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, | |
732 ExpressionClassifier* classifier, bool* ok); | |
733 void AddTemplateExpression(ExpressionT); | |
734 ExpressionT ParseSuperExpression(bool is_new, | |
735 ExpressionClassifier* classifier, bool* ok); | |
736 ExpressionT ParseNewTargetExpression(bool* ok); | |
737 ExpressionT ParseStrongInitializationExpression( | |
738 ExpressionClassifier* classifier, bool* ok); | |
739 ExpressionT ParseStrongSuperCallExpression(ExpressionClassifier* classifier, | |
740 bool* ok); | |
741 | |
742 void ParseFormalParameter(FormalParametersT* parameters, | |
743 ExpressionClassifier* classifier, bool* ok); | |
744 void ParseFormalParameterList(FormalParametersT* parameters, | |
745 ExpressionClassifier* classifier, bool* ok); | |
746 void CheckArityRestrictions( | |
747 int param_count, FunctionLiteral::ArityRestriction arity_restriction, | |
748 bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok); | |
749 | |
750 bool IsNextLetKeyword(); | |
751 | |
752 // Checks if the expression is a valid reference expression (e.g., on the | |
753 // left-hand side of assignments). Although ruled out by ECMA as early errors, | |
754 // we allow calls for web compatibility and rewrite them to a runtime throw. | |
755 ExpressionT CheckAndRewriteReferenceExpression( | |
756 ExpressionT expression, int beg_pos, int end_pos, | |
757 MessageTemplate::Template message, bool* ok); | |
758 ExpressionT CheckAndRewriteReferenceExpression( | |
759 ExpressionT expression, int beg_pos, int end_pos, | |
760 MessageTemplate::Template message, ParseErrorType type, bool* ok); | |
761 | |
762 // Used to validate property names in object literals and class literals | |
763 enum PropertyKind { | |
764 kAccessorProperty, | |
765 kValueProperty, | |
766 kMethodProperty | |
767 }; | |
768 | |
769 class ObjectLiteralCheckerBase { | |
770 public: | |
771 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {} | |
772 | |
773 virtual void CheckProperty(Token::Value property, PropertyKind type, | |
774 bool is_static, bool is_generator, bool* ok) = 0; | |
775 | |
776 virtual ~ObjectLiteralCheckerBase() {} | |
777 | |
778 protected: | |
779 ParserBase* parser() const { return parser_; } | |
780 Scanner* scanner() const { return parser_->scanner(); } | |
781 | |
782 private: | |
783 ParserBase* parser_; | |
784 }; | |
785 | |
786 // Validation per ES6 object literals. | |
787 class ObjectLiteralChecker : public ObjectLiteralCheckerBase { | |
788 public: | |
789 explicit ObjectLiteralChecker(ParserBase* parser) | |
790 : ObjectLiteralCheckerBase(parser), has_seen_proto_(false) {} | |
791 | |
792 void CheckProperty(Token::Value property, PropertyKind type, bool is_static, | |
793 bool is_generator, bool* ok) override; | |
794 | |
795 private: | |
796 bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); } | |
797 | |
798 bool has_seen_proto_; | |
799 }; | |
800 | |
801 // Validation per ES6 class literals. | |
802 class ClassLiteralChecker : public ObjectLiteralCheckerBase { | |
803 public: | |
804 explicit ClassLiteralChecker(ParserBase* parser) | |
805 : ObjectLiteralCheckerBase(parser), has_seen_constructor_(false) {} | |
806 | |
807 void CheckProperty(Token::Value property, PropertyKind type, bool is_static, | |
808 bool is_generator, bool* ok) override; | |
809 | |
810 private: | |
811 bool IsConstructor() { | |
812 return this->scanner()->LiteralMatches("constructor", 11); | |
813 } | |
814 bool IsPrototype() { | |
815 return this->scanner()->LiteralMatches("prototype", 9); | |
816 } | |
817 | |
818 bool has_seen_constructor_; | |
819 }; | |
820 | |
821 // If true, the next (and immediately following) function literal is | |
822 // preceded by a parenthesis. | |
823 // Heuristically that means that the function will be called immediately, | |
824 // so never lazily compile it. | |
825 bool parenthesized_function_; | |
826 | |
827 Scope* scope_; // Scope stack. | |
828 FunctionState* function_state_; // Function state stack. | |
829 v8::Extension* extension_; | |
830 FuncNameInferrer* fni_; | |
831 AstValueFactory* ast_value_factory_; // Not owned. | |
832 ParserRecorder* log_; | |
833 Mode mode_; | |
834 uintptr_t stack_limit_; | |
835 | |
836 private: | |
837 Zone* zone_; | |
838 | |
839 Scanner* scanner_; | |
840 bool stack_overflow_; | |
841 | |
842 bool allow_lazy_; | |
843 bool allow_natives_; | |
844 bool allow_harmony_sloppy_; | |
845 bool allow_harmony_sloppy_function_; | |
846 bool allow_harmony_sloppy_let_; | |
847 bool allow_harmony_rest_parameters_; | |
848 bool allow_harmony_default_parameters_; | |
849 bool allow_harmony_destructuring_bind_; | |
850 bool allow_strong_mode_; | |
851 bool allow_legacy_const_; | |
852 bool allow_harmony_do_expressions_; | |
853 }; | |
854 | |
855 | |
856 class PreParserIdentifier { | |
857 public: | |
858 PreParserIdentifier() : type_(kUnknownIdentifier) {} | |
859 static PreParserIdentifier Default() { | |
860 return PreParserIdentifier(kUnknownIdentifier); | |
861 } | |
862 static PreParserIdentifier Eval() { | |
863 return PreParserIdentifier(kEvalIdentifier); | |
864 } | |
865 static PreParserIdentifier Arguments() { | |
866 return PreParserIdentifier(kArgumentsIdentifier); | |
867 } | |
868 static PreParserIdentifier Undefined() { | |
869 return PreParserIdentifier(kUndefinedIdentifier); | |
870 } | |
871 static PreParserIdentifier FutureReserved() { | |
872 return PreParserIdentifier(kFutureReservedIdentifier); | |
873 } | |
874 static PreParserIdentifier FutureStrictReserved() { | |
875 return PreParserIdentifier(kFutureStrictReservedIdentifier); | |
876 } | |
877 static PreParserIdentifier Let() { | |
878 return PreParserIdentifier(kLetIdentifier); | |
879 } | |
880 static PreParserIdentifier Static() { | |
881 return PreParserIdentifier(kStaticIdentifier); | |
882 } | |
883 static PreParserIdentifier Yield() { | |
884 return PreParserIdentifier(kYieldIdentifier); | |
885 } | |
886 static PreParserIdentifier Prototype() { | |
887 return PreParserIdentifier(kPrototypeIdentifier); | |
888 } | |
889 static PreParserIdentifier Constructor() { | |
890 return PreParserIdentifier(kConstructorIdentifier); | |
891 } | |
892 bool IsEval() const { return type_ == kEvalIdentifier; } | |
893 bool IsArguments() const { return type_ == kArgumentsIdentifier; } | |
894 bool IsEvalOrArguments() const { return IsEval() || IsArguments(); } | |
895 bool IsUndefined() const { return type_ == kUndefinedIdentifier; } | |
896 bool IsLet() const { return type_ == kLetIdentifier; } | |
897 bool IsStatic() const { return type_ == kStaticIdentifier; } | |
898 bool IsYield() const { return type_ == kYieldIdentifier; } | |
899 bool IsPrototype() const { return type_ == kPrototypeIdentifier; } | |
900 bool IsConstructor() const { return type_ == kConstructorIdentifier; } | |
901 bool IsFutureReserved() const { return type_ == kFutureReservedIdentifier; } | |
902 bool IsFutureStrictReserved() const { | |
903 return type_ == kFutureStrictReservedIdentifier || | |
904 type_ == kLetIdentifier || type_ == kStaticIdentifier || | |
905 type_ == kYieldIdentifier; | |
906 } | |
907 | |
908 // Allow identifier->name()[->length()] to work. The preparser | |
909 // does not need the actual positions/lengths of the identifiers. | |
910 const PreParserIdentifier* operator->() const { return this; } | |
911 const PreParserIdentifier raw_name() const { return *this; } | |
912 | |
913 int position() const { return 0; } | |
914 int length() const { return 0; } | |
915 | |
916 private: | |
917 enum Type { | |
918 kUnknownIdentifier, | |
919 kFutureReservedIdentifier, | |
920 kFutureStrictReservedIdentifier, | |
921 kLetIdentifier, | |
922 kStaticIdentifier, | |
923 kYieldIdentifier, | |
924 kEvalIdentifier, | |
925 kArgumentsIdentifier, | |
926 kUndefinedIdentifier, | |
927 kPrototypeIdentifier, | |
928 kConstructorIdentifier | |
929 }; | |
930 | |
931 explicit PreParserIdentifier(Type type) : type_(type) {} | |
932 Type type_; | |
933 | |
934 friend class PreParserExpression; | |
935 }; | |
936 | |
937 | |
938 class PreParserExpression { | |
939 public: | |
940 static PreParserExpression Default() { | |
941 return PreParserExpression(TypeField::encode(kExpression)); | |
942 } | |
943 | |
944 static PreParserExpression Spread(PreParserExpression expression) { | |
945 return PreParserExpression(TypeField::encode(kSpreadExpression)); | |
946 } | |
947 | |
948 static PreParserExpression FromIdentifier(PreParserIdentifier id) { | |
949 return PreParserExpression(TypeField::encode(kIdentifierExpression) | | |
950 IdentifierTypeField::encode(id.type_)); | |
951 } | |
952 | |
953 static PreParserExpression BinaryOperation(PreParserExpression left, | |
954 Token::Value op, | |
955 PreParserExpression right) { | |
956 return PreParserExpression( | |
957 TypeField::encode(kBinaryOperationExpression) | | |
958 HasRestField::encode(op == Token::COMMA && | |
959 right->IsSpreadExpression())); | |
960 } | |
961 | |
962 static PreParserExpression ObjectLiteral() { | |
963 return PreParserExpression(TypeField::encode(kObjectLiteralExpression)); | |
964 } | |
965 | |
966 static PreParserExpression ArrayLiteral() { | |
967 return PreParserExpression(TypeField::encode(kArrayLiteralExpression)); | |
968 } | |
969 | |
970 static PreParserExpression StringLiteral() { | |
971 return PreParserExpression(TypeField::encode(kStringLiteralExpression)); | |
972 } | |
973 | |
974 static PreParserExpression UseStrictStringLiteral() { | |
975 return PreParserExpression(TypeField::encode(kStringLiteralExpression) | | |
976 IsUseStrictField::encode(true)); | |
977 } | |
978 | |
979 static PreParserExpression UseStrongStringLiteral() { | |
980 return PreParserExpression(TypeField::encode(kStringLiteralExpression) | | |
981 IsUseStrongField::encode(true)); | |
982 } | |
983 | |
984 static PreParserExpression This() { | |
985 return PreParserExpression(TypeField::encode(kExpression) | | |
986 ExpressionTypeField::encode(kThisExpression)); | |
987 } | |
988 | |
989 static PreParserExpression ThisProperty() { | |
990 return PreParserExpression( | |
991 TypeField::encode(kExpression) | | |
992 ExpressionTypeField::encode(kThisPropertyExpression)); | |
993 } | |
994 | |
995 static PreParserExpression Property() { | |
996 return PreParserExpression( | |
997 TypeField::encode(kExpression) | | |
998 ExpressionTypeField::encode(kPropertyExpression)); | |
999 } | |
1000 | |
1001 static PreParserExpression Call() { | |
1002 return PreParserExpression(TypeField::encode(kExpression) | | |
1003 ExpressionTypeField::encode(kCallExpression)); | |
1004 } | |
1005 | |
1006 static PreParserExpression SuperCallReference() { | |
1007 return PreParserExpression( | |
1008 TypeField::encode(kExpression) | | |
1009 ExpressionTypeField::encode(kSuperCallReference)); | |
1010 } | |
1011 | |
1012 static PreParserExpression NoTemplateTag() { | |
1013 return PreParserExpression( | |
1014 TypeField::encode(kExpression) | | |
1015 ExpressionTypeField::encode(kNoTemplateTagExpression)); | |
1016 } | |
1017 | |
1018 bool IsIdentifier() const { | |
1019 return TypeField::decode(code_) == kIdentifierExpression; | |
1020 } | |
1021 | |
1022 PreParserIdentifier AsIdentifier() const { | |
1023 DCHECK(IsIdentifier()); | |
1024 return PreParserIdentifier(IdentifierTypeField::decode(code_)); | |
1025 } | |
1026 | |
1027 bool IsObjectLiteral() const { | |
1028 return TypeField::decode(code_) == kObjectLiteralExpression; | |
1029 } | |
1030 | |
1031 bool IsArrayLiteral() const { | |
1032 return TypeField::decode(code_) == kArrayLiteralExpression; | |
1033 } | |
1034 | |
1035 bool IsStringLiteral() const { | |
1036 return TypeField::decode(code_) == kStringLiteralExpression; | |
1037 } | |
1038 | |
1039 bool IsUseStrictLiteral() const { | |
1040 return TypeField::decode(code_) == kStringLiteralExpression && | |
1041 IsUseStrictField::decode(code_); | |
1042 } | |
1043 | |
1044 bool IsUseStrongLiteral() const { | |
1045 return TypeField::decode(code_) == kStringLiteralExpression && | |
1046 IsUseStrongField::decode(code_); | |
1047 } | |
1048 | |
1049 bool IsThis() const { | |
1050 return TypeField::decode(code_) == kExpression && | |
1051 ExpressionTypeField::decode(code_) == kThisExpression; | |
1052 } | |
1053 | |
1054 bool IsThisProperty() const { | |
1055 return TypeField::decode(code_) == kExpression && | |
1056 ExpressionTypeField::decode(code_) == kThisPropertyExpression; | |
1057 } | |
1058 | |
1059 bool IsProperty() const { | |
1060 return TypeField::decode(code_) == kExpression && | |
1061 (ExpressionTypeField::decode(code_) == kPropertyExpression || | |
1062 ExpressionTypeField::decode(code_) == kThisPropertyExpression); | |
1063 } | |
1064 | |
1065 bool IsCall() const { | |
1066 return TypeField::decode(code_) == kExpression && | |
1067 ExpressionTypeField::decode(code_) == kCallExpression; | |
1068 } | |
1069 | |
1070 bool IsSuperCallReference() const { | |
1071 return TypeField::decode(code_) == kExpression && | |
1072 ExpressionTypeField::decode(code_) == kSuperCallReference; | |
1073 } | |
1074 | |
1075 bool IsValidReferenceExpression() const { | |
1076 return IsIdentifier() || IsProperty(); | |
1077 } | |
1078 | |
1079 // At the moment PreParser doesn't track these expression types. | |
1080 bool IsFunctionLiteral() const { return false; } | |
1081 bool IsCallNew() const { return false; } | |
1082 | |
1083 bool IsNoTemplateTag() const { | |
1084 return TypeField::decode(code_) == kExpression && | |
1085 ExpressionTypeField::decode(code_) == kNoTemplateTagExpression; | |
1086 } | |
1087 | |
1088 bool IsSpreadExpression() const { | |
1089 return TypeField::decode(code_) == kSpreadExpression; | |
1090 } | |
1091 | |
1092 bool IsArrowFunctionFormalParametersWithRestParameter() const { | |
1093 // Iff the expression classifier has determined that this expression is a | |
1094 // valid arrow fformal parameter list, return true if the formal parameter | |
1095 // list ends with a rest parameter. | |
1096 return IsSpreadExpression() || | |
1097 (IsBinaryOperation() && HasRestField::decode(code_)); | |
1098 } | |
1099 | |
1100 PreParserExpression AsFunctionLiteral() { return *this; } | |
1101 | |
1102 bool IsBinaryOperation() const { | |
1103 return TypeField::decode(code_) == kBinaryOperationExpression; | |
1104 } | |
1105 | |
1106 // Dummy implementation for making expression->somefunc() work in both Parser | |
1107 // and PreParser. | |
1108 PreParserExpression* operator->() { return this; } | |
1109 | |
1110 // More dummy implementations of things PreParser doesn't need to track: | |
1111 void set_index(int index) {} // For YieldExpressions | |
1112 void set_should_eager_compile() {} | |
1113 | |
1114 int position() const { return RelocInfo::kNoPosition; } | |
1115 void set_function_token_position(int position) {} | |
1116 | |
1117 private: | |
1118 enum Type { | |
1119 kExpression, | |
1120 kIdentifierExpression, | |
1121 kStringLiteralExpression, | |
1122 kBinaryOperationExpression, | |
1123 kSpreadExpression, | |
1124 kObjectLiteralExpression, | |
1125 kArrayLiteralExpression | |
1126 }; | |
1127 | |
1128 enum ExpressionType { | |
1129 kThisExpression, | |
1130 kThisPropertyExpression, | |
1131 kPropertyExpression, | |
1132 kCallExpression, | |
1133 kSuperCallReference, | |
1134 kNoTemplateTagExpression | |
1135 }; | |
1136 | |
1137 explicit PreParserExpression(uint32_t expression_code) | |
1138 : code_(expression_code) {} | |
1139 | |
1140 // The first three bits are for the Type. | |
1141 typedef BitField<Type, 0, 3> TypeField; | |
1142 | |
1143 // The rest of the bits are interpreted depending on the value | |
1144 // of the Type field, so they can share the storage. | |
1145 typedef BitField<ExpressionType, TypeField::kNext, 3> ExpressionTypeField; | |
1146 typedef BitField<bool, TypeField::kNext, 1> IsUseStrictField; | |
1147 typedef BitField<bool, IsUseStrictField::kNext, 1> IsUseStrongField; | |
1148 typedef BitField<PreParserIdentifier::Type, TypeField::kNext, 10> | |
1149 IdentifierTypeField; | |
1150 typedef BitField<bool, TypeField::kNext, 1> HasRestField; | |
1151 | |
1152 uint32_t code_; | |
1153 }; | |
1154 | |
1155 | |
1156 // The pre-parser doesn't need to build lists of expressions, identifiers, or | |
1157 // the like. | |
1158 template <typename T> | |
1159 class PreParserList { | |
1160 public: | |
1161 // These functions make list->Add(some_expression) work (and do nothing). | |
1162 PreParserList() : length_(0) {} | |
1163 PreParserList* operator->() { return this; } | |
1164 void Add(T, void*) { ++length_; } | |
1165 int length() const { return length_; } | |
1166 private: | |
1167 int length_; | |
1168 }; | |
1169 | |
1170 | |
1171 typedef PreParserList<PreParserExpression> PreParserExpressionList; | |
1172 | |
1173 | |
1174 class PreParserStatement { | |
1175 public: | |
1176 static PreParserStatement Default() { | |
1177 return PreParserStatement(kUnknownStatement); | |
1178 } | |
1179 | |
1180 static PreParserStatement Jump() { | |
1181 return PreParserStatement(kJumpStatement); | |
1182 } | |
1183 | |
1184 static PreParserStatement FunctionDeclaration() { | |
1185 return PreParserStatement(kFunctionDeclaration); | |
1186 } | |
1187 | |
1188 // Creates expression statement from expression. | |
1189 // Preserves being an unparenthesized string literal, possibly | |
1190 // "use strict". | |
1191 static PreParserStatement ExpressionStatement( | |
1192 PreParserExpression expression) { | |
1193 if (expression.IsUseStrictLiteral()) { | |
1194 return PreParserStatement(kUseStrictExpressionStatement); | |
1195 } | |
1196 if (expression.IsUseStrongLiteral()) { | |
1197 return PreParserStatement(kUseStrongExpressionStatement); | |
1198 } | |
1199 if (expression.IsStringLiteral()) { | |
1200 return PreParserStatement(kStringLiteralExpressionStatement); | |
1201 } | |
1202 return Default(); | |
1203 } | |
1204 | |
1205 bool IsStringLiteral() { | |
1206 return code_ == kStringLiteralExpressionStatement; | |
1207 } | |
1208 | |
1209 bool IsUseStrictLiteral() { | |
1210 return code_ == kUseStrictExpressionStatement; | |
1211 } | |
1212 | |
1213 bool IsUseStrongLiteral() { return code_ == kUseStrongExpressionStatement; } | |
1214 | |
1215 bool IsFunctionDeclaration() { | |
1216 return code_ == kFunctionDeclaration; | |
1217 } | |
1218 | |
1219 bool IsJumpStatement() { | |
1220 return code_ == kJumpStatement; | |
1221 } | |
1222 | |
1223 private: | |
1224 enum Type { | |
1225 kUnknownStatement, | |
1226 kJumpStatement, | |
1227 kStringLiteralExpressionStatement, | |
1228 kUseStrictExpressionStatement, | |
1229 kUseStrongExpressionStatement, | |
1230 kFunctionDeclaration | |
1231 }; | |
1232 | |
1233 explicit PreParserStatement(Type code) : code_(code) {} | |
1234 Type code_; | |
1235 }; | |
1236 | |
1237 | |
1238 typedef PreParserList<PreParserStatement> PreParserStatementList; | |
1239 | |
1240 | |
1241 class PreParserFactory { | |
1242 public: | |
1243 explicit PreParserFactory(void* unused_value_factory) {} | |
1244 PreParserExpression NewStringLiteral(PreParserIdentifier identifier, | |
1245 int pos) { | |
1246 return PreParserExpression::Default(); | |
1247 } | |
1248 PreParserExpression NewNumberLiteral(double number, | |
1249 int pos) { | |
1250 return PreParserExpression::Default(); | |
1251 } | |
1252 PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern, | |
1253 int js_flags, int literal_index, | |
1254 bool is_strong, int pos) { | |
1255 return PreParserExpression::Default(); | |
1256 } | |
1257 PreParserExpression NewArrayLiteral(PreParserExpressionList values, | |
1258 int literal_index, | |
1259 bool is_strong, | |
1260 int pos) { | |
1261 return PreParserExpression::ArrayLiteral(); | |
1262 } | |
1263 PreParserExpression NewArrayLiteral(PreParserExpressionList values, | |
1264 int first_spread_index, int literal_index, | |
1265 bool is_strong, int pos) { | |
1266 return PreParserExpression::ArrayLiteral(); | |
1267 } | |
1268 PreParserExpression NewObjectLiteralProperty(PreParserExpression key, | |
1269 PreParserExpression value, | |
1270 ObjectLiteralProperty::Kind kind, | |
1271 bool is_static, | |
1272 bool is_computed_name) { | |
1273 return PreParserExpression::Default(); | |
1274 } | |
1275 PreParserExpression NewObjectLiteralProperty(PreParserExpression key, | |
1276 PreParserExpression value, | |
1277 bool is_static, | |
1278 bool is_computed_name) { | |
1279 return PreParserExpression::Default(); | |
1280 } | |
1281 PreParserExpression NewObjectLiteral(PreParserExpressionList properties, | |
1282 int literal_index, | |
1283 int boilerplate_properties, | |
1284 bool has_function, | |
1285 bool is_strong, | |
1286 int pos) { | |
1287 return PreParserExpression::ObjectLiteral(); | |
1288 } | |
1289 PreParserExpression NewVariableProxy(void* variable) { | |
1290 return PreParserExpression::Default(); | |
1291 } | |
1292 PreParserExpression NewProperty(PreParserExpression obj, | |
1293 PreParserExpression key, | |
1294 int pos) { | |
1295 if (obj.IsThis()) { | |
1296 return PreParserExpression::ThisProperty(); | |
1297 } | |
1298 return PreParserExpression::Property(); | |
1299 } | |
1300 PreParserExpression NewUnaryOperation(Token::Value op, | |
1301 PreParserExpression expression, | |
1302 int pos) { | |
1303 return PreParserExpression::Default(); | |
1304 } | |
1305 PreParserExpression NewBinaryOperation(Token::Value op, | |
1306 PreParserExpression left, | |
1307 PreParserExpression right, int pos) { | |
1308 return PreParserExpression::BinaryOperation(left, op, right); | |
1309 } | |
1310 PreParserExpression NewCompareOperation(Token::Value op, | |
1311 PreParserExpression left, | |
1312 PreParserExpression right, int pos) { | |
1313 return PreParserExpression::Default(); | |
1314 } | |
1315 PreParserExpression NewAssignment(Token::Value op, | |
1316 PreParserExpression left, | |
1317 PreParserExpression right, | |
1318 int pos) { | |
1319 return PreParserExpression::Default(); | |
1320 } | |
1321 PreParserExpression NewYield(PreParserExpression generator_object, | |
1322 PreParserExpression expression, | |
1323 Yield::Kind yield_kind, | |
1324 int pos) { | |
1325 return PreParserExpression::Default(); | |
1326 } | |
1327 PreParserExpression NewConditional(PreParserExpression condition, | |
1328 PreParserExpression then_expression, | |
1329 PreParserExpression else_expression, | |
1330 int pos) { | |
1331 return PreParserExpression::Default(); | |
1332 } | |
1333 PreParserExpression NewCountOperation(Token::Value op, | |
1334 bool is_prefix, | |
1335 PreParserExpression expression, | |
1336 int pos) { | |
1337 return PreParserExpression::Default(); | |
1338 } | |
1339 PreParserExpression NewCall(PreParserExpression expression, | |
1340 PreParserExpressionList arguments, | |
1341 int pos) { | |
1342 return PreParserExpression::Call(); | |
1343 } | |
1344 PreParserExpression NewCallNew(PreParserExpression expression, | |
1345 PreParserExpressionList arguments, | |
1346 int pos) { | |
1347 return PreParserExpression::Default(); | |
1348 } | |
1349 PreParserExpression NewCallRuntime(const AstRawString* name, | |
1350 const Runtime::Function* function, | |
1351 PreParserExpressionList arguments, | |
1352 int pos) { | |
1353 return PreParserExpression::Default(); | |
1354 } | |
1355 PreParserStatement NewReturnStatement(PreParserExpression expression, | |
1356 int pos) { | |
1357 return PreParserStatement::Default(); | |
1358 } | |
1359 PreParserExpression NewFunctionLiteral( | |
1360 PreParserIdentifier name, AstValueFactory* ast_value_factory, | |
1361 Scope* scope, PreParserStatementList body, int materialized_literal_count, | |
1362 int expected_property_count, int parameter_count, | |
1363 FunctionLiteral::ParameterFlag has_duplicate_parameters, | |
1364 FunctionLiteral::FunctionType function_type, | |
1365 FunctionLiteral::IsFunctionFlag is_function, | |
1366 FunctionLiteral::EagerCompileHint eager_compile_hint, FunctionKind kind, | |
1367 int position) { | |
1368 return PreParserExpression::Default(); | |
1369 } | |
1370 | |
1371 PreParserExpression NewSpread(PreParserExpression expression, int pos) { | |
1372 return PreParserExpression::Spread(expression); | |
1373 } | |
1374 | |
1375 PreParserExpression NewEmptyParentheses(int pos) { | |
1376 return PreParserExpression::Default(); | |
1377 } | |
1378 | |
1379 // Return the object itself as AstVisitor and implement the needed | |
1380 // dummy method right in this class. | |
1381 PreParserFactory* visitor() { return this; } | |
1382 int* ast_properties() { | |
1383 static int dummy = 42; | |
1384 return &dummy; | |
1385 } | |
1386 }; | |
1387 | |
1388 | |
1389 struct PreParserFormalParameters : FormalParametersBase { | |
1390 explicit PreParserFormalParameters(Scope* scope) | |
1391 : FormalParametersBase(scope) {} | |
1392 int arity = 0; | |
1393 | |
1394 int Arity() const { return arity; } | |
1395 PreParserIdentifier at(int i) { return PreParserIdentifier(); } // Dummy | |
1396 }; | |
1397 | |
1398 | |
1399 class PreParser; | |
1400 | |
1401 class PreParserTraits { | |
1402 public: | |
1403 struct Type { | |
1404 // TODO(marja): To be removed. The Traits object should contain all the data | |
1405 // it needs. | |
1406 typedef PreParser* Parser; | |
1407 | |
1408 // PreParser doesn't need to store generator variables. | |
1409 typedef void GeneratorVariable; | |
1410 | |
1411 typedef int AstProperties; | |
1412 | |
1413 // Return types for traversing functions. | |
1414 typedef PreParserIdentifier Identifier; | |
1415 typedef PreParserExpression Expression; | |
1416 typedef PreParserExpression YieldExpression; | |
1417 typedef PreParserExpression FunctionLiteral; | |
1418 typedef PreParserExpression ClassLiteral; | |
1419 typedef PreParserExpression ObjectLiteralProperty; | |
1420 typedef PreParserExpression Literal; | |
1421 typedef PreParserExpressionList ExpressionList; | |
1422 typedef PreParserExpressionList PropertyList; | |
1423 typedef PreParserIdentifier FormalParameter; | |
1424 typedef PreParserFormalParameters FormalParameters; | |
1425 typedef PreParserStatementList StatementList; | |
1426 | |
1427 // For constructing objects returned by the traversing functions. | |
1428 typedef PreParserFactory Factory; | |
1429 }; | |
1430 | |
1431 explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {} | |
1432 | |
1433 // Helper functions for recursive descent. | |
1434 static bool IsEval(PreParserIdentifier identifier) { | |
1435 return identifier.IsEval(); | |
1436 } | |
1437 | |
1438 static bool IsArguments(PreParserIdentifier identifier) { | |
1439 return identifier.IsArguments(); | |
1440 } | |
1441 | |
1442 static bool IsEvalOrArguments(PreParserIdentifier identifier) { | |
1443 return identifier.IsEvalOrArguments(); | |
1444 } | |
1445 | |
1446 static bool IsUndefined(PreParserIdentifier identifier) { | |
1447 return identifier.IsUndefined(); | |
1448 } | |
1449 | |
1450 static bool IsPrototype(PreParserIdentifier identifier) { | |
1451 return identifier.IsPrototype(); | |
1452 } | |
1453 | |
1454 static bool IsConstructor(PreParserIdentifier identifier) { | |
1455 return identifier.IsConstructor(); | |
1456 } | |
1457 | |
1458 // Returns true if the expression is of type "this.foo". | |
1459 static bool IsThisProperty(PreParserExpression expression) { | |
1460 return expression.IsThisProperty(); | |
1461 } | |
1462 | |
1463 static bool IsIdentifier(PreParserExpression expression) { | |
1464 return expression.IsIdentifier(); | |
1465 } | |
1466 | |
1467 static PreParserIdentifier AsIdentifier(PreParserExpression expression) { | |
1468 return expression.AsIdentifier(); | |
1469 } | |
1470 | |
1471 static bool IsFutureStrictReserved(PreParserIdentifier identifier) { | |
1472 return identifier.IsFutureStrictReserved(); | |
1473 } | |
1474 | |
1475 static bool IsBoilerplateProperty(PreParserExpression property) { | |
1476 // PreParser doesn't count boilerplate properties. | |
1477 return false; | |
1478 } | |
1479 | |
1480 static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) { | |
1481 return false; | |
1482 } | |
1483 | |
1484 static PreParserExpression GetPropertyValue(PreParserExpression property) { | |
1485 return PreParserExpression::Default(); | |
1486 } | |
1487 | |
1488 // Functions for encapsulating the differences between parsing and preparsing; | |
1489 // operations interleaved with the recursive descent. | |
1490 static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) { | |
1491 // PreParser should not use FuncNameInferrer. | |
1492 UNREACHABLE(); | |
1493 } | |
1494 | |
1495 static void PushPropertyName(FuncNameInferrer* fni, | |
1496 PreParserExpression expression) { | |
1497 // PreParser should not use FuncNameInferrer. | |
1498 UNREACHABLE(); | |
1499 } | |
1500 | |
1501 static void InferFunctionName(FuncNameInferrer* fni, | |
1502 PreParserExpression expression) { | |
1503 // PreParser should not use FuncNameInferrer. | |
1504 UNREACHABLE(); | |
1505 } | |
1506 | |
1507 static void CheckFunctionLiteralInsideTopLevelObjectLiteral( | |
1508 Scope* scope, PreParserExpression property, bool* has_function) {} | |
1509 | |
1510 static void CheckAssigningFunctionLiteralToProperty( | |
1511 PreParserExpression left, PreParserExpression right) {} | |
1512 | |
1513 static void CheckPossibleEvalCall(PreParserExpression expression, | |
1514 Scope* scope) { | |
1515 if (IsIdentifier(expression) && IsEval(AsIdentifier(expression))) { | |
1516 scope->DeclarationScope()->RecordEvalCall(); | |
1517 scope->RecordEvalCall(); | |
1518 } | |
1519 } | |
1520 | |
1521 static PreParserExpression MarkExpressionAsAssigned( | |
1522 PreParserExpression expression) { | |
1523 // TODO(marja): To be able to produce the same errors, the preparser needs | |
1524 // to start tracking which expressions are variables and which are assigned. | |
1525 return expression; | |
1526 } | |
1527 | |
1528 bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x, | |
1529 PreParserExpression y, | |
1530 Token::Value op, | |
1531 int pos, | |
1532 PreParserFactory* factory) { | |
1533 return false; | |
1534 } | |
1535 | |
1536 PreParserExpression BuildUnaryExpression(PreParserExpression expression, | |
1537 Token::Value op, int pos, | |
1538 PreParserFactory* factory) { | |
1539 return PreParserExpression::Default(); | |
1540 } | |
1541 | |
1542 PreParserExpression NewThrowReferenceError(MessageTemplate::Template message, | |
1543 int pos) { | |
1544 return PreParserExpression::Default(); | |
1545 } | |
1546 PreParserExpression NewThrowSyntaxError(MessageTemplate::Template message, | |
1547 Handle<Object> arg, int pos) { | |
1548 return PreParserExpression::Default(); | |
1549 } | |
1550 PreParserExpression NewThrowTypeError(MessageTemplate::Template message, | |
1551 Handle<Object> arg, int pos) { | |
1552 return PreParserExpression::Default(); | |
1553 } | |
1554 | |
1555 // Reporting errors. | |
1556 void ReportMessageAt(Scanner::Location location, | |
1557 MessageTemplate::Template message, | |
1558 const char* arg = NULL, | |
1559 ParseErrorType error_type = kSyntaxError); | |
1560 void ReportMessageAt(int start_pos, int end_pos, | |
1561 MessageTemplate::Template message, | |
1562 const char* arg = NULL, | |
1563 ParseErrorType error_type = kSyntaxError); | |
1564 | |
1565 // "null" return type creators. | |
1566 static PreParserIdentifier EmptyIdentifier() { | |
1567 return PreParserIdentifier::Default(); | |
1568 } | |
1569 static PreParserIdentifier EmptyIdentifierString() { | |
1570 return PreParserIdentifier::Default(); | |
1571 } | |
1572 static PreParserExpression EmptyExpression() { | |
1573 return PreParserExpression::Default(); | |
1574 } | |
1575 static PreParserExpression EmptyLiteral() { | |
1576 return PreParserExpression::Default(); | |
1577 } | |
1578 static PreParserExpression EmptyObjectLiteralProperty() { | |
1579 return PreParserExpression::Default(); | |
1580 } | |
1581 static PreParserExpression EmptyFunctionLiteral() { | |
1582 return PreParserExpression::Default(); | |
1583 } | |
1584 static PreParserExpressionList NullExpressionList() { | |
1585 return PreParserExpressionList(); | |
1586 } | |
1587 | |
1588 // Odd-ball literal creators. | |
1589 static PreParserExpression GetLiteralTheHole(int position, | |
1590 PreParserFactory* factory) { | |
1591 return PreParserExpression::Default(); | |
1592 } | |
1593 | |
1594 // Producing data during the recursive descent. | |
1595 PreParserIdentifier GetSymbol(Scanner* scanner); | |
1596 PreParserIdentifier GetNumberAsSymbol(Scanner* scanner); | |
1597 | |
1598 static PreParserIdentifier GetNextSymbol(Scanner* scanner) { | |
1599 return PreParserIdentifier::Default(); | |
1600 } | |
1601 | |
1602 static PreParserExpression ThisExpression(Scope* scope, | |
1603 PreParserFactory* factory, | |
1604 int pos) { | |
1605 return PreParserExpression::This(); | |
1606 } | |
1607 | |
1608 static PreParserExpression SuperPropertyReference(Scope* scope, | |
1609 PreParserFactory* factory, | |
1610 int pos) { | |
1611 return PreParserExpression::Default(); | |
1612 } | |
1613 | |
1614 static PreParserExpression SuperCallReference(Scope* scope, | |
1615 PreParserFactory* factory, | |
1616 int pos) { | |
1617 return PreParserExpression::SuperCallReference(); | |
1618 } | |
1619 | |
1620 static PreParserExpression NewTargetExpression(Scope* scope, | |
1621 PreParserFactory* factory, | |
1622 int pos) { | |
1623 return PreParserExpression::Default(); | |
1624 } | |
1625 | |
1626 static PreParserExpression DefaultConstructor(bool call_super, Scope* scope, | |
1627 int pos, int end_pos) { | |
1628 return PreParserExpression::Default(); | |
1629 } | |
1630 | |
1631 static PreParserExpression ExpressionFromLiteral( | |
1632 Token::Value token, int pos, Scanner* scanner, | |
1633 PreParserFactory* factory) { | |
1634 return PreParserExpression::Default(); | |
1635 } | |
1636 | |
1637 static PreParserExpression ExpressionFromIdentifier( | |
1638 PreParserIdentifier name, int start_position, int end_position, | |
1639 Scope* scope, PreParserFactory* factory) { | |
1640 return PreParserExpression::FromIdentifier(name); | |
1641 } | |
1642 | |
1643 PreParserExpression ExpressionFromString(int pos, | |
1644 Scanner* scanner, | |
1645 PreParserFactory* factory = NULL); | |
1646 | |
1647 PreParserExpression GetIterator(PreParserExpression iterable, | |
1648 PreParserFactory* factory) { | |
1649 return PreParserExpression::Default(); | |
1650 } | |
1651 | |
1652 static PreParserExpressionList NewExpressionList(int size, Zone* zone) { | |
1653 return PreParserExpressionList(); | |
1654 } | |
1655 | |
1656 static PreParserStatementList NewStatementList(int size, Zone* zone) { | |
1657 return PreParserStatementList(); | |
1658 } | |
1659 | |
1660 static PreParserExpressionList NewPropertyList(int size, Zone* zone) { | |
1661 return PreParserExpressionList(); | |
1662 } | |
1663 | |
1664 static void AddParameterInitializationBlock( | |
1665 const PreParserFormalParameters& parameters, | |
1666 PreParserStatementList list, bool* ok) {} | |
1667 | |
1668 V8_INLINE void SkipLazyFunctionBody(int* materialized_literal_count, | |
1669 int* expected_property_count, bool* ok) { | |
1670 UNREACHABLE(); | |
1671 } | |
1672 | |
1673 V8_INLINE PreParserStatementList ParseEagerFunctionBody( | |
1674 PreParserIdentifier function_name, int pos, | |
1675 const PreParserFormalParameters& parameters, FunctionKind kind, | |
1676 FunctionLiteral::FunctionType function_type, bool* ok); | |
1677 | |
1678 V8_INLINE void ParseArrowFunctionFormalParameterList( | |
1679 PreParserFormalParameters* parameters, | |
1680 PreParserExpression expression, const Scanner::Location& params_loc, | |
1681 Scanner::Location* duplicate_loc, bool* ok); | |
1682 | |
1683 void ReindexLiterals(const PreParserFormalParameters& paramaters) {} | |
1684 | |
1685 struct TemplateLiteralState {}; | |
1686 | |
1687 TemplateLiteralState OpenTemplateLiteral(int pos) { | |
1688 return TemplateLiteralState(); | |
1689 } | |
1690 void AddTemplateSpan(TemplateLiteralState*, bool) {} | |
1691 void AddTemplateExpression(TemplateLiteralState*, PreParserExpression) {} | |
1692 PreParserExpression CloseTemplateLiteral(TemplateLiteralState*, int, | |
1693 PreParserExpression tag) { | |
1694 if (IsTaggedTemplate(tag)) { | |
1695 // Emulate generation of array literals for tag callsite | |
1696 // 1st is array of cooked strings, second is array of raw strings | |
1697 MaterializeTemplateCallsiteLiterals(); | |
1698 } | |
1699 return EmptyExpression(); | |
1700 } | |
1701 inline void MaterializeTemplateCallsiteLiterals(); | |
1702 PreParserExpression NoTemplateTag() { | |
1703 return PreParserExpression::NoTemplateTag(); | |
1704 } | |
1705 static bool IsTaggedTemplate(const PreParserExpression tag) { | |
1706 return !tag.IsNoTemplateTag(); | |
1707 } | |
1708 | |
1709 void AddFormalParameter(PreParserFormalParameters* parameters, | |
1710 PreParserExpression pattern, | |
1711 PreParserExpression initializer, | |
1712 int initializer_end_position, bool is_rest) { | |
1713 ++parameters->arity; | |
1714 } | |
1715 void DeclareFormalParameter(Scope* scope, PreParserIdentifier parameter, | |
1716 ExpressionClassifier* classifier) { | |
1717 if (!classifier->is_simple_parameter_list()) { | |
1718 scope->SetHasNonSimpleParameters(); | |
1719 } | |
1720 } | |
1721 | |
1722 void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {} | |
1723 | |
1724 // Temporary glue; these functions will move to ParserBase. | |
1725 PreParserExpression ParseV8Intrinsic(bool* ok); | |
1726 V8_INLINE PreParserExpression ParseDoExpression(bool* ok); | |
1727 PreParserExpression ParseFunctionLiteral( | |
1728 PreParserIdentifier name, Scanner::Location function_name_location, | |
1729 FunctionNameValidity function_name_validity, FunctionKind kind, | |
1730 int function_token_position, FunctionLiteral::FunctionType type, | |
1731 FunctionLiteral::ArityRestriction arity_restriction, | |
1732 LanguageMode language_mode, bool* ok); | |
1733 | |
1734 PreParserExpression ParseClassLiteral(PreParserIdentifier name, | |
1735 Scanner::Location class_name_location, | |
1736 bool name_is_strict_reserved, int pos, | |
1737 bool* ok); | |
1738 | |
1739 PreParserExpressionList PrepareSpreadArguments(PreParserExpressionList list) { | |
1740 return list; | |
1741 } | |
1742 | |
1743 inline void MaterializeUnspreadArgumentsLiterals(int count); | |
1744 | |
1745 inline PreParserExpression SpreadCall(PreParserExpression function, | |
1746 PreParserExpressionList args, int pos); | |
1747 | |
1748 inline PreParserExpression SpreadCallNew(PreParserExpression function, | |
1749 PreParserExpressionList args, | |
1750 int pos); | |
1751 | |
1752 private: | |
1753 PreParser* pre_parser_; | |
1754 }; | |
1755 | |
1756 | |
1757 // Preparsing checks a JavaScript program and emits preparse-data that helps | |
1758 // a later parsing to be faster. | |
1759 // See preparse-data-format.h for the data format. | |
1760 | |
1761 // The PreParser checks that the syntax follows the grammar for JavaScript, | |
1762 // and collects some information about the program along the way. | |
1763 // The grammar check is only performed in order to understand the program | |
1764 // sufficiently to deduce some information about it, that can be used | |
1765 // to speed up later parsing. Finding errors is not the goal of pre-parsing, | |
1766 // rather it is to speed up properly written and correct programs. | |
1767 // That means that contextual checks (like a label being declared where | |
1768 // it is used) are generally omitted. | |
1769 class PreParser : public ParserBase<PreParserTraits> { | |
1770 public: | |
1771 typedef PreParserIdentifier Identifier; | |
1772 typedef PreParserExpression Expression; | |
1773 typedef PreParserStatement Statement; | |
1774 | |
1775 enum PreParseResult { | |
1776 kPreParseStackOverflow, | |
1777 kPreParseSuccess | |
1778 }; | |
1779 | |
1780 PreParser(Zone* zone, Scanner* scanner, AstValueFactory* ast_value_factory, | |
1781 ParserRecorder* log, uintptr_t stack_limit) | |
1782 : ParserBase<PreParserTraits>(zone, scanner, stack_limit, NULL, | |
1783 ast_value_factory, log, this) {} | |
1784 | |
1785 // Pre-parse the program from the character stream; returns true on | |
1786 // success (even if parsing failed, the pre-parse data successfully | |
1787 // captured the syntax error), and false if a stack-overflow happened | |
1788 // during parsing. | |
1789 PreParseResult PreParseProgram(int* materialized_literals = 0) { | |
1790 Scope* scope = NewScope(scope_, SCRIPT_SCOPE); | |
1791 PreParserFactory factory(NULL); | |
1792 FunctionState top_scope(&function_state_, &scope_, scope, kNormalFunction, | |
1793 &factory); | |
1794 bool ok = true; | |
1795 int start_position = scanner()->peek_location().beg_pos; | |
1796 ParseStatementList(Token::EOS, &ok); | |
1797 if (stack_overflow()) return kPreParseStackOverflow; | |
1798 if (!ok) { | |
1799 ReportUnexpectedToken(scanner()->current_token()); | |
1800 } else if (is_strict(scope_->language_mode())) { | |
1801 CheckStrictOctalLiteral(start_position, scanner()->location().end_pos, | |
1802 &ok); | |
1803 } | |
1804 if (materialized_literals) { | |
1805 *materialized_literals = function_state_->materialized_literal_count(); | |
1806 } | |
1807 return kPreParseSuccess; | |
1808 } | |
1809 | |
1810 // Parses a single function literal, from the opening parentheses before | |
1811 // parameters to the closing brace after the body. | |
1812 // Returns a FunctionEntry describing the body of the function in enough | |
1813 // detail that it can be lazily compiled. | |
1814 // The scanner is expected to have matched the "function" or "function*" | |
1815 // keyword and parameters, and have consumed the initial '{'. | |
1816 // At return, unless an error occurred, the scanner is positioned before the | |
1817 // the final '}'. | |
1818 PreParseResult PreParseLazyFunction( | |
1819 LanguageMode language_mode, FunctionKind kind, bool has_simple_parameters, | |
1820 ParserRecorder* log, Scanner::BookmarkScope* bookmark = nullptr); | |
1821 | |
1822 private: | |
1823 friend class PreParserTraits; | |
1824 | |
1825 static const int kLazyParseTrialLimit = 200; | |
1826 | |
1827 // These types form an algebra over syntactic categories that is just | |
1828 // rich enough to let us recognize and propagate the constructs that | |
1829 // are either being counted in the preparser data, or is important | |
1830 // to throw the correct syntax error exceptions. | |
1831 | |
1832 // All ParseXXX functions take as the last argument an *ok parameter | |
1833 // which is set to false if parsing failed; it is unchanged otherwise. | |
1834 // By making the 'exception handling' explicit, we are forced to check | |
1835 // for failure at the call sites. | |
1836 Statement ParseStatementListItem(bool* ok); | |
1837 void ParseStatementList(int end_token, bool* ok, | |
1838 Scanner::BookmarkScope* bookmark = nullptr); | |
1839 Statement ParseStatement(bool* ok); | |
1840 Statement ParseSubStatement(bool* ok); | |
1841 Statement ParseFunctionDeclaration(bool* ok); | |
1842 Statement ParseClassDeclaration(bool* ok); | |
1843 Statement ParseBlock(bool* ok); | |
1844 Statement ParseVariableStatement(VariableDeclarationContext var_context, | |
1845 bool* ok); | |
1846 Statement ParseVariableDeclarations(VariableDeclarationContext var_context, | |
1847 int* num_decl, bool* is_lexical, | |
1848 bool* is_binding_pattern, | |
1849 Scanner::Location* first_initializer_loc, | |
1850 Scanner::Location* bindings_loc, | |
1851 bool* ok); | |
1852 Statement ParseExpressionOrLabelledStatement(bool* ok); | |
1853 Statement ParseIfStatement(bool* ok); | |
1854 Statement ParseContinueStatement(bool* ok); | |
1855 Statement ParseBreakStatement(bool* ok); | |
1856 Statement ParseReturnStatement(bool* ok); | |
1857 Statement ParseWithStatement(bool* ok); | |
1858 Statement ParseSwitchStatement(bool* ok); | |
1859 Statement ParseDoWhileStatement(bool* ok); | |
1860 Statement ParseWhileStatement(bool* ok); | |
1861 Statement ParseForStatement(bool* ok); | |
1862 Statement ParseThrowStatement(bool* ok); | |
1863 Statement ParseTryStatement(bool* ok); | |
1864 Statement ParseDebuggerStatement(bool* ok); | |
1865 Expression ParseConditionalExpression(bool accept_IN, bool* ok); | |
1866 Expression ParseObjectLiteral(bool* ok); | |
1867 Expression ParseV8Intrinsic(bool* ok); | |
1868 Expression ParseDoExpression(bool* ok); | |
1869 | |
1870 V8_INLINE void SkipLazyFunctionBody(int* materialized_literal_count, | |
1871 int* expected_property_count, bool* ok); | |
1872 V8_INLINE PreParserStatementList ParseEagerFunctionBody( | |
1873 PreParserIdentifier function_name, int pos, | |
1874 const PreParserFormalParameters& parameters, FunctionKind kind, | |
1875 FunctionLiteral::FunctionType function_type, bool* ok); | |
1876 | |
1877 Expression ParseFunctionLiteral( | |
1878 Identifier name, Scanner::Location function_name_location, | |
1879 FunctionNameValidity function_name_validity, FunctionKind kind, | |
1880 int function_token_pos, FunctionLiteral::FunctionType function_type, | |
1881 FunctionLiteral::ArityRestriction arity_restriction, | |
1882 LanguageMode language_mode, bool* ok); | |
1883 void ParseLazyFunctionLiteralBody(bool* ok, | |
1884 Scanner::BookmarkScope* bookmark = nullptr); | |
1885 | |
1886 PreParserExpression ParseClassLiteral(PreParserIdentifier name, | |
1887 Scanner::Location class_name_location, | |
1888 bool name_is_strict_reserved, int pos, | |
1889 bool* ok); | |
1890 }; | |
1891 | |
1892 | |
1893 void PreParserTraits::MaterializeTemplateCallsiteLiterals() { | |
1894 pre_parser_->function_state_->NextMaterializedLiteralIndex(); | |
1895 pre_parser_->function_state_->NextMaterializedLiteralIndex(); | |
1896 } | |
1897 | |
1898 | |
1899 void PreParserTraits::MaterializeUnspreadArgumentsLiterals(int count) { | |
1900 for (int i = 0; i < count; ++i) { | |
1901 pre_parser_->function_state_->NextMaterializedLiteralIndex(); | |
1902 } | |
1903 } | |
1904 | |
1905 | |
1906 PreParserExpression PreParserTraits::SpreadCall(PreParserExpression function, | |
1907 PreParserExpressionList args, | |
1908 int pos) { | |
1909 return pre_parser_->factory()->NewCall(function, args, pos); | |
1910 } | |
1911 | |
1912 PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function, | |
1913 PreParserExpressionList args, | |
1914 int pos) { | |
1915 return pre_parser_->factory()->NewCallNew(function, args, pos); | |
1916 } | |
1917 | |
1918 | |
1919 void PreParserTraits::ParseArrowFunctionFormalParameterList( | |
1920 PreParserFormalParameters* parameters, | |
1921 PreParserExpression params, const Scanner::Location& params_loc, | |
1922 Scanner::Location* duplicate_loc, bool* ok) { | |
1923 // TODO(wingo): Detect duplicated identifiers in paramlists. Detect parameter | |
1924 // lists that are too long. | |
1925 | |
1926 // Accomodate array literal for rest parameter. | |
1927 if (params.IsArrowFunctionFormalParametersWithRestParameter()) { | |
1928 ++parameters->materialized_literals_count; | |
1929 pre_parser_->function_state_->NextMaterializedLiteralIndex(); | |
1930 } | |
1931 } | |
1932 | |
1933 | |
1934 PreParserExpression PreParserTraits::ParseDoExpression(bool* ok) { | |
1935 return pre_parser_->ParseDoExpression(ok); | |
1936 } | |
1937 | |
1938 | |
1939 PreParserStatementList PreParser::ParseEagerFunctionBody( | |
1940 PreParserIdentifier function_name, int pos, | |
1941 const PreParserFormalParameters& parameters, FunctionKind kind, | |
1942 FunctionLiteral::FunctionType function_type, bool* ok) { | |
1943 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | |
1944 | |
1945 ParseStatementList(Token::RBRACE, ok); | |
1946 if (!*ok) return PreParserStatementList(); | |
1947 | |
1948 Expect(Token::RBRACE, ok); | |
1949 return PreParserStatementList(); | |
1950 } | |
1951 | |
1952 | |
1953 PreParserStatementList PreParserTraits::ParseEagerFunctionBody( | |
1954 PreParserIdentifier function_name, int pos, | |
1955 const PreParserFormalParameters& parameters, FunctionKind kind, | |
1956 FunctionLiteral::FunctionType function_type, bool* ok) { | |
1957 return pre_parser_->ParseEagerFunctionBody(function_name, pos, parameters, | |
1958 kind, function_type, ok); | |
1959 } | |
1960 | |
1961 | |
1962 template <class Traits> | |
1963 ParserBase<Traits>::FunctionState::FunctionState( | |
1964 FunctionState** function_state_stack, Scope** scope_stack, Scope* scope, | |
1965 FunctionKind kind, typename Traits::Type::Factory* factory) | |
1966 : next_materialized_literal_index_(0), | |
1967 expected_property_count_(0), | |
1968 this_location_(Scanner::Location::invalid()), | |
1969 return_location_(Scanner::Location::invalid()), | |
1970 super_location_(Scanner::Location::invalid()), | |
1971 kind_(kind), | |
1972 generator_object_variable_(NULL), | |
1973 function_state_stack_(function_state_stack), | |
1974 outer_function_state_(*function_state_stack), | |
1975 scope_stack_(scope_stack), | |
1976 outer_scope_(*scope_stack), | |
1977 factory_(factory) { | |
1978 *scope_stack_ = scope; | |
1979 *function_state_stack = this; | |
1980 } | |
1981 | |
1982 | |
1983 template <class Traits> | |
1984 ParserBase<Traits>::FunctionState::~FunctionState() { | |
1985 *scope_stack_ = outer_scope_; | |
1986 *function_state_stack_ = outer_function_state_; | |
1987 } | |
1988 | |
1989 | |
1990 template <class Traits> | |
1991 void ParserBase<Traits>::GetUnexpectedTokenMessage( | |
1992 Token::Value token, MessageTemplate::Template* message, const char** arg, | |
1993 MessageTemplate::Template default_) { | |
1994 // Four of the tokens are treated specially | |
1995 switch (token) { | |
1996 case Token::EOS: | |
1997 *message = MessageTemplate::kUnexpectedEOS; | |
1998 *arg = nullptr; | |
1999 break; | |
2000 case Token::SMI: | |
2001 case Token::NUMBER: | |
2002 *message = MessageTemplate::kUnexpectedTokenNumber; | |
2003 *arg = nullptr; | |
2004 break; | |
2005 case Token::STRING: | |
2006 *message = MessageTemplate::kUnexpectedTokenString; | |
2007 *arg = nullptr; | |
2008 break; | |
2009 case Token::IDENTIFIER: | |
2010 *message = MessageTemplate::kUnexpectedTokenIdentifier; | |
2011 *arg = nullptr; | |
2012 break; | |
2013 case Token::FUTURE_RESERVED_WORD: | |
2014 *message = MessageTemplate::kUnexpectedReserved; | |
2015 *arg = nullptr; | |
2016 break; | |
2017 case Token::LET: | |
2018 case Token::STATIC: | |
2019 case Token::YIELD: | |
2020 case Token::FUTURE_STRICT_RESERVED_WORD: | |
2021 *message = is_strict(language_mode()) | |
2022 ? MessageTemplate::kUnexpectedStrictReserved | |
2023 : MessageTemplate::kUnexpectedTokenIdentifier; | |
2024 *arg = nullptr; | |
2025 break; | |
2026 case Token::TEMPLATE_SPAN: | |
2027 case Token::TEMPLATE_TAIL: | |
2028 *message = MessageTemplate::kUnexpectedTemplateString; | |
2029 *arg = nullptr; | |
2030 break; | |
2031 case Token::ESCAPED_STRICT_RESERVED_WORD: | |
2032 case Token::ESCAPED_KEYWORD: | |
2033 *message = MessageTemplate::kInvalidEscapedReservedWord; | |
2034 *arg = nullptr; | |
2035 break; | |
2036 default: | |
2037 const char* name = Token::String(token); | |
2038 DCHECK(name != NULL); | |
2039 *arg = name; | |
2040 break; | |
2041 } | |
2042 } | |
2043 | |
2044 | |
2045 template <class Traits> | |
2046 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) { | |
2047 return ReportUnexpectedTokenAt(scanner_->location(), token); | |
2048 } | |
2049 | |
2050 | |
2051 template <class Traits> | |
2052 void ParserBase<Traits>::ReportUnexpectedTokenAt( | |
2053 Scanner::Location source_location, Token::Value token, | |
2054 MessageTemplate::Template message) { | |
2055 const char* arg; | |
2056 GetUnexpectedTokenMessage(token, &message, &arg); | |
2057 Traits::ReportMessageAt(source_location, message, arg); | |
2058 } | |
2059 | |
2060 | |
2061 template <class Traits> | |
2062 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( | |
2063 AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) { | |
2064 ExpressionClassifier classifier; | |
2065 auto result = ParseAndClassifyIdentifier(&classifier, ok); | |
2066 if (!*ok) return Traits::EmptyIdentifier(); | |
2067 | |
2068 if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) { | |
2069 ValidateAssignmentPattern(&classifier, ok); | |
2070 if (!*ok) return Traits::EmptyIdentifier(); | |
2071 ValidateBindingPattern(&classifier, ok); | |
2072 if (!*ok) return Traits::EmptyIdentifier(); | |
2073 } else { | |
2074 ValidateExpression(&classifier, ok); | |
2075 if (!*ok) return Traits::EmptyIdentifier(); | |
2076 } | |
2077 | |
2078 return result; | |
2079 } | |
2080 | |
2081 | |
2082 template <class Traits> | |
2083 typename ParserBase<Traits>::IdentifierT | |
2084 ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier, | |
2085 bool* ok) { | |
2086 Token::Value next = Next(); | |
2087 if (next == Token::IDENTIFIER) { | |
2088 IdentifierT name = this->GetSymbol(scanner()); | |
2089 // When this function is used to read a formal parameter, we don't always | |
2090 // know whether the function is going to be strict or sloppy. Indeed for | |
2091 // arrow functions we don't always know that the identifier we are reading | |
2092 // is actually a formal parameter. Therefore besides the errors that we | |
2093 // must detect because we know we're in strict mode, we also record any | |
2094 // error that we might make in the future once we know the language mode. | |
2095 if (this->IsEval(name)) { | |
2096 classifier->RecordStrictModeFormalParameterError( | |
2097 scanner()->location(), MessageTemplate::kStrictEvalArguments); | |
2098 if (is_strict(language_mode())) { | |
2099 classifier->RecordBindingPatternError( | |
2100 scanner()->location(), MessageTemplate::kStrictEvalArguments); | |
2101 } | |
2102 } | |
2103 if (this->IsArguments(name)) { | |
2104 scope_->RecordArgumentsUsage(); | |
2105 classifier->RecordStrictModeFormalParameterError( | |
2106 scanner()->location(), MessageTemplate::kStrictEvalArguments); | |
2107 if (is_strict(language_mode())) { | |
2108 classifier->RecordBindingPatternError( | |
2109 scanner()->location(), MessageTemplate::kStrictEvalArguments); | |
2110 } | |
2111 if (is_strong(language_mode())) { | |
2112 classifier->RecordExpressionError(scanner()->location(), | |
2113 MessageTemplate::kStrongArguments); | |
2114 } | |
2115 } | |
2116 if (this->IsUndefined(name)) { | |
2117 classifier->RecordStrongModeFormalParameterError( | |
2118 scanner()->location(), MessageTemplate::kStrongUndefined); | |
2119 if (is_strong(language_mode())) { | |
2120 // TODO(dslomov): allow 'undefined' in nested patterns. | |
2121 classifier->RecordBindingPatternError( | |
2122 scanner()->location(), MessageTemplate::kStrongUndefined); | |
2123 classifier->RecordAssignmentPatternError( | |
2124 scanner()->location(), MessageTemplate::kStrongUndefined); | |
2125 } | |
2126 } | |
2127 | |
2128 if (classifier->duplicate_finder() != nullptr && | |
2129 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { | |
2130 classifier->RecordDuplicateFormalParameterError(scanner()->location()); | |
2131 } | |
2132 return name; | |
2133 } else if (is_sloppy(language_mode()) && | |
2134 (next == Token::FUTURE_STRICT_RESERVED_WORD || | |
2135 next == Token::ESCAPED_STRICT_RESERVED_WORD || | |
2136 next == Token::LET || next == Token::STATIC || | |
2137 (next == Token::YIELD && !is_generator()))) { | |
2138 classifier->RecordStrictModeFormalParameterError( | |
2139 scanner()->location(), MessageTemplate::kUnexpectedStrictReserved); | |
2140 if (next == Token::ESCAPED_STRICT_RESERVED_WORD && | |
2141 is_strict(language_mode())) { | |
2142 ReportUnexpectedToken(next); | |
2143 *ok = false; | |
2144 return Traits::EmptyIdentifier(); | |
2145 } | |
2146 if (next == Token::LET) { | |
2147 classifier->RecordLetPatternError(scanner()->location(), | |
2148 MessageTemplate::kLetInLexicalBinding); | |
2149 } | |
2150 return this->GetSymbol(scanner()); | |
2151 } else { | |
2152 this->ReportUnexpectedToken(next); | |
2153 *ok = false; | |
2154 return Traits::EmptyIdentifier(); | |
2155 } | |
2156 } | |
2157 | |
2158 | |
2159 template <class Traits> | |
2160 typename ParserBase<Traits>::IdentifierT | |
2161 ParserBase<Traits>::ParseIdentifierOrStrictReservedWord( | |
2162 bool is_generator, bool* is_strict_reserved, bool* ok) { | |
2163 Token::Value next = Next(); | |
2164 if (next == Token::IDENTIFIER) { | |
2165 *is_strict_reserved = false; | |
2166 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET || | |
2167 next == Token::STATIC || (next == Token::YIELD && !is_generator)) { | |
2168 *is_strict_reserved = true; | |
2169 } else { | |
2170 ReportUnexpectedToken(next); | |
2171 *ok = false; | |
2172 return Traits::EmptyIdentifier(); | |
2173 } | |
2174 | |
2175 IdentifierT name = this->GetSymbol(scanner()); | |
2176 if (this->IsArguments(name)) scope_->RecordArgumentsUsage(); | |
2177 return name; | |
2178 } | |
2179 | |
2180 | |
2181 template <class Traits> | |
2182 typename ParserBase<Traits>::IdentifierT | |
2183 ParserBase<Traits>::ParseIdentifierName(bool* ok) { | |
2184 Token::Value next = Next(); | |
2185 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD && | |
2186 next != Token::LET && next != Token::STATIC && next != Token::YIELD && | |
2187 next != Token::FUTURE_STRICT_RESERVED_WORD && | |
2188 next != Token::ESCAPED_KEYWORD && | |
2189 next != Token::ESCAPED_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) { | |
2190 this->ReportUnexpectedToken(next); | |
2191 *ok = false; | |
2192 return Traits::EmptyIdentifier(); | |
2193 } | |
2194 | |
2195 IdentifierT name = this->GetSymbol(scanner()); | |
2196 if (this->IsArguments(name)) scope_->RecordArgumentsUsage(); | |
2197 return name; | |
2198 } | |
2199 | |
2200 | |
2201 template <class Traits> | |
2202 typename ParserBase<Traits>::IdentifierT | |
2203 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get, | |
2204 bool* is_set, | |
2205 bool* ok) { | |
2206 IdentifierT result = ParseIdentifierName(ok); | |
2207 if (!*ok) return Traits::EmptyIdentifier(); | |
2208 scanner()->IsGetOrSet(is_get, is_set); | |
2209 return result; | |
2210 } | |
2211 | |
2212 | |
2213 template <class Traits> | |
2214 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral( | |
2215 bool seen_equal, ExpressionClassifier* classifier, bool* ok) { | |
2216 int pos = peek_position(); | |
2217 if (!scanner()->ScanRegExpPattern(seen_equal)) { | |
2218 Next(); | |
2219 ReportMessage(MessageTemplate::kUnterminatedRegExp); | |
2220 *ok = false; | |
2221 return Traits::EmptyExpression(); | |
2222 } | |
2223 | |
2224 int literal_index = function_state_->NextMaterializedLiteralIndex(); | |
2225 | |
2226 IdentifierT js_pattern = this->GetNextSymbol(scanner()); | |
2227 Maybe<RegExp::Flags> flags = scanner()->ScanRegExpFlags(); | |
2228 if (flags.IsNothing()) { | |
2229 Next(); | |
2230 ReportMessage(MessageTemplate::kMalformedRegExpFlags); | |
2231 *ok = false; | |
2232 return Traits::EmptyExpression(); | |
2233 } | |
2234 int js_flags = flags.FromJust(); | |
2235 Next(); | |
2236 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, | |
2237 is_strong(language_mode()), pos); | |
2238 } | |
2239 | |
2240 | |
2241 #define CHECK_OK ok); \ | |
2242 if (!*ok) return this->EmptyExpression(); \ | |
2243 ((void)0 | |
2244 #define DUMMY ) // to make indentation work | |
2245 #undef DUMMY | |
2246 | |
2247 // Used in functions where the return type is not ExpressionT. | |
2248 #define CHECK_OK_CUSTOM(x) ok); \ | |
2249 if (!*ok) return this->x(); \ | |
2250 ((void)0 | |
2251 #define DUMMY ) // to make indentation work | |
2252 #undef DUMMY | |
2253 | |
2254 | |
2255 template <class Traits> | |
2256 typename ParserBase<Traits>::ExpressionT | |
2257 ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, | |
2258 bool* ok) { | |
2259 // PrimaryExpression :: | |
2260 // 'this' | |
2261 // 'null' | |
2262 // 'true' | |
2263 // 'false' | |
2264 // Identifier | |
2265 // Number | |
2266 // String | |
2267 // ArrayLiteral | |
2268 // ObjectLiteral | |
2269 // RegExpLiteral | |
2270 // ClassLiteral | |
2271 // '(' Expression ')' | |
2272 // TemplateLiteral | |
2273 // do Block | |
2274 | |
2275 int beg_pos = peek_position(); | |
2276 switch (peek()) { | |
2277 case Token::THIS: { | |
2278 BindingPatternUnexpectedToken(classifier); | |
2279 Consume(Token::THIS); | |
2280 if (FLAG_strong_this && is_strong(language_mode())) { | |
2281 // Constructors' usages of 'this' in strong mode are parsed separately. | |
2282 // TODO(rossberg): this does not work with arrow functions yet. | |
2283 if (IsClassConstructor(function_state_->kind())) { | |
2284 ReportMessage(MessageTemplate::kStrongConstructorThis); | |
2285 *ok = false; | |
2286 return this->EmptyExpression(); | |
2287 } | |
2288 } | |
2289 return this->ThisExpression(scope_, factory(), beg_pos); | |
2290 } | |
2291 | |
2292 case Token::NULL_LITERAL: | |
2293 case Token::TRUE_LITERAL: | |
2294 case Token::FALSE_LITERAL: | |
2295 BindingPatternUnexpectedToken(classifier); | |
2296 return this->ExpressionFromLiteral(Next(), beg_pos, scanner(), factory()); | |
2297 case Token::SMI: | |
2298 case Token::NUMBER: | |
2299 classifier->RecordBindingPatternError( | |
2300 scanner()->peek_location(), MessageTemplate::kUnexpectedTokenNumber); | |
2301 return this->ExpressionFromLiteral(Next(), beg_pos, scanner(), factory()); | |
2302 | |
2303 case Token::IDENTIFIER: | |
2304 case Token::LET: | |
2305 case Token::STATIC: | |
2306 case Token::YIELD: | |
2307 case Token::ESCAPED_STRICT_RESERVED_WORD: | |
2308 case Token::FUTURE_STRICT_RESERVED_WORD: { | |
2309 // Using eval or arguments in this context is OK even in strict mode. | |
2310 IdentifierT name = ParseAndClassifyIdentifier(classifier, CHECK_OK); | |
2311 return this->ExpressionFromIdentifier( | |
2312 name, beg_pos, scanner()->location().end_pos, scope_, factory()); | |
2313 } | |
2314 | |
2315 case Token::STRING: { | |
2316 classifier->RecordBindingPatternError( | |
2317 scanner()->peek_location(), MessageTemplate::kUnexpectedTokenString); | |
2318 Consume(Token::STRING); | |
2319 return this->ExpressionFromString(beg_pos, scanner(), factory()); | |
2320 } | |
2321 | |
2322 case Token::ASSIGN_DIV: | |
2323 classifier->RecordBindingPatternError( | |
2324 scanner()->peek_location(), MessageTemplate::kUnexpectedTokenRegExp); | |
2325 return this->ParseRegExpLiteral(true, classifier, ok); | |
2326 | |
2327 case Token::DIV: | |
2328 classifier->RecordBindingPatternError( | |
2329 scanner()->peek_location(), MessageTemplate::kUnexpectedTokenRegExp); | |
2330 return this->ParseRegExpLiteral(false, classifier, ok); | |
2331 | |
2332 case Token::LBRACK: | |
2333 if (!allow_harmony_destructuring_bind()) { | |
2334 BindingPatternUnexpectedToken(classifier); | |
2335 } | |
2336 return this->ParseArrayLiteral(classifier, ok); | |
2337 | |
2338 case Token::LBRACE: | |
2339 if (!allow_harmony_destructuring_bind()) { | |
2340 BindingPatternUnexpectedToken(classifier); | |
2341 } | |
2342 return this->ParseObjectLiteral(classifier, ok); | |
2343 | |
2344 case Token::LPAREN: { | |
2345 // Arrow function formal parameters are either a single identifier or a | |
2346 // list of BindingPattern productions enclosed in parentheses. | |
2347 // Parentheses are not valid on the LHS of a BindingPattern, so we use the | |
2348 // is_valid_binding_pattern() check to detect multiple levels of | |
2349 // parenthesization. | |
2350 if (!classifier->is_valid_binding_pattern()) { | |
2351 ArrowFormalParametersUnexpectedToken(classifier); | |
2352 } | |
2353 BindingPatternUnexpectedToken(classifier); | |
2354 Consume(Token::LPAREN); | |
2355 if (Check(Token::RPAREN)) { | |
2356 // ()=>x. The continuation that looks for the => is in | |
2357 // ParseAssignmentExpression. | |
2358 classifier->RecordExpressionError(scanner()->location(), | |
2359 MessageTemplate::kUnexpectedToken, | |
2360 Token::String(Token::RPAREN)); | |
2361 classifier->RecordBindingPatternError(scanner()->location(), | |
2362 MessageTemplate::kUnexpectedToken, | |
2363 Token::String(Token::RPAREN)); | |
2364 return factory()->NewEmptyParentheses(beg_pos); | |
2365 } else if (allow_harmony_rest_parameters() && Check(Token::ELLIPSIS)) { | |
2366 // (...x)=>x. The continuation that looks for the => is in | |
2367 // ParseAssignmentExpression. | |
2368 int ellipsis_pos = position(); | |
2369 classifier->RecordExpressionError(scanner()->location(), | |
2370 MessageTemplate::kUnexpectedToken, | |
2371 Token::String(Token::ELLIPSIS)); | |
2372 classifier->RecordNonSimpleParameter(); | |
2373 Scanner::Location expr_loc = scanner()->peek_location(); | |
2374 Token::Value tok = peek(); | |
2375 ExpressionT expr = | |
2376 this->ParseAssignmentExpression(true, classifier, CHECK_OK); | |
2377 // Patterns are not allowed as rest parameters. There is no way we can | |
2378 // succeed so go ahead and use the convenient ReportUnexpectedToken | |
2379 // interface. | |
2380 if (!Traits::IsIdentifier(expr)) { | |
2381 ReportUnexpectedTokenAt(expr_loc, tok); | |
2382 *ok = false; | |
2383 return this->EmptyExpression(); | |
2384 } | |
2385 if (peek() == Token::COMMA) { | |
2386 ReportMessageAt(scanner()->peek_location(), | |
2387 MessageTemplate::kParamAfterRest); | |
2388 *ok = false; | |
2389 return this->EmptyExpression(); | |
2390 } | |
2391 Expect(Token::RPAREN, CHECK_OK); | |
2392 return factory()->NewSpread(expr, ellipsis_pos); | |
2393 } | |
2394 // Heuristically try to detect immediately called functions before | |
2395 // seeing the call parentheses. | |
2396 parenthesized_function_ = (peek() == Token::FUNCTION); | |
2397 ExpressionT expr = this->ParseExpression(true, classifier, CHECK_OK); | |
2398 Expect(Token::RPAREN, CHECK_OK); | |
2399 return expr; | |
2400 } | |
2401 | |
2402 case Token::CLASS: { | |
2403 BindingPatternUnexpectedToken(classifier); | |
2404 Consume(Token::CLASS); | |
2405 if (!allow_harmony_sloppy() && is_sloppy(language_mode())) { | |
2406 ReportMessage(MessageTemplate::kSloppyLexical); | |
2407 *ok = false; | |
2408 return this->EmptyExpression(); | |
2409 } | |
2410 int class_token_position = position(); | |
2411 IdentifierT name = this->EmptyIdentifier(); | |
2412 bool is_strict_reserved_name = false; | |
2413 Scanner::Location class_name_location = Scanner::Location::invalid(); | |
2414 if (peek_any_identifier()) { | |
2415 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, | |
2416 CHECK_OK); | |
2417 class_name_location = scanner()->location(); | |
2418 } | |
2419 return this->ParseClassLiteral(name, class_name_location, | |
2420 is_strict_reserved_name, | |
2421 class_token_position, ok); | |
2422 } | |
2423 | |
2424 case Token::TEMPLATE_SPAN: | |
2425 case Token::TEMPLATE_TAIL: | |
2426 classifier->RecordBindingPatternError( | |
2427 scanner()->peek_location(), | |
2428 MessageTemplate::kUnexpectedTemplateString); | |
2429 return this->ParseTemplateLiteral(Traits::NoTemplateTag(), beg_pos, | |
2430 classifier, ok); | |
2431 | |
2432 case Token::MOD: | |
2433 if (allow_natives() || extension_ != NULL) { | |
2434 BindingPatternUnexpectedToken(classifier); | |
2435 return this->ParseV8Intrinsic(ok); | |
2436 } | |
2437 break; | |
2438 | |
2439 case Token::DO: | |
2440 if (allow_harmony_do_expressions()) { | |
2441 BindingPatternUnexpectedToken(classifier); | |
2442 return Traits::ParseDoExpression(ok); | |
2443 } | |
2444 break; | |
2445 | |
2446 default: | |
2447 break; | |
2448 } | |
2449 | |
2450 ReportUnexpectedToken(Next()); | |
2451 *ok = false; | |
2452 return this->EmptyExpression(); | |
2453 } | |
2454 | |
2455 | |
2456 template <class Traits> | |
2457 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( | |
2458 bool accept_IN, bool* ok) { | |
2459 ExpressionClassifier classifier; | |
2460 ExpressionT result = ParseExpression(accept_IN, &classifier, CHECK_OK); | |
2461 ValidateExpression(&classifier, CHECK_OK); | |
2462 return result; | |
2463 } | |
2464 | |
2465 | |
2466 // Precedence = 1 | |
2467 template <class Traits> | |
2468 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( | |
2469 bool accept_IN, ExpressionClassifier* classifier, bool* ok) { | |
2470 // Expression :: | |
2471 // AssignmentExpression | |
2472 // Expression ',' AssignmentExpression | |
2473 | |
2474 ExpressionClassifier binding_classifier; | |
2475 ExpressionT result = | |
2476 this->ParseAssignmentExpression(accept_IN, &binding_classifier, CHECK_OK); | |
2477 classifier->Accumulate(binding_classifier, | |
2478 ExpressionClassifier::AllProductions); | |
2479 bool is_simple_parameter_list = this->IsIdentifier(result); | |
2480 bool seen_rest = false; | |
2481 while (peek() == Token::COMMA) { | |
2482 if (seen_rest) { | |
2483 // At this point the production can't possibly be valid, but we don't know | |
2484 // which error to signal. | |
2485 classifier->RecordArrowFormalParametersError( | |
2486 scanner()->peek_location(), MessageTemplate::kParamAfterRest); | |
2487 } | |
2488 Consume(Token::COMMA); | |
2489 bool is_rest = false; | |
2490 if (allow_harmony_rest_parameters() && peek() == Token::ELLIPSIS) { | |
2491 // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only | |
2492 // as the formal parameters of'(x, y, ...z) => foo', and is not itself a | |
2493 // valid expression or binding pattern. | |
2494 ExpressionUnexpectedToken(classifier); | |
2495 BindingPatternUnexpectedToken(classifier); | |
2496 Consume(Token::ELLIPSIS); | |
2497 seen_rest = is_rest = true; | |
2498 } | |
2499 int pos = position(); | |
2500 ExpressionT right = this->ParseAssignmentExpression( | |
2501 accept_IN, &binding_classifier, CHECK_OK); | |
2502 if (is_rest) right = factory()->NewSpread(right, pos); | |
2503 is_simple_parameter_list = | |
2504 is_simple_parameter_list && this->IsIdentifier(right); | |
2505 classifier->Accumulate(binding_classifier, | |
2506 ExpressionClassifier::AllProductions); | |
2507 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos); | |
2508 } | |
2509 if (!is_simple_parameter_list || seen_rest) { | |
2510 classifier->RecordNonSimpleParameter(); | |
2511 } | |
2512 return result; | |
2513 } | |
2514 | |
2515 | |
2516 template <class Traits> | |
2517 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral( | |
2518 ExpressionClassifier* classifier, bool* ok) { | |
2519 // ArrayLiteral :: | |
2520 // '[' Expression? (',' Expression?)* ']' | |
2521 | |
2522 int pos = peek_position(); | |
2523 typename Traits::Type::ExpressionList values = | |
2524 this->NewExpressionList(4, zone_); | |
2525 int first_spread_index = -1; | |
2526 Expect(Token::LBRACK, CHECK_OK); | |
2527 while (peek() != Token::RBRACK) { | |
2528 bool seen_spread = false; | |
2529 ExpressionT elem = this->EmptyExpression(); | |
2530 if (peek() == Token::COMMA) { | |
2531 if (is_strong(language_mode())) { | |
2532 ReportMessageAt(scanner()->peek_location(), | |
2533 MessageTemplate::kStrongEllision); | |
2534 *ok = false; | |
2535 return this->EmptyExpression(); | |
2536 } | |
2537 elem = this->GetLiteralTheHole(peek_position(), factory()); | |
2538 } else if (peek() == Token::ELLIPSIS) { | |
2539 int start_pos = peek_position(); | |
2540 Consume(Token::ELLIPSIS); | |
2541 ExpressionT argument = | |
2542 this->ParseAssignmentExpression(true, classifier, CHECK_OK); | |
2543 elem = factory()->NewSpread(argument, start_pos); | |
2544 seen_spread = true; | |
2545 if (first_spread_index < 0) { | |
2546 first_spread_index = values->length(); | |
2547 } | |
2548 } else { | |
2549 elem = this->ParseAssignmentExpression(true, classifier, CHECK_OK); | |
2550 } | |
2551 values->Add(elem, zone_); | |
2552 if (peek() != Token::RBRACK) { | |
2553 if (seen_spread) { | |
2554 BindingPatternUnexpectedToken(classifier); | |
2555 } | |
2556 Expect(Token::COMMA, CHECK_OK); | |
2557 } | |
2558 } | |
2559 Expect(Token::RBRACK, CHECK_OK); | |
2560 | |
2561 // Update the scope information before the pre-parsing bailout. | |
2562 int literal_index = function_state_->NextMaterializedLiteralIndex(); | |
2563 | |
2564 return factory()->NewArrayLiteral(values, first_spread_index, literal_index, | |
2565 is_strong(language_mode()), pos); | |
2566 } | |
2567 | |
2568 | |
2569 template <class Traits> | |
2570 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName( | |
2571 IdentifierT* name, bool* is_get, bool* is_set, bool* is_static, | |
2572 bool* is_computed_name, bool* is_identifier, bool* is_escaped_keyword, | |
2573 ExpressionClassifier* classifier, bool* ok) { | |
2574 Token::Value token = peek(); | |
2575 int pos = peek_position(); | |
2576 | |
2577 // For non computed property names we normalize the name a bit: | |
2578 // | |
2579 // "12" -> 12 | |
2580 // 12.3 -> "12.3" | |
2581 // 12.30 -> "12.3" | |
2582 // identifier -> "identifier" | |
2583 // | |
2584 // This is important because we use the property name as a key in a hash | |
2585 // table when we compute constant properties. | |
2586 switch (token) { | |
2587 case Token::STRING: | |
2588 Consume(Token::STRING); | |
2589 *name = this->GetSymbol(scanner()); | |
2590 break; | |
2591 | |
2592 case Token::SMI: | |
2593 Consume(Token::SMI); | |
2594 *name = this->GetNumberAsSymbol(scanner()); | |
2595 break; | |
2596 | |
2597 case Token::NUMBER: | |
2598 Consume(Token::NUMBER); | |
2599 *name = this->GetNumberAsSymbol(scanner()); | |
2600 break; | |
2601 | |
2602 case Token::LBRACK: { | |
2603 *is_computed_name = true; | |
2604 Consume(Token::LBRACK); | |
2605 ExpressionClassifier computed_name_classifier; | |
2606 ExpressionT expression = | |
2607 ParseAssignmentExpression(true, &computed_name_classifier, CHECK_OK); | |
2608 classifier->Accumulate(computed_name_classifier, | |
2609 ExpressionClassifier::ExpressionProductions); | |
2610 Expect(Token::RBRACK, CHECK_OK); | |
2611 return expression; | |
2612 } | |
2613 | |
2614 case Token::ESCAPED_KEYWORD: | |
2615 *is_escaped_keyword = true; | |
2616 *name = ParseIdentifierNameOrGetOrSet(is_get, is_set, CHECK_OK); | |
2617 break; | |
2618 | |
2619 case Token::STATIC: | |
2620 *is_static = true; | |
2621 | |
2622 // Fall through. | |
2623 default: | |
2624 *is_identifier = true; | |
2625 *name = ParseIdentifierNameOrGetOrSet(is_get, is_set, CHECK_OK); | |
2626 break; | |
2627 } | |
2628 | |
2629 uint32_t index; | |
2630 return this->IsArrayIndex(*name, &index) | |
2631 ? factory()->NewNumberLiteral(index, pos) | |
2632 : factory()->NewStringLiteral(*name, pos); | |
2633 } | |
2634 | |
2635 | |
2636 template <class Traits> | |
2637 typename ParserBase<Traits>::ObjectLiteralPropertyT | |
2638 ParserBase<Traits>::ParsePropertyDefinition( | |
2639 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, | |
2640 bool is_static, bool* is_computed_name, bool* has_seen_constructor, | |
2641 ExpressionClassifier* classifier, bool* ok) { | |
2642 DCHECK(!in_class || is_static || has_seen_constructor != nullptr); | |
2643 ExpressionT value = this->EmptyExpression(); | |
2644 IdentifierT name = this->EmptyIdentifier(); | |
2645 bool is_get = false; | |
2646 bool is_set = false; | |
2647 bool name_is_static = false; | |
2648 bool is_generator = Check(Token::MUL); | |
2649 | |
2650 Token::Value name_token = peek(); | |
2651 int next_beg_pos = scanner()->peek_location().beg_pos; | |
2652 int next_end_pos = scanner()->peek_location().end_pos; | |
2653 bool is_identifier = false; | |
2654 bool is_escaped_keyword = false; | |
2655 ExpressionT name_expression = ParsePropertyName( | |
2656 &name, &is_get, &is_set, &name_is_static, is_computed_name, | |
2657 &is_identifier, &is_escaped_keyword, classifier, | |
2658 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2659 | |
2660 if (fni_ != nullptr && !*is_computed_name) { | |
2661 this->PushLiteralName(fni_, name); | |
2662 } | |
2663 | |
2664 bool escaped_static = | |
2665 is_escaped_keyword && | |
2666 scanner()->is_literal_contextual_keyword(CStrVector("static")); | |
2667 | |
2668 if (!in_class && !is_generator) { | |
2669 DCHECK(!is_static); | |
2670 | |
2671 if (peek() == Token::COLON) { | |
2672 // PropertyDefinition | |
2673 // PropertyName ':' AssignmentExpression | |
2674 if (!*is_computed_name) { | |
2675 checker->CheckProperty(name_token, kValueProperty, false, false, | |
2676 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2677 } | |
2678 Consume(Token::COLON); | |
2679 value = this->ParseAssignmentExpression( | |
2680 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2681 return factory()->NewObjectLiteralProperty(name_expression, value, false, | |
2682 *is_computed_name); | |
2683 } | |
2684 | |
2685 if ((is_identifier || is_escaped_keyword) && | |
2686 (peek() == Token::COMMA || peek() == Token::RBRACE || | |
2687 peek() == Token::ASSIGN)) { | |
2688 // PropertyDefinition | |
2689 // IdentifierReference | |
2690 // CoverInitializedName | |
2691 // | |
2692 // CoverInitializedName | |
2693 // IdentifierReference Initializer? | |
2694 if (!Token::IsIdentifier(name_token, language_mode(), | |
2695 this->is_generator())) { | |
2696 if (!escaped_static) { | |
2697 ReportUnexpectedTokenAt(scanner()->location(), name_token); | |
2698 *ok = false; | |
2699 return this->EmptyObjectLiteralProperty(); | |
2700 } | |
2701 } | |
2702 if (classifier->duplicate_finder() != nullptr && | |
2703 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { | |
2704 classifier->RecordDuplicateFormalParameterError(scanner()->location()); | |
2705 } | |
2706 if (name_token == Token::LET) { | |
2707 classifier->RecordLetPatternError( | |
2708 scanner()->location(), MessageTemplate::kLetInLexicalBinding); | |
2709 } | |
2710 | |
2711 ExpressionT lhs = this->ExpressionFromIdentifier( | |
2712 name, next_beg_pos, next_end_pos, scope_, factory()); | |
2713 | |
2714 if (peek() == Token::ASSIGN) { | |
2715 this->ExpressionUnexpectedToken(classifier); | |
2716 Consume(Token::ASSIGN); | |
2717 ExpressionClassifier rhs_classifier; | |
2718 ExpressionT rhs = this->ParseAssignmentExpression( | |
2719 true, &rhs_classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2720 classifier->Accumulate(rhs_classifier, | |
2721 ExpressionClassifier::ExpressionProductions); | |
2722 value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs, | |
2723 RelocInfo::kNoPosition); | |
2724 } else { | |
2725 value = lhs; | |
2726 } | |
2727 | |
2728 return factory()->NewObjectLiteralProperty( | |
2729 name_expression, value, ObjectLiteralProperty::COMPUTED, false, | |
2730 false); | |
2731 } | |
2732 } | |
2733 | |
2734 if (in_class && escaped_static && !is_static) { | |
2735 ReportUnexpectedTokenAt(scanner()->location(), name_token); | |
2736 *ok = false; | |
2737 return this->EmptyObjectLiteralProperty(); | |
2738 } | |
2739 | |
2740 if (is_generator || peek() == Token::LPAREN) { | |
2741 // MethodDefinition | |
2742 // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | |
2743 // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' | |
2744 if (!*is_computed_name) { | |
2745 checker->CheckProperty(name_token, kMethodProperty, is_static, | |
2746 is_generator, | |
2747 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2748 } | |
2749 | |
2750 FunctionKind kind = is_generator ? FunctionKind::kConciseGeneratorMethod | |
2751 : FunctionKind::kConciseMethod; | |
2752 | |
2753 if (in_class && !is_static && this->IsConstructor(name)) { | |
2754 *has_seen_constructor = true; | |
2755 kind = has_extends ? FunctionKind::kSubclassConstructor | |
2756 : FunctionKind::kBaseConstructor; | |
2757 } | |
2758 | |
2759 if (!in_class) kind = WithObjectLiteralBit(kind); | |
2760 | |
2761 value = this->ParseFunctionLiteral( | |
2762 name, scanner()->location(), kSkipFunctionNameCheck, kind, | |
2763 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, | |
2764 FunctionLiteral::NORMAL_ARITY, language_mode(), | |
2765 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2766 | |
2767 return factory()->NewObjectLiteralProperty(name_expression, value, | |
2768 ObjectLiteralProperty::COMPUTED, | |
2769 is_static, *is_computed_name); | |
2770 } | |
2771 | |
2772 if (in_class && name_is_static && !is_static) { | |
2773 // ClassElement (static) | |
2774 // 'static' MethodDefinition | |
2775 return ParsePropertyDefinition(checker, true, has_extends, true, | |
2776 is_computed_name, nullptr, classifier, ok); | |
2777 } | |
2778 | |
2779 if (is_get || is_set) { | |
2780 // MethodDefinition (Accessors) | |
2781 // get PropertyName '(' ')' '{' FunctionBody '}' | |
2782 // set PropertyName '(' PropertySetParameterList ')' '{' FunctionBody '}' | |
2783 name = this->EmptyIdentifier(); | |
2784 bool dont_care = false; | |
2785 name_token = peek(); | |
2786 | |
2787 name_expression = ParsePropertyName( | |
2788 &name, &dont_care, &dont_care, &dont_care, is_computed_name, &dont_care, | |
2789 &dont_care, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2790 | |
2791 if (!*is_computed_name) { | |
2792 checker->CheckProperty(name_token, kAccessorProperty, is_static, | |
2793 is_generator, | |
2794 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2795 } | |
2796 | |
2797 FunctionKind kind = FunctionKind::kAccessorFunction; | |
2798 if (!in_class) kind = WithObjectLiteralBit(kind); | |
2799 typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral( | |
2800 name, scanner()->location(), kSkipFunctionNameCheck, kind, | |
2801 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, | |
2802 is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY, | |
2803 language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
2804 | |
2805 // Make sure the name expression is a string since we need a Name for | |
2806 // Runtime_DefineAccessorPropertyUnchecked and since we can determine this | |
2807 // statically we can skip the extra runtime check. | |
2808 if (!*is_computed_name) { | |
2809 name_expression = | |
2810 factory()->NewStringLiteral(name, name_expression->position()); | |
2811 } | |
2812 | |
2813 return factory()->NewObjectLiteralProperty( | |
2814 name_expression, value, | |
2815 is_get ? ObjectLiteralProperty::GETTER : ObjectLiteralProperty::SETTER, | |
2816 is_static, *is_computed_name); | |
2817 } | |
2818 | |
2819 Token::Value next = Next(); | |
2820 ReportUnexpectedToken(next); | |
2821 *ok = false; | |
2822 return this->EmptyObjectLiteralProperty(); | |
2823 } | |
2824 | |
2825 | |
2826 template <class Traits> | |
2827 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral( | |
2828 ExpressionClassifier* classifier, bool* ok) { | |
2829 // ObjectLiteral :: | |
2830 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' | |
2831 | |
2832 int pos = peek_position(); | |
2833 typename Traits::Type::PropertyList properties = | |
2834 this->NewPropertyList(4, zone_); | |
2835 int number_of_boilerplate_properties = 0; | |
2836 bool has_function = false; | |
2837 bool has_computed_names = false; | |
2838 ObjectLiteralChecker checker(this); | |
2839 | |
2840 Expect(Token::LBRACE, CHECK_OK); | |
2841 | |
2842 while (peek() != Token::RBRACE) { | |
2843 if (fni_ != nullptr) fni_->Enter(); | |
2844 | |
2845 const bool in_class = false; | |
2846 const bool is_static = false; | |
2847 const bool has_extends = false; | |
2848 bool is_computed_name = false; | |
2849 ObjectLiteralPropertyT property = this->ParsePropertyDefinition( | |
2850 &checker, in_class, has_extends, is_static, &is_computed_name, NULL, | |
2851 classifier, CHECK_OK); | |
2852 | |
2853 if (is_computed_name) { | |
2854 has_computed_names = true; | |
2855 } | |
2856 | |
2857 // Mark top-level object literals that contain function literals and | |
2858 // pretenure the literal so it can be added as a constant function | |
2859 // property. (Parser only.) | |
2860 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, property, | |
2861 &has_function); | |
2862 | |
2863 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | |
2864 if (!has_computed_names && this->IsBoilerplateProperty(property)) { | |
2865 number_of_boilerplate_properties++; | |
2866 } | |
2867 properties->Add(property, zone()); | |
2868 | |
2869 if (peek() != Token::RBRACE) { | |
2870 // Need {} because of the CHECK_OK macro. | |
2871 Expect(Token::COMMA, CHECK_OK); | |
2872 } | |
2873 | |
2874 if (fni_ != nullptr) { | |
2875 fni_->Infer(); | |
2876 fni_->Leave(); | |
2877 } | |
2878 } | |
2879 Expect(Token::RBRACE, CHECK_OK); | |
2880 | |
2881 // Computation of literal_index must happen before pre parse bailout. | |
2882 int literal_index = function_state_->NextMaterializedLiteralIndex(); | |
2883 | |
2884 return factory()->NewObjectLiteral(properties, | |
2885 literal_index, | |
2886 number_of_boilerplate_properties, | |
2887 has_function, | |
2888 is_strong(language_mode()), | |
2889 pos); | |
2890 } | |
2891 | |
2892 | |
2893 template <class Traits> | |
2894 typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments( | |
2895 Scanner::Location* first_spread_arg_loc, ExpressionClassifier* classifier, | |
2896 bool* ok) { | |
2897 // Arguments :: | |
2898 // '(' (AssignmentExpression)*[','] ')' | |
2899 | |
2900 Scanner::Location spread_arg = Scanner::Location::invalid(); | |
2901 typename Traits::Type::ExpressionList result = | |
2902 this->NewExpressionList(4, zone_); | |
2903 Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList)); | |
2904 bool done = (peek() == Token::RPAREN); | |
2905 bool was_unspread = false; | |
2906 int unspread_sequences_count = 0; | |
2907 while (!done) { | |
2908 int start_pos = peek_position(); | |
2909 bool is_spread = Check(Token::ELLIPSIS); | |
2910 | |
2911 ExpressionT argument = this->ParseAssignmentExpression( | |
2912 true, classifier, CHECK_OK_CUSTOM(NullExpressionList)); | |
2913 if (is_spread) { | |
2914 if (!spread_arg.IsValid()) { | |
2915 spread_arg.beg_pos = start_pos; | |
2916 spread_arg.end_pos = peek_position(); | |
2917 } | |
2918 argument = factory()->NewSpread(argument, start_pos); | |
2919 } | |
2920 result->Add(argument, zone_); | |
2921 | |
2922 // unspread_sequences_count is the number of sequences of parameters which | |
2923 // are not prefixed with a spread '...' operator. | |
2924 if (is_spread) { | |
2925 was_unspread = false; | |
2926 } else if (!was_unspread) { | |
2927 was_unspread = true; | |
2928 unspread_sequences_count++; | |
2929 } | |
2930 | |
2931 if (result->length() > Code::kMaxArguments) { | |
2932 ReportMessage(MessageTemplate::kTooManyArguments); | |
2933 *ok = false; | |
2934 return this->NullExpressionList(); | |
2935 } | |
2936 done = (peek() != Token::COMMA); | |
2937 if (!done) { | |
2938 Next(); | |
2939 } | |
2940 } | |
2941 Scanner::Location location = scanner_->location(); | |
2942 if (Token::RPAREN != Next()) { | |
2943 ReportMessageAt(location, MessageTemplate::kUnterminatedArgList); | |
2944 *ok = false; | |
2945 return this->NullExpressionList(); | |
2946 } | |
2947 *first_spread_arg_loc = spread_arg; | |
2948 | |
2949 if (spread_arg.IsValid()) { | |
2950 // Unspread parameter sequences are translated into array literals in the | |
2951 // parser. Ensure that the number of materialized literals matches between | |
2952 // the parser and preparser | |
2953 Traits::MaterializeUnspreadArgumentsLiterals(unspread_sequences_count); | |
2954 } | |
2955 | |
2956 return result; | |
2957 } | |
2958 | |
2959 // Precedence = 2 | |
2960 template <class Traits> | |
2961 typename ParserBase<Traits>::ExpressionT | |
2962 ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, | |
2963 ExpressionClassifier* classifier, | |
2964 bool* ok) { | |
2965 // AssignmentExpression :: | |
2966 // ConditionalExpression | |
2967 // ArrowFunction | |
2968 // YieldExpression | |
2969 // LeftHandSideExpression AssignmentOperator AssignmentExpression | |
2970 | |
2971 int lhs_beg_pos = peek_position(); | |
2972 | |
2973 if (peek() == Token::YIELD && is_generator()) { | |
2974 return this->ParseYieldExpression(classifier, ok); | |
2975 } | |
2976 | |
2977 if (fni_ != NULL) fni_->Enter(); | |
2978 ParserBase<Traits>::Checkpoint checkpoint(this); | |
2979 ExpressionClassifier arrow_formals_classifier(classifier->duplicate_finder()); | |
2980 bool parenthesized_formals = peek() == Token::LPAREN; | |
2981 if (!parenthesized_formals) { | |
2982 ArrowFormalParametersUnexpectedToken(&arrow_formals_classifier); | |
2983 } | |
2984 ExpressionT expression = this->ParseConditionalExpression( | |
2985 accept_IN, &arrow_formals_classifier, CHECK_OK); | |
2986 if (peek() == Token::ARROW) { | |
2987 BindingPatternUnexpectedToken(classifier); | |
2988 ValidateArrowFormalParameters(&arrow_formals_classifier, expression, | |
2989 parenthesized_formals, CHECK_OK); | |
2990 Scanner::Location loc(lhs_beg_pos, scanner()->location().end_pos); | |
2991 Scope* scope = | |
2992 this->NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction); | |
2993 // Because the arrow's parameters were parsed in the outer scope, any | |
2994 // usage flags that might have been triggered there need to be copied | |
2995 // to the arrow scope. | |
2996 scope_->PropagateUsageFlagsToScope(scope); | |
2997 FormalParametersT parameters(scope); | |
2998 if (!arrow_formals_classifier.is_simple_parameter_list()) { | |
2999 scope->SetHasNonSimpleParameters(); | |
3000 parameters.is_simple = false; | |
3001 } | |
3002 | |
3003 Scanner::Location duplicate_loc = Scanner::Location::invalid(); | |
3004 this->ParseArrowFunctionFormalParameterList(¶meters, expression, loc, | |
3005 &duplicate_loc, CHECK_OK); | |
3006 | |
3007 checkpoint.Restore(¶meters.materialized_literals_count); | |
3008 | |
3009 scope->set_start_position(lhs_beg_pos); | |
3010 if (duplicate_loc.IsValid()) { | |
3011 arrow_formals_classifier.RecordDuplicateFormalParameterError( | |
3012 duplicate_loc); | |
3013 } | |
3014 expression = this->ParseArrowFunctionLiteral( | |
3015 accept_IN, parameters, arrow_formals_classifier, CHECK_OK); | |
3016 return expression; | |
3017 } | |
3018 | |
3019 // "expression" was not itself an arrow function parameter list, but it might | |
3020 // form part of one. Propagate speculative formal parameter error locations. | |
3021 classifier->Accumulate(arrow_formals_classifier, | |
3022 ExpressionClassifier::StandardProductions | | |
3023 ExpressionClassifier::FormalParametersProductions); | |
3024 | |
3025 if (!Token::IsAssignmentOp(peek())) { | |
3026 if (fni_ != NULL) fni_->Leave(); | |
3027 // Parsed conditional expression only (no assignment). | |
3028 return expression; | |
3029 } | |
3030 | |
3031 if (!(allow_harmony_destructuring_bind() || | |
3032 allow_harmony_default_parameters())) { | |
3033 BindingPatternUnexpectedToken(classifier); | |
3034 } | |
3035 | |
3036 expression = this->CheckAndRewriteReferenceExpression( | |
3037 expression, lhs_beg_pos, scanner()->location().end_pos, | |
3038 MessageTemplate::kInvalidLhsInAssignment, CHECK_OK); | |
3039 expression = this->MarkExpressionAsAssigned(expression); | |
3040 | |
3041 Token::Value op = Next(); // Get assignment operator. | |
3042 if (op != Token::ASSIGN) { | |
3043 classifier->RecordBindingPatternError(scanner()->location(), | |
3044 MessageTemplate::kUnexpectedToken, | |
3045 Token::String(op)); | |
3046 } | |
3047 int pos = position(); | |
3048 | |
3049 ExpressionClassifier rhs_classifier; | |
3050 ExpressionT right = | |
3051 this->ParseAssignmentExpression(accept_IN, &rhs_classifier, CHECK_OK); | |
3052 classifier->Accumulate(rhs_classifier, | |
3053 ExpressionClassifier::ExpressionProductions); | |
3054 | |
3055 // TODO(1231235): We try to estimate the set of properties set by | |
3056 // constructors. We define a new property whenever there is an | |
3057 // assignment to a property of 'this'. We should probably only add | |
3058 // properties if we haven't seen them before. Otherwise we'll | |
3059 // probably overestimate the number of properties. | |
3060 if (op == Token::ASSIGN && this->IsThisProperty(expression)) { | |
3061 function_state_->AddProperty(); | |
3062 } | |
3063 | |
3064 this->CheckAssigningFunctionLiteralToProperty(expression, right); | |
3065 | |
3066 if (fni_ != NULL) { | |
3067 // Check if the right hand side is a call to avoid inferring a | |
3068 // name if we're dealing with "a = function(){...}();"-like | |
3069 // expression. | |
3070 if ((op == Token::INIT || op == Token::ASSIGN) && | |
3071 (!right->IsCall() && !right->IsCallNew())) { | |
3072 fni_->Infer(); | |
3073 } else { | |
3074 fni_->RemoveLastFunction(); | |
3075 } | |
3076 fni_->Leave(); | |
3077 } | |
3078 | |
3079 return factory()->NewAssignment(op, expression, right, pos); | |
3080 } | |
3081 | |
3082 template <class Traits> | |
3083 typename ParserBase<Traits>::ExpressionT | |
3084 ParserBase<Traits>::ParseYieldExpression(ExpressionClassifier* classifier, | |
3085 bool* ok) { | |
3086 // YieldExpression :: | |
3087 // 'yield' ([no line terminator] '*'? AssignmentExpression)? | |
3088 int pos = peek_position(); | |
3089 BindingPatternUnexpectedToken(classifier); | |
3090 FormalParameterInitializerUnexpectedToken(classifier); | |
3091 Expect(Token::YIELD, CHECK_OK); | |
3092 ExpressionT generator_object = | |
3093 factory()->NewVariableProxy(function_state_->generator_object_variable()); | |
3094 ExpressionT expression = Traits::EmptyExpression(); | |
3095 Yield::Kind kind = Yield::kSuspend; | |
3096 if (!scanner()->HasAnyLineTerminatorBeforeNext()) { | |
3097 if (Check(Token::MUL)) kind = Yield::kDelegating; | |
3098 switch (peek()) { | |
3099 case Token::EOS: | |
3100 case Token::SEMICOLON: | |
3101 case Token::RBRACE: | |
3102 case Token::RBRACK: | |
3103 case Token::RPAREN: | |
3104 case Token::COLON: | |
3105 case Token::COMMA: | |
3106 // The above set of tokens is the complete set of tokens that can appear | |
3107 // after an AssignmentExpression, and none of them can start an | |
3108 // AssignmentExpression. This allows us to avoid looking for an RHS for | |
3109 // a Yield::kSuspend operation, given only one look-ahead token. | |
3110 if (kind == Yield::kSuspend) | |
3111 break; | |
3112 DCHECK_EQ(Yield::kDelegating, kind); | |
3113 // Delegating yields require an RHS; fall through. | |
3114 default: | |
3115 expression = ParseAssignmentExpression(false, classifier, CHECK_OK); | |
3116 break; | |
3117 } | |
3118 } | |
3119 if (kind == Yield::kDelegating) { | |
3120 // var iterator = subject[Symbol.iterator](); | |
3121 expression = this->GetIterator(expression, factory()); | |
3122 } | |
3123 typename Traits::Type::YieldExpression yield = | |
3124 factory()->NewYield(generator_object, expression, kind, pos); | |
3125 return yield; | |
3126 } | |
3127 | |
3128 | |
3129 // Precedence = 3 | |
3130 template <class Traits> | |
3131 typename ParserBase<Traits>::ExpressionT | |
3132 ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, | |
3133 ExpressionClassifier* classifier, | |
3134 bool* ok) { | |
3135 // ConditionalExpression :: | |
3136 // LogicalOrExpression | |
3137 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression | |
3138 | |
3139 int pos = peek_position(); | |
3140 // We start using the binary expression parser for prec >= 4 only! | |
3141 ExpressionT expression = | |
3142 this->ParseBinaryExpression(4, accept_IN, classifier, CHECK_OK); | |
3143 if (peek() != Token::CONDITIONAL) return expression; | |
3144 ArrowFormalParametersUnexpectedToken(classifier); | |
3145 BindingPatternUnexpectedToken(classifier); | |
3146 Consume(Token::CONDITIONAL); | |
3147 // In parsing the first assignment expression in conditional | |
3148 // expressions we always accept the 'in' keyword; see ECMA-262, | |
3149 // section 11.12, page 58. | |
3150 ExpressionT left = ParseAssignmentExpression(true, classifier, CHECK_OK); | |
3151 Expect(Token::COLON, CHECK_OK); | |
3152 ExpressionT right = | |
3153 ParseAssignmentExpression(accept_IN, classifier, CHECK_OK); | |
3154 return factory()->NewConditional(expression, left, right, pos); | |
3155 } | |
3156 | |
3157 | |
3158 // Precedence >= 4 | |
3159 template <class Traits> | |
3160 typename ParserBase<Traits>::ExpressionT | |
3161 ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, | |
3162 ExpressionClassifier* classifier, | |
3163 bool* ok) { | |
3164 DCHECK(prec >= 4); | |
3165 ExpressionT x = this->ParseUnaryExpression(classifier, CHECK_OK); | |
3166 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { | |
3167 // prec1 >= 4 | |
3168 while (Precedence(peek(), accept_IN) == prec1) { | |
3169 BindingPatternUnexpectedToken(classifier); | |
3170 ArrowFormalParametersUnexpectedToken(classifier); | |
3171 Token::Value op = Next(); | |
3172 Scanner::Location op_location = scanner()->location(); | |
3173 int pos = position(); | |
3174 ExpressionT y = | |
3175 ParseBinaryExpression(prec1 + 1, accept_IN, classifier, CHECK_OK); | |
3176 | |
3177 if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos, | |
3178 factory())) { | |
3179 continue; | |
3180 } | |
3181 | |
3182 // For now we distinguish between comparisons and other binary | |
3183 // operations. (We could combine the two and get rid of this | |
3184 // code and AST node eventually.) | |
3185 if (Token::IsCompareOp(op)) { | |
3186 // We have a comparison. | |
3187 Token::Value cmp = op; | |
3188 switch (op) { | |
3189 case Token::NE: cmp = Token::EQ; break; | |
3190 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break; | |
3191 default: break; | |
3192 } | |
3193 if (cmp == Token::EQ && is_strong(language_mode())) { | |
3194 ReportMessageAt(op_location, MessageTemplate::kStrongEqual); | |
3195 *ok = false; | |
3196 return this->EmptyExpression(); | |
3197 } | |
3198 x = factory()->NewCompareOperation(cmp, x, y, pos); | |
3199 if (cmp != op) { | |
3200 // The comparison was negated - add a NOT. | |
3201 x = factory()->NewUnaryOperation(Token::NOT, x, pos); | |
3202 } | |
3203 | |
3204 } else { | |
3205 // We have a "normal" binary operation. | |
3206 x = factory()->NewBinaryOperation(op, x, y, pos); | |
3207 } | |
3208 } | |
3209 } | |
3210 return x; | |
3211 } | |
3212 | |
3213 | |
3214 template <class Traits> | |
3215 typename ParserBase<Traits>::ExpressionT | |
3216 ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier, | |
3217 bool* ok) { | |
3218 // UnaryExpression :: | |
3219 // PostfixExpression | |
3220 // 'delete' UnaryExpression | |
3221 // 'void' UnaryExpression | |
3222 // 'typeof' UnaryExpression | |
3223 // '++' UnaryExpression | |
3224 // '--' UnaryExpression | |
3225 // '+' UnaryExpression | |
3226 // '-' UnaryExpression | |
3227 // '~' UnaryExpression | |
3228 // '!' UnaryExpression | |
3229 | |
3230 Token::Value op = peek(); | |
3231 if (Token::IsUnaryOp(op)) { | |
3232 BindingPatternUnexpectedToken(classifier); | |
3233 ArrowFormalParametersUnexpectedToken(classifier); | |
3234 | |
3235 op = Next(); | |
3236 int pos = position(); | |
3237 ExpressionT expression = ParseUnaryExpression(classifier, CHECK_OK); | |
3238 | |
3239 if (op == Token::DELETE && is_strict(language_mode())) { | |
3240 if (is_strong(language_mode())) { | |
3241 ReportMessage(MessageTemplate::kStrongDelete); | |
3242 *ok = false; | |
3243 return this->EmptyExpression(); | |
3244 } else if (this->IsIdentifier(expression)) { | |
3245 // "delete identifier" is a syntax error in strict mode. | |
3246 ReportMessage(MessageTemplate::kStrictDelete); | |
3247 *ok = false; | |
3248 return this->EmptyExpression(); | |
3249 } | |
3250 } | |
3251 | |
3252 // Allow Traits do rewrite the expression. | |
3253 return this->BuildUnaryExpression(expression, op, pos, factory()); | |
3254 } else if (Token::IsCountOp(op)) { | |
3255 BindingPatternUnexpectedToken(classifier); | |
3256 ArrowFormalParametersUnexpectedToken(classifier); | |
3257 op = Next(); | |
3258 int beg_pos = peek_position(); | |
3259 ExpressionT expression = this->ParseUnaryExpression(classifier, CHECK_OK); | |
3260 expression = this->CheckAndRewriteReferenceExpression( | |
3261 expression, beg_pos, scanner()->location().end_pos, | |
3262 MessageTemplate::kInvalidLhsInPrefixOp, CHECK_OK); | |
3263 this->MarkExpressionAsAssigned(expression); | |
3264 | |
3265 return factory()->NewCountOperation(op, | |
3266 true /* prefix */, | |
3267 expression, | |
3268 position()); | |
3269 | |
3270 } else { | |
3271 return this->ParsePostfixExpression(classifier, ok); | |
3272 } | |
3273 } | |
3274 | |
3275 | |
3276 template <class Traits> | |
3277 typename ParserBase<Traits>::ExpressionT | |
3278 ParserBase<Traits>::ParsePostfixExpression(ExpressionClassifier* classifier, | |
3279 bool* ok) { | |
3280 // PostfixExpression :: | |
3281 // LeftHandSideExpression ('++' | '--')? | |
3282 | |
3283 int lhs_beg_pos = peek_position(); | |
3284 ExpressionT expression = | |
3285 this->ParseLeftHandSideExpression(classifier, CHECK_OK); | |
3286 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | |
3287 Token::IsCountOp(peek())) { | |
3288 BindingPatternUnexpectedToken(classifier); | |
3289 ArrowFormalParametersUnexpectedToken(classifier); | |
3290 | |
3291 expression = this->CheckAndRewriteReferenceExpression( | |
3292 expression, lhs_beg_pos, scanner()->location().end_pos, | |
3293 MessageTemplate::kInvalidLhsInPostfixOp, CHECK_OK); | |
3294 expression = this->MarkExpressionAsAssigned(expression); | |
3295 | |
3296 Token::Value next = Next(); | |
3297 expression = | |
3298 factory()->NewCountOperation(next, | |
3299 false /* postfix */, | |
3300 expression, | |
3301 position()); | |
3302 } | |
3303 return expression; | |
3304 } | |
3305 | |
3306 | |
3307 template <class Traits> | |
3308 typename ParserBase<Traits>::ExpressionT | |
3309 ParserBase<Traits>::ParseLeftHandSideExpression( | |
3310 ExpressionClassifier* classifier, bool* ok) { | |
3311 // LeftHandSideExpression :: | |
3312 // (NewExpression | MemberExpression) ... | |
3313 | |
3314 ExpressionT result = | |
3315 this->ParseMemberWithNewPrefixesExpression(classifier, CHECK_OK); | |
3316 | |
3317 while (true) { | |
3318 switch (peek()) { | |
3319 case Token::LBRACK: { | |
3320 BindingPatternUnexpectedToken(classifier); | |
3321 ArrowFormalParametersUnexpectedToken(classifier); | |
3322 Consume(Token::LBRACK); | |
3323 int pos = position(); | |
3324 ExpressionT index = ParseExpression(true, classifier, CHECK_OK); | |
3325 result = factory()->NewProperty(result, index, pos); | |
3326 Expect(Token::RBRACK, CHECK_OK); | |
3327 break; | |
3328 } | |
3329 | |
3330 case Token::LPAREN: { | |
3331 BindingPatternUnexpectedToken(classifier); | |
3332 ArrowFormalParametersUnexpectedToken(classifier); | |
3333 | |
3334 if (is_strong(language_mode()) && this->IsIdentifier(result) && | |
3335 this->IsEval(this->AsIdentifier(result))) { | |
3336 ReportMessage(MessageTemplate::kStrongDirectEval); | |
3337 *ok = false; | |
3338 return this->EmptyExpression(); | |
3339 } | |
3340 int pos; | |
3341 if (scanner()->current_token() == Token::IDENTIFIER || | |
3342 scanner()->current_token() == Token::SUPER) { | |
3343 // For call of an identifier we want to report position of | |
3344 // the identifier as position of the call in the stack trace. | |
3345 pos = position(); | |
3346 } else { | |
3347 // For other kinds of calls we record position of the parenthesis as | |
3348 // position of the call. Note that this is extremely important for | |
3349 // expressions of the form function(){...}() for which call position | |
3350 // should not point to the closing brace otherwise it will intersect | |
3351 // with positions recorded for function literal and confuse debugger. | |
3352 pos = peek_position(); | |
3353 // Also the trailing parenthesis are a hint that the function will | |
3354 // be called immediately. If we happen to have parsed a preceding | |
3355 // function literal eagerly, we can also compile it eagerly. | |
3356 if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) { | |
3357 result->AsFunctionLiteral()->set_should_eager_compile(); | |
3358 } | |
3359 } | |
3360 Scanner::Location spread_pos; | |
3361 typename Traits::Type::ExpressionList args = | |
3362 ParseArguments(&spread_pos, classifier, CHECK_OK); | |
3363 | |
3364 // Keep track of eval() calls since they disable all local variable | |
3365 // optimizations. | |
3366 // The calls that need special treatment are the | |
3367 // direct eval calls. These calls are all of the form eval(...), with | |
3368 // no explicit receiver. | |
3369 // These calls are marked as potentially direct eval calls. Whether | |
3370 // they are actually direct calls to eval is determined at run time. | |
3371 this->CheckPossibleEvalCall(result, scope_); | |
3372 | |
3373 bool is_super_call = result->IsSuperCallReference(); | |
3374 if (spread_pos.IsValid()) { | |
3375 args = Traits::PrepareSpreadArguments(args); | |
3376 result = Traits::SpreadCall(result, args, pos); | |
3377 } else { | |
3378 result = factory()->NewCall(result, args, pos); | |
3379 } | |
3380 | |
3381 // Explicit calls to the super constructor using super() perform an | |
3382 // implicit binding assignment to the 'this' variable. | |
3383 if (is_super_call) { | |
3384 ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos); | |
3385 result = | |
3386 factory()->NewAssignment(Token::INIT, this_expr, result, pos); | |
3387 } | |
3388 | |
3389 if (fni_ != NULL) fni_->RemoveLastFunction(); | |
3390 break; | |
3391 } | |
3392 | |
3393 case Token::PERIOD: { | |
3394 BindingPatternUnexpectedToken(classifier); | |
3395 ArrowFormalParametersUnexpectedToken(classifier); | |
3396 Consume(Token::PERIOD); | |
3397 int pos = position(); | |
3398 IdentifierT name = ParseIdentifierName(CHECK_OK); | |
3399 result = factory()->NewProperty( | |
3400 result, factory()->NewStringLiteral(name, pos), pos); | |
3401 if (fni_ != NULL) this->PushLiteralName(fni_, name); | |
3402 break; | |
3403 } | |
3404 | |
3405 case Token::TEMPLATE_SPAN: | |
3406 case Token::TEMPLATE_TAIL: { | |
3407 BindingPatternUnexpectedToken(classifier); | |
3408 ArrowFormalParametersUnexpectedToken(classifier); | |
3409 result = ParseTemplateLiteral(result, position(), classifier, CHECK_OK); | |
3410 break; | |
3411 } | |
3412 | |
3413 default: | |
3414 return result; | |
3415 } | |
3416 } | |
3417 } | |
3418 | |
3419 | |
3420 template <class Traits> | |
3421 typename ParserBase<Traits>::ExpressionT | |
3422 ParserBase<Traits>::ParseMemberWithNewPrefixesExpression( | |
3423 ExpressionClassifier* classifier, bool* ok) { | |
3424 // NewExpression :: | |
3425 // ('new')+ MemberExpression | |
3426 // | |
3427 // NewTarget :: | |
3428 // 'new' '.' 'target' | |
3429 | |
3430 // The grammar for new expressions is pretty warped. We can have several 'new' | |
3431 // keywords following each other, and then a MemberExpression. When we see '(' | |
3432 // after the MemberExpression, it's associated with the rightmost unassociated | |
3433 // 'new' to create a NewExpression with arguments. However, a NewExpression | |
3434 // can also occur without arguments. | |
3435 | |
3436 // Examples of new expression: | |
3437 // new foo.bar().baz means (new (foo.bar)()).baz | |
3438 // new foo()() means (new foo())() | |
3439 // new new foo()() means (new (new foo())()) | |
3440 // new new foo means new (new foo) | |
3441 // new new foo() means new (new foo()) | |
3442 // new new foo().bar().baz means (new (new foo()).bar()).baz | |
3443 | |
3444 if (peek() == Token::NEW) { | |
3445 BindingPatternUnexpectedToken(classifier); | |
3446 ArrowFormalParametersUnexpectedToken(classifier); | |
3447 Consume(Token::NEW); | |
3448 int new_pos = position(); | |
3449 ExpressionT result = this->EmptyExpression(); | |
3450 if (peek() == Token::SUPER) { | |
3451 const bool is_new = true; | |
3452 result = ParseSuperExpression(is_new, classifier, CHECK_OK); | |
3453 } else if (peek() == Token::PERIOD) { | |
3454 return ParseNewTargetExpression(CHECK_OK); | |
3455 } else { | |
3456 result = this->ParseMemberWithNewPrefixesExpression(classifier, CHECK_OK); | |
3457 } | |
3458 if (peek() == Token::LPAREN) { | |
3459 // NewExpression with arguments. | |
3460 Scanner::Location spread_pos; | |
3461 typename Traits::Type::ExpressionList args = | |
3462 this->ParseArguments(&spread_pos, classifier, CHECK_OK); | |
3463 | |
3464 if (spread_pos.IsValid()) { | |
3465 args = Traits::PrepareSpreadArguments(args); | |
3466 result = Traits::SpreadCallNew(result, args, new_pos); | |
3467 } else { | |
3468 result = factory()->NewCallNew(result, args, new_pos); | |
3469 } | |
3470 // The expression can still continue with . or [ after the arguments. | |
3471 result = | |
3472 this->ParseMemberExpressionContinuation(result, classifier, CHECK_OK); | |
3473 return result; | |
3474 } | |
3475 // NewExpression without arguments. | |
3476 return factory()->NewCallNew(result, this->NewExpressionList(0, zone_), | |
3477 new_pos); | |
3478 } | |
3479 // No 'new' or 'super' keyword. | |
3480 return this->ParseMemberExpression(classifier, ok); | |
3481 } | |
3482 | |
3483 | |
3484 template <class Traits> | |
3485 typename ParserBase<Traits>::ExpressionT | |
3486 ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier, | |
3487 bool* ok) { | |
3488 // MemberExpression :: | |
3489 // (PrimaryExpression | FunctionLiteral | ClassLiteral) | |
3490 // ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)* | |
3491 | |
3492 // The '[' Expression ']' and '.' Identifier parts are parsed by | |
3493 // ParseMemberExpressionContinuation, and the Arguments part is parsed by the | |
3494 // caller. | |
3495 | |
3496 // Parse the initial primary or function expression. | |
3497 ExpressionT result = this->EmptyExpression(); | |
3498 if (peek() == Token::FUNCTION) { | |
3499 BindingPatternUnexpectedToken(classifier); | |
3500 ArrowFormalParametersUnexpectedToken(classifier); | |
3501 | |
3502 Consume(Token::FUNCTION); | |
3503 int function_token_position = position(); | |
3504 bool is_generator = Check(Token::MUL); | |
3505 IdentifierT name = this->EmptyIdentifier(); | |
3506 bool is_strict_reserved_name = false; | |
3507 Scanner::Location function_name_location = Scanner::Location::invalid(); | |
3508 FunctionLiteral::FunctionType function_type = | |
3509 FunctionLiteral::ANONYMOUS_EXPRESSION; | |
3510 if (peek_any_identifier()) { | |
3511 name = ParseIdentifierOrStrictReservedWord( | |
3512 is_generator, &is_strict_reserved_name, CHECK_OK); | |
3513 function_name_location = scanner()->location(); | |
3514 function_type = FunctionLiteral::NAMED_EXPRESSION; | |
3515 } | |
3516 result = this->ParseFunctionLiteral( | |
3517 name, function_name_location, | |
3518 is_strict_reserved_name ? kFunctionNameIsStrictReserved | |
3519 : kFunctionNameValidityUnknown, | |
3520 is_generator ? FunctionKind::kGeneratorFunction | |
3521 : FunctionKind::kNormalFunction, | |
3522 function_token_position, function_type, FunctionLiteral::NORMAL_ARITY, | |
3523 language_mode(), CHECK_OK); | |
3524 } else if (peek() == Token::SUPER) { | |
3525 const bool is_new = false; | |
3526 result = ParseSuperExpression(is_new, classifier, CHECK_OK); | |
3527 } else { | |
3528 result = ParsePrimaryExpression(classifier, CHECK_OK); | |
3529 } | |
3530 | |
3531 result = ParseMemberExpressionContinuation(result, classifier, CHECK_OK); | |
3532 return result; | |
3533 } | |
3534 | |
3535 | |
3536 template <class Traits> | |
3537 typename ParserBase<Traits>::ExpressionT | |
3538 ParserBase<Traits>::ParseStrongInitializationExpression( | |
3539 ExpressionClassifier* classifier, bool* ok) { | |
3540 // InitializationExpression :: (strong mode) | |
3541 // 'this' '.' IdentifierName '=' AssignmentExpression | |
3542 // 'this' '[' Expression ']' '=' AssignmentExpression | |
3543 | |
3544 if (fni_ != NULL) fni_->Enter(); | |
3545 | |
3546 Consume(Token::THIS); | |
3547 int pos = position(); | |
3548 function_state_->set_this_location(scanner()->location()); | |
3549 ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos); | |
3550 | |
3551 ExpressionT left = this->EmptyExpression(); | |
3552 switch (peek()) { | |
3553 case Token::LBRACK: { | |
3554 Consume(Token::LBRACK); | |
3555 int pos = position(); | |
3556 ExpressionT index = this->ParseExpression(true, classifier, CHECK_OK); | |
3557 left = factory()->NewProperty(this_expr, index, pos); | |
3558 if (fni_ != NULL) { | |
3559 this->PushPropertyName(fni_, index); | |
3560 } | |
3561 Expect(Token::RBRACK, CHECK_OK); | |
3562 break; | |
3563 } | |
3564 case Token::PERIOD: { | |
3565 Consume(Token::PERIOD); | |
3566 int pos = position(); | |
3567 IdentifierT name = ParseIdentifierName(CHECK_OK); | |
3568 left = factory()->NewProperty( | |
3569 this_expr, factory()->NewStringLiteral(name, pos), pos); | |
3570 if (fni_ != NULL) { | |
3571 this->PushLiteralName(fni_, name); | |
3572 } | |
3573 break; | |
3574 } | |
3575 default: | |
3576 ReportMessage(MessageTemplate::kStrongConstructorThis); | |
3577 *ok = false; | |
3578 return this->EmptyExpression(); | |
3579 } | |
3580 | |
3581 if (peek() != Token::ASSIGN) { | |
3582 ReportMessageAt(function_state_->this_location(), | |
3583 MessageTemplate::kStrongConstructorThis); | |
3584 *ok = false; | |
3585 return this->EmptyExpression(); | |
3586 } | |
3587 Consume(Token::ASSIGN); | |
3588 left = this->MarkExpressionAsAssigned(left); | |
3589 | |
3590 ExpressionT right = | |
3591 this->ParseAssignmentExpression(true, classifier, CHECK_OK); | |
3592 this->CheckAssigningFunctionLiteralToProperty(left, right); | |
3593 function_state_->AddProperty(); | |
3594 if (fni_ != NULL) { | |
3595 // Check if the right hand side is a call to avoid inferring a | |
3596 // name if we're dealing with "this.a = function(){...}();"-like | |
3597 // expression. | |
3598 if (!right->IsCall() && !right->IsCallNew()) { | |
3599 fni_->Infer(); | |
3600 } else { | |
3601 fni_->RemoveLastFunction(); | |
3602 } | |
3603 fni_->Leave(); | |
3604 } | |
3605 | |
3606 if (function_state_->return_location().IsValid()) { | |
3607 ReportMessageAt(function_state_->return_location(), | |
3608 MessageTemplate::kStrongConstructorReturnMisplaced); | |
3609 *ok = false; | |
3610 return this->EmptyExpression(); | |
3611 } | |
3612 | |
3613 return factory()->NewAssignment(Token::ASSIGN, left, right, pos); | |
3614 } | |
3615 | |
3616 | |
3617 template <class Traits> | |
3618 typename ParserBase<Traits>::ExpressionT | |
3619 ParserBase<Traits>::ParseStrongSuperCallExpression( | |
3620 ExpressionClassifier* classifier, bool* ok) { | |
3621 // SuperCallExpression :: (strong mode) | |
3622 // 'super' '(' ExpressionList ')' | |
3623 BindingPatternUnexpectedToken(classifier); | |
3624 | |
3625 Consume(Token::SUPER); | |
3626 int pos = position(); | |
3627 Scanner::Location super_loc = scanner()->location(); | |
3628 ExpressionT expr = this->SuperCallReference(scope_, factory(), pos); | |
3629 | |
3630 if (peek() != Token::LPAREN) { | |
3631 ReportMessage(MessageTemplate::kStrongConstructorSuper); | |
3632 *ok = false; | |
3633 return this->EmptyExpression(); | |
3634 } | |
3635 | |
3636 Scanner::Location spread_pos; | |
3637 typename Traits::Type::ExpressionList args = | |
3638 ParseArguments(&spread_pos, classifier, CHECK_OK); | |
3639 | |
3640 // TODO(rossberg): This doesn't work with arrow functions yet. | |
3641 if (!IsSubclassConstructor(function_state_->kind())) { | |
3642 ReportMessage(MessageTemplate::kUnexpectedSuper); | |
3643 *ok = false; | |
3644 return this->EmptyExpression(); | |
3645 } else if (function_state_->super_location().IsValid()) { | |
3646 ReportMessageAt(scanner()->location(), | |
3647 MessageTemplate::kStrongSuperCallDuplicate); | |
3648 *ok = false; | |
3649 return this->EmptyExpression(); | |
3650 } else if (function_state_->this_location().IsValid()) { | |
3651 ReportMessageAt(scanner()->location(), | |
3652 MessageTemplate::kStrongSuperCallMisplaced); | |
3653 *ok = false; | |
3654 return this->EmptyExpression(); | |
3655 } else if (function_state_->return_location().IsValid()) { | |
3656 ReportMessageAt(function_state_->return_location(), | |
3657 MessageTemplate::kStrongConstructorReturnMisplaced); | |
3658 *ok = false; | |
3659 return this->EmptyExpression(); | |
3660 } | |
3661 | |
3662 function_state_->set_super_location(super_loc); | |
3663 if (spread_pos.IsValid()) { | |
3664 args = Traits::PrepareSpreadArguments(args); | |
3665 expr = Traits::SpreadCall(expr, args, pos); | |
3666 } else { | |
3667 expr = factory()->NewCall(expr, args, pos); | |
3668 } | |
3669 | |
3670 // Explicit calls to the super constructor using super() perform an implicit | |
3671 // binding assignment to the 'this' variable. | |
3672 ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos); | |
3673 return factory()->NewAssignment(Token::INIT, this_expr, expr, pos); | |
3674 } | |
3675 | |
3676 | |
3677 template <class Traits> | |
3678 typename ParserBase<Traits>::ExpressionT | |
3679 ParserBase<Traits>::ParseSuperExpression(bool is_new, | |
3680 ExpressionClassifier* classifier, | |
3681 bool* ok) { | |
3682 Expect(Token::SUPER, CHECK_OK); | |
3683 int pos = position(); | |
3684 | |
3685 Scope* scope = scope_->ReceiverScope(); | |
3686 FunctionKind kind = scope->function_kind(); | |
3687 if (IsConciseMethod(kind) || IsAccessorFunction(kind) || | |
3688 IsClassConstructor(kind)) { | |
3689 if (peek() == Token::PERIOD || peek() == Token::LBRACK) { | |
3690 scope->RecordSuperPropertyUsage(); | |
3691 return this->SuperPropertyReference(scope_, factory(), pos); | |
3692 } | |
3693 // new super() is never allowed. | |
3694 // super() is only allowed in derived constructor | |
3695 if (!is_new && peek() == Token::LPAREN && IsSubclassConstructor(kind)) { | |
3696 if (is_strong(language_mode())) { | |
3697 // Super calls in strong mode are parsed separately. | |
3698 ReportMessageAt(scanner()->location(), | |
3699 MessageTemplate::kStrongConstructorSuper); | |
3700 *ok = false; | |
3701 return this->EmptyExpression(); | |
3702 } | |
3703 // TODO(rossberg): This might not be the correct FunctionState for the | |
3704 // method here. | |
3705 function_state_->set_super_location(scanner()->location()); | |
3706 return this->SuperCallReference(scope_, factory(), pos); | |
3707 } | |
3708 } | |
3709 | |
3710 ReportMessageAt(scanner()->location(), MessageTemplate::kUnexpectedSuper); | |
3711 *ok = false; | |
3712 return this->EmptyExpression(); | |
3713 } | |
3714 | |
3715 | |
3716 template <class Traits> | |
3717 typename ParserBase<Traits>::ExpressionT | |
3718 ParserBase<Traits>::ParseNewTargetExpression(bool* ok) { | |
3719 int pos = position(); | |
3720 Consume(Token::PERIOD); | |
3721 ExpectContextualKeyword(CStrVector("target"), CHECK_OK); | |
3722 | |
3723 if (!scope_->ReceiverScope()->is_function_scope()) { | |
3724 ReportMessageAt(scanner()->location(), | |
3725 MessageTemplate::kUnexpectedNewTarget); | |
3726 *ok = false; | |
3727 return this->EmptyExpression(); | |
3728 } | |
3729 | |
3730 return this->NewTargetExpression(scope_, factory(), pos); | |
3731 } | |
3732 | |
3733 | |
3734 template <class Traits> | |
3735 typename ParserBase<Traits>::ExpressionT | |
3736 ParserBase<Traits>::ParseMemberExpressionContinuation( | |
3737 ExpressionT expression, ExpressionClassifier* classifier, bool* ok) { | |
3738 // Parses this part of MemberExpression: | |
3739 // ('[' Expression ']' | '.' Identifier | TemplateLiteral)* | |
3740 while (true) { | |
3741 switch (peek()) { | |
3742 case Token::LBRACK: { | |
3743 BindingPatternUnexpectedToken(classifier); | |
3744 ArrowFormalParametersUnexpectedToken(classifier); | |
3745 | |
3746 Consume(Token::LBRACK); | |
3747 int pos = position(); | |
3748 ExpressionT index = this->ParseExpression(true, classifier, CHECK_OK); | |
3749 expression = factory()->NewProperty(expression, index, pos); | |
3750 if (fni_ != NULL) { | |
3751 this->PushPropertyName(fni_, index); | |
3752 } | |
3753 Expect(Token::RBRACK, CHECK_OK); | |
3754 break; | |
3755 } | |
3756 case Token::PERIOD: { | |
3757 BindingPatternUnexpectedToken(classifier); | |
3758 ArrowFormalParametersUnexpectedToken(classifier); | |
3759 | |
3760 Consume(Token::PERIOD); | |
3761 int pos = position(); | |
3762 IdentifierT name = ParseIdentifierName(CHECK_OK); | |
3763 expression = factory()->NewProperty( | |
3764 expression, factory()->NewStringLiteral(name, pos), pos); | |
3765 if (fni_ != NULL) { | |
3766 this->PushLiteralName(fni_, name); | |
3767 } | |
3768 break; | |
3769 } | |
3770 case Token::TEMPLATE_SPAN: | |
3771 case Token::TEMPLATE_TAIL: { | |
3772 BindingPatternUnexpectedToken(classifier); | |
3773 ArrowFormalParametersUnexpectedToken(classifier); | |
3774 int pos; | |
3775 if (scanner()->current_token() == Token::IDENTIFIER) { | |
3776 pos = position(); | |
3777 } else { | |
3778 pos = peek_position(); | |
3779 if (expression->IsFunctionLiteral() && mode() == PARSE_EAGERLY) { | |
3780 // If the tag function looks like an IIFE, set_parenthesized() to | |
3781 // force eager compilation. | |
3782 expression->AsFunctionLiteral()->set_should_eager_compile(); | |
3783 } | |
3784 } | |
3785 expression = | |
3786 ParseTemplateLiteral(expression, pos, classifier, CHECK_OK); | |
3787 break; | |
3788 } | |
3789 default: | |
3790 return expression; | |
3791 } | |
3792 } | |
3793 DCHECK(false); | |
3794 return this->EmptyExpression(); | |
3795 } | |
3796 | |
3797 | |
3798 template <class Traits> | |
3799 void ParserBase<Traits>::ParseFormalParameter( | |
3800 FormalParametersT* parameters, ExpressionClassifier* classifier, bool* ok) { | |
3801 // FormalParameter[Yield,GeneratorParameter] : | |
3802 // BindingElement[?Yield, ?GeneratorParameter] | |
3803 bool is_rest = parameters->has_rest; | |
3804 | |
3805 Token::Value next = peek(); | |
3806 ExpressionT pattern = ParsePrimaryExpression(classifier, ok); | |
3807 if (!*ok) return; | |
3808 | |
3809 ValidateBindingPattern(classifier, ok); | |
3810 if (!*ok) return; | |
3811 | |
3812 if (!Traits::IsIdentifier(pattern)) { | |
3813 if (is_rest || !allow_harmony_destructuring_bind()) { | |
3814 ReportUnexpectedToken(next); | |
3815 *ok = false; | |
3816 return; | |
3817 } | |
3818 parameters->is_simple = false; | |
3819 ValidateFormalParameterInitializer(classifier, ok); | |
3820 if (!*ok) return; | |
3821 classifier->RecordNonSimpleParameter(); | |
3822 } | |
3823 | |
3824 if (is_rest) { | |
3825 parameters->rest_array_literal_index = | |
3826 function_state_->NextMaterializedLiteralIndex(); | |
3827 ++parameters->materialized_literals_count; | |
3828 } | |
3829 | |
3830 ExpressionT initializer = Traits::EmptyExpression(); | |
3831 if (!is_rest && allow_harmony_default_parameters() && Check(Token::ASSIGN)) { | |
3832 ExpressionClassifier init_classifier; | |
3833 initializer = ParseAssignmentExpression(true, &init_classifier, ok); | |
3834 if (!*ok) return; | |
3835 ValidateExpression(&init_classifier, ok); | |
3836 ValidateFormalParameterInitializer(&init_classifier, ok); | |
3837 if (!*ok) return; | |
3838 parameters->is_simple = false; | |
3839 classifier->RecordNonSimpleParameter(); | |
3840 } | |
3841 | |
3842 Traits::AddFormalParameter(parameters, pattern, initializer, | |
3843 scanner()->location().end_pos, is_rest); | |
3844 } | |
3845 | |
3846 | |
3847 template <class Traits> | |
3848 void ParserBase<Traits>::ParseFormalParameterList( | |
3849 FormalParametersT* parameters, ExpressionClassifier* classifier, bool* ok) { | |
3850 // FormalParameters[Yield,GeneratorParameter] : | |
3851 // [empty] | |
3852 // FormalParameterList[?Yield, ?GeneratorParameter] | |
3853 // | |
3854 // FormalParameterList[Yield,GeneratorParameter] : | |
3855 // FunctionRestParameter[?Yield] | |
3856 // FormalsList[?Yield, ?GeneratorParameter] | |
3857 // FormalsList[?Yield, ?GeneratorParameter] , FunctionRestParameter[?Yield] | |
3858 // | |
3859 // FormalsList[Yield,GeneratorParameter] : | |
3860 // FormalParameter[?Yield, ?GeneratorParameter] | |
3861 // FormalsList[?Yield, ?GeneratorParameter] , | |
3862 // FormalParameter[?Yield,?GeneratorParameter] | |
3863 | |
3864 DCHECK_EQ(0, parameters->Arity()); | |
3865 | |
3866 if (peek() != Token::RPAREN) { | |
3867 do { | |
3868 if (parameters->Arity() > Code::kMaxArguments) { | |
3869 ReportMessage(MessageTemplate::kTooManyParameters); | |
3870 *ok = false; | |
3871 return; | |
3872 } | |
3873 parameters->has_rest = | |
3874 allow_harmony_rest_parameters() && Check(Token::ELLIPSIS); | |
3875 ParseFormalParameter(parameters, classifier, ok); | |
3876 if (!*ok) return; | |
3877 } while (!parameters->has_rest && Check(Token::COMMA)); | |
3878 | |
3879 if (parameters->has_rest) { | |
3880 parameters->is_simple = false; | |
3881 classifier->RecordNonSimpleParameter(); | |
3882 if (peek() == Token::COMMA) { | |
3883 ReportMessageAt(scanner()->peek_location(), | |
3884 MessageTemplate::kParamAfterRest); | |
3885 *ok = false; | |
3886 return; | |
3887 } | |
3888 } | |
3889 } | |
3890 | |
3891 for (int i = 0; i < parameters->Arity(); ++i) { | |
3892 auto parameter = parameters->at(i); | |
3893 Traits::DeclareFormalParameter(parameters->scope, parameter, classifier); | |
3894 } | |
3895 } | |
3896 | |
3897 | |
3898 template <class Traits> | |
3899 void ParserBase<Traits>::CheckArityRestrictions( | |
3900 int param_count, FunctionLiteral::ArityRestriction arity_restriction, | |
3901 bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok) { | |
3902 switch (arity_restriction) { | |
3903 case FunctionLiteral::GETTER_ARITY: | |
3904 if (param_count != 0) { | |
3905 ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos), | |
3906 MessageTemplate::kBadGetterArity); | |
3907 *ok = false; | |
3908 } | |
3909 break; | |
3910 case FunctionLiteral::SETTER_ARITY: | |
3911 if (param_count != 1) { | |
3912 ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos), | |
3913 MessageTemplate::kBadSetterArity); | |
3914 *ok = false; | |
3915 } | |
3916 if (has_rest) { | |
3917 ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos), | |
3918 MessageTemplate::kBadSetterRestParameter); | |
3919 *ok = false; | |
3920 } | |
3921 break; | |
3922 default: | |
3923 break; | |
3924 } | |
3925 } | |
3926 | |
3927 | |
3928 template <class Traits> | |
3929 bool ParserBase<Traits>::IsNextLetKeyword() { | |
3930 DCHECK(peek() == Token::LET); | |
3931 if (!allow_let()) { | |
3932 return false; | |
3933 } | |
3934 Token::Value next_next = PeekAhead(); | |
3935 switch (next_next) { | |
3936 case Token::LBRACE: | |
3937 case Token::LBRACK: | |
3938 case Token::IDENTIFIER: | |
3939 case Token::STATIC: | |
3940 case Token::LET: // Yes, you can do let let = ... in sloppy mode | |
3941 case Token::YIELD: | |
3942 return true; | |
3943 default: | |
3944 return false; | |
3945 } | |
3946 } | |
3947 | |
3948 | |
3949 template <class Traits> | |
3950 typename ParserBase<Traits>::ExpressionT | |
3951 ParserBase<Traits>::ParseArrowFunctionLiteral( | |
3952 bool accept_IN, const FormalParametersT& formal_parameters, | |
3953 const ExpressionClassifier& formals_classifier, bool* ok) { | |
3954 if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) { | |
3955 // ASI inserts `;` after arrow parameters if a line terminator is found. | |
3956 // `=> ...` is never a valid expression, so report as syntax error. | |
3957 // If next token is not `=>`, it's a syntax error anyways. | |
3958 ReportUnexpectedTokenAt(scanner_->peek_location(), Token::ARROW); | |
3959 *ok = false; | |
3960 return this->EmptyExpression(); | |
3961 } | |
3962 | |
3963 typename Traits::Type::StatementList body; | |
3964 int num_parameters = formal_parameters.scope->num_parameters(); | |
3965 int materialized_literal_count = -1; | |
3966 int expected_property_count = -1; | |
3967 Scanner::Location super_loc; | |
3968 | |
3969 { | |
3970 typename Traits::Type::Factory function_factory(ast_value_factory()); | |
3971 FunctionState function_state(&function_state_, &scope_, | |
3972 formal_parameters.scope, kArrowFunction, | |
3973 &function_factory); | |
3974 | |
3975 function_state.SkipMaterializedLiterals( | |
3976 formal_parameters.materialized_literals_count); | |
3977 | |
3978 this->ReindexLiterals(formal_parameters); | |
3979 | |
3980 Expect(Token::ARROW, CHECK_OK); | |
3981 | |
3982 if (peek() == Token::LBRACE) { | |
3983 // Multiple statement body | |
3984 Consume(Token::LBRACE); | |
3985 bool is_lazily_parsed = | |
3986 (mode() == PARSE_LAZILY && scope_->AllowsLazyCompilation()); | |
3987 if (is_lazily_parsed) { | |
3988 body = this->NewStatementList(0, zone()); | |
3989 this->SkipLazyFunctionBody(&materialized_literal_count, | |
3990 &expected_property_count, CHECK_OK); | |
3991 | |
3992 if (formal_parameters.materialized_literals_count > 0) { | |
3993 materialized_literal_count += | |
3994 formal_parameters.materialized_literals_count; | |
3995 } | |
3996 } else { | |
3997 body = this->ParseEagerFunctionBody( | |
3998 this->EmptyIdentifier(), RelocInfo::kNoPosition, formal_parameters, | |
3999 kArrowFunction, FunctionLiteral::ANONYMOUS_EXPRESSION, CHECK_OK); | |
4000 materialized_literal_count = | |
4001 function_state.materialized_literal_count(); | |
4002 expected_property_count = function_state.expected_property_count(); | |
4003 } | |
4004 } else { | |
4005 // Single-expression body | |
4006 int pos = position(); | |
4007 parenthesized_function_ = false; | |
4008 ExpressionClassifier classifier; | |
4009 ExpressionT expression = | |
4010 ParseAssignmentExpression(accept_IN, &classifier, CHECK_OK); | |
4011 ValidateExpression(&classifier, CHECK_OK); | |
4012 body = this->NewStatementList(1, zone()); | |
4013 this->AddParameterInitializationBlock(formal_parameters, body, CHECK_OK); | |
4014 body->Add(factory()->NewReturnStatement(expression, pos), zone()); | |
4015 materialized_literal_count = function_state.materialized_literal_count(); | |
4016 expected_property_count = function_state.expected_property_count(); | |
4017 } | |
4018 super_loc = function_state.super_location(); | |
4019 | |
4020 formal_parameters.scope->set_end_position(scanner()->location().end_pos); | |
4021 | |
4022 // Arrow function formal parameters are parsed as StrictFormalParameterList, | |
4023 // which is not the same as "parameters of a strict function"; it only means | |
4024 // that duplicates are not allowed. Of course, the arrow function may | |
4025 // itself be strict as well. | |
4026 const bool allow_duplicate_parameters = false; | |
4027 this->ValidateFormalParameters(&formals_classifier, language_mode(), | |
4028 allow_duplicate_parameters, CHECK_OK); | |
4029 | |
4030 // Validate strict mode. | |
4031 if (is_strict(language_mode())) { | |
4032 CheckStrictOctalLiteral(formal_parameters.scope->start_position(), | |
4033 scanner()->location().end_pos, CHECK_OK); | |
4034 } | |
4035 if (is_strict(language_mode()) || allow_harmony_sloppy()) { | |
4036 this->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK); | |
4037 } | |
4038 } | |
4039 | |
4040 FunctionLiteralT function_literal = factory()->NewFunctionLiteral( | |
4041 this->EmptyIdentifierString(), ast_value_factory(), | |
4042 formal_parameters.scope, body, materialized_literal_count, | |
4043 expected_property_count, num_parameters, | |
4044 FunctionLiteral::kNoDuplicateParameters, | |
4045 FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction, | |
4046 FunctionLiteral::kShouldLazyCompile, FunctionKind::kArrowFunction, | |
4047 formal_parameters.scope->start_position()); | |
4048 | |
4049 function_literal->set_function_token_position( | |
4050 formal_parameters.scope->start_position()); | |
4051 if (super_loc.IsValid()) function_state_->set_super_location(super_loc); | |
4052 | |
4053 if (fni_ != NULL) this->InferFunctionName(fni_, function_literal); | |
4054 | |
4055 return function_literal; | |
4056 } | |
4057 | |
4058 | |
4059 template <typename Traits> | |
4060 typename ParserBase<Traits>::ExpressionT | |
4061 ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start, | |
4062 ExpressionClassifier* classifier, | |
4063 bool* ok) { | |
4064 // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal | |
4065 // text followed by a substitution expression), finalized by a single | |
4066 // TEMPLATE_TAIL. | |
4067 // | |
4068 // In terms of draft language, TEMPLATE_SPAN may be either the TemplateHead or | |
4069 // TemplateMiddle productions, while TEMPLATE_TAIL is either TemplateTail, or | |
4070 // NoSubstitutionTemplate. | |
4071 // | |
4072 // When parsing a TemplateLiteral, we must have scanned either an initial | |
4073 // TEMPLATE_SPAN, or a TEMPLATE_TAIL. | |
4074 CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL); | |
4075 | |
4076 // If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate. | |
4077 // In this case we may simply consume the token and build a template with a | |
4078 // single TEMPLATE_SPAN and no expressions. | |
4079 if (peek() == Token::TEMPLATE_TAIL) { | |
4080 Consume(Token::TEMPLATE_TAIL); | |
4081 int pos = position(); | |
4082 CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK); | |
4083 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos); | |
4084 Traits::AddTemplateSpan(&ts, true); | |
4085 return Traits::CloseTemplateLiteral(&ts, start, tag); | |
4086 } | |
4087 | |
4088 Consume(Token::TEMPLATE_SPAN); | |
4089 int pos = position(); | |
4090 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos); | |
4091 Traits::AddTemplateSpan(&ts, false); | |
4092 Token::Value next; | |
4093 | |
4094 // If we open with a TEMPLATE_SPAN, we must scan the subsequent expression, | |
4095 // and repeat if the following token is a TEMPLATE_SPAN as well (in this | |
4096 // case, representing a TemplateMiddle). | |
4097 | |
4098 do { | |
4099 CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK); | |
4100 next = peek(); | |
4101 if (next == Token::EOS) { | |
4102 ReportMessageAt(Scanner::Location(start, peek_position()), | |
4103 MessageTemplate::kUnterminatedTemplate); | |
4104 *ok = false; | |
4105 return Traits::EmptyExpression(); | |
4106 } else if (next == Token::ILLEGAL) { | |
4107 Traits::ReportMessageAt( | |
4108 Scanner::Location(position() + 1, peek_position()), | |
4109 MessageTemplate::kUnexpectedToken, "ILLEGAL", kSyntaxError); | |
4110 *ok = false; | |
4111 return Traits::EmptyExpression(); | |
4112 } | |
4113 | |
4114 int expr_pos = peek_position(); | |
4115 ExpressionT expression = this->ParseExpression(true, classifier, CHECK_OK); | |
4116 Traits::AddTemplateExpression(&ts, expression); | |
4117 | |
4118 if (peek() != Token::RBRACE) { | |
4119 ReportMessageAt(Scanner::Location(expr_pos, peek_position()), | |
4120 MessageTemplate::kUnterminatedTemplateExpr); | |
4121 *ok = false; | |
4122 return Traits::EmptyExpression(); | |
4123 } | |
4124 | |
4125 // If we didn't die parsing that expression, our next token should be a | |
4126 // TEMPLATE_SPAN or TEMPLATE_TAIL. | |
4127 next = scanner()->ScanTemplateContinuation(); | |
4128 Next(); | |
4129 pos = position(); | |
4130 | |
4131 if (next == Token::EOS) { | |
4132 ReportMessageAt(Scanner::Location(start, pos), | |
4133 MessageTemplate::kUnterminatedTemplate); | |
4134 *ok = false; | |
4135 return Traits::EmptyExpression(); | |
4136 } else if (next == Token::ILLEGAL) { | |
4137 Traits::ReportMessageAt( | |
4138 Scanner::Location(position() + 1, peek_position()), | |
4139 MessageTemplate::kUnexpectedToken, "ILLEGAL", kSyntaxError); | |
4140 *ok = false; | |
4141 return Traits::EmptyExpression(); | |
4142 } | |
4143 | |
4144 Traits::AddTemplateSpan(&ts, next == Token::TEMPLATE_TAIL); | |
4145 } while (next == Token::TEMPLATE_SPAN); | |
4146 | |
4147 DCHECK_EQ(next, Token::TEMPLATE_TAIL); | |
4148 CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK); | |
4149 // Once we've reached a TEMPLATE_TAIL, we can close the TemplateLiteral. | |
4150 return Traits::CloseTemplateLiteral(&ts, start, tag); | |
4151 } | |
4152 | |
4153 | |
4154 template <typename Traits> | |
4155 typename ParserBase<Traits>::ExpressionT | |
4156 ParserBase<Traits>::CheckAndRewriteReferenceExpression( | |
4157 ExpressionT expression, int beg_pos, int end_pos, | |
4158 MessageTemplate::Template message, bool* ok) { | |
4159 return this->CheckAndRewriteReferenceExpression(expression, beg_pos, end_pos, | |
4160 message, kReferenceError, ok); | |
4161 } | |
4162 | |
4163 | |
4164 template <typename Traits> | |
4165 typename ParserBase<Traits>::ExpressionT | |
4166 ParserBase<Traits>::CheckAndRewriteReferenceExpression( | |
4167 ExpressionT expression, int beg_pos, int end_pos, | |
4168 MessageTemplate::Template message, ParseErrorType type, bool* ok) { | |
4169 Scanner::Location location(beg_pos, end_pos); | |
4170 if (this->IsIdentifier(expression)) { | |
4171 if (is_strict(language_mode()) && | |
4172 this->IsEvalOrArguments(this->AsIdentifier(expression))) { | |
4173 this->ReportMessageAt(location, MessageTemplate::kStrictEvalArguments, | |
4174 kSyntaxError); | |
4175 *ok = false; | |
4176 return this->EmptyExpression(); | |
4177 } | |
4178 if (is_strong(language_mode()) && | |
4179 this->IsUndefined(this->AsIdentifier(expression))) { | |
4180 this->ReportMessageAt(location, MessageTemplate::kStrongUndefined, | |
4181 kSyntaxError); | |
4182 *ok = false; | |
4183 return this->EmptyExpression(); | |
4184 } | |
4185 } | |
4186 if (expression->IsValidReferenceExpression()) { | |
4187 return expression; | |
4188 } else if (expression->IsCall()) { | |
4189 // If it is a call, make it a runtime error for legacy web compatibility. | |
4190 // Rewrite `expr' to `expr[throw ReferenceError]'. | |
4191 int pos = location.beg_pos; | |
4192 ExpressionT error = this->NewThrowReferenceError(message, pos); | |
4193 return factory()->NewProperty(expression, error, pos); | |
4194 } else { | |
4195 this->ReportMessageAt(location, message, type); | |
4196 *ok = false; | |
4197 return this->EmptyExpression(); | |
4198 } | |
4199 } | |
4200 | |
4201 | |
4202 #undef CHECK_OK | |
4203 #undef CHECK_OK_CUSTOM | |
4204 | |
4205 | |
4206 template <typename Traits> | |
4207 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( | |
4208 Token::Value property, PropertyKind type, bool is_static, bool is_generator, | |
4209 bool* ok) { | |
4210 DCHECK(!is_static); | |
4211 DCHECK(!is_generator || type == kMethodProperty); | |
4212 | |
4213 if (property == Token::SMI || property == Token::NUMBER) return; | |
4214 | |
4215 if (type == kValueProperty && IsProto()) { | |
4216 if (has_seen_proto_) { | |
4217 this->parser()->ReportMessage(MessageTemplate::kDuplicateProto); | |
4218 *ok = false; | |
4219 return; | |
4220 } | |
4221 has_seen_proto_ = true; | |
4222 return; | |
4223 } | |
4224 } | |
4225 | |
4226 | |
4227 template <typename Traits> | |
4228 void ParserBase<Traits>::ClassLiteralChecker::CheckProperty( | |
4229 Token::Value property, PropertyKind type, bool is_static, bool is_generator, | |
4230 bool* ok) { | |
4231 DCHECK(type == kMethodProperty || type == kAccessorProperty); | |
4232 | |
4233 if (property == Token::SMI || property == Token::NUMBER) return; | |
4234 | |
4235 if (is_static) { | |
4236 if (IsPrototype()) { | |
4237 this->parser()->ReportMessage(MessageTemplate::kStaticPrototype); | |
4238 *ok = false; | |
4239 return; | |
4240 } | |
4241 } else if (IsConstructor()) { | |
4242 if (is_generator || type == kAccessorProperty) { | |
4243 MessageTemplate::Template msg = | |
4244 is_generator ? MessageTemplate::kConstructorIsGenerator | |
4245 : MessageTemplate::kConstructorIsAccessor; | |
4246 this->parser()->ReportMessage(msg); | |
4247 *ok = false; | |
4248 return; | |
4249 } | |
4250 if (has_seen_constructor_) { | |
4251 this->parser()->ReportMessage(MessageTemplate::kDuplicateConstructor); | |
4252 *ok = false; | |
4253 return; | |
4254 } | |
4255 has_seen_constructor_ = true; | |
4256 return; | |
4257 } | |
4258 } | |
4259 } // namespace internal | |
4260 } // namespace v8 | |
4261 | |
4262 #endif // V8_PREPARSER_H | |
OLD | NEW |