| Index: src/parsing/parser.cc
|
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
|
| index dcb973da78ebc39f91b7f157621f37be41c66fad..781ed491ed02b4445b4ab28eb0a3c692f2b2fe18 100644
|
| --- a/src/parsing/parser.cc
|
| +++ b/src/parsing/parser.cc
|
| @@ -553,6 +553,7 @@ Parser::Parser(ParseInfo* info)
|
| set_allow_harmony_trailing_commas(FLAG_harmony_trailing_commas);
|
| set_allow_harmony_class_fields(FLAG_harmony_class_fields);
|
| set_allow_harmony_object_rest_spread(FLAG_harmony_object_rest_spread);
|
| + set_allow_harmony_async_iteration(FLAG_harmony_async_iteration);
|
| for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
|
| ++feature) {
|
| use_counts_[feature] = 0;
|
| @@ -1754,10 +1755,16 @@ Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block,
|
| }
|
| }
|
|
|
| -// !%_IsJSReceiver(result = iterator.next()) &&
|
| -// %ThrowIteratorResultNotAnObject(result)
|
| +// [if (IteratorType == kNormal)]
|
| +// !%_IsJSReceiver(result = iterator.next()) &&
|
| +// %ThrowIteratorResultNotAnObject(result)
|
| +// [else if (IteratorType == kAsync)]
|
| +// !%_IsJSReceiver(result = Await(iterator.next())) &&
|
| +// %ThrowIteratorResultNotAnObject(result)
|
| +// [endif]
|
| Expression* Parser::BuildIteratorNextResult(Expression* iterator,
|
| - Variable* result, int pos) {
|
| + Variable* result, IteratorType type,
|
| + int pos) {
|
| Expression* next_literal = factory()->NewStringLiteral(
|
| ast_value_factory()->next_string(), kNoSourcePosition);
|
| Expression* next_property =
|
| @@ -1766,6 +1773,9 @@ Expression* Parser::BuildIteratorNextResult(Expression* iterator,
|
| new (zone()) ZoneList<Expression*>(0, zone());
|
| Expression* next_call =
|
| factory()->NewCall(next_property, next_arguments, pos);
|
| + if (type == IteratorType::kAsync) {
|
| + next_call = RewriteAwaitExpression(next_call, pos);
|
| + }
|
| Expression* result_proxy = factory()->NewVariableProxy(result);
|
| Expression* left =
|
| factory()->NewAssignment(Token::ASSIGN, result_proxy, next_call, pos);
|
| @@ -1800,7 +1810,7 @@ Statement* Parser::InitializeForEachStatement(ForEachStatement* stmt,
|
| if (for_of != NULL) {
|
| const bool finalize = true;
|
| return InitializeForOfStatement(for_of, each, subject, body, finalize,
|
| - each_keyword_pos);
|
| + IteratorType::kNormal, each_keyword_pos);
|
| } else {
|
| if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
|
| Variable* temp = NewTemporary(ast_value_factory()->empty_string());
|
| @@ -1954,16 +1964,16 @@ Block* Parser::CreateForEachStatementTDZ(Block* init_block,
|
| return init_block;
|
| }
|
|
|
| -Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of,
|
| - Expression* each,
|
| - Expression* iterable,
|
| - Statement* body, bool finalize,
|
| - int next_result_pos) {
|
| +Statement* Parser::InitializeForOfStatement(
|
| + ForEachStatement* for_each, Expression* each, Expression* iterable,
|
| + Statement* body, bool finalize, IteratorType type, int next_result_pos) {
|
| // Create the auxiliary expressions needed for iterating over the iterable,
|
| // and initialize the given ForOfStatement with them.
|
| // If finalize is true, also instrument the loop with code that performs the
|
| // proper ES6 iterator finalization. In that case, the result is not
|
| // immediately a ForOfStatement.
|
| + DCHECK(for_each->IsForOfStatement());
|
| + ForOfStatement* for_of = for_each->AsForOfStatement();
|
|
|
| const int nopos = kNoSourcePosition;
|
| auto avfactory = ast_value_factory();
|
| @@ -1972,22 +1982,27 @@ Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of,
|
| Variable* result = NewTemporary(avfactory->dot_result_string());
|
| Variable* completion = NewTemporary(avfactory->empty_string());
|
|
|
| - // iterator = GetIterator(iterable)
|
| + // iterator = GetIterator(iterable, type)
|
| Expression* assign_iterator;
|
| {
|
| assign_iterator = factory()->NewAssignment(
|
| Token::ASSIGN, factory()->NewVariableProxy(iterator),
|
| - factory()->NewGetIterator(iterable, iterable->position()),
|
| + factory()->NewGetIterator(iterable, type, iterable->position()),
|
| iterable->position());
|
| }
|
|
|
| - // !%_IsJSReceiver(result = iterator.next()) &&
|
| - // %ThrowIteratorResultNotAnObject(result)
|
| + // [if (IteratorType == kNormal)]
|
| + // !%_IsJSReceiver(result = iterator.next()) &&
|
| + // %ThrowIteratorResultNotAnObject(result)
|
| + // [else if (IteratorType == kAsync)]
|
| + // !%_IsJSReceiver(result = Await(iterator.next())) &&
|
| + // %ThrowIteratorResultNotAnObject(result)
|
| + // [endif]
|
| Expression* next_result;
|
| {
|
| Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
|
| next_result =
|
| - BuildIteratorNextResult(iterator_proxy, result, next_result_pos);
|
| + BuildIteratorNextResult(iterator_proxy, result, type, next_result_pos);
|
| }
|
|
|
| // result.done
|
| @@ -2075,7 +2090,8 @@ Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of,
|
|
|
| for_of->Initialize(body, iterator, assign_iterator, next_result, result_done,
|
| assign_each);
|
| - return finalize ? FinalizeForOfStatement(for_of, completion, nopos) : for_of;
|
| + return finalize ? FinalizeForOfStatement(for_of, completion, type, nopos)
|
| + : for_of;
|
| }
|
|
|
| Statement* Parser::DesugarLexicalBindingsInForStatement(
|
| @@ -2740,6 +2756,7 @@ Parser::LazyParsingResult Parser::SkipFunction(
|
| SET_ALLOW(harmony_trailing_commas);
|
| SET_ALLOW(harmony_class_fields);
|
| SET_ALLOW(harmony_object_rest_spread);
|
| + SET_ALLOW(harmony_async_iteration);
|
| #undef SET_ALLOW
|
| }
|
| // Aborting inner function preparsing would leave scopes in an inconsistent
|
| @@ -4153,7 +4170,7 @@ Expression* Parser::RewriteSpreads(ArrayLiteral* lit) {
|
| const bool finalize = false;
|
| InitializeForOfStatement(loop->AsForOfStatement(),
|
| factory()->NewVariableProxy(each), subject,
|
| - append_body, finalize);
|
| + append_body, finalize, IteratorType::kNormal);
|
| do_block->statements()->Add(loop, zone());
|
| }
|
| }
|
| @@ -4345,7 +4362,8 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
|
| Variable* var_iterator = NewTemporary(ast_value_factory()->empty_string());
|
| Statement* get_iterator;
|
| {
|
| - Expression* iterator = factory()->NewGetIterator(iterable, nopos);
|
| + Expression* iterator =
|
| + factory()->NewGetIterator(iterable, GetIterator::Hint::kNormal, nopos);
|
| Expression* iterator_proxy = factory()->NewVariableProxy(var_iterator);
|
| Expression* assignment = factory()->NewAssignment(
|
| Token::ASSIGN, iterator_proxy, iterator, nopos);
|
| @@ -4427,7 +4445,8 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
|
| Block* then = factory()->NewBlock(nullptr, 4 + 1, false, nopos);
|
| BuildIteratorCloseForCompletion(
|
| scope(), then->statements(), var_iterator,
|
| - factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos));
|
| + factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos),
|
| + IteratorType::kNormal);
|
| then->statements()->Add(throw_call, zone());
|
| check_throw = factory()->NewIfStatement(
|
| condition, then, factory()->NewEmptyStatement(nopos), nopos);
|
| @@ -4706,7 +4725,13 @@ void Parser::BuildIteratorClose(ZoneList<Statement*>* statements,
|
| // if (IS_NULL_OR_UNDEFINED(iteratorReturn) {
|
| // return {value: input, done: true};
|
| // }
|
| - // output = %_Call(iteratorReturn, iterator, input);
|
| + //
|
| + // [if (IteratorType == kAsync)]
|
| + // output = Await(%_Call(iteratorReturn, iterator, input));
|
| + // [else]
|
| + // output = %_Call(iteratorReturn, iterator, input);
|
| + // [endif]
|
| + //
|
| // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
|
| //
|
|
|
| @@ -4794,7 +4819,8 @@ void Parser::BuildIteratorClose(ZoneList<Statement*>* statements,
|
|
|
| void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion,
|
| Expression* condition, Variable* iter,
|
| - Block* iterator_use, Block* target) {
|
| + Block* iterator_use, Block* target,
|
| + IteratorType type) {
|
| //
|
| // This function adds two statements to [target], corresponding to the
|
| // following code:
|
| @@ -4850,8 +4876,8 @@ void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion,
|
| {
|
| Block* block = factory()->NewBlock(nullptr, 2, true, nopos);
|
| Expression* proxy = factory()->NewVariableProxy(completion);
|
| - BuildIteratorCloseForCompletion(use_scope, block->statements(), iter,
|
| - proxy);
|
| + BuildIteratorCloseForCompletion(use_scope, block->statements(), iter, proxy,
|
| + type);
|
| DCHECK(block->statements()->length() == 2);
|
|
|
| maybe_close = factory()->NewBlock(nullptr, 1, true, nopos);
|
| @@ -4910,7 +4936,8 @@ void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion,
|
| void Parser::BuildIteratorCloseForCompletion(Scope* scope,
|
| ZoneList<Statement*>* statements,
|
| Variable* iterator,
|
| - Expression* completion) {
|
| + Expression* completion,
|
| + IteratorType type) {
|
| //
|
| // This function adds two statements to [statements], corresponding to the
|
| // following code:
|
| @@ -4968,6 +4995,10 @@ void Parser::BuildIteratorCloseForCompletion(Scope* scope,
|
| Expression* call =
|
| factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos);
|
|
|
| + if (type == IteratorType::kAsync) {
|
| + call = RewriteAwaitExpression(call, nopos);
|
| + }
|
| +
|
| Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos);
|
| try_block->statements()->Add(factory()->NewExpressionStatement(call, nopos),
|
| zone());
|
| @@ -5067,7 +5098,8 @@ void Parser::BuildIteratorCloseForCompletion(Scope* scope,
|
| }
|
|
|
| Statement* Parser::FinalizeForOfStatement(ForOfStatement* loop,
|
| - Variable* var_completion, int pos) {
|
| + Variable* var_completion,
|
| + IteratorType type, int pos) {
|
| //
|
| // This function replaces the loop with the following wrapping:
|
| //
|
| @@ -5111,7 +5143,7 @@ Statement* Parser::FinalizeForOfStatement(ForOfStatement* loop,
|
| DCHECK_EQ(scope()->scope_type(), BLOCK_SCOPE);
|
|
|
| FinalizeIteratorUse(loop_scope, var_completion, closing_condition,
|
| - loop->iterator(), try_block, final_loop);
|
| + loop->iterator(), try_block, final_loop, type);
|
| }
|
|
|
| return final_loop;
|
|
|