OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |