Index: src/parsing/parser.cc |
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc |
index e3bd5eb67515ba70a29d143597a825c8338e1974..6efcb5beeff03b18ddb2dad8ea872459a4e2a98d 100644 |
--- a/src/parsing/parser.cc |
+++ b/src/parsing/parser.cc |
@@ -1754,6 +1754,70 @@ Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block, |
} |
} |
+void Parser::ParseAndRewriteGeneratorFunctionBody(int pos, FunctionKind kind, |
+ ZoneList<Statement*>* body, |
+ bool* ok) { |
+ // We produce: |
+ // |
+ // try { InitialYield; ...body...; return {value: undefined, done: true} } |
+ // finally { %_GeneratorClose(generator) } |
+ // |
+ // - InitialYield yields the actual generator object. |
+ // - Any return statement inside the body will have its argument wrapped |
+ // in a "done" iterator result object. |
+ // - If the generator terminates for whatever reason, we must close it. |
+ // Hence the finally clause. |
+ |
+ Block* try_block = factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); |
+ Expression* initial_yield = BuildInitialYield(pos, kind); |
+ try_block->statements()->Add( |
+ factory()->NewExpressionStatement(initial_yield, kNoSourcePosition), |
+ zone()); |
+ ParseStatementList(try_block->statements(), Token::RBRACE, ok); |
+ if (!*ok) return; |
+ |
+ Statement* final_return = factory()->NewReturnStatement( |
+ BuildIteratorResult(nullptr, true), kNoSourcePosition); |
+ try_block->statements()->Add(final_return, zone()); |
+ |
+ Block* finally_block = |
+ factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); |
+ ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); |
+ VariableProxy* call_proxy = |
+ factory()->NewVariableProxy(function_state_->generator_object_variable()); |
+ args->Add(call_proxy, zone()); |
+ Expression* call = factory()->NewCallRuntime(Runtime::kInlineGeneratorClose, |
+ args, kNoSourcePosition); |
+ finally_block->statements()->Add( |
+ factory()->NewExpressionStatement(call, kNoSourcePosition), zone()); |
+ |
+ body->Add(factory()->NewTryFinallyStatement(try_block, finally_block, |
+ kNoSourcePosition), |
+ zone()); |
+} |
+ |
+void Parser::CreateFunctionNameAssignment( |
+ const AstRawString* function_name, int pos, |
+ FunctionLiteral::FunctionType function_type, |
+ DeclarationScope* function_scope, ZoneList<Statement*>* result, int index) { |
+ if (function_type == FunctionLiteral::kNamedExpression) { |
+ StatementT statement = factory()->NewEmptyStatement(kNoSourcePosition); |
+ if (function_scope->LookupLocal(function_name) == nullptr) { |
+ // Now that we know the language mode, we can create the const assignment |
+ // in the previously reserved spot. |
+ DCHECK_EQ(function_scope, scope()); |
+ Variable* fvar = function_scope->DeclareFunctionVar(function_name); |
+ VariableProxy* fproxy = factory()->NewVariableProxy(fvar); |
+ statement = factory()->NewExpressionStatement( |
+ factory()->NewAssignment(Token::INIT, fproxy, |
+ factory()->NewThisFunction(pos), |
+ kNoSourcePosition), |
+ kNoSourcePosition); |
+ } |
+ result->Set(index, statement); |
+ } |
+} |
+ |
// !%_IsJSReceiver(result = iterator.next()) && |
// %ThrowIteratorResultNotAnObject(result) |
Expression* Parser::BuildIteratorNextResult(Expression* iterator, |
@@ -2920,7 +2984,7 @@ Block* Parser::BuildParameterInitializationBlock( |
return init_block; |
} |
-Block* Parser::BuildRejectPromiseOnException(Block* inner_block, bool* ok) { |
+Block* Parser::BuildRejectPromiseOnException(Block* inner_block) { |
// .promise = %AsyncFunctionPromiseCreate(); |
// try { |
// <inner_block> |
@@ -3082,8 +3146,8 @@ ZoneList<Statement*>* Parser::ParseFunction( |
CHECK_OK); |
Expect(Token::LBRACE, CHECK_OK); |
- ZoneList<Statement*>* body = ParseEagerFunctionBody( |
- function_name, pos, formals, kind, function_type, ok); |
+ ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(8, zone()); |
+ ParseFunctionBody(body, function_name, pos, formals, kind, function_type, ok); |
// Validate parameter names. We can do this only after parsing the function, |
// since the function can declare itself strict. |
@@ -3103,161 +3167,6 @@ ZoneList<Statement*>* Parser::ParseFunction( |
return body; |
} |
-ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
- const AstRawString* function_name, int pos, |
- const ParserFormalParameters& parameters, FunctionKind kind, |
- FunctionLiteral::FunctionType function_type, bool* ok) { |
- ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); |
- |
- static const int kFunctionNameAssignmentIndex = 0; |
- if (function_type == FunctionLiteral::kNamedExpression) { |
- DCHECK(function_name != NULL); |
- // If we have a named function expression, we add a local variable |
- // declaration to the body of the function with the name of the |
- // function and let it refer to the function itself (closure). |
- // Not having parsed the function body, the language mode may still change, |
- // so we reserve a spot and create the actual const assignment later. |
- DCHECK_EQ(kFunctionNameAssignmentIndex, result->length()); |
- result->Add(NULL, zone()); |
- } |
- |
- ZoneList<Statement*>* body = result; |
- DeclarationScope* function_scope = scope()->AsDeclarationScope(); |
- DeclarationScope* inner_scope = function_scope; |
- Block* inner_block = nullptr; |
- if (!parameters.is_simple) { |
- inner_scope = NewVarblockScope(); |
- inner_scope->set_start_position(scanner()->location().beg_pos); |
- inner_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition); |
- inner_block->set_scope(inner_scope); |
- body = inner_block->statements(); |
- } |
- |
- { |
- BlockState block_state(&scope_state_, inner_scope); |
- |
- if (IsGeneratorFunction(kind)) { |
- // We produce: |
- // |
- // try { InitialYield; ...body...; return {value: undefined, done: true} } |
- // finally { %_GeneratorClose(generator) } |
- // |
- // - InitialYield yields the actual generator object. |
- // - Any return statement inside the body will have its argument wrapped |
- // in a "done" iterator result object. |
- // - If the generator terminates for whatever reason, we must close it. |
- // Hence the finally clause. |
- |
- Block* try_block = |
- factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); |
- Expression* initial_yield = BuildInitialYield(pos, kind); |
- try_block->statements()->Add( |
- factory()->NewExpressionStatement(initial_yield, kNoSourcePosition), |
- zone()); |
- ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK); |
- |
- Statement* final_return = factory()->NewReturnStatement( |
- BuildIteratorResult(nullptr, true), kNoSourcePosition); |
- try_block->statements()->Add(final_return, zone()); |
- |
- Block* finally_block = |
- factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); |
- ZoneList<Expression*>* args = |
- new (zone()) ZoneList<Expression*>(1, zone()); |
- VariableProxy* call_proxy = factory()->NewVariableProxy( |
- function_state_->generator_object_variable()); |
- args->Add(call_proxy, zone()); |
- Expression* call = factory()->NewCallRuntime( |
- Runtime::kInlineGeneratorClose, args, kNoSourcePosition); |
- finally_block->statements()->Add( |
- factory()->NewExpressionStatement(call, kNoSourcePosition), zone()); |
- |
- body->Add(factory()->NewTryFinallyStatement(try_block, finally_block, |
- kNoSourcePosition), |
- zone()); |
- } else if (IsAsyncFunction(kind)) { |
- const bool accept_IN = true; |
- ParseAsyncFunctionBody(inner_scope, body, kind, FunctionBodyType::kNormal, |
- accept_IN, pos, CHECK_OK); |
- } else { |
- ParseStatementList(body, Token::RBRACE, CHECK_OK); |
- } |
- |
- if (IsDerivedConstructor(kind)) { |
- body->Add(factory()->NewReturnStatement(ThisExpression(kNoSourcePosition), |
- kNoSourcePosition), |
- zone()); |
- } |
- } |
- |
- Expect(Token::RBRACE, CHECK_OK); |
- scope()->set_end_position(scanner()->location().end_pos); |
- |
- if (!parameters.is_simple) { |
- DCHECK_NOT_NULL(inner_scope); |
- DCHECK_EQ(function_scope, scope()); |
- DCHECK_EQ(function_scope, inner_scope->outer_scope()); |
- DCHECK_EQ(body, inner_block->statements()); |
- SetLanguageMode(function_scope, inner_scope->language_mode()); |
- Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); |
- |
- if (is_sloppy(inner_scope->language_mode())) { |
- InsertSloppyBlockFunctionVarBindings(inner_scope); |
- } |
- |
- // TODO(littledan): Merge the two rejection blocks into one |
- if (IsAsyncFunction(kind)) { |
- init_block = BuildRejectPromiseOnException(init_block, CHECK_OK); |
- } |
- |
- DCHECK_NOT_NULL(init_block); |
- |
- inner_scope->set_end_position(scanner()->location().end_pos); |
- if (inner_scope->FinalizeBlockScope() != nullptr) { |
- CheckConflictingVarDeclarations(inner_scope, CHECK_OK); |
- InsertShadowingVarBindingInitializers(inner_block); |
- } |
- inner_scope = nullptr; |
- |
- result->Add(init_block, zone()); |
- result->Add(inner_block, zone()); |
- } else { |
- DCHECK_EQ(inner_scope, function_scope); |
- if (is_sloppy(function_scope->language_mode())) { |
- InsertSloppyBlockFunctionVarBindings(function_scope); |
- } |
- } |
- |
- if (!IsArrowFunction(kind)) { |
- // Declare arguments after parsing the function since lexical 'arguments' |
- // masks the arguments object. Declare arguments before declaring the |
- // function var since the arguments object masks 'function arguments'. |
- function_scope->DeclareArguments(ast_value_factory()); |
- } |
- |
- if (function_type == FunctionLiteral::kNamedExpression) { |
- Statement* statement; |
- if (function_scope->LookupLocal(function_name) == nullptr) { |
- // Now that we know the language mode, we can create the const assignment |
- // in the previously reserved spot. |
- DCHECK_EQ(function_scope, scope()); |
- Variable* fvar = function_scope->DeclareFunctionVar(function_name); |
- VariableProxy* fproxy = factory()->NewVariableProxy(fvar); |
- statement = factory()->NewExpressionStatement( |
- factory()->NewAssignment(Token::INIT, fproxy, |
- factory()->NewThisFunction(pos), |
- kNoSourcePosition), |
- kNoSourcePosition); |
- } else { |
- statement = factory()->NewEmptyStatement(kNoSourcePosition); |
- } |
- result->Set(kFunctionNameAssignmentIndex, statement); |
- } |
- |
- MarkCollectedTailCallExpressions(); |
- return result; |
-} |
- |
void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope, |
ClassInfo* class_info, int class_token_pos, |
bool* ok) { |
@@ -3880,7 +3789,7 @@ void Parser::RewriteAsyncFunctionBody(ZoneList<Statement*>* body, Block* block, |
block->statements()->Add( |
factory()->NewReturnStatement(return_value, return_value->position()), |
zone()); |
- block = BuildRejectPromiseOnException(block, CHECK_OK_VOID); |
+ block = BuildRejectPromiseOnException(block); |
body->Add(block, zone()); |
} |