Index: runtime/vm/parser.cc |
=================================================================== |
--- runtime/vm/parser.cc (revision 44150) |
+++ runtime/vm/parser.cc (working copy) |
@@ -5996,17 +5996,14 @@ |
ASSERT(try_blocks_list_ != NULL); |
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. |
- current_block_->statements->Add( |
- AwaitTransformer::RestoreSavedTryContext( |
- Z, |
- current_block_->scope->parent()->parent()->parent(), |
- try_blocks_list_->outer_try_block()->try_index())); |
+ const TryBlocks* outer_try_block = try_blocks_list_->outer_try_block(); |
+ if (outer_try_block != NULL) { |
+ LocalScope* scope = outer_try_block->try_block()->scope; |
+ if (scope->function_level() == current_block_->scope->function_level()) { |
+ current_block_->statements->Add( |
+ AwaitTransformer::RestoreSavedTryContext( |
+ Z, scope->parent(), outer_try_block->try_index())); |
+ } |
} |
// Complete the async future with an error. |
@@ -8336,12 +8333,12 @@ |
innermost_function().IsSyncGenClosure() || |
innermost_function().IsSyncGenerator()) && |
(try_blocks_list_ != NULL)) { |
- // We need two unchain two scopes: finally clause, and the try block level. |
- current_block_->statements->Add( |
- AwaitTransformer::RestoreSavedTryContext( |
- Z, |
- current_block_->scope->parent()->parent(), |
- try_blocks_list_->try_index())); |
+ LocalScope* scope = try_blocks_list_->try_block()->scope; |
+ if (scope->function_level() == current_block_->scope->function_level()) { |
+ current_block_->statements->Add( |
+ AwaitTransformer::RestoreSavedTryContext( |
+ Z, scope->parent(), try_blocks_list_->try_index())); |
+ } |
} |
ParseStatementSequence(); |
@@ -8493,17 +8490,15 @@ |
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() == |
- current_block_->scope->function_level())) { |
- // We need to unchain three scope levels: catch clause, catch |
- // parameters, and the general try block. |
- current_block_->statements->Add( |
- AwaitTransformer::RestoreSavedTryContext( |
- Z, |
- current_block_->scope->parent()->parent()->parent(), |
- try_blocks_list_->outer_try_block()->try_index())); |
+ const TryBlocks* try_block = try_blocks_list_->outer_try_block(); |
+ if (try_block != NULL) { |
+ LocalScope* scope = try_block->try_block()->scope; |
+ if (scope->function_level() == |
+ current_block_->scope->function_level()) { |
+ current_block_->statements->Add( |
+ AwaitTransformer::RestoreSavedTryContext( |
+ Z, scope->parent(), try_block->try_index())); |
+ } |
} |
SaveExceptionAndStacktrace(exception_var, stack_trace_var); |
} |
@@ -8594,47 +8589,34 @@ |
} |
// If the last body was entered conditionally and there is no need to add |
// a rethrow, use an empty else body (current = NULL above). |
- |
while (!type_tests.is_empty()) { |
AstNode* type_test = type_tests.RemoveLast(); |
SequenceNode* catch_block = catch_blocks.RemoveLast(); |
- |
- // TODO(regis): Understand the purpose of the following code restoring |
- // :saved_try_context_var. This code was added as part of r39926. |
- // In some cases, this code even crashed the compiler (debug mode assert), |
- // because the scope unchaining was starting from the wrong block. |
- // The catch clause(s) emitted below contain the same restoring code. |
- // So why is it necessary? Could it be an attempt to handle the case where |
- // the catch clause is replaced by a throw because of a bad type? It is not |
- // necessary in this case either, because no await could have been executed |
- // between the setup of :saved_try_context_var in the try clause and here |
- // (it is the execution of an await that clears all stack-based variables). |
- |
- // In case of async closures we need to restore the saved try index of an |
- // outer try block (if it exists). |
+ current_block_->statements->Add(new(Z) IfNode( |
+ type_test->token_pos(), type_test, catch_block, current)); |
+ current = CloseBlock(); |
+ } |
+ // Restore :saved_try_context_var before executing the catch clauses. |
+ if (current != NULL) { |
ASSERT(try_blocks_list_ != NULL); |
if (innermost_function().IsAsyncClosure() || |
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() == |
- current_block_->scope->function_level())) { |
- // We need to unchain three scope levels (from the catch block and not |
- // from the current block): catch clause, catch |
- // parameters, and the general try block. |
- current_block_->statements->Add( |
- AwaitTransformer::RestoreSavedTryContext( |
- Z, |
- catch_block->scope()->parent()->parent()->parent(), |
- try_blocks_list_->outer_try_block()->try_index())); |
+ const TryBlocks* try_block = try_blocks_list_->outer_try_block(); |
+ if (try_block != NULL) { |
+ LocalScope* scope = try_block->try_block()->scope; |
+ if (scope->function_level() == |
+ current_block_->scope->function_level()) { |
+ SequenceNode* restore_code = new(Z) SequenceNode(handler_pos, NULL); |
+ restore_code->Add( |
+ AwaitTransformer::RestoreSavedTryContext( |
+ Z, scope->parent(), try_block->try_index())); |
+ restore_code->Add(current); |
+ current = restore_code; |
+ } |
} |
} |
- |
- current_block_->statements->Add(new(Z) IfNode( |
- type_test->token_pos(), type_test, catch_block, current)); |
- current = CloseBlock(); |
} |
return current; |
} |