Index: src/parsing/parser.cc |
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc |
index ed63b543b46cae98d24debebc9334fcfa1f6f6ec..856f2c3614a0313980a704c3718c229288c87496 100644 |
--- a/src/parsing/parser.cc |
+++ b/src/parsing/parser.cc |
@@ -2681,7 +2681,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) { |
} |
ExpectSemicolon(CHECK_OK); |
- if (is_generator()) { |
+ if (is_generator() || is_async_function()) { |
return_value = BuildIteratorResult(return_value, true); |
} |
@@ -4026,6 +4026,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
? peek_position() : function_token_pos; |
bool is_generator = IsGeneratorFunction(kind); |
+ bool is_async = IsAsyncFunction(kind); |
// Anonymous functions were passed either the empty symbol or a null |
// handle as the function name. Remember if we were passed a non-empty |
@@ -4057,7 +4058,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
scope_->SetScopeName(function_name); |
ExpressionClassifier formals_classifier(this, &duplicate_finder); |
- if (is_generator) { |
+ if (is_generator || is_async) { |
// For generators, allocating variables in contexts is currently a win |
// because it minimizes the work needed to suspend and resume an |
// activation. The machine code produced for generators (by full-codegen) |
@@ -4541,27 +4542,28 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
Block* try_block = |
factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition); |
- { |
- ZoneList<Expression*>* arguments = |
- new (zone()) ZoneList<Expression*>(2, zone()); |
- arguments->Add(factory()->NewThisFunction(pos), zone()); |
- arguments->Add( |
- ThisExpression(scope_, factory(), RelocInfo::kNoPosition), zone()); |
- CallRuntime* allocation = factory()->NewCallRuntime( |
- Runtime::kCreateJSGeneratorObject, arguments, pos); |
- |
- VariableProxy* init_proxy = factory()->NewVariableProxy( |
- function_state_->generator_object_variable()); |
- Assignment* assignment = factory()->NewAssignment( |
- Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition); |
- VariableProxy* get_proxy = factory()->NewVariableProxy( |
- function_state_->generator_object_variable()); |
- Yield* yield = |
- factory()->NewYield(get_proxy, assignment, RelocInfo::kNoPosition); |
- try_block->statements()->Add( |
- factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition), |
- zone()); |
- } |
+ ZoneList<Expression*>* arguments = |
caitp (gmail)
2016/04/16 18:33:03
Bunch of phantom edits to clean up, since the asyn
|
+ new (zone()) ZoneList<Expression*>(2, zone()); |
+ arguments->Add(factory()->NewThisFunction(pos), zone()); |
+ arguments->Add(ThisExpression(scope_, factory(), RelocInfo::kNoPosition), |
+ zone()); |
+ CallRuntime* allocation = factory()->NewCallRuntime( |
+ Runtime::kCreateJSGeneratorObject, arguments, pos); |
+ |
+ VariableProxy* init_proxy = factory()->NewVariableProxy( |
+ function_state_->generator_object_variable()); |
+ Assignment* assignment = factory()->NewAssignment( |
+ Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition); |
+ |
+ VariableProxy* get_proxy = factory()->NewVariableProxy( |
+ function_state_->generator_object_variable()); |
+ |
+ Yield* yield = |
+ factory()->NewYield(get_proxy, assignment, RelocInfo::kNoPosition); |
+ |
+ try_block->statements()->Add( |
+ factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition), |
+ zone()); |
ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK); |
@@ -4578,6 +4580,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
args->Add(call_proxy, zone()); |
Expression* call = factory()->NewCallRuntime( |
Runtime::kGeneratorClose, args, RelocInfo::kNoPosition); |
+ |
finally_block->statements()->Add( |
factory()->NewExpressionStatement(call, RelocInfo::kNoPosition), |
zone()); |
@@ -4585,6 +4588,41 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
body->Add(factory()->NewTryFinallyStatement(try_block, finally_block, |
RelocInfo::kNoPosition), |
zone()); |
+ } else if (IsAsyncFunction(kind)) { |
+ ZoneList<Expression*>* arguments = |
+ new (zone()) ZoneList<Expression*>(2, zone()); |
+ arguments->Add(factory()->NewThisFunction(pos), zone()); |
+ arguments->Add(ThisExpression(scope_, factory(), RelocInfo::kNoPosition), |
+ zone()); |
+ CallRuntime* allocation = factory()->NewCallRuntime( |
+ Runtime::kCreateJSGeneratorObject, arguments, pos); |
+ |
+ VariableProxy* init_proxy = factory()->NewVariableProxy( |
+ function_state_->generator_object_variable()); |
+ Assignment* assignment = factory()->NewAssignment( |
+ Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition); |
+ |
+ VariableProxy* get_proxy = factory()->NewVariableProxy( |
+ function_state_->generator_object_variable()); |
+ |
+ ZoneList<Expression*>* async_function_start_args = |
+ new (zone()) ZoneList<Expression*>(1, zone()); |
+ async_function_start_args->Add(get_proxy, zone()); |
+ CallRuntime* async_function_start = factory()->NewCallRuntime( |
+ Context::ASYNC_FUNCTION_START_INDEX, async_function_start_args, |
+ RelocInfo::kNoPosition); |
+ Yield* yield = factory()->NewAsyncFunctionStart( |
+ assignment, async_function_start, RelocInfo::kNoPosition); |
+ |
+ body->Add( |
+ factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition), |
+ zone()); |
+ |
+ ParseStatementList(body, Token::RBRACE, CHECK_OK); |
+ |
+ Statement* final_return = factory()->NewReturnStatement( |
+ BuildIteratorResult(nullptr, true), RelocInfo::kNoPosition); |
+ body->Add(final_return, zone()); |
} else { |
ParseStatementList(body, Token::RBRACE, CHECK_OK); |
} |
@@ -4606,6 +4644,39 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
DCHECK_EQ(body, inner_block->statements()); |
SetLanguageMode(scope_, inner_scope->language_mode()); |
Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); |
+ |
+ if (IsAsyncFunction(kind)) { |
+ // If an exception occurs during parameter initialization, return a |
+ // rejected promise. |
+ // |
+ // try { <init_block> } catch (error) { return Promise.reject(error); } |
+ Block* try_block = init_block; |
+ Scope* catch_scope = NewScope(scope_, CATCH_SCOPE); |
+ Variable* catch_variable = |
+ catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), |
+ VAR, kCreatedInitialized, Variable::NORMAL); |
+ Block* catch_block = |
+ factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition); |
+ |
+ ZoneList<Expression*>* promise_reject_arguments = |
+ new (zone()) ZoneList<Expression*>(1, zone()); |
+ promise_reject_arguments->Add(factory()->NewVariableProxy(catch_variable), |
+ zone()); |
+ CallRuntime* promise_reject = factory()->NewCallRuntime( |
+ Context::PROMISE_CREATE_REJECTED_INDEX, promise_reject_arguments, |
+ RelocInfo::kNoPosition); |
+ ReturnStatement* return_promise_reject = |
+ factory()->NewReturnStatement(promise_reject, RelocInfo::kNoPosition); |
+ catch_block->statements()->Add(return_promise_reject, zone()); |
+ TryStatement* try_catch_statement = factory()->NewTryCatchStatement( |
+ try_block, catch_scope, catch_variable, catch_block, |
+ RelocInfo::kNoPosition); |
+ |
+ init_block = |
+ factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition); |
+ init_block->statements()->Add(try_catch_statement, zone()); |
+ } |
+ |
DCHECK_NOT_NULL(init_block); |
inner_scope->set_end_position(scanner()->location().end_pos); |
@@ -5396,7 +5467,10 @@ void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier, |
Expression* ParserTraits::RewriteAwaitExpression(Expression* value, int pos) { |
// TODO(caitp): Implement AsyncFunctionAwait() |
// per tc39.github.io/ecmascript-asyncawait/#abstract-ops-async-function-await |
- return value; |
+ Expression* generator_object = parser_->factory()->NewVariableProxy( |
+ parser_->function_state_->generator_object_variable()); |
+ value = BuildIteratorResult(value, false); |
+ return parser_->factory()->NewYield(generator_object, value, pos); |
} |
Zone* ParserTraits::zone() const { |