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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: src/parsing/parser-base.h
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
index 777cad1ac79dfdcdceb8872bdc7bd316ffbb42ea..c2db29a8afbeb50effed013015c6ed30781f091e 100644
--- a/src/parsing/parser-base.h
+++ b/src/parsing/parser-base.h
@@ -225,7 +225,8 @@ class ParserBase {
allow_harmony_trailing_commas_(false),
allow_harmony_class_fields_(false),
allow_harmony_object_rest_spread_(false),
- allow_harmony_dynamic_import_(false) {}
+ allow_harmony_dynamic_import_(false),
+ allow_harmony_async_iteration_(false) {}
#define ALLOW_ACCESSORS(name) \
bool allow_##name() const { return allow_##name##_; } \
@@ -240,6 +241,7 @@ class ParserBase {
ALLOW_ACCESSORS(harmony_class_fields);
ALLOW_ACCESSORS(harmony_object_rest_spread);
ALLOW_ACCESSORS(harmony_dynamic_import);
+ ALLOW_ACCESSORS(harmony_async_iteration);
#undef ALLOW_ACCESSORS
@@ -1307,6 +1309,8 @@ class ParserBase {
ForInfo* for_info, BlockState* for_state,
ZoneList<const AstRawString*>* labels,
bool* ok);
+ StatementT ParseForAwaitStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
bool IsNextLetKeyword();
bool IsTrivialExpression();
@@ -1503,6 +1507,7 @@ class ParserBase {
bool allow_harmony_class_fields_;
bool allow_harmony_object_rest_spread_;
bool allow_harmony_dynamic_import_;
+ bool allow_harmony_async_iteration_;
friend class DiscardableZoneScope;
};
@@ -4815,6 +4820,10 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement(
case Token::WHILE:
return ParseWhileStatement(labels, ok);
case Token::FOR:
+ if (V8_UNLIKELY(allow_harmony_async_iteration() && is_async_function() &&
+ PeekAhead() == Token::AWAIT)) {
+ return ParseForAwaitStatement(labels, ok);
+ }
return ParseForStatement(labels, ok);
case Token::CONTINUE:
case Token::BREAK:
@@ -5721,6 +5730,160 @@ void ParserBase<Impl>::MarkLoopVariableAsAssigned(Scope* scope, Variable* var) {
}
template <typename Impl>
+typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
+ ZoneList<const AstRawString*>* labels, bool* ok) {
+ // for await '(' ForDeclaration of AssignmentExpression ')'
+ DCHECK(is_async_function());
+ DCHECK(allow_harmony_async_iteration());
+
+ int stmt_pos = peek_position();
+
+ ForInfo for_info(this);
+ for_info.mode = ForEachStatement::ITERATE;
+
+ // Create an in-between scope for let-bound iteration variables.
+ BlockState for_state(zone(), &scope_state_);
+ Expect(Token::FOR, CHECK_OK);
+ Expect(Token::AWAIT, CHECK_OK);
+ Expect(Token::LPAREN, CHECK_OK);
+ for_state.set_start_position(scanner()->location().beg_pos);
+ for_state.set_is_hidden();
+
+ auto loop = factory()->NewForEachStatement(for_info.mode, labels, stmt_pos);
+ typename Types::Target target(this, loop);
+
+ ExpressionT each_variable = impl()->EmptyExpression();
+
+ bool has_declarations = false;
+
+ switch (peek()) {
+ case Token::LET:
+ 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.
+ /* falls through */
+ case Token::VAR:
+ case Token::CONST: {
+ // The initializer contains declarations
+ // 'for' 'await' '(' ForDeclaration 'of' AssignmentExpression ')'
+ // Statement
+ // 'for' 'await' '(' 'var' ForBinding 'of' AssignmentExpression ')'
+ // Statement
+ has_declarations = true;
+ ParseVariableDeclarations(kForStatement, &for_info.parsing_result,
+ nullptr, CHECK_OK);
+ for_info.position = scanner()->location().beg_pos;
+
+ // Only a single declaration is allowed in for-await-of loops
+ if (for_info.parsing_result.declarations.length() != 1) {
+ impl()->ReportMessageAt(for_info.parsing_result.bindings_loc,
+ MessageTemplate::kForInOfLoopMultiBindings,
+ "for-await-of");
+ *ok = false;
+ return impl()->NullStatement();
+ }
+
+ // for-await-of's declarations do not permit initializers.
+ if (for_info.parsing_result.first_initializer_loc.IsValid()) {
+ impl()->ReportMessageAt(for_info.parsing_result.first_initializer_loc,
+ MessageTemplate::kForInOfLoopInitializer,
+ "for-await-of");
+ *ok = false;
+ return impl()->NullStatement();
+ }
+ break;
+ }
+
+ default:
+ parse_lhs : {
+ // The initializer does not contain declarations.
+ // 'for' 'await' '(' LeftHandSideExpression 'of' AssignmentExpression ')'
+ // Statement
+ int lhs_beg_pos = peek_position();
+ ExpressionClassifier classifier(this);
+ ExpressionT lhs = each_variable = ParseLeftHandSideExpression(CHECK_OK);
+ int lhs_end_pos = scanner()->location().end_pos;
+
+ if (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()) {
+ ValidateAssignmentPattern(CHECK_OK);
+ } else {
+ impl()->RewriteNonPattern(CHECK_OK);
+ each_variable = impl()->CheckAndRewriteReferenceExpression(
+ lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
+ kSyntaxError, CHECK_OK);
+ }
+ } break;
+ }
+
+ ExpectContextualKeyword(CStrVector("of"), CHECK_OK);
+ int each_keyword_pos = scanner()->location().beg_pos;
+
+ const bool kAllowIn = true;
+ ExpressionT iterable = impl()->EmptyExpression();
+
+ {
+ ExpressionClassifier classifier(this);
+ iterable = ParseAssignmentExpression(kAllowIn, CHECK_OK);
+ impl()->RewriteNonPattern(CHECK_OK);
+ }
+
+ Expect(Token::RPAREN, CHECK_OK);
+
+ StatementT final_loop = impl()->NullStatement();
+ {
+ ReturnExprScope no_tail_calls(function_state_,
+ ReturnExprContext::kInsideForInOfBody);
+ BlockState block_state(zone(), &scope_state_);
+ block_state.set_start_position(scanner()->location().beg_pos);
+
+ // 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
+ // if statements in allowing a function declaration for a body
+ StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK);
+ block_state.set_end_position(scanner()->location().end_pos);
+
+ if (has_declarations) {
+ BlockT body_block = impl()->NullBlock();
+ impl()->DesugarBindingInForEachStatement(&for_info, &body_block,
+ &each_variable, CHECK_OK);
+ body_block->statements()->Add(body, zone());
+ body_block->set_scope(block_state.FinalizedBlockScope());
+ for_state.set_end_position(scanner()->location().end_pos);
+
+ const bool finalize = true;
+ final_loop = impl()->InitializeForOfStatement(
+ loop, each_variable, iterable, body_block, finalize,
+ IteratorType::kAsync, each_keyword_pos);
+ } else {
+ const bool finalize = true;
+ final_loop = impl()->InitializeForOfStatement(
+ loop, each_variable, iterable, body, finalize, IteratorType::kAsync,
+ each_keyword_pos);
+
+ Scope* for_scope = for_state.FinalizedBlockScope();
+ DCHECK_NULL(for_scope);
+ USE(for_scope);
+ Scope* block_scope = block_state.FinalizedBlockScope();
+ DCHECK_NULL(block_scope);
+ USE(block_scope);
+ return final_loop;
+ }
+ }
+
+ DCHECK(has_declarations);
+ BlockT init_block =
+ impl()->CreateForEachStatementTDZ(impl()->NullBlock(), for_info, ok);
+
+ for_state.set_end_position(scanner()->location().end_pos);
+ Scope* for_scope = for_state.FinalizedBlockScope();
+ // Parsed for-in loop w/ variable declarations.
+ if (!impl()->IsNullStatement(init_block)) {
+ init_block->statements()->Add(final_loop, zone());
+ init_block->set_scope(for_scope);
+ return init_block;
+ }
+ DCHECK_NULL(for_scope);
+ return final_loop;
+}
+
+template <typename Impl>
void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto(
Token::Value property) {
if (property == Token::SMI || property == Token::NUMBER) return;

Powered by Google App Engine
This is Rietveld 408576698