Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(753)

Side by Side Diff: src/parsing/parser.cc

Issue 1895603002: [esnext] prototype runtime implementation for async functions (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@AsyncFunction
Patch Set: fix test nits Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/parsing/parser.h" 5 #include "src/parsing/parser.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast/ast.h" 8 #include "src/ast/ast.h"
9 #include "src/ast/ast-expression-rewriter.h" 9 #include "src/ast/ast-expression-rewriter.h"
10 #include "src/ast/ast-expression-visitor.h" 10 #include "src/ast/ast-expression-visitor.h"
(...skipping 2697 matching lines...) Expand 10 before | Expand all | Expand 10 after
2708 if (allow_tailcalls() && !is_sloppy(language_mode())) { 2708 if (allow_tailcalls() && !is_sloppy(language_mode())) {
2709 // ES6 14.6.1 Static Semantics: IsInTailPosition 2709 // ES6 14.6.1 Static Semantics: IsInTailPosition
2710 function_state_->AddImplicitTailCallExpression(return_value); 2710 function_state_->AddImplicitTailCallExpression(return_value);
2711 } 2711 }
2712 } 2712 }
2713 } 2713 }
2714 ExpectSemicolon(CHECK_OK); 2714 ExpectSemicolon(CHECK_OK);
2715 2715
2716 if (is_generator()) { 2716 if (is_generator()) {
2717 return_value = BuildIteratorResult(return_value, true); 2717 return_value = BuildIteratorResult(return_value, true);
2718 } else if (is_async_function()) {
2719 return_value = BuildPromiseResolve(return_value, return_value->position());
2718 } 2720 }
2719 2721
2720 result = factory()->NewReturnStatement(return_value, loc.beg_pos); 2722 result = factory()->NewReturnStatement(return_value, loc.beg_pos);
2721 2723
2722 Scope* decl_scope = scope_->DeclarationScope(); 2724 Scope* decl_scope = scope_->DeclarationScope();
2723 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { 2725 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) {
2724 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); 2726 ReportMessageAt(loc, MessageTemplate::kIllegalReturn);
2725 *ok = false; 2727 *ok = false;
2726 return NULL; 2728 return NULL;
2727 } 2729 }
(...skipping 1220 matching lines...) Expand 10 before | Expand all | Expand 10 after
3948 expr = assignment->target(); 3950 expr = assignment->target();
3949 3951
3950 // TODO(adamk): Only call this if necessary. 3952 // TODO(adamk): Only call this if necessary.
3951 RewriteParameterInitializerScope(parser_->stack_limit(), initializer, 3953 RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
3952 parser_->scope_, parameters->scope); 3954 parser_->scope_, parameters->scope);
3953 } 3955 }
3954 3956
3955 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest); 3957 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest);
3956 } 3958 }
3957 3959
3960 void ParserTraits::ParseAsyncArrowSingleExpressionBody(
3961 ZoneList<Statement*>* body, bool accept_IN,
3962 Type::ExpressionClassifier* classifier, int pos, bool* ok) {
3963 parser_->DesugarAsyncFunctionBody(
3964 parser_->ast_value_factory()->empty_string(), parser_->scope_, body,
3965 classifier, kAsyncArrowFunction, FunctionBody::SingleExpression,
3966 accept_IN, pos, ok);
3967 }
3968
3969 void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name,
3970 Scope* scope, ZoneList<Statement*>* body,
3971 ExpressionClassifier* classifier,
3972 FunctionKind kind, FunctionBody body_type,
3973 bool accept_IN, int pos, bool* ok) {
3974 // function async_function() {
3975 // try {
3976 // .generator_object = %CreateGeneratorObject();
3977 // ... function body ...
3978 // } catch (e) {
3979 // return Promise.reject(e);
3980 // }
3981 // }
3982 scope->ForceContextAllocation();
3983 Variable* temp =
3984 scope_->NewTemporary(ast_value_factory()->dot_generator_object_string());
3985 function_state_->set_generator_object_variable(temp);
3986
3987 Expression* init_generator_variable = factory()->NewAssignment(
3988 Token::INIT, factory()->NewVariableProxy(temp),
3989 BuildCreateJSGeneratorObject(pos), RelocInfo::kNoPosition);
3990 body->Add(factory()->NewExpressionStatement(init_generator_variable,
3991 RelocInfo::kNoPosition),
3992 zone());
3993
3994 Block* try_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
3995
3996 ZoneList<Statement*>* inner_body = try_block->statements();
3997
3998 Expression* return_value = nullptr;
3999 if (body_type == FunctionBody::Normal) {
4000 ParseStatementList(inner_body, Token::RBRACE, ok);
4001 if (!*ok) return;
4002 return_value = factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
4003 } else {
4004 return_value = ParseAssignmentExpression(accept_IN, classifier, ok);
4005 if (!*ok) return;
4006 ParserTraits::RewriteNonPattern(classifier, ok);
4007 if (!*ok) return;
4008 }
4009
4010 return_value = BuildPromiseResolve(return_value, return_value->position());
4011 inner_body->Add(
4012 factory()->NewReturnStatement(return_value, return_value->position()),
4013 zone());
4014 body->Add(BuildRejectPromiseOnException(try_block), zone());
4015 scope->set_end_position(scanner()->location().end_pos);
4016 }
3958 4017
3959 DoExpression* Parser::ParseDoExpression(bool* ok) { 4018 DoExpression* Parser::ParseDoExpression(bool* ok) {
3960 // AssignmentExpression :: 4019 // AssignmentExpression ::
3961 // do '{' StatementList '}' 4020 // do '{' StatementList '}'
3962 int pos = peek_position(); 4021 int pos = peek_position();
3963 4022
3964 Expect(Token::DO, CHECK_OK); 4023 Expect(Token::DO, CHECK_OK);
3965 Variable* result = 4024 Variable* result =
3966 scope_->NewTemporary(ast_value_factory()->dot_result_string()); 4025 scope_->NewTemporary(ast_value_factory()->dot_result_string());
3967 Block* block = ParseBlock(nullptr, false, CHECK_OK); 4026 Block* block = ParseBlock(nullptr, false, CHECK_OK);
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
4496 param_scope = param_scope->FinalizeBlockScope(); 4555 param_scope = param_scope->FinalizeBlockScope();
4497 if (param_scope != nullptr) { 4556 if (param_scope != nullptr) {
4498 CheckConflictingVarDeclarations(param_scope, CHECK_OK); 4557 CheckConflictingVarDeclarations(param_scope, CHECK_OK);
4499 } 4558 }
4500 init_block->statements()->Add(param_block, zone()); 4559 init_block->statements()->Add(param_block, zone());
4501 } 4560 }
4502 } 4561 }
4503 return init_block; 4562 return init_block;
4504 } 4563 }
4505 4564
4565 Block* Parser::BuildRejectPromiseOnException(Block* block) {
4566 // try { <block> } catch (error) { return Promise.reject(error); }
4567 Block* try_block = block;
4568 Scope* catch_scope = NewScope(scope_, CATCH_SCOPE);
4569 catch_scope->set_is_hidden();
4570 Variable* catch_variable =
4571 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR,
4572 kCreatedInitialized, Variable::NORMAL);
4573 Block* catch_block =
4574 factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
4575
4576 Expression* promise_reject = BuildPromiseReject(
4577 factory()->NewVariableProxy(catch_variable), RelocInfo::kNoPosition);
4578
4579 ReturnStatement* return_promise_reject =
4580 factory()->NewReturnStatement(promise_reject, RelocInfo::kNoPosition);
4581 catch_block->statements()->Add(return_promise_reject, zone());
4582 TryStatement* try_catch_statement =
4583 factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable,
4584 catch_block, RelocInfo::kNoPosition);
4585
4586 block = factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
4587 block->statements()->Add(try_catch_statement, zone());
4588 return block;
4589 }
4590
4591 Expression* Parser::BuildCreateJSGeneratorObject(int pos) {
4592 DCHECK_NOT_NULL(function_state_->generator_object_variable());
4593 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
4594 args->Add(factory()->NewThisFunction(pos), zone());
4595 args->Add(ThisExpression(scope_, factory(), RelocInfo::kNoPosition), zone());
4596 return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args,
4597 pos);
4598 }
4599
4600 Expression* Parser::BuildPromiseResolve(Expression* value, int pos) {
4601 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
4602 args->Add(value, zone());
4603 return factory()->NewCallRuntime(Context::PROMISE_CREATE_RESOLVED_INDEX, args,
4604 pos);
4605 }
4606
4607 Expression* Parser::BuildPromiseReject(Expression* value, int pos) {
4608 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
4609 args->Add(value, zone());
4610 return factory()->NewCallRuntime(Context::PROMISE_CREATE_REJECTED_INDEX, args,
4611 pos);
4612 }
4506 4613
4507 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( 4614 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
4508 const AstRawString* function_name, int pos, 4615 const AstRawString* function_name, int pos,
4509 const ParserFormalParameters& parameters, FunctionKind kind, 4616 const ParserFormalParameters& parameters, FunctionKind kind,
4510 FunctionLiteral::FunctionType function_type, bool* ok) { 4617 FunctionLiteral::FunctionType function_type, bool* ok) {
4511 // Everything inside an eagerly parsed function will be parsed eagerly 4618 // Everything inside an eagerly parsed function will be parsed eagerly
4512 // (see comment above). 4619 // (see comment above).
4513 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); 4620 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
4514 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); 4621 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
4515 4622
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4549 // - InitialYield yields the actual generator object. 4656 // - InitialYield yields the actual generator object.
4550 // - Any return statement inside the body will have its argument wrapped 4657 // - Any return statement inside the body will have its argument wrapped
4551 // in a "done" iterator result object. 4658 // in a "done" iterator result object.
4552 // - If the generator terminates for whatever reason, we must close it. 4659 // - If the generator terminates for whatever reason, we must close it.
4553 // Hence the finally clause. 4660 // Hence the finally clause.
4554 4661
4555 Block* try_block = 4662 Block* try_block =
4556 factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition); 4663 factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition);
4557 4664
4558 { 4665 {
4559 ZoneList<Expression*>* arguments = 4666 Expression* allocation = BuildCreateJSGeneratorObject(pos);
4560 new (zone()) ZoneList<Expression*>(2, zone());
4561 arguments->Add(factory()->NewThisFunction(pos), zone());
4562 arguments->Add(
4563 ThisExpression(scope_, factory(), RelocInfo::kNoPosition), zone());
4564 CallRuntime* allocation = factory()->NewCallRuntime(
4565 Runtime::kCreateJSGeneratorObject, arguments, pos);
4566
4567 VariableProxy* init_proxy = factory()->NewVariableProxy( 4667 VariableProxy* init_proxy = factory()->NewVariableProxy(
4568 function_state_->generator_object_variable()); 4668 function_state_->generator_object_variable());
4569 Assignment* assignment = factory()->NewAssignment( 4669 Assignment* assignment = factory()->NewAssignment(
4570 Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition); 4670 Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition);
4571 VariableProxy* get_proxy = factory()->NewVariableProxy( 4671 VariableProxy* get_proxy = factory()->NewVariableProxy(
4572 function_state_->generator_object_variable()); 4672 function_state_->generator_object_variable());
4573 Yield* yield = 4673 Yield* yield =
4574 factory()->NewYield(get_proxy, assignment, RelocInfo::kNoPosition); 4674 factory()->NewYield(get_proxy, assignment, RelocInfo::kNoPosition);
4575 try_block->statements()->Add( 4675 try_block->statements()->Add(
4576 factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition), 4676 factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
(...skipping 15 matching lines...) Expand all
4592 args->Add(call_proxy, zone()); 4692 args->Add(call_proxy, zone());
4593 Expression* call = factory()->NewCallRuntime( 4693 Expression* call = factory()->NewCallRuntime(
4594 Runtime::kGeneratorClose, args, RelocInfo::kNoPosition); 4694 Runtime::kGeneratorClose, args, RelocInfo::kNoPosition);
4595 finally_block->statements()->Add( 4695 finally_block->statements()->Add(
4596 factory()->NewExpressionStatement(call, RelocInfo::kNoPosition), 4696 factory()->NewExpressionStatement(call, RelocInfo::kNoPosition),
4597 zone()); 4697 zone());
4598 4698
4599 body->Add(factory()->NewTryFinallyStatement(try_block, finally_block, 4699 body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
4600 RelocInfo::kNoPosition), 4700 RelocInfo::kNoPosition),
4601 zone()); 4701 zone());
4702 } else if (IsAsyncFunction(kind)) {
4703 const bool accept_IN = true;
4704 DesugarAsyncFunctionBody(function_name, inner_scope, body, nullptr, kind,
4705 FunctionBody::Normal, accept_IN, pos, CHECK_OK);
4602 } else { 4706 } else {
4603 ParseStatementList(body, Token::RBRACE, CHECK_OK); 4707 ParseStatementList(body, Token::RBRACE, CHECK_OK);
4604 } 4708 }
4605 4709
4606 if (IsSubclassConstructor(kind)) { 4710 if (IsSubclassConstructor(kind)) {
4607 body->Add( 4711 body->Add(
4608 factory()->NewReturnStatement( 4712 factory()->NewReturnStatement(
4609 this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition), 4713 this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition),
4610 RelocInfo::kNoPosition), 4714 RelocInfo::kNoPosition),
4611 zone()); 4715 zone());
4612 } 4716 }
4613 } 4717 }
4614 4718
4615 Expect(Token::RBRACE, CHECK_OK); 4719 Expect(Token::RBRACE, CHECK_OK);
4616 scope_->set_end_position(scanner()->location().end_pos); 4720 scope_->set_end_position(scanner()->location().end_pos);
4617 4721
4618 if (!parameters.is_simple) { 4722 if (!parameters.is_simple) {
4619 DCHECK_NOT_NULL(inner_scope); 4723 DCHECK_NOT_NULL(inner_scope);
4620 DCHECK_EQ(body, inner_block->statements()); 4724 DCHECK_EQ(body, inner_block->statements());
4621 SetLanguageMode(scope_, inner_scope->language_mode()); 4725 SetLanguageMode(scope_, inner_scope->language_mode());
4622 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); 4726 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
4727
4728 if (IsAsyncFunction(kind)) {
4729 init_block = BuildRejectPromiseOnException(init_block);
4730 }
4731
4623 DCHECK_NOT_NULL(init_block); 4732 DCHECK_NOT_NULL(init_block);
4624 4733
4625 inner_scope->set_end_position(scanner()->location().end_pos); 4734 inner_scope->set_end_position(scanner()->location().end_pos);
4626 inner_scope = inner_scope->FinalizeBlockScope(); 4735 inner_scope = inner_scope->FinalizeBlockScope();
4627 if (inner_scope != nullptr) { 4736 if (inner_scope != nullptr) {
4628 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); 4737 CheckConflictingVarDeclarations(inner_scope, CHECK_OK);
4629 InsertShadowingVarBindingInitializers(inner_block); 4738 InsertShadowingVarBindingInitializers(inner_block);
4630 } 4739 }
4631 4740
4632 result->Add(init_block, zone()); 4741 result->Add(init_block, zone());
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after
5417 int pos) { 5526 int pos) {
5418 return parser_->RewriteAssignExponentiation(left, right, pos); 5527 return parser_->RewriteAssignExponentiation(left, right, pos);
5419 } 5528 }
5420 5529
5421 void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier, 5530 void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier,
5422 bool* ok) { 5531 bool* ok) {
5423 parser_->RewriteNonPattern(classifier, ok); 5532 parser_->RewriteNonPattern(classifier, ok);
5424 } 5533 }
5425 5534
5426 Expression* ParserTraits::RewriteAwaitExpression(Expression* value, int pos) { 5535 Expression* ParserTraits::RewriteAwaitExpression(Expression* value, int pos) {
5427 // TODO(caitp): Implement AsyncFunctionAwait() 5536 // yield %AsyncFunctionAwait(.generator_object, <operand>)
5428 // per tc39.github.io/ecmascript-asyncawait/#abstract-ops-async-function-await 5537 Variable* generator_object_variable =
5429 return value; 5538 parser_->function_state_->generator_object_variable();
5539
5540 DCHECK_NOT_NULL(generator_object_variable);
5541
5542 Expression* generator_object =
5543 parser_->factory()->NewVariableProxy(generator_object_variable);
5544
5545 ZoneList<Expression*>* async_function_await_args =
5546 new (zone()) ZoneList<Expression*>(2, zone());
5547 async_function_await_args->Add(generator_object, zone());
5548 async_function_await_args->Add(value, zone());
5549 Expression* async_function_await = parser_->factory()->NewCallRuntime(
5550 Context::ASYNC_FUNCTION_AWAIT_INDEX, async_function_await_args,
5551 RelocInfo::kNoPosition);
5552
5553 generator_object =
5554 parser_->factory()->NewVariableProxy(generator_object_variable);
5555 return parser_->factory()->NewYield(generator_object, async_function_await,
5556 pos);
5430 } 5557 }
5431 5558
5432 Zone* ParserTraits::zone() const { 5559 Zone* ParserTraits::zone() const {
5433 return parser_->function_state_->scope()->zone(); 5560 return parser_->function_state_->scope()->zone();
5434 } 5561 }
5435 5562
5436 5563
5437 ZoneList<Expression*>* ParserTraits::GetNonPatternList() const { 5564 ZoneList<Expression*>* ParserTraits::GetNonPatternList() const {
5438 return parser_->function_state_->non_patterns_to_rewrite(); 5565 return parser_->function_state_->non_patterns_to_rewrite();
5439 } 5566 }
(...skipping 1473 matching lines...) Expand 10 before | Expand all | Expand 10 after
6913 try_block, target); 7040 try_block, target);
6914 final_loop = target; 7041 final_loop = target;
6915 } 7042 }
6916 7043
6917 return final_loop; 7044 return final_loop;
6918 } 7045 }
6919 7046
6920 7047
6921 } // namespace internal 7048 } // namespace internal
6922 } // namespace v8 7049 } // namespace v8
OLDNEW
« src/builtins.cc ('K') | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698