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

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: ...and uncomment the previously failing tests... Created 3 years, 10 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 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile), 218 default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile),
219 function_literal_id_(0), 219 function_literal_id_(0),
220 allow_natives_(false), 220 allow_natives_(false),
221 allow_tailcalls_(false), 221 allow_tailcalls_(false),
222 allow_harmony_do_expressions_(false), 222 allow_harmony_do_expressions_(false),
223 allow_harmony_function_sent_(false), 223 allow_harmony_function_sent_(false),
224 allow_harmony_restrictive_generators_(false), 224 allow_harmony_restrictive_generators_(false),
225 allow_harmony_trailing_commas_(false), 225 allow_harmony_trailing_commas_(false),
226 allow_harmony_class_fields_(false), 226 allow_harmony_class_fields_(false),
227 allow_harmony_object_rest_spread_(false), 227 allow_harmony_object_rest_spread_(false),
228 allow_harmony_dynamic_import_(false) {} 228 allow_harmony_dynamic_import_(false),
229 allow_harmony_async_iteration_(false) {}
229 230
230 #define ALLOW_ACCESSORS(name) \ 231 #define ALLOW_ACCESSORS(name) \
231 bool allow_##name() const { return allow_##name##_; } \ 232 bool allow_##name() const { return allow_##name##_; } \
232 void set_allow_##name(bool allow) { allow_##name##_ = allow; } 233 void set_allow_##name(bool allow) { allow_##name##_ = allow; }
233 234
234 ALLOW_ACCESSORS(natives); 235 ALLOW_ACCESSORS(natives);
235 ALLOW_ACCESSORS(tailcalls); 236 ALLOW_ACCESSORS(tailcalls);
236 ALLOW_ACCESSORS(harmony_do_expressions); 237 ALLOW_ACCESSORS(harmony_do_expressions);
237 ALLOW_ACCESSORS(harmony_function_sent); 238 ALLOW_ACCESSORS(harmony_function_sent);
238 ALLOW_ACCESSORS(harmony_restrictive_generators); 239 ALLOW_ACCESSORS(harmony_restrictive_generators);
239 ALLOW_ACCESSORS(harmony_trailing_commas); 240 ALLOW_ACCESSORS(harmony_trailing_commas);
240 ALLOW_ACCESSORS(harmony_class_fields); 241 ALLOW_ACCESSORS(harmony_class_fields);
241 ALLOW_ACCESSORS(harmony_object_rest_spread); 242 ALLOW_ACCESSORS(harmony_object_rest_spread);
242 ALLOW_ACCESSORS(harmony_dynamic_import); 243 ALLOW_ACCESSORS(harmony_dynamic_import);
244 ALLOW_ACCESSORS(harmony_async_iteration);
243 245
244 #undef ALLOW_ACCESSORS 246 #undef ALLOW_ACCESSORS
245 247
246 uintptr_t stack_limit() const { return stack_limit_; } 248 uintptr_t stack_limit() const { return stack_limit_; }
247 249
248 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } 250 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; }
249 251
250 void set_default_eager_compile_hint( 252 void set_default_eager_compile_hint(
251 FunctionLiteral::EagerCompileHint eager_compile_hint) { 253 FunctionLiteral::EagerCompileHint eager_compile_hint) {
252 default_eager_compile_hint_ = eager_compile_hint; 254 default_eager_compile_hint_ = eager_compile_hint;
(...skipping 1047 matching lines...) Expand 10 before | Expand all | Expand 10 after
1300 int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos, 1302 int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos,
1301 ForInfo* for_info, BlockState* for_state, 1303 ForInfo* for_info, BlockState* for_state,
1302 ZoneList<const AstRawString*>* labels, bool* ok); 1304 ZoneList<const AstRawString*>* labels, bool* ok);
1303 1305
1304 // Parse a C-style for loop: 'for (<init>; <cond>; <step>) { ... }' 1306 // Parse a C-style for loop: 'for (<init>; <cond>; <step>) { ... }'
1305 StatementT ParseStandardForLoop(int stmt_pos, StatementT init, 1307 StatementT ParseStandardForLoop(int stmt_pos, StatementT init,
1306 bool bound_names_are_lexical, 1308 bool bound_names_are_lexical,
1307 ForInfo* for_info, BlockState* for_state, 1309 ForInfo* for_info, BlockState* for_state,
1308 ZoneList<const AstRawString*>* labels, 1310 ZoneList<const AstRawString*>* labels,
1309 bool* ok); 1311 bool* ok);
1312 StatementT ParseForAwaitStatement(ZoneList<const AstRawString*>* labels,
1313 bool* ok);
1310 1314
1311 bool IsNextLetKeyword(); 1315 bool IsNextLetKeyword();
1312 bool IsTrivialExpression(); 1316 bool IsTrivialExpression();
1313 1317
1314 // Checks if the expression is a valid reference expression (e.g., on the 1318 // Checks if the expression is a valid reference expression (e.g., on the
1315 // left-hand side of assignments). Although ruled out by ECMA as early errors, 1319 // left-hand side of assignments). Although ruled out by ECMA as early errors,
1316 // we allow calls for web compatibility and rewrite them to a runtime throw. 1320 // we allow calls for web compatibility and rewrite them to a runtime throw.
1317 ExpressionT CheckAndRewriteReferenceExpression( 1321 ExpressionT CheckAndRewriteReferenceExpression(
1318 ExpressionT expression, int beg_pos, int end_pos, 1322 ExpressionT expression, int beg_pos, int end_pos,
1319 MessageTemplate::Template message, bool* ok); 1323 MessageTemplate::Template message, bool* ok);
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1496 1500
1497 bool allow_natives_; 1501 bool allow_natives_;
1498 bool allow_tailcalls_; 1502 bool allow_tailcalls_;
1499 bool allow_harmony_do_expressions_; 1503 bool allow_harmony_do_expressions_;
1500 bool allow_harmony_function_sent_; 1504 bool allow_harmony_function_sent_;
1501 bool allow_harmony_restrictive_generators_; 1505 bool allow_harmony_restrictive_generators_;
1502 bool allow_harmony_trailing_commas_; 1506 bool allow_harmony_trailing_commas_;
1503 bool allow_harmony_class_fields_; 1507 bool allow_harmony_class_fields_;
1504 bool allow_harmony_object_rest_spread_; 1508 bool allow_harmony_object_rest_spread_;
1505 bool allow_harmony_dynamic_import_; 1509 bool allow_harmony_dynamic_import_;
1510 bool allow_harmony_async_iteration_;
1506 1511
1507 friend class DiscardableZoneScope; 1512 friend class DiscardableZoneScope;
1508 }; 1513 };
1509 1514
1510 template <typename Impl> 1515 template <typename Impl>
1511 ParserBase<Impl>::FunctionState::FunctionState( 1516 ParserBase<Impl>::FunctionState::FunctionState(
1512 FunctionState** function_state_stack, ScopeState** scope_stack, 1517 FunctionState** function_state_stack, ScopeState** scope_stack,
1513 DeclarationScope* scope) 1518 DeclarationScope* scope)
1514 : ScopeState(scope_stack, scope), 1519 : ScopeState(scope_stack, scope),
1515 next_materialized_literal_index_(0), 1520 next_materialized_literal_index_(0),
(...skipping 3292 matching lines...) Expand 10 before | Expand all | Expand 10 after
4808 case Token::SEMICOLON: 4813 case Token::SEMICOLON:
4809 Next(); 4814 Next();
4810 return factory()->NewEmptyStatement(kNoSourcePosition); 4815 return factory()->NewEmptyStatement(kNoSourcePosition);
4811 case Token::IF: 4816 case Token::IF:
4812 return ParseIfStatement(labels, ok); 4817 return ParseIfStatement(labels, ok);
4813 case Token::DO: 4818 case Token::DO:
4814 return ParseDoWhileStatement(labels, ok); 4819 return ParseDoWhileStatement(labels, ok);
4815 case Token::WHILE: 4820 case Token::WHILE:
4816 return ParseWhileStatement(labels, ok); 4821 return ParseWhileStatement(labels, ok);
4817 case Token::FOR: 4822 case Token::FOR:
4823 if (V8_UNLIKELY(allow_harmony_async_iteration() && is_async_function() &&
4824 PeekAhead() == Token::AWAIT)) {
4825 return ParseForAwaitStatement(labels, ok);
4826 }
4818 return ParseForStatement(labels, ok); 4827 return ParseForStatement(labels, ok);
4819 case Token::CONTINUE: 4828 case Token::CONTINUE:
4820 case Token::BREAK: 4829 case Token::BREAK:
4821 case Token::RETURN: 4830 case Token::RETURN:
4822 case Token::THROW: 4831 case Token::THROW:
4823 case Token::TRY: { 4832 case Token::TRY: {
4824 // These statements must have their labels preserved in an enclosing 4833 // These statements must have their labels preserved in an enclosing
4825 // block, as the corresponding AST nodes do not currently store their 4834 // block, as the corresponding AST nodes do not currently store their
4826 // labels. 4835 // labels.
4827 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. 4836 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes.
(...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after
5714 } 5723 }
5715 5724
5716 template <typename Impl> 5725 template <typename Impl>
5717 void ParserBase<Impl>::MarkLoopVariableAsAssigned(Scope* scope, Variable* var) { 5726 void ParserBase<Impl>::MarkLoopVariableAsAssigned(Scope* scope, Variable* var) {
5718 if (!IsLexicalVariableMode(var->mode()) && !scope->is_function_scope()) { 5727 if (!IsLexicalVariableMode(var->mode()) && !scope->is_function_scope()) {
5719 var->set_maybe_assigned(); 5728 var->set_maybe_assigned();
5720 } 5729 }
5721 } 5730 }
5722 5731
5723 template <typename Impl> 5732 template <typename Impl>
5733 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
5734 ZoneList<const AstRawString*>* labels, bool* ok) {
5735 // for await '(' ForDeclaration of AssignmentExpression ')'
5736 DCHECK(is_async_function());
5737 DCHECK(allow_harmony_async_iteration());
5738
5739 int stmt_pos = peek_position();
5740
5741 ForInfo for_info(this);
5742 for_info.mode = ForEachStatement::ITERATE;
5743
5744 // Create an in-between scope for let-bound iteration variables.
5745 BlockState for_state(zone(), &scope_state_);
5746 Expect(Token::FOR, CHECK_OK);
5747 Expect(Token::AWAIT, CHECK_OK);
5748 Expect(Token::LPAREN, CHECK_OK);
5749 for_state.set_start_position(scanner()->location().beg_pos);
5750 for_state.set_is_hidden();
5751
5752 auto loop = factory()->NewForEachStatement(for_info.mode, labels, stmt_pos);
5753 typename Types::Target target(this, loop);
5754
5755 ExpressionT each_variable = impl()->EmptyExpression();
5756
5757 bool has_declarations = false;
5758
5759 switch (peek()) {
5760 case Token::LET:
5761 if (!IsNextLetKeyword()) goto parse_lhs;
adamk 2017/02/14 18:47:53 This is the first goto in the parser. Given that i
caitp 2017/02/14 20:27:29 Seems harder to read, to me, but alright
caitp 2017/02/14 21:40:58 Done.
5762 /* falls through */
5763 case Token::VAR:
5764 case Token::CONST: {
5765 // The initializer contains declarations
5766 // 'for' 'await' '(' ForDeclaration 'of' AssignmentExpression ')'
5767 // Statement
5768 // 'for' 'await' '(' 'var' ForBinding 'of' AssignmentExpression ')'
5769 // Statement
5770 has_declarations = true;
5771 ParseVariableDeclarations(kForStatement, &for_info.parsing_result,
5772 nullptr, CHECK_OK);
5773 for_info.position = scanner()->location().beg_pos;
5774
5775 // Only a single declaration is allowed in for-await-of loops
5776 if (for_info.parsing_result.declarations.length() != 1) {
5777 impl()->ReportMessageAt(for_info.parsing_result.bindings_loc,
5778 MessageTemplate::kForInOfLoopMultiBindings,
5779 "for-await-of");
5780 *ok = false;
5781 return impl()->NullStatement();
5782 }
5783
5784 // for-await-of's declarations do not permit initializers.
5785 if (for_info.parsing_result.first_initializer_loc.IsValid()) {
5786 impl()->ReportMessageAt(for_info.parsing_result.first_initializer_loc,
5787 MessageTemplate::kForInOfLoopInitializer,
5788 "for-await-of");
5789 *ok = false;
5790 return impl()->NullStatement();
5791 }
5792 break;
5793 }
5794
5795 default:
5796 parse_lhs : {
5797 // The initializer does not contain declarations.
5798 // 'for' 'await' '(' LeftHandSideExpression 'of' AssignmentExpression ')'
5799 // Statement
5800 int lhs_beg_pos = peek_position();
5801 ExpressionClassifier classifier(this);
5802 ExpressionT lhs = each_variable = ParseLeftHandSideExpression(CHECK_OK);
5803 int lhs_end_pos = scanner()->location().end_pos;
5804
5805 if (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()) {
5806 ValidateAssignmentPattern(CHECK_OK);
5807 } else {
5808 impl()->RewriteNonPattern(CHECK_OK);
5809 each_variable = impl()->CheckAndRewriteReferenceExpression(
5810 lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
5811 kSyntaxError, CHECK_OK);
5812 }
5813 } break;
5814 }
5815
5816 ExpectContextualKeyword(CStrVector("of"), CHECK_OK);
5817 int each_keyword_pos = scanner()->location().beg_pos;
5818
5819 const bool kAllowIn = true;
5820 ExpressionT iterable = impl()->EmptyExpression();
5821
5822 {
5823 ExpressionClassifier classifier(this);
5824 iterable = ParseAssignmentExpression(kAllowIn, CHECK_OK);
5825 impl()->RewriteNonPattern(CHECK_OK);
5826 }
5827
5828 Expect(Token::RPAREN, CHECK_OK);
5829
5830 StatementT final_loop = impl()->NullStatement();
5831 {
5832 ReturnExprScope no_tail_calls(function_state_,
5833 ReturnExprContext::kInsideForInOfBody);
5834 BlockState block_state(zone(), &scope_state_);
5835 block_state.set_start_position(scanner()->location().beg_pos);
5836
5837 // For legacy compat reasons, give for loops similar treatment to
adamk 2017/02/14 18:47:53 Seems odd that new syntax still maintains this leg
caitp 2017/02/14 20:27:29 The spec doesn't say anything about any of this, b
5838 // if statements in allowing a function declaration for a body
5839 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK);
5840 block_state.set_end_position(scanner()->location().end_pos);
5841
5842 if (has_declarations) {
5843 BlockT body_block = impl()->NullBlock();
5844 impl()->DesugarBindingInForEachStatement(&for_info, &body_block,
5845 &each_variable, CHECK_OK);
5846 body_block->statements()->Add(body, zone());
5847 body_block->set_scope(block_state.FinalizedBlockScope());
5848 for_state.set_end_position(scanner()->location().end_pos);
5849
5850 const bool finalize = true;
5851 final_loop = impl()->InitializeForOfStatement(
5852 loop, each_variable, iterable, body_block, finalize,
5853 IteratorType::kAsync, each_keyword_pos);
5854 } else {
5855 const bool finalize = true;
5856 final_loop = impl()->InitializeForOfStatement(
5857 loop, each_variable, iterable, body, finalize, IteratorType::kAsync,
5858 each_keyword_pos);
5859
5860 Scope* for_scope = for_state.FinalizedBlockScope();
5861 DCHECK_NULL(for_scope);
5862 USE(for_scope);
5863 Scope* block_scope = block_state.FinalizedBlockScope();
5864 DCHECK_NULL(block_scope);
5865 USE(block_scope);
5866 return final_loop;
5867 }
5868 }
5869
5870 DCHECK(has_declarations);
5871 BlockT init_block =
5872 impl()->CreateForEachStatementTDZ(impl()->NullBlock(), for_info, ok);
5873
5874 for_state.set_end_position(scanner()->location().end_pos);
5875 Scope* for_scope = for_state.FinalizedBlockScope();
5876 // Parsed for-in loop w/ variable declarations.
5877 if (!impl()->IsNullStatement(init_block)) {
5878 init_block->statements()->Add(final_loop, zone());
5879 init_block->set_scope(for_scope);
5880 return init_block;
5881 }
5882 DCHECK_NULL(for_scope);
5883 return final_loop;
5884 }
5885
5886 template <typename Impl>
5724 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( 5887 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto(
5725 Token::Value property) { 5888 Token::Value property) {
5726 if (property == Token::SMI || property == Token::NUMBER) return; 5889 if (property == Token::SMI || property == Token::NUMBER) return;
5727 5890
5728 if (IsProto()) { 5891 if (IsProto()) {
5729 if (has_seen_proto_) { 5892 if (has_seen_proto_) {
5730 this->parser()->classifier()->RecordExpressionError( 5893 this->parser()->classifier()->RecordExpressionError(
5731 this->scanner()->location(), MessageTemplate::kDuplicateProto); 5894 this->scanner()->location(), MessageTemplate::kDuplicateProto);
5732 return; 5895 return;
5733 } 5896 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
5771 } 5934 }
5772 5935
5773 #undef CHECK_OK 5936 #undef CHECK_OK
5774 #undef CHECK_OK_CUSTOM 5937 #undef CHECK_OK_CUSTOM
5775 #undef CHECK_OK_VOID 5938 #undef CHECK_OK_VOID
5776 5939
5777 } // namespace internal 5940 } // namespace internal
5778 } // namespace v8 5941 } // namespace v8
5779 5942
5780 #endif // V8_PARSING_PARSER_BASE_H 5943 #endif // V8_PARSING_PARSER_BASE_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698