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

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

Issue 2637403008: [async-iteration] add support for for-await-of loops in Async Functions (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_PARSING_PARSER_BASE_H 5 #ifndef V8_PARSING_PARSER_BASE_H
6 #define V8_PARSING_PARSER_BASE_H 6 #define V8_PARSING_PARSER_BASE_H
7 7
8 #include "src/ast/ast.h" 8 #include "src/ast/ast.h"
9 #include "src/ast/scopes.h" 9 #include "src/ast/scopes.h"
10 #include "src/bailout-reason.h" 10 #include "src/bailout-reason.h"
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 stack_overflow_(false), 211 stack_overflow_(false),
212 default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile), 212 default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile),
213 function_literal_id_(0), 213 function_literal_id_(0),
214 allow_natives_(false), 214 allow_natives_(false),
215 allow_tailcalls_(false), 215 allow_tailcalls_(false),
216 allow_harmony_do_expressions_(false), 216 allow_harmony_do_expressions_(false),
217 allow_harmony_function_sent_(false), 217 allow_harmony_function_sent_(false),
218 allow_harmony_restrictive_generators_(false), 218 allow_harmony_restrictive_generators_(false),
219 allow_harmony_trailing_commas_(false), 219 allow_harmony_trailing_commas_(false),
220 allow_harmony_class_fields_(false), 220 allow_harmony_class_fields_(false),
221 allow_harmony_object_rest_spread_(false) {} 221 allow_harmony_object_rest_spread_(false),
222 allow_harmony_async_iteration_(false) {}
222 223
223 #define ALLOW_ACCESSORS(name) \ 224 #define ALLOW_ACCESSORS(name) \
224 bool allow_##name() const { return allow_##name##_; } \ 225 bool allow_##name() const { return allow_##name##_; } \
225 void set_allow_##name(bool allow) { allow_##name##_ = allow; } 226 void set_allow_##name(bool allow) { allow_##name##_ = allow; }
226 227
227 ALLOW_ACCESSORS(natives); 228 ALLOW_ACCESSORS(natives);
228 ALLOW_ACCESSORS(tailcalls); 229 ALLOW_ACCESSORS(tailcalls);
229 ALLOW_ACCESSORS(harmony_do_expressions); 230 ALLOW_ACCESSORS(harmony_do_expressions);
230 ALLOW_ACCESSORS(harmony_function_sent); 231 ALLOW_ACCESSORS(harmony_function_sent);
231 ALLOW_ACCESSORS(harmony_restrictive_generators); 232 ALLOW_ACCESSORS(harmony_restrictive_generators);
232 ALLOW_ACCESSORS(harmony_trailing_commas); 233 ALLOW_ACCESSORS(harmony_trailing_commas);
233 ALLOW_ACCESSORS(harmony_class_fields); 234 ALLOW_ACCESSORS(harmony_class_fields);
234 ALLOW_ACCESSORS(harmony_object_rest_spread); 235 ALLOW_ACCESSORS(harmony_object_rest_spread);
236 ALLOW_ACCESSORS(harmony_async_iteration);
235 237
236 #undef ALLOW_ACCESSORS 238 #undef ALLOW_ACCESSORS
237 239
238 uintptr_t stack_limit() const { return stack_limit_; } 240 uintptr_t stack_limit() const { return stack_limit_; }
239 241
240 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } 242 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; }
241 243
242 void set_default_eager_compile_hint( 244 void set_default_eager_compile_hint(
243 FunctionLiteral::EagerCompileHint eager_compile_hint) { 245 FunctionLiteral::EagerCompileHint eager_compile_hint) {
244 default_eager_compile_hint_ = eager_compile_hint; 246 default_eager_compile_hint_ = eager_compile_hint;
(...skipping 1038 matching lines...) Expand 10 before | Expand all | Expand 10 after
1283 bool* ok); 1285 bool* ok);
1284 StatementT ParseDoWhileStatement(ZoneList<const AstRawString*>* labels, 1286 StatementT ParseDoWhileStatement(ZoneList<const AstRawString*>* labels,
1285 bool* ok); 1287 bool* ok);
1286 StatementT ParseWhileStatement(ZoneList<const AstRawString*>* labels, 1288 StatementT ParseWhileStatement(ZoneList<const AstRawString*>* labels,
1287 bool* ok); 1289 bool* ok);
1288 StatementT ParseThrowStatement(bool* ok); 1290 StatementT ParseThrowStatement(bool* ok);
1289 StatementT ParseSwitchStatement(ZoneList<const AstRawString*>* labels, 1291 StatementT ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
1290 bool* ok); 1292 bool* ok);
1291 StatementT ParseTryStatement(bool* ok); 1293 StatementT ParseTryStatement(bool* ok);
1292 StatementT ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok); 1294 StatementT ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok);
1295 StatementT ParseForAwaitStatement(ZoneList<const AstRawString*>* labels,
1296 bool* ok);
1293 1297
1294 bool IsNextLetKeyword(); 1298 bool IsNextLetKeyword();
1295 bool IsTrivialExpression(); 1299 bool IsTrivialExpression();
1296 1300
1297 // Checks if the expression is a valid reference expression (e.g., on the 1301 // Checks if the expression is a valid reference expression (e.g., on the
1298 // left-hand side of assignments). Although ruled out by ECMA as early errors, 1302 // left-hand side of assignments). Although ruled out by ECMA as early errors,
1299 // we allow calls for web compatibility and rewrite them to a runtime throw. 1303 // we allow calls for web compatibility and rewrite them to a runtime throw.
1300 ExpressionT CheckAndRewriteReferenceExpression( 1304 ExpressionT CheckAndRewriteReferenceExpression(
1301 ExpressionT expression, int beg_pos, int end_pos, 1305 ExpressionT expression, int beg_pos, int end_pos,
1302 MessageTemplate::Template message, bool* ok); 1306 MessageTemplate::Template message, bool* ok);
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1451 int function_literal_id_; 1455 int function_literal_id_;
1452 1456
1453 bool allow_natives_; 1457 bool allow_natives_;
1454 bool allow_tailcalls_; 1458 bool allow_tailcalls_;
1455 bool allow_harmony_do_expressions_; 1459 bool allow_harmony_do_expressions_;
1456 bool allow_harmony_function_sent_; 1460 bool allow_harmony_function_sent_;
1457 bool allow_harmony_restrictive_generators_; 1461 bool allow_harmony_restrictive_generators_;
1458 bool allow_harmony_trailing_commas_; 1462 bool allow_harmony_trailing_commas_;
1459 bool allow_harmony_class_fields_; 1463 bool allow_harmony_class_fields_;
1460 bool allow_harmony_object_rest_spread_; 1464 bool allow_harmony_object_rest_spread_;
1465 bool allow_harmony_async_iteration_;
1461 1466
1462 friend class DiscardableZoneScope; 1467 friend class DiscardableZoneScope;
1463 }; 1468 };
1464 1469
1465 template <typename Impl> 1470 template <typename Impl>
1466 ParserBase<Impl>::FunctionState::FunctionState( 1471 ParserBase<Impl>::FunctionState::FunctionState(
1467 FunctionState** function_state_stack, ScopeState** scope_stack, 1472 FunctionState** function_state_stack, ScopeState** scope_stack,
1468 DeclarationScope* scope) 1473 DeclarationScope* scope)
1469 : ScopeState(scope_stack, scope), 1474 : ScopeState(scope_stack, scope),
1470 next_materialized_literal_index_(0), 1475 next_materialized_literal_index_(0),
(...skipping 3155 matching lines...) Expand 10 before | Expand all | Expand 10 after
4626 case Token::SEMICOLON: 4631 case Token::SEMICOLON:
4627 Next(); 4632 Next();
4628 return factory()->NewEmptyStatement(kNoSourcePosition); 4633 return factory()->NewEmptyStatement(kNoSourcePosition);
4629 case Token::IF: 4634 case Token::IF:
4630 return ParseIfStatement(labels, ok); 4635 return ParseIfStatement(labels, ok);
4631 case Token::DO: 4636 case Token::DO:
4632 return ParseDoWhileStatement(labels, ok); 4637 return ParseDoWhileStatement(labels, ok);
4633 case Token::WHILE: 4638 case Token::WHILE:
4634 return ParseWhileStatement(labels, ok); 4639 return ParseWhileStatement(labels, ok);
4635 case Token::FOR: 4640 case Token::FOR:
4641 if (V8_UNLIKELY(allow_harmony_async_iteration() && is_async_function() &&
4642 PeekAhead() == Token::AWAIT)) {
4643 return ParseForAwaitStatement(labels, ok);
4644 }
4636 return ParseForStatement(labels, ok); 4645 return ParseForStatement(labels, ok);
4637 case Token::CONTINUE: 4646 case Token::CONTINUE:
4638 case Token::BREAK: 4647 case Token::BREAK:
4639 case Token::RETURN: 4648 case Token::RETURN:
4640 case Token::THROW: 4649 case Token::THROW:
4641 case Token::TRY: { 4650 case Token::TRY: {
4642 // These statements must have their labels preserved in an enclosing 4651 // These statements must have their labels preserved in an enclosing
4643 // block, as the corresponding AST nodes do not currently store their 4652 // block, as the corresponding AST nodes do not currently store their
4644 // labels. 4653 // labels.
4645 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. 4654 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes.
(...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after
5503 block->set_scope(for_scope); 5512 block->set_scope(for_scope);
5504 loop->Initialize(init, cond, next, body); 5513 loop->Initialize(init, cond, next, body);
5505 return block; 5514 return block;
5506 } else { 5515 } else {
5507 loop->Initialize(init, cond, next, body); 5516 loop->Initialize(init, cond, next, body);
5508 return loop; 5517 return loop;
5509 } 5518 }
5510 } 5519 }
5511 } 5520 }
5512 5521
5522 template <typename Impl>
5523 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
5524 ZoneList<const AstRawString*>* labels, bool* ok) {
5525 // for await '(' ForDeclaration of AssignmentExpression ')'
5526 DCHECK(is_async_function());
5527 DCHECK(allow_harmony_async_iteration());
5528
5529 int stmt_pos = peek_position();
5530 bool bound_names_are_lexical = false;
5531
5532 ForInfo for_info(this);
5533 for_info.mode = ForEachStatement::ITERATE;
5534
5535 // Create an in-between scope for let-bound iteration variables.
5536 BlockState for_state(zone(), &scope_state_);
5537 Expect(Token::FOR, CHECK_OK);
5538 Expect(Token::AWAIT, CHECK_OK);
5539 Expect(Token::LPAREN, CHECK_OK);
5540 for_state.set_start_position(scanner()->location().beg_pos);
5541 for_state.set_is_hidden();
5542
5543 auto loop = factory()->NewForEachStatement(for_info.mode, labels, stmt_pos);
5544 typename Types::Target target(this, loop);
5545
5546 ExpressionT each_variable = impl()->EmptyExpression();
5547
5548 bool has_declarations = false;
5549
5550 switch (peek()) {
5551 case Token::LET:
5552 if (!IsNextLetKeyword()) goto parse_lhs;
5553 /* falls through */
5554 case Token::VAR:
5555 case Token::CONST: {
5556 // The initializer contains declarations
5557 // 'for' 'await' '(' ForDeclaration 'of' AssignmentExpression ')'
5558 // Statement
5559 // 'for' 'await' '(' 'var' ForBinding 'of' AssignmentExpression ')'
5560 // Statement
5561 has_declarations = true;
5562 ParseVariableDeclarations(kForStatement, &for_info.parsing_result,
5563 nullptr, CHECK_OK);
5564 bound_names_are_lexical =
5565 IsLexicalVariableMode(for_info.parsing_result.descriptor.mode);
5566
5567 for_info.position = scanner()->location().beg_pos;
5568
5569 // Only a single declaration is allowed in for-await-of loops
5570 if (for_info.parsing_result.declarations.length() != 1) {
5571 impl()->ReportMessageAt(for_info.parsing_result.bindings_loc,
5572 MessageTemplate::kForInOfLoopMultiBindings,
5573 "for-await-of");
5574 *ok = false;
5575 return impl()->NullStatement();
5576 }
5577
5578 // for-await-of's declarations do not permit initializers.
5579 if (for_info.parsing_result.first_initializer_loc.IsValid()) {
5580 impl()->ReportMessageAt(for_info.parsing_result.first_initializer_loc,
5581 MessageTemplate::kForInOfLoopInitializer,
5582 "for-await-of");
5583 *ok = false;
5584 return impl()->NullStatement();
5585 }
5586 break;
5587 }
5588
5589 default:
5590 parse_lhs : {
5591 // The initializer does not contain declarations.
5592 // 'for' 'await' '(' LeftHandSideExpression 'of' AssignmentExpression ')'
5593 // Statement
5594 int lhs_beg_pos = peek_position();
5595 ExpressionClassifier classifier(this);
5596 ExpressionT lhs = each_variable = ParseLeftHandSideExpression(CHECK_OK);
5597 int lhs_end_pos = scanner()->location().end_pos;
5598
5599 if (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()) {
5600 ValidateAssignmentPattern(CHECK_OK);
5601 } else {
5602 impl()->RewriteNonPattern(CHECK_OK);
5603 each_variable = impl()->CheckAndRewriteReferenceExpression(
5604 lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
5605 kSyntaxError, CHECK_OK);
5606 }
5607 } break;
5608 }
5609
5610 ExpectContextualKeyword(CStrVector("of"), CHECK_OK);
5611 int each_keyword_pos = scanner()->location().beg_pos;
5612
5613 const bool kAllowIn = true;
5614 ExpressionT iterable = impl()->EmptyExpression();
5615
5616 {
5617 ExpressionClassifier classifier(this);
5618 iterable = ParseAssignmentExpression(kAllowIn, CHECK_OK);
5619 impl()->RewriteNonPattern(CHECK_OK);
5620 }
5621
5622 Expect(Token::RPAREN, CHECK_OK);
5623
5624 {
5625 ReturnExprScope no_tail_calls(function_state_,
5626 ReturnExprContext::kInsideForInOfBody);
5627 BlockState block_state(zone(), &scope_state_);
5628 block_state.set_start_position(scanner()->location().beg_pos);
5629
5630 // For legacy compat reasons, give for loops similar treatment to
5631 // if statements in allowing a function declaration for a body
5632 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK);
5633 block_state.set_end_position(scanner()->location().end_pos);
5634
5635 if (has_declarations) {
5636 BlockT body_block = impl()->NullBlock();
5637 impl()->DesugarBindingInForEachStatement(&for_info, &body_block,
5638 &each_variable, CHECK_OK);
5639 body_block->statements()->Add(body, zone());
5640 body_block->set_scope(block_state.FinalizedBlockScope());
5641 for_state.set_end_position(scanner()->location().end_pos);
5642
5643 StatementT final_loop = impl()->InitializeForAwaitOfStatement(
5644 loop, each_variable, iterable, body_block, each_keyword_pos);
5645
5646 BlockT init_block =
5647 impl()->CreateForEachStatementTDZ(impl()->NullBlock(), for_info, ok);
5648
5649 Scope* for_scope = for_state.FinalizedBlockScope();
5650 // Parsed for-in loop w/ variable declarations.
5651 if (!impl()->IsNullStatement(init_block)) {
5652 init_block->statements()->Add(final_loop, zone());
5653 init_block->set_scope(for_scope);
5654 return init_block;
5655 } else {
5656 DCHECK_NULL(for_scope);
5657 return final_loop;
5658 }
5659 } else {
5660 StatementT final_loop = impl()->InitializeForAwaitOfStatement(
5661 loop, each_variable, iterable, body, each_keyword_pos);
5662
5663 Scope* for_scope = for_state.FinalizedBlockScope();
5664 DCHECK_NULL(for_scope);
5665 USE(for_scope);
5666 Scope* block_scope = block_state.FinalizedBlockScope();
5667 DCHECK_NULL(block_scope);
5668 USE(block_scope);
5669 return final_loop;
5670 }
5671
5672 UNREACHABLE();
5673 return impl()->NullStatement();
5674 }
5675 }
5676
5513 #undef CHECK_OK 5677 #undef CHECK_OK
5514 #undef CHECK_OK_CUSTOM 5678 #undef CHECK_OK_CUSTOM
5515 5679
5516 template <typename Impl> 5680 template <typename Impl>
5517 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( 5681 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto(
5518 Token::Value property) { 5682 Token::Value property) {
5519 if (property == Token::SMI || property == Token::NUMBER) return; 5683 if (property == Token::SMI || property == Token::NUMBER) return;
5520 5684
5521 if (IsProto()) { 5685 if (IsProto()) {
5522 if (has_seen_proto_) { 5686 if (has_seen_proto_) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
5561 has_seen_constructor_ = true; 5725 has_seen_constructor_ = true;
5562 return; 5726 return;
5563 } 5727 }
5564 } 5728 }
5565 5729
5566 5730
5567 } // namespace internal 5731 } // namespace internal
5568 } // namespace v8 5732 } // namespace v8
5569 5733
5570 #endif // V8_PARSING_PARSER_BASE_H 5734 #endif // V8_PARSING_PARSER_BASE_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698