Chromium Code Reviews| Index: src/parsing/parser.cc |
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc |
| index 444b20cbf87352cdd4b214938e837c2a7b3b2b52..554ea8edb6a773bcd1b5739f73468decd8ac2947 100644 |
| --- a/src/parsing/parser.cc |
| +++ b/src/parsing/parser.cc |
| @@ -3336,6 +3336,7 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt, |
| } |
| for_of->Initialize(each, subject, body, |
| + iterator, |
| assign_iterator, |
| next_result, |
| result_done, |
| @@ -3613,9 +3614,6 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( |
| Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
| bool* ok) { |
| - // ForStatement :: |
| - // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
| - |
| int stmt_pos = peek_position(); |
| Statement* init = NULL; |
| ZoneList<const AstRawString*> lexical_bindings(1, zone()); |
| @@ -3775,6 +3773,11 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
| } |
| } |
| + if (loop->IsForOfStatement()) { |
| + FinalizeForOfStatement( |
| + loop->AsForOfStatement(), RelocInfo::kNoPosition); |
| + } |
| + |
| for_scope->set_end_position(scanner()->location().end_pos); |
| for_scope = for_scope->FinalizeBlockScope(); |
| // Parsed for-in loop w/ variable declarations. |
| @@ -3861,6 +3864,10 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
| for_scope = for_scope->FinalizeBlockScope(); |
| DCHECK(for_scope == nullptr); |
| // Parsed for-in loop. |
| + if (loop->IsForOfStatement()) { |
| + FinalizeForOfStatement( |
| + loop->AsForOfStatement(), RelocInfo::kNoPosition); |
| + } |
| return loop; |
| } else { |
| @@ -5741,7 +5748,7 @@ Expression* Parser::RewriteSpreads(ArrayLiteral* lit) { |
| ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition); |
| ForOfStatement* for_of = loop->AsForOfStatement(); |
| for_of->Initialize(factory()->NewVariableProxy(each), subject, |
| - append_body, assign_iterator, next_element, |
| + append_body, iterator, assign_iterator, next_element, |
| element_done, assign_each); |
| do_block->statements()->Add(for_of, zone()); |
| } |
| @@ -5899,7 +5906,6 @@ Expression* ParserTraits::RewriteYieldStar( |
| auto scope = parser_->scope_; |
| auto zone = parser_->zone(); |
| - Statement* skip = factory->NewEmptyStatement(nopos); |
|
neis
2016/02/12 12:30:13
The changes to RewriteYieldStar are unrelated.
|
| // Forward definition for break/continue statements. |
| WhileStatement* loop = factory->NewWhileStatement(nullptr, nopos); |
| @@ -5971,8 +5977,8 @@ Expression* ParserTraits::RewriteYieldStar( |
| throw_call = factory->NewExpressionStatement(call, nopos); |
| } |
| - validate_iterator = |
| - factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); |
| + validate_iterator = factory->NewIfStatement( |
| + is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos); |
| } |
| @@ -6015,8 +6021,8 @@ Expression* ParserTraits::RewriteYieldStar( |
| throw_call = factory->NewExpressionStatement(call, nopos); |
| } |
| - validate_next_output = |
| - factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); |
| + validate_next_output = factory->NewIfStatement( |
| + is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos); |
| } |
| @@ -6052,11 +6058,12 @@ Expression* ParserTraits::RewriteYieldStar( |
| Statement* throw_call = factory->NewExpressionStatement(call, nopos); |
| Block* then = factory->NewBlock(nullptr, 4+1, false, nopos); |
| - BuildIteratorClose(then->statements(), var_iterator, Nothing<Variable*>(), |
| - Nothing<Variable*>()); |
| + Variable* var_tmp = scope->NewTemporary(avfactory->empty_string()); |
| + BuildIteratorClose( |
| + then->statements(), var_iterator, Nothing<Variable*>(), var_tmp); |
| then->statements()->Add(throw_call, zone); |
| - check_throw = |
| - factory->NewIfStatement(condition, then, skip, nopos); |
| + check_throw = factory->NewIfStatement( |
| + condition, then, factory->NewEmptyStatement(nopos), nopos); |
| } |
| @@ -6095,8 +6102,8 @@ Expression* ParserTraits::RewriteYieldStar( |
| throw_call = factory->NewExpressionStatement(call, nopos); |
| } |
| - validate_throw_output = |
| - factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); |
| + validate_throw_output = factory->NewIfStatement( |
| + is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos); |
| } |
| @@ -6108,7 +6115,8 @@ Expression* ParserTraits::RewriteYieldStar( |
| factory->NewStringLiteral(avfactory->done_string(), nopos); |
| Expression* property = factory->NewProperty(output_proxy, literal, nopos); |
| BreakStatement* break_loop = factory->NewBreakStatement(loop, nopos); |
| - if_done = factory->NewIfStatement(property, break_loop, skip, nopos); |
| + if_done = factory->NewIfStatement( |
| + property, break_loop, factory->NewEmptyStatement(nopos), nopos); |
| } |
| @@ -6227,8 +6235,7 @@ Expression* ParserTraits::RewriteYieldStar( |
| case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone); |
| auto case_return = new (zone) ZoneList<Statement*>(5, zone); |
| - BuildIteratorClose( |
| - case_return, var_iterator, Just(var_input), Just(var_output)); |
| + BuildIteratorClose(case_return, var_iterator, Just(var_input), var_output); |
| case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone); |
| auto case_throw = new (zone) ZoneList<Statement*>(5, zone); |
| @@ -6295,16 +6302,28 @@ Expression* ParserTraits::RewriteYieldStar( |
| void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, |
|
neis
2016/02/12 12:30:13
The changes to this BuildIteratorClose are unrelat
|
| Variable* iterator, |
| Maybe<Variable*> input, |
| - Maybe<Variable*> output) { |
| + Variable* var_output) { |
| + // |
| + // This function adds four statements to [statements], corresponding to the |
| + // following code: |
| + // |
| + // let iteratorReturn = iterator.return; |
| + // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return |input|; |
| + // output = %_Call(iteratorReturn, iterator|, input|); |
| + // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); |
| + // |
| + // Here, |...| denotes optional parts, depending on the presence of the |
| + // input variable. |
| + // |
| + |
| const int nopos = RelocInfo::kNoPosition; |
| auto factory = parser_->factory(); |
| auto avfactory = parser_->ast_value_factory(); |
| - auto scope = parser_->scope_; |
| auto zone = parser_->zone(); |
| - Statement* skip = factory->NewEmptyStatement(nopos); |
| + |
| // let iteratorReturn = iterator.return; |
| - Variable* var = scope->NewTemporary(avfactory->empty_string()); |
| + Variable* var_return = var_output; // Reusing the output variable. |
| Statement* get_return; |
| { |
| Expression* iterator_proxy = factory->NewVariableProxy(iterator); |
| @@ -6312,18 +6331,18 @@ void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, |
| factory->NewStringLiteral(avfactory->return_string(), nopos); |
| Expression* property = |
| factory->NewProperty(iterator_proxy, literal, nopos); |
| - Expression* return_proxy = factory->NewVariableProxy(var); |
| + Expression* return_proxy = factory->NewVariableProxy(var_return); |
| Expression* assignment = factory->NewAssignment( |
| Token::ASSIGN, return_proxy, property, nopos); |
| get_return = factory->NewExpressionStatement(assignment, nopos); |
| } |
| - // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return; OR |
| - // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return input; |
| + |
| + // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return |input|; |
| Statement* check_return; |
| { |
| Expression* condition = factory->NewCompareOperation( |
| - Token::EQ, factory->NewVariableProxy(var), |
| + Token::EQ, factory->NewVariableProxy(var_return), |
| factory->NewNullLiteral(nopos), nopos); |
| Expression* value = input.IsJust() ? |
| @@ -6332,16 +6351,16 @@ void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, |
| Statement* return_undefined = factory->NewReturnStatement(value, nopos); |
| - check_return = |
| - factory->NewIfStatement(condition, return_undefined, skip, nopos); |
| + check_return = factory->NewIfStatement( |
| + condition, return_undefined, factory->NewEmptyStatement(nopos), nopos); |
| } |
| - // let output = %_Call(iteratorReturn, iterator); OR |
| - // output = %_Call(iteratorReturn, iterator, input); |
| + |
| + // output = %_Call(iteratorReturn, iterator|, input|); |
| Statement* call_return; |
| { |
| auto args = new (zone) ZoneList<Expression*>(3, zone); |
| - args->Add(factory->NewVariableProxy(var), zone); |
| + args->Add(factory->NewVariableProxy(var_return), zone); |
| args->Add(factory->NewVariableProxy(iterator), zone); |
| if (input.IsJust()) { |
| args->Add(factory->NewVariableProxy(input.FromJust()), zone); |
| @@ -6349,20 +6368,20 @@ void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, |
| Expression* call = |
| factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); |
| - Expression* output_proxy = factory->NewVariableProxy( |
| - output.IsJust() ? output.FromJust() : var); |
| + Expression* output_proxy = factory->NewVariableProxy(var_output); |
| Expression* assignment = factory->NewAssignment( |
| Token::ASSIGN, output_proxy, call, nopos); |
| call_return = factory->NewExpressionStatement(assignment, nopos); |
| } |
| - // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); |
| + |
| + // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output); |
| Statement* validate_output; |
| { |
| Expression* is_receiver_call; |
| { |
| auto args = new (zone) ZoneList<Expression*>(1, zone); |
| - args->Add(factory->NewVariableProxy(var), zone); |
| + args->Add(factory->NewVariableProxy(var_output), zone); |
| is_receiver_call = |
| factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); |
| } |
| @@ -6370,16 +6389,17 @@ void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, |
| Statement* throw_call; |
| { |
| auto args = new (zone) ZoneList<Expression*>(1, zone); |
| - args->Add(factory->NewVariableProxy(var), zone); |
| + args->Add(factory->NewVariableProxy(var_output), zone); |
| Expression* call = factory->NewCallRuntime( |
| Runtime::kThrowIteratorResultNotAnObject, args, nopos); |
| throw_call = factory->NewExpressionStatement(call, nopos); |
| } |
| - validate_output = |
| - factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); |
| + validate_output = factory->NewIfStatement( |
| + is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos); |
| } |
| + |
| statements->Add(get_return, zone); |
| statements->Add(check_return, zone); |
| statements->Add(call_return, zone); |
| @@ -6387,5 +6407,346 @@ void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, |
| } |
| + |
| + |
| + |
| + |
| + |
| + |
| + |
| + |
| + |
| +enum { THROW, RETURN_OR_BREAK, NORMAL }; |
| + |
| + |
| +void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, |
| + Variable* iterator, |
| + Variable* completion) { |
| + // |
| + // This function adds two statements to [statements], corresponding to the |
| + // following code: |
| + // |
| + // let iteratorReturn = iterator.return; |
| + // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { |
| + // let output; |
| + // if (completion === THROW) { |
| + // if (!IS_CALLABLE(iteratorReturn)) { |
| + // throw MakeTypeError(kReturnMethodNotCallable); |
| + // } |
| + // try { output = %_Call(iteratorReturn, iterator) } catch (_) { } |
| + // } else { |
| + // output = %_Call(iteratorReturn, iterator); |
| + // } |
| + // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); |
| + // } |
| + // |
| + |
| + const int nopos = RelocInfo::kNoPosition; |
| + auto factory = parser_->factory(); |
| + auto avfactory = parser_->ast_value_factory(); |
| + auto scope = parser_->scope_; |
| + auto zone = parser_->zone(); |
| + |
| + |
| + // let output; |
| + Variable* var_output = scope->NewTemporary(avfactory->empty_string()); |
| + |
| + |
| + // let iteratorReturn = iterator.return; |
| + Variable* var_return = var_output; // Reusing the output variable. |
| + Statement* get_return; |
| + { |
| + Expression* iterator_proxy = factory->NewVariableProxy(iterator); |
| + Expression* literal = |
| + factory->NewStringLiteral(avfactory->return_string(), nopos); |
| + Expression* property = |
| + factory->NewProperty(iterator_proxy, literal, nopos); |
| + Expression* return_proxy = factory->NewVariableProxy(var_return); |
| + Expression* assignment = factory->NewAssignment( |
| + Token::ASSIGN, return_proxy, property, nopos); |
| + get_return = factory->NewExpressionStatement(assignment, nopos); |
| + } |
| + |
| + |
| + // if (!IS_CALLABLE(iteratorReturn)) { |
| + // throw MakeTypeError(kReturnMethodNotCallable); |
| + // } |
| + Statement* check_return_callable; |
| + { |
| + Expression* type_of = factory->NewUnaryOperation( |
| + Token::TYPEOF, factory->NewVariableProxy(var_return), nopos); |
| + Expression* function_literal = factory->NewStringLiteral( |
| + avfactory->function_string(), nopos); |
| + Expression* condition = factory->NewCompareOperation( |
| + Token::EQ_STRICT, type_of, function_literal, nopos); |
| + |
| + Expression* call = NewThrowTypeError( |
| + MessageTemplate::kReturnMethodNotCallable, |
| + avfactory->empty_string(), nopos); |
| + Statement* throw_call = factory->NewExpressionStatement(call, nopos); |
| + |
| + check_return_callable = factory->NewIfStatement( |
| + condition, factory->NewEmptyStatement(nopos), throw_call, nopos); |
| + } |
| + |
| + |
| + // output = %_Call(iteratorReturn, iterator); |
| + Statement* call_return; |
| + { |
| + auto args = new (zone) ZoneList<Expression*>(2, zone); |
| + args->Add(factory->NewVariableProxy(var_return), zone); |
| + args->Add(factory->NewVariableProxy(iterator), zone); |
| + Expression* call = |
| + factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); |
| + |
| + Expression* output_proxy = factory->NewVariableProxy(var_output); |
| + Expression* assignment = factory->NewAssignment( |
| + Token::ASSIGN, output_proxy, call, nopos); |
| + call_return = factory->NewExpressionStatement(assignment, nopos); |
| + } |
| + |
| + |
| + // try { output = %_Call(iteratorReturn, iterator) } catch (_) { } |
| + Statement* try_call_return; |
| + { |
| + auto args = new (zone) ZoneList<Expression*>(2, zone); |
| + args->Add(factory->NewVariableProxy(var_return), zone); |
| + args->Add(factory->NewVariableProxy(iterator), zone); |
| + |
| + Expression* call = |
| + factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); |
| + Expression* assignment = factory->NewAssignment( |
| + Token::ASSIGN, factory->NewVariableProxy(var_output), call, nopos); |
| + |
| + Block* try_block = factory->NewBlock(nullptr, 1, false, nopos); |
| + try_block->statements()->Add( |
| + factory->NewExpressionStatement(assignment, nopos), zone); |
| + |
| + Block* catch_block = factory->NewBlock(nullptr, 0, false, nopos); |
| + |
| + Scope* catch_scope = NewScope(scope, CATCH_SCOPE); |
| + Variable* catch_variable = catch_scope->DeclareLocal( |
| + avfactory->dot_catch_string(), VAR, kCreatedInitialized, |
| + Variable::NORMAL); |
| + |
| + try_call_return = factory->NewTryCatchStatement( |
| + try_block, catch_scope, catch_variable, catch_block, nopos); |
| + } |
| + |
| + |
| + // if (completion === THROW) { |
| + // #check_return_callable; |
| + // #try_call_return; |
| + // } else { |
| + // #call_return; |
| + // } |
| + Statement* call_return_carefully; |
| + { |
| + Expression* condition = factory->NewCompareOperation( |
| + Token::EQ_STRICT, factory->NewVariableProxy(completion), |
| + factory->NewSmiLiteral(THROW, nopos), nopos); |
| + |
| + Block* then_block = factory->NewBlock(nullptr, 2, false, nopos); |
| + then_block->statements()->Add(check_return_callable, zone); |
| + then_block->statements()->Add(try_call_return, zone); |
| + |
| + call_return_carefully = |
| + factory->NewIfStatement(condition, then_block, call_return, nopos); |
| + } |
| + |
| + |
| + // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output); |
| + Statement* validate_output; |
| + { |
| + Expression* is_receiver_call; |
| + { |
| + auto args = new (zone) ZoneList<Expression*>(1, zone); |
| + args->Add(factory->NewVariableProxy(var_output), zone); |
| + is_receiver_call = |
| + factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); |
| + } |
| + |
| + Statement* throw_call; |
| + { |
| + auto args = new (zone) ZoneList<Expression*>(1, zone); |
| + args->Add(factory->NewVariableProxy(var_output), zone); |
| + Expression* call = factory->NewCallRuntime( |
| + Runtime::kThrowIteratorResultNotAnObject, args, nopos); |
| + throw_call = factory->NewExpressionStatement(call, nopos); |
| + } |
| + |
| + validate_output = factory->NewIfStatement( |
| + is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos); |
| + } |
| + |
| + |
| + // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { ... } |
| + Statement* maybe_call_return; |
| + { |
| + Expression* condition = factory->NewCompareOperation( |
| + Token::EQ, factory->NewVariableProxy(var_return), |
| + factory->NewNullLiteral(nopos), nopos); |
| + |
| + Block* block = factory->NewBlock(nullptr, 2, false, nopos); |
| + block->statements()->Add(call_return_carefully, zone); |
| + block->statements()->Add(validate_output, zone); // GAGA |
| + |
| + maybe_call_return = factory->NewIfStatement( |
| + condition, factory->NewEmptyStatement(nopos), block, nopos); |
| + } |
| + |
| + |
| + statements->Add(get_return, zone); |
| + statements->Add(maybe_call_return, zone); |
| +} |
| + |
| + |
| +void ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) { |
| + // |
| + // This function replaces the loop's body with the following wrapping: |
| + // |
| + // let completion = RETURN_OR_BREAK; |
| + // try { |
| + // #body; |
| + // {{completion = NORMAL}}; |
| + // } catch(e) { |
| + // completion = THROW; |
| + // throw e; |
| + // } finally { |
| + // if (completion !== NORMAL) { |
| + // #BuildIteratorClose(iterator, completion) // See above. |
| + // } |
| + // } |
| + // |
| + |
| + const int nopos = RelocInfo::kNoPosition; |
| + auto factory = parser_->factory(); |
| + auto avfactory = parser_->ast_value_factory(); |
| + auto scope = parser_->scope_; |
| + auto zone = parser_->zone(); |
| + |
| + |
| + // let completion = RETURN_OR_BREAK; |
| + Variable* var_completion = scope->NewTemporary(avfactory->empty_string()); |
| + Statement* initialize_completion; |
| + { |
| + Expression* proxy = factory->NewVariableProxy(var_completion); |
| + Expression* assignment = factory->NewAssignment( |
| + Token::ASSIGN, proxy, |
| + factory->NewSmiLiteral(RETURN_OR_BREAK, nopos), nopos); |
| + initialize_completion = |
| + factory->NewExpressionStatement(assignment, nopos); |
| + } |
| + |
| + |
| + // {{completion = NORMAL}} |
| + Statement* set_completion_normal; |
| + { |
| + Expression* proxy = factory->NewVariableProxy(var_completion); |
| + Expression* assignment = factory->NewAssignment( |
| + Token::ASSIGN, proxy, factory->NewSmiLiteral(NORMAL, nopos), nopos); |
| + |
| + Block* block = factory->NewBlock(nullptr, 1, true, nopos); |
| + block->statements()->Add( |
| + factory->NewExpressionStatement(assignment, nopos), zone); |
| + set_completion_normal = block; |
| + } |
| + |
| + |
| + // completion = THROW; |
| + Statement* set_completion_throw; |
| + { |
| + Expression* proxy = factory->NewVariableProxy(var_completion); |
| + Expression* assignment = factory->NewAssignment( |
| + Token::ASSIGN, proxy, factory->NewSmiLiteral(THROW, nopos), nopos); |
| + set_completion_throw = factory->NewExpressionStatement(assignment, nopos); |
| + } |
| + |
| + |
| + // #body; |
| + // #set_completion_normal; |
| + Block* try_block; |
| + { |
| + try_block = factory->NewBlock(nullptr, 2, false, nopos); |
| + try_block->statements()->Add(loop->body(), zone); |
| + try_block->statements()->Add(set_completion_normal, zone); |
| + } |
| + |
| + |
| + // if (completion !== NORMAL) { |
| + // #BuildIteratorClose |
| + // } |
| + Block* maybe_close; |
| + { |
| + Expression* condition = factory->NewCompareOperation( |
| + Token::EQ_STRICT, factory->NewVariableProxy(var_completion), |
| + factory->NewSmiLiteral(NORMAL, nopos), nopos); |
| + |
| + Block* block = factory->NewBlock(nullptr, 2, false, nopos); |
| + BuildIteratorClose( |
| + block->statements(), loop->iterator(), var_completion); |
| + DCHECK(block->statements()->length() == 2); |
| + |
| + maybe_close = factory->NewBlock(nullptr, 1, false, nopos); |
| + maybe_close->statements()->Add(factory->NewIfStatement( |
| + condition, factory->NewEmptyStatement(nopos), block, nopos), zone); |
| + } |
| + |
| + |
| + // try { #try_block } |
| + // catch(e) { |
| + // #set_completion_throw; |
| + // throw e; |
| + // } |
| + Statement* try_catch; |
| + { |
| + Block* catch_block; |
| + Scope* catch_scope = NewScope(scope, CATCH_SCOPE); |
| + Variable* catch_variable = catch_scope->DeclareLocal( |
| + avfactory->dot_catch_string(), VAR, kCreatedInitialized, |
| + Variable::NORMAL); |
| + |
| + Statement* rethrow; |
| + { |
| + Expression* proxy = factory->NewVariableProxy(catch_variable); |
| + rethrow = factory->NewExpressionStatement( |
| + factory->NewThrow(proxy, nopos), nopos); |
| + } |
| + |
| + catch_block = factory->NewBlock(nullptr, 2, false, nopos); |
| + catch_block->statements()->Add(set_completion_throw, zone); |
| + catch_block->statements()->Add(rethrow, zone); |
| + |
| + try_catch = factory->NewTryCatchStatement( |
| + try_block, catch_scope, catch_variable, catch_block, nopos); |
| + } |
| + |
| + |
| + // try { #try_catch } finally { #maybe_close } |
| + Statement* try_finally; |
| + { |
| + Block* try_block = factory->NewBlock(nullptr, 1, false, nopos); |
| + try_block->statements()->Add(try_catch, zone); |
| + |
| + try_finally = |
| + factory->NewTryFinallyStatement(try_block, maybe_close, nopos); |
| + } |
| + |
| + |
| + // #initialize_completion; |
| + // #try_finally; |
| + Statement* new_body; |
| + { |
| + Block* block = factory->NewBlock(nullptr, 2, false, nopos); |
| + block->statements()->Add(initialize_completion, zone); |
| + block->statements()->Add(try_finally, zone); |
| + new_body = block; |
| + } |
| + |
| + |
| + loop->set_body(new_body); |
| +} |
| + |
| + |
| } // namespace internal |
| } // namespace v8 |