| Index: runtime/vm/parser.cc
|
| ===================================================================
|
| --- runtime/vm/parser.cc (revision 43705)
|
| +++ runtime/vm/parser.cc (working copy)
|
| @@ -3171,7 +3171,7 @@
|
| } else if (func.IsSyncGenClosure()) {
|
| // The closure containing the body of a sync generator is debuggable.
|
| ASSERT(func.is_debuggable());
|
| - // Nothing special to do.
|
| + async_temp_scope_ = current_block_->scope;
|
| }
|
|
|
| BoolScope allow_await(&this->await_is_keyword_,
|
| @@ -5975,21 +5975,20 @@
|
| }
|
|
|
| ASSERT(try_blocks_list_ != NULL);
|
| - if (innermost_function().IsAsyncClosure() ||
|
| - innermost_function().IsAsyncFunction()) {
|
| - if ((try_blocks_list_->outer_try_block() != NULL) &&
|
| - (try_blocks_list_->outer_try_block()->try_block()
|
| - ->scope->function_level() ==
|
| - current_block_->scope->function_level())) {
|
| - // We need to unchain three scope levels: catch clause, catch
|
| - // parameters, and the general try block.
|
| - RestoreSavedTryContext(
|
| - current_block_->scope->parent()->parent()->parent(),
|
| - try_blocks_list_->outer_try_block()->try_index(),
|
| - current_block_->statements);
|
| - } else {
|
| - parsed_function()->reset_saved_try_ctx_vars();
|
| - }
|
| + ASSERT(innermost_function().IsAsyncClosure() ||
|
| + innermost_function().IsAsyncFunction());
|
| + if ((try_blocks_list_->outer_try_block() != NULL) &&
|
| + (try_blocks_list_->outer_try_block()->try_block()
|
| + ->scope->function_level() ==
|
| + current_block_->scope->function_level())) {
|
| + // We need to unchain three scope levels: catch clause, catch
|
| + // parameters, and the general try block.
|
| + RestoreSavedTryContext(
|
| + current_block_->scope->parent()->parent()->parent(),
|
| + try_blocks_list_->outer_try_block()->try_index(),
|
| + current_block_->statements);
|
| + } else {
|
| + parsed_function()->reset_saved_try_ctx_vars();
|
| }
|
|
|
| // Complete the async future with an error.
|
| @@ -6081,7 +6080,9 @@
|
| PushTryBlock(current_block_);
|
|
|
| if (innermost_function().IsAsyncClosure() ||
|
| - innermost_function().IsAsyncFunction()) {
|
| + innermost_function().IsAsyncFunction() ||
|
| + innermost_function().IsSyncGenClosure() ||
|
| + innermost_function().IsSyncGenerator()) {
|
| SetupSavedTryContext(context_var);
|
| }
|
| }
|
| @@ -6164,10 +6165,7 @@
|
| OpenFunctionBlock(body);
|
| AddFormalParamsToScope(&closure_params, current_block_->scope);
|
| OpenBlock();
|
| -
|
| - /*
|
| - async_temp_scope_ = current_block_->scope; // Is this needed?
|
| - */
|
| + async_temp_scope_ = current_block_->scope;
|
| return body.raw();
|
| }
|
|
|
| @@ -8196,7 +8194,9 @@
|
| // outer try block (if it exists). The current try block has already been
|
| // removed from the stack of try blocks.
|
| if ((innermost_function().IsAsyncClosure() ||
|
| - innermost_function().IsAsyncFunction()) &&
|
| + innermost_function().IsAsyncFunction() ||
|
| + innermost_function().IsSyncGenClosure() ||
|
| + innermost_function().IsSyncGenerator()) &&
|
| (try_blocks_list_ != NULL)) {
|
| // We need two unchain two scopes: finally clause, and the try block level.
|
| RestoreSavedTryContext(current_block_->scope->parent()->parent(),
|
| @@ -8356,7 +8356,9 @@
|
| // outer try block (if it exists).
|
| ASSERT(try_blocks_list_ != NULL);
|
| if (innermost_function().IsAsyncClosure() ||
|
| - innermost_function().IsAsyncFunction()) {
|
| + innermost_function().IsAsyncFunction() ||
|
| + innermost_function().IsSyncGenClosure() ||
|
| + innermost_function().IsSyncGenerator()) {
|
| if ((try_blocks_list_->outer_try_block() != NULL) &&
|
| (try_blocks_list_->outer_try_block()->try_block()
|
| ->scope->function_level() ==
|
| @@ -8464,7 +8466,9 @@
|
| // outer try block (if it exists).
|
| ASSERT(try_blocks_list_ != NULL);
|
| if (innermost_function().IsAsyncClosure() ||
|
| - innermost_function().IsAsyncFunction()) {
|
| + innermost_function().IsAsyncFunction() ||
|
| + innermost_function().IsSyncGenClosure() ||
|
| + innermost_function().IsSyncGenerator()) {
|
| if ((try_blocks_list_->outer_try_block() != NULL) &&
|
| (try_blocks_list_->outer_try_block()->try_block()
|
| ->scope->function_level() ==
|
| @@ -8495,6 +8499,7 @@
|
| Scanner::kNoSourcePos,
|
| async_saved_try_ctx_name,
|
| Type::ZoneHandle(Z, Type::DynamicType()));
|
| + ASSERT(async_temp_scope_ != NULL);
|
| async_temp_scope_->AddVariable(async_saved_try_ctx);
|
| async_saved_try_ctx->set_is_captured();
|
| async_saved_try_ctx = current_block_->scope->LookupVariable(
|
| @@ -8600,7 +8605,9 @@
|
| ExpectToken(Token::kLBRACE);
|
|
|
| if (innermost_function().IsAsyncClosure() ||
|
| - innermost_function().IsAsyncFunction()) {
|
| + innermost_function().IsAsyncFunction() ||
|
| + innermost_function().IsSyncGenClosure() ||
|
| + innermost_function().IsSyncGenerator()) {
|
| SetupSavedTryContext(context_var);
|
| }
|
|
|
| @@ -8842,6 +8849,22 @@
|
| new(Z) LiteralNode(TokenPos(), Bool::True()));
|
| return_true->set_return_type(ReturnNode::kContinuationTarget);
|
| yield->AddNode(return_true);
|
| +
|
| + // If this expression is part of a try block, also append the code for
|
| + // restoring the saved try context that lives on the stack.
|
| + const String& async_saved_try_ctx_name =
|
| + String::Handle(Z, parsed_function()->async_saved_try_ctx_name());
|
| + if (!async_saved_try_ctx_name.IsNull()) {
|
| + LocalVariable* async_saved_try_ctx =
|
| + current_block_->scope->LookupVariable(async_saved_try_ctx_name,
|
| + false);
|
| + ASSERT(async_saved_try_ctx != NULL);
|
| + yield->AddNode(new (Z) StoreLocalNode(
|
| + Scanner::kNoSourcePos,
|
| + parsed_function()->saved_try_ctx(),
|
| + new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_saved_try_ctx)));
|
| + }
|
| +
|
| statement = yield;
|
| ExpectSemicolon();
|
| } else if (token == Token::kIF) {
|
|
|