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 2734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2745 if (allow_tailcalls() && !is_sloppy(language_mode())) { | 2745 if (allow_tailcalls() && !is_sloppy(language_mode())) { |
2746 // ES6 14.6.1 Static Semantics: IsInTailPosition | 2746 // ES6 14.6.1 Static Semantics: IsInTailPosition |
2747 function_state_->AddImplicitTailCallExpression(return_value); | 2747 function_state_->AddImplicitTailCallExpression(return_value); |
2748 } | 2748 } |
2749 } | 2749 } |
2750 } | 2750 } |
2751 ExpectSemicolon(CHECK_OK); | 2751 ExpectSemicolon(CHECK_OK); |
2752 | 2752 |
2753 if (is_generator()) { | 2753 if (is_generator()) { |
2754 return_value = BuildIteratorResult(return_value, true); | 2754 return_value = BuildIteratorResult(return_value, true); |
| 2755 } else if (is_async_function()) { |
| 2756 return_value = BuildPromiseResolve(return_value, return_value->position()); |
2755 } | 2757 } |
2756 | 2758 |
2757 result = factory()->NewReturnStatement(return_value, loc.beg_pos); | 2759 result = factory()->NewReturnStatement(return_value, loc.beg_pos); |
2758 | 2760 |
2759 Scope* decl_scope = scope_->DeclarationScope(); | 2761 Scope* decl_scope = scope_->DeclarationScope(); |
2760 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { | 2762 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { |
2761 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); | 2763 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); |
2762 *ok = false; | 2764 *ok = false; |
2763 return NULL; | 2765 return NULL; |
2764 } | 2766 } |
(...skipping 1220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3985 expr = assignment->target(); | 3987 expr = assignment->target(); |
3986 | 3988 |
3987 // TODO(adamk): Only call this if necessary. | 3989 // TODO(adamk): Only call this if necessary. |
3988 RewriteParameterInitializerScope(parser_->stack_limit(), initializer, | 3990 RewriteParameterInitializerScope(parser_->stack_limit(), initializer, |
3989 parser_->scope_, parameters->scope); | 3991 parser_->scope_, parameters->scope); |
3990 } | 3992 } |
3991 | 3993 |
3992 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest); | 3994 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest); |
3993 } | 3995 } |
3994 | 3996 |
| 3997 void ParserTraits::ParseAsyncArrowSingleExpressionBody( |
| 3998 ZoneList<Statement*>* body, bool accept_IN, |
| 3999 Type::ExpressionClassifier* classifier, int pos, bool* ok) { |
| 4000 parser_->DesugarAsyncFunctionBody( |
| 4001 parser_->ast_value_factory()->empty_string(), parser_->scope_, body, |
| 4002 classifier, kAsyncArrowFunction, FunctionBody::SingleExpression, |
| 4003 accept_IN, pos, ok); |
| 4004 } |
| 4005 |
| 4006 void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name, |
| 4007 Scope* scope, ZoneList<Statement*>* body, |
| 4008 ExpressionClassifier* classifier, |
| 4009 FunctionKind kind, FunctionBody body_type, |
| 4010 bool accept_IN, int pos, bool* ok) { |
| 4011 // function async_function() { |
| 4012 // try { |
| 4013 // .generator_object = %CreateGeneratorObject(); |
| 4014 // ... function body ... |
| 4015 // } catch (e) { |
| 4016 // return Promise.reject(e); |
| 4017 // } |
| 4018 // } |
| 4019 scope->ForceContextAllocation(); |
| 4020 Variable* temp = |
| 4021 scope_->NewTemporary(ast_value_factory()->dot_generator_object_string()); |
| 4022 function_state_->set_generator_object_variable(temp); |
| 4023 |
| 4024 Expression* init_generator_variable = factory()->NewAssignment( |
| 4025 Token::INIT, factory()->NewVariableProxy(temp), |
| 4026 BuildCreateJSGeneratorObject(pos), RelocInfo::kNoPosition); |
| 4027 body->Add(factory()->NewExpressionStatement(init_generator_variable, |
| 4028 RelocInfo::kNoPosition), |
| 4029 zone()); |
| 4030 |
| 4031 Block* try_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition); |
| 4032 |
| 4033 ZoneList<Statement*>* inner_body = try_block->statements(); |
| 4034 |
| 4035 Expression* return_value = nullptr; |
| 4036 if (body_type == FunctionBody::Normal) { |
| 4037 ParseStatementList(inner_body, Token::RBRACE, ok); |
| 4038 if (!*ok) return; |
| 4039 return_value = factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); |
| 4040 } else { |
| 4041 return_value = ParseAssignmentExpression(accept_IN, classifier, ok); |
| 4042 if (!*ok) return; |
| 4043 ParserTraits::RewriteNonPattern(classifier, ok); |
| 4044 if (!*ok) return; |
| 4045 } |
| 4046 |
| 4047 return_value = BuildPromiseResolve(return_value, return_value->position()); |
| 4048 inner_body->Add( |
| 4049 factory()->NewReturnStatement(return_value, return_value->position()), |
| 4050 zone()); |
| 4051 body->Add(BuildRejectPromiseOnException(try_block), zone()); |
| 4052 scope->set_end_position(scanner()->location().end_pos); |
| 4053 } |
3995 | 4054 |
3996 DoExpression* Parser::ParseDoExpression(bool* ok) { | 4055 DoExpression* Parser::ParseDoExpression(bool* ok) { |
3997 // AssignmentExpression :: | 4056 // AssignmentExpression :: |
3998 // do '{' StatementList '}' | 4057 // do '{' StatementList '}' |
3999 int pos = peek_position(); | 4058 int pos = peek_position(); |
4000 | 4059 |
4001 Expect(Token::DO, CHECK_OK); | 4060 Expect(Token::DO, CHECK_OK); |
4002 Variable* result = | 4061 Variable* result = |
4003 scope_->NewTemporary(ast_value_factory()->dot_result_string()); | 4062 scope_->NewTemporary(ast_value_factory()->dot_result_string()); |
4004 Block* block = ParseBlock(nullptr, false, CHECK_OK); | 4063 Block* block = ParseBlock(nullptr, false, CHECK_OK); |
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4531 param_scope = param_scope->FinalizeBlockScope(); | 4590 param_scope = param_scope->FinalizeBlockScope(); |
4532 if (param_scope != nullptr) { | 4591 if (param_scope != nullptr) { |
4533 CheckConflictingVarDeclarations(param_scope, CHECK_OK); | 4592 CheckConflictingVarDeclarations(param_scope, CHECK_OK); |
4534 } | 4593 } |
4535 init_block->statements()->Add(param_block, zone()); | 4594 init_block->statements()->Add(param_block, zone()); |
4536 } | 4595 } |
4537 } | 4596 } |
4538 return init_block; | 4597 return init_block; |
4539 } | 4598 } |
4540 | 4599 |
| 4600 Block* Parser::BuildRejectPromiseOnException(Block* block) { |
| 4601 // try { <block> } catch (error) { return Promise.reject(error); } |
| 4602 Block* try_block = block; |
| 4603 Scope* catch_scope = NewScope(scope_, CATCH_SCOPE); |
| 4604 catch_scope->set_is_hidden(); |
| 4605 Variable* catch_variable = |
| 4606 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, |
| 4607 kCreatedInitialized, Variable::NORMAL); |
| 4608 Block* catch_block = |
| 4609 factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition); |
| 4610 |
| 4611 Expression* promise_reject = BuildPromiseReject( |
| 4612 factory()->NewVariableProxy(catch_variable), RelocInfo::kNoPosition); |
| 4613 |
| 4614 ReturnStatement* return_promise_reject = |
| 4615 factory()->NewReturnStatement(promise_reject, RelocInfo::kNoPosition); |
| 4616 catch_block->statements()->Add(return_promise_reject, zone()); |
| 4617 TryStatement* try_catch_statement = |
| 4618 factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable, |
| 4619 catch_block, RelocInfo::kNoPosition); |
| 4620 |
| 4621 block = factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition); |
| 4622 block->statements()->Add(try_catch_statement, zone()); |
| 4623 return block; |
| 4624 } |
| 4625 |
| 4626 Expression* Parser::BuildCreateJSGeneratorObject(int pos) { |
| 4627 DCHECK_NOT_NULL(function_state_->generator_object_variable()); |
| 4628 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); |
| 4629 args->Add(factory()->NewThisFunction(pos), zone()); |
| 4630 args->Add(ThisExpression(scope_, factory(), RelocInfo::kNoPosition), zone()); |
| 4631 return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args, |
| 4632 pos); |
| 4633 } |
| 4634 |
| 4635 Expression* Parser::BuildPromiseResolve(Expression* value, int pos) { |
| 4636 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); |
| 4637 args->Add(value, zone()); |
| 4638 return factory()->NewCallRuntime(Context::PROMISE_CREATE_RESOLVED_INDEX, args, |
| 4639 pos); |
| 4640 } |
| 4641 |
| 4642 Expression* Parser::BuildPromiseReject(Expression* value, int pos) { |
| 4643 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); |
| 4644 args->Add(value, zone()); |
| 4645 return factory()->NewCallRuntime(Context::PROMISE_CREATE_REJECTED_INDEX, args, |
| 4646 pos); |
| 4647 } |
4541 | 4648 |
4542 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( | 4649 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
4543 const AstRawString* function_name, int pos, | 4650 const AstRawString* function_name, int pos, |
4544 const ParserFormalParameters& parameters, FunctionKind kind, | 4651 const ParserFormalParameters& parameters, FunctionKind kind, |
4545 FunctionLiteral::FunctionType function_type, bool* ok) { | 4652 FunctionLiteral::FunctionType function_type, bool* ok) { |
4546 // Everything inside an eagerly parsed function will be parsed eagerly | 4653 // Everything inside an eagerly parsed function will be parsed eagerly |
4547 // (see comment above). | 4654 // (see comment above). |
4548 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | 4655 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); |
4549 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); | 4656 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); |
4550 | 4657 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4584 // - InitialYield yields the actual generator object. | 4691 // - InitialYield yields the actual generator object. |
4585 // - Any return statement inside the body will have its argument wrapped | 4692 // - Any return statement inside the body will have its argument wrapped |
4586 // in a "done" iterator result object. | 4693 // in a "done" iterator result object. |
4587 // - If the generator terminates for whatever reason, we must close it. | 4694 // - If the generator terminates for whatever reason, we must close it. |
4588 // Hence the finally clause. | 4695 // Hence the finally clause. |
4589 | 4696 |
4590 Block* try_block = | 4697 Block* try_block = |
4591 factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition); | 4698 factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition); |
4592 | 4699 |
4593 { | 4700 { |
4594 ZoneList<Expression*>* arguments = | 4701 Expression* allocation = BuildCreateJSGeneratorObject(pos); |
4595 new (zone()) ZoneList<Expression*>(2, zone()); | |
4596 arguments->Add(factory()->NewThisFunction(pos), zone()); | |
4597 arguments->Add( | |
4598 ThisExpression(scope_, factory(), RelocInfo::kNoPosition), zone()); | |
4599 CallRuntime* allocation = factory()->NewCallRuntime( | |
4600 Runtime::kCreateJSGeneratorObject, arguments, pos); | |
4601 | |
4602 VariableProxy* init_proxy = factory()->NewVariableProxy( | 4702 VariableProxy* init_proxy = factory()->NewVariableProxy( |
4603 function_state_->generator_object_variable()); | 4703 function_state_->generator_object_variable()); |
4604 Assignment* assignment = factory()->NewAssignment( | 4704 Assignment* assignment = factory()->NewAssignment( |
4605 Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition); | 4705 Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition); |
4606 VariableProxy* get_proxy = factory()->NewVariableProxy( | 4706 VariableProxy* get_proxy = factory()->NewVariableProxy( |
4607 function_state_->generator_object_variable()); | 4707 function_state_->generator_object_variable()); |
4608 Yield* yield = | 4708 Yield* yield = |
4609 factory()->NewYield(get_proxy, assignment, RelocInfo::kNoPosition); | 4709 factory()->NewYield(get_proxy, assignment, RelocInfo::kNoPosition); |
4610 try_block->statements()->Add( | 4710 try_block->statements()->Add( |
4611 factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition), | 4711 factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition), |
(...skipping 15 matching lines...) Expand all Loading... |
4627 args->Add(call_proxy, zone()); | 4727 args->Add(call_proxy, zone()); |
4628 Expression* call = factory()->NewCallRuntime( | 4728 Expression* call = factory()->NewCallRuntime( |
4629 Runtime::kGeneratorClose, args, RelocInfo::kNoPosition); | 4729 Runtime::kGeneratorClose, args, RelocInfo::kNoPosition); |
4630 finally_block->statements()->Add( | 4730 finally_block->statements()->Add( |
4631 factory()->NewExpressionStatement(call, RelocInfo::kNoPosition), | 4731 factory()->NewExpressionStatement(call, RelocInfo::kNoPosition), |
4632 zone()); | 4732 zone()); |
4633 | 4733 |
4634 body->Add(factory()->NewTryFinallyStatement(try_block, finally_block, | 4734 body->Add(factory()->NewTryFinallyStatement(try_block, finally_block, |
4635 RelocInfo::kNoPosition), | 4735 RelocInfo::kNoPosition), |
4636 zone()); | 4736 zone()); |
| 4737 } else if (IsAsyncFunction(kind)) { |
| 4738 const bool accept_IN = true; |
| 4739 DesugarAsyncFunctionBody(function_name, inner_scope, body, nullptr, kind, |
| 4740 FunctionBody::Normal, accept_IN, pos, CHECK_OK); |
4637 } else { | 4741 } else { |
4638 ParseStatementList(body, Token::RBRACE, CHECK_OK); | 4742 ParseStatementList(body, Token::RBRACE, CHECK_OK); |
4639 } | 4743 } |
4640 | 4744 |
4641 if (IsSubclassConstructor(kind)) { | 4745 if (IsSubclassConstructor(kind)) { |
4642 body->Add( | 4746 body->Add( |
4643 factory()->NewReturnStatement( | 4747 factory()->NewReturnStatement( |
4644 this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition), | 4748 this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition), |
4645 RelocInfo::kNoPosition), | 4749 RelocInfo::kNoPosition), |
4646 zone()); | 4750 zone()); |
4647 } | 4751 } |
4648 } | 4752 } |
4649 | 4753 |
4650 Expect(Token::RBRACE, CHECK_OK); | 4754 Expect(Token::RBRACE, CHECK_OK); |
4651 scope_->set_end_position(scanner()->location().end_pos); | 4755 scope_->set_end_position(scanner()->location().end_pos); |
4652 | 4756 |
4653 if (!parameters.is_simple) { | 4757 if (!parameters.is_simple) { |
4654 DCHECK_NOT_NULL(inner_scope); | 4758 DCHECK_NOT_NULL(inner_scope); |
4655 DCHECK_EQ(body, inner_block->statements()); | 4759 DCHECK_EQ(body, inner_block->statements()); |
4656 SetLanguageMode(scope_, inner_scope->language_mode()); | 4760 SetLanguageMode(scope_, inner_scope->language_mode()); |
4657 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); | 4761 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); |
| 4762 |
| 4763 if (IsAsyncFunction(kind)) { |
| 4764 init_block = BuildRejectPromiseOnException(init_block); |
| 4765 } |
| 4766 |
4658 DCHECK_NOT_NULL(init_block); | 4767 DCHECK_NOT_NULL(init_block); |
4659 | 4768 |
4660 inner_scope->set_end_position(scanner()->location().end_pos); | 4769 inner_scope->set_end_position(scanner()->location().end_pos); |
4661 inner_scope = inner_scope->FinalizeBlockScope(); | 4770 inner_scope = inner_scope->FinalizeBlockScope(); |
4662 if (inner_scope != nullptr) { | 4771 if (inner_scope != nullptr) { |
4663 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); | 4772 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); |
4664 InsertShadowingVarBindingInitializers(inner_block); | 4773 InsertShadowingVarBindingInitializers(inner_block); |
4665 } | 4774 } |
4666 | 4775 |
4667 result->Add(init_block, zone()); | 4776 result->Add(init_block, zone()); |
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5452 int pos) { | 5561 int pos) { |
5453 return parser_->RewriteAssignExponentiation(left, right, pos); | 5562 return parser_->RewriteAssignExponentiation(left, right, pos); |
5454 } | 5563 } |
5455 | 5564 |
5456 void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier, | 5565 void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier, |
5457 bool* ok) { | 5566 bool* ok) { |
5458 parser_->RewriteNonPattern(classifier, ok); | 5567 parser_->RewriteNonPattern(classifier, ok); |
5459 } | 5568 } |
5460 | 5569 |
5461 Expression* ParserTraits::RewriteAwaitExpression(Expression* value, int pos) { | 5570 Expression* ParserTraits::RewriteAwaitExpression(Expression* value, int pos) { |
5462 // TODO(caitp): Implement AsyncFunctionAwait() | 5571 // yield %AsyncFunctionAwait(.generator_object, <operand>) |
5463 // per tc39.github.io/ecmascript-asyncawait/#abstract-ops-async-function-await | 5572 Variable* generator_object_variable = |
5464 return value; | 5573 parser_->function_state_->generator_object_variable(); |
| 5574 |
| 5575 // If generator_object_variable is null, |
| 5576 if (!generator_object_variable) return value; |
| 5577 |
| 5578 Expression* generator_object = |
| 5579 parser_->factory()->NewVariableProxy(generator_object_variable); |
| 5580 |
| 5581 ZoneList<Expression*>* async_function_await_args = |
| 5582 new (zone()) ZoneList<Expression*>(2, zone()); |
| 5583 async_function_await_args->Add(generator_object, zone()); |
| 5584 async_function_await_args->Add(value, zone()); |
| 5585 Expression* async_function_await = parser_->factory()->NewCallRuntime( |
| 5586 Context::ASYNC_FUNCTION_AWAIT_INDEX, async_function_await_args, |
| 5587 RelocInfo::kNoPosition); |
| 5588 |
| 5589 generator_object = |
| 5590 parser_->factory()->NewVariableProxy(generator_object_variable); |
| 5591 return parser_->factory()->NewYield(generator_object, async_function_await, |
| 5592 pos); |
5465 } | 5593 } |
5466 | 5594 |
5467 Zone* ParserTraits::zone() const { | 5595 Zone* ParserTraits::zone() const { |
5468 return parser_->function_state_->scope()->zone(); | 5596 return parser_->function_state_->scope()->zone(); |
5469 } | 5597 } |
5470 | 5598 |
5471 | 5599 |
5472 ZoneList<Expression*>* ParserTraits::GetNonPatternList() const { | 5600 ZoneList<Expression*>* ParserTraits::GetNonPatternList() const { |
5473 return parser_->function_state_->non_patterns_to_rewrite(); | 5601 return parser_->function_state_->non_patterns_to_rewrite(); |
5474 } | 5602 } |
(...skipping 1473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6948 try_block, target); | 7076 try_block, target); |
6949 final_loop = target; | 7077 final_loop = target; |
6950 } | 7078 } |
6951 | 7079 |
6952 return final_loop; | 7080 return final_loop; |
6953 } | 7081 } |
6954 | 7082 |
6955 | 7083 |
6956 } // namespace internal | 7084 } // namespace internal |
6957 } // namespace v8 | 7085 } // namespace v8 |
OLD | NEW |