| Index: src/parsing/parser.cc
|
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
|
| index ecde4f28831eced822e4e9d7a25b9a0293407fef..1fce16a6112e62dd385f0df04422a4c523eb897f 100644
|
| --- a/src/parsing/parser.cc
|
| +++ b/src/parsing/parser.cc
|
| @@ -554,6 +554,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_spread(FLAG_harmony_object_spread);
|
| + set_allow_harmony_async_iteration(FLAG_harmony_async_iteration);
|
| for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
|
| ++feature) {
|
| use_counts_[feature] = 0;
|
| @@ -1805,6 +1806,45 @@ Expression* Parser::BuildIteratorNextResult(Expression* iterator,
|
| throw_call, pos);
|
| }
|
|
|
| +Expression* Parser::AwaitIteratorNextResult(Expression* iterator,
|
| + Variable* result, int pos) {
|
| + Expression* next_literal = factory()->NewStringLiteral(
|
| + ast_value_factory()->next_string(), kNoSourcePosition);
|
| + Expression* next_property =
|
| + factory()->NewProperty(iterator, next_literal, kNoSourcePosition);
|
| + ZoneList<Expression*>* next_arguments =
|
| + new (zone()) ZoneList<Expression*>(0, zone());
|
| + Expression* next_call =
|
| + factory()->NewCall(next_property, next_arguments, pos);
|
| +
|
| + // Await(iterator.next())
|
| + Expression* await_next_call = RewriteAwaitExpression(next_call, pos);
|
| +
|
| + Expression* result_proxy = factory()->NewVariableProxy(result);
|
| + Expression* left = factory()->NewAssignment(Token::ASSIGN, result_proxy,
|
| + await_next_call, pos);
|
| +
|
| + // %_IsJSReceiver(...)
|
| + ZoneList<Expression*>* is_spec_object_args =
|
| + new (zone()) ZoneList<Expression*>(1, zone());
|
| + is_spec_object_args->Add(left, zone());
|
| + Expression* is_spec_object_call = factory()->NewCallRuntime(
|
| + Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
|
| +
|
| + // %ThrowIteratorResultNotAnObject(result)
|
| + Expression* result_proxy_again = factory()->NewVariableProxy(result);
|
| + ZoneList<Expression*>* throw_arguments =
|
| + new (zone()) ZoneList<Expression*>(1, zone());
|
| + throw_arguments->Add(result_proxy_again, zone());
|
| + Expression* throw_call = factory()->NewCallRuntime(
|
| + Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos);
|
| +
|
| + return factory()->NewBinaryOperation(
|
| + Token::AND,
|
| + factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos),
|
| + throw_call, pos);
|
| +}
|
| +
|
| Statement* Parser::InitializeForEachStatement(ForEachStatement* stmt,
|
| Expression* each,
|
| Expression* subject,
|
| @@ -2092,6 +2132,132 @@ Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of,
|
| return finalize ? FinalizeForOfStatement(for_of, completion, nopos) : for_of;
|
| }
|
|
|
| +Statement* Parser::InitializeForAwaitOfStatement(ForEachStatement* stmt,
|
| + Expression* each,
|
| + Expression* iterable,
|
| + Statement* body, bool finalize,
|
| + int next_result_pos) {
|
| + DCHECK(stmt->IsForOfStatement());
|
| + ForOfStatement* for_of = stmt->AsForOfStatement();
|
| +
|
| + // 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.
|
| +
|
| + const int nopos = kNoSourcePosition;
|
| + auto avfactory = ast_value_factory();
|
| +
|
| + Variable* iterator = NewTemporary(ast_value_factory()->dot_iterator_string());
|
| + Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
|
| + Variable* completion = NewTemporary(avfactory->empty_string());
|
| +
|
| + // iterator = GetIterator(iterable, async)
|
| + Expression* assign_iterator;
|
| + {
|
| + assign_iterator = factory()->NewAssignment(
|
| + Token::ASSIGN, factory()->NewVariableProxy(iterator),
|
| + factory()->NewGetIterator(iterable, GetIterator::kAsync,
|
| + iterable->position()),
|
| + iterable->position());
|
| + }
|
| +
|
| + Expression* next_result;
|
| + {
|
| + Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
|
| + next_result =
|
| + AwaitIteratorNextResult(iterator_proxy, result, next_result_pos);
|
| + }
|
| +
|
| + // result.done
|
| + Expression* result_done;
|
| + {
|
| + Expression* done_literal = factory()->NewStringLiteral(
|
| + ast_value_factory()->done_string(), kNoSourcePosition);
|
| + Expression* result_proxy = factory()->NewVariableProxy(result);
|
| + result_done =
|
| + factory()->NewProperty(result_proxy, done_literal, kNoSourcePosition);
|
| + }
|
| +
|
| + // result.value
|
| + Expression* result_value;
|
| + {
|
| + Expression* value_literal =
|
| + factory()->NewStringLiteral(avfactory->value_string(), nopos);
|
| + Expression* result_proxy = factory()->NewVariableProxy(result);
|
| + result_value = factory()->NewProperty(result_proxy, value_literal, nopos);
|
| + }
|
| +
|
| + // {{completion = kAbruptCompletion;}}
|
| + Statement* set_completion_abrupt;
|
| + if (finalize) {
|
| + Expression* proxy = factory()->NewVariableProxy(completion);
|
| + Expression* assignment = factory()->NewAssignment(
|
| + Token::ASSIGN, proxy,
|
| + factory()->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);
|
| +
|
| + Block* block = factory()->NewBlock(nullptr, 1, true, nopos);
|
| + block->statements()->Add(
|
| + factory()->NewExpressionStatement(assignment, nopos), zone());
|
| + set_completion_abrupt = block;
|
| + }
|
| +
|
| + // do { let tmp = #result_value; #set_completion_abrupt; tmp }
|
| + // Expression* result_value (gets overwritten)
|
| + if (finalize) {
|
| + Variable* var_tmp = NewTemporary(avfactory->empty_string());
|
| + Expression* tmp = factory()->NewVariableProxy(var_tmp);
|
| + Expression* assignment =
|
| + factory()->NewAssignment(Token::ASSIGN, tmp, result_value, nopos);
|
| +
|
| + Block* block = factory()->NewBlock(nullptr, 2, false, nopos);
|
| + block->statements()->Add(
|
| + factory()->NewExpressionStatement(assignment, nopos), zone());
|
| + block->statements()->Add(set_completion_abrupt, zone());
|
| +
|
| + result_value = factory()->NewDoExpression(block, var_tmp, nopos);
|
| + }
|
| +
|
| + // each = #result_value;
|
| + Expression* assign_each;
|
| + {
|
| + assign_each =
|
| + factory()->NewAssignment(Token::ASSIGN, each, result_value, nopos);
|
| + if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
|
| + assign_each = PatternRewriter::RewriteDestructuringAssignment(
|
| + this, assign_each->AsAssignment(), scope());
|
| + }
|
| + }
|
| +
|
| + // {{completion = kNormalCompletion;}}
|
| + Statement* set_completion_normal;
|
| + if (finalize) {
|
| + Expression* proxy = factory()->NewVariableProxy(completion);
|
| + Expression* assignment = factory()->NewAssignment(
|
| + Token::ASSIGN, proxy,
|
| + factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
|
| +
|
| + Block* block = factory()->NewBlock(nullptr, 1, true, nopos);
|
| + block->statements()->Add(
|
| + factory()->NewExpressionStatement(assignment, nopos), zone());
|
| + set_completion_normal = block;
|
| + }
|
| +
|
| + // { #loop-body; #set_completion_normal }
|
| + // Statement* body (gets overwritten)
|
| + if (finalize) {
|
| + Block* block = factory()->NewBlock(nullptr, 2, false, nopos);
|
| + block->statements()->Add(body, zone());
|
| + block->statements()->Add(set_completion_normal, zone());
|
| + body = block;
|
| + }
|
| +
|
| + for_of->Initialize(body, iterator, assign_iterator, next_result, result_done,
|
| + assign_each);
|
| + return finalize ? FinalizeForOfStatement(for_of, completion, nopos) : for_of;
|
| +}
|
| +
|
| Statement* Parser::DesugarLexicalBindingsInForStatement(
|
| ForStatement* loop, Statement* init, Expression* cond, Statement* next,
|
| Statement* body, Scope* inner_scope, const ForInfo& for_info, bool* ok) {
|
| @@ -2755,6 +2921,7 @@ Parser::LazyParsingResult Parser::SkipFunction(
|
| SET_ALLOW(harmony_trailing_commas);
|
| SET_ALLOW(harmony_class_fields);
|
| SET_ALLOW(harmony_object_spread);
|
| + SET_ALLOW(harmony_async_iteration);
|
| #undef SET_ALLOW
|
| }
|
| // Aborting inner function preparsing would leave scopes in an inconsistent
|
| @@ -3925,6 +4092,20 @@ Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) {
|
|
|
| const int nopos = kNoSourcePosition;
|
|
|
| + if (is_async_generator()) {
|
| + ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
|
| + Expression* generator_object =
|
| + factory()->NewVariableProxy(generator_object_variable);
|
| + args->Add(generator_object, zone());
|
| + args->Add(value, zone());
|
| +
|
| + Expression* await = factory()->NewCallRuntime(
|
| + Context::ASYNC_GENERATOR_AWAIT_CAUGHT, args, nopos);
|
| +
|
| + return factory()->NewYield(generator_object, await, nopos,
|
| + Yield::kOnExceptionRethrow, Yield::kAwait);
|
| + }
|
| +
|
| Block* do_block = factory()->NewBlock(nullptr, 2, false, nopos);
|
|
|
| Variable* promise = PromiseVariable();
|
| @@ -3960,7 +4141,7 @@ Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) {
|
|
|
| generator_object = factory()->NewVariableProxy(generator_object_variable);
|
| return factory()->NewYield(generator_object, do_expr, nopos,
|
| - Yield::kOnExceptionRethrow);
|
| + Yield::kOnExceptionRethrow, Yield::kAwait);
|
| }
|
|
|
| class NonPatternRewriter : public AstExpressionRewriter {
|
|
|