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 <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
(...skipping 2445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2456 // ES6 14.6.1 Static Semantics: IsInTailPosition | 2456 // ES6 14.6.1 Static Semantics: IsInTailPosition |
2457 function_state_->AddImplicitTailCallExpression(return_value); | 2457 function_state_->AddImplicitTailCallExpression(return_value); |
2458 } | 2458 } |
2459 } | 2459 } |
2460 } | 2460 } |
2461 ExpectSemicolon(CHECK_OK); | 2461 ExpectSemicolon(CHECK_OK); |
2462 | 2462 |
2463 if (is_generator()) { | 2463 if (is_generator()) { |
2464 return_value = BuildIteratorResult(return_value, true); | 2464 return_value = BuildIteratorResult(return_value, true); |
2465 } else if (is_async_function()) { | 2465 } else if (is_async_function()) { |
2466 return_value = BuildPromiseResolve(return_value, return_value->position()); | 2466 return_value = BuildResolvePromise(return_value, return_value->position()); |
2467 } | 2467 } |
2468 | 2468 |
2469 result = factory()->NewReturnStatement(return_value, loc.beg_pos); | 2469 result = factory()->NewReturnStatement(return_value, loc.beg_pos); |
2470 | 2470 |
2471 DeclarationScope* decl_scope = GetDeclarationScope(); | 2471 DeclarationScope* decl_scope = GetDeclarationScope(); |
2472 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { | 2472 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { |
2473 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); | 2473 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); |
2474 *ok = false; | 2474 *ok = false; |
2475 return NULL; | 2475 return NULL; |
2476 } | 2476 } |
(...skipping 1308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3785 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest); | 3785 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest); |
3786 } | 3786 } |
3787 | 3787 |
3788 void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name, | 3788 void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name, |
3789 Scope* scope, ZoneList<Statement*>* body, | 3789 Scope* scope, ZoneList<Statement*>* body, |
3790 ExpressionClassifier* classifier, | 3790 ExpressionClassifier* classifier, |
3791 FunctionKind kind, | 3791 FunctionKind kind, |
3792 FunctionBodyType body_type, | 3792 FunctionBodyType body_type, |
3793 bool accept_IN, int pos, bool* ok) { | 3793 bool accept_IN, int pos, bool* ok) { |
3794 // function async_function() { | 3794 // function async_function() { |
3795 // try { | 3795 // .generator_object = %CreateGeneratorObject(); |
3796 // .generator_object = %CreateGeneratorObject(); | 3796 // BuildRejectPromiseOnException({ |
3797 // ... function body ... | 3797 // ... function body ... |
3798 // } catch (e) { | 3798 // return %ResolvePromise(.promise, expr), .promise; |
3799 // return Promise.reject(e); | 3799 // }) |
3800 // } | |
3801 // } | 3800 // } |
3802 scope->ForceContextAllocation(); | 3801 scope->ForceContextAllocation(); |
3803 Variable* temp = | 3802 Variable* temp = |
3804 NewTemporary(ast_value_factory()->dot_generator_object_string()); | 3803 NewTemporary(ast_value_factory()->dot_generator_object_string()); |
3805 function_state_->set_generator_object_variable(temp); | 3804 function_state_->set_generator_object_variable(temp); |
3806 | 3805 |
3807 Expression* init_generator_variable = factory()->NewAssignment( | 3806 Expression* init_generator_variable = factory()->NewAssignment( |
3808 Token::INIT, factory()->NewVariableProxy(temp), | 3807 Token::INIT, factory()->NewVariableProxy(temp), |
3809 BuildCreateJSGeneratorObject(pos, kind), kNoSourcePosition); | 3808 BuildCreateJSGeneratorObject(pos, kind), kNoSourcePosition); |
3810 body->Add(factory()->NewExpressionStatement(init_generator_variable, | 3809 body->Add(factory()->NewExpressionStatement(init_generator_variable, |
3811 kNoSourcePosition), | 3810 kNoSourcePosition), |
3812 zone()); | 3811 zone()); |
3813 | 3812 |
3814 Block* try_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition); | 3813 Block* block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition); |
3815 | |
3816 ZoneList<Statement*>* inner_body = try_block->statements(); | |
3817 | 3814 |
3818 Expression* return_value = nullptr; | 3815 Expression* return_value = nullptr; |
3819 if (body_type == FunctionBodyType::kNormal) { | 3816 if (body_type == FunctionBodyType::kNormal) { |
3820 ParseStatementList(inner_body, Token::RBRACE, CHECK_OK_VOID); | 3817 ParseStatementList(block->statements(), Token::RBRACE, CHECK_OK_VOID); |
3821 return_value = factory()->NewUndefinedLiteral(kNoSourcePosition); | 3818 return_value = factory()->NewUndefinedLiteral(kNoSourcePosition); |
3822 } else { | 3819 } else { |
3823 return_value = | 3820 return_value = |
3824 ParseAssignmentExpression(accept_IN, classifier, CHECK_OK_VOID); | 3821 ParseAssignmentExpression(accept_IN, classifier, CHECK_OK_VOID); |
3825 RewriteNonPattern(classifier, CHECK_OK_VOID); | 3822 RewriteNonPattern(classifier, CHECK_OK_VOID); |
3826 } | 3823 } |
3827 | 3824 |
3828 return_value = BuildPromiseResolve(return_value, return_value->position()); | 3825 return_value = BuildResolvePromise(return_value, return_value->position()); |
3829 inner_body->Add( | 3826 block->statements()->Add( |
3830 factory()->NewReturnStatement(return_value, return_value->position()), | 3827 factory()->NewReturnStatement(return_value, return_value->position()), |
3831 zone()); | 3828 zone()); |
3832 body->Add(BuildRejectPromiseOnException(try_block), zone()); | 3829 block = BuildRejectPromiseOnException(block, CHECK_OK_VOID); |
| 3830 body->Add(block, zone()); |
3833 scope->set_end_position(scanner()->location().end_pos); | 3831 scope->set_end_position(scanner()->location().end_pos); |
3834 } | 3832 } |
3835 | 3833 |
3836 DoExpression* Parser::ParseDoExpression(bool* ok) { | 3834 DoExpression* Parser::ParseDoExpression(bool* ok) { |
3837 // AssignmentExpression :: | 3835 // AssignmentExpression :: |
3838 // do '{' StatementList '}' | 3836 // do '{' StatementList '}' |
3839 int pos = peek_position(); | 3837 int pos = peek_position(); |
3840 | 3838 |
3841 Expect(Token::DO, CHECK_OK); | 3839 Expect(Token::DO, CHECK_OK); |
3842 Variable* result = NewTemporary(ast_value_factory()->dot_result_string()); | 3840 Variable* result = NewTemporary(ast_value_factory()->dot_result_string()); |
(...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4380 param_scope = block_state.FinalizedBlockScope(); | 4378 param_scope = block_state.FinalizedBlockScope(); |
4381 if (param_scope != nullptr) { | 4379 if (param_scope != nullptr) { |
4382 CheckConflictingVarDeclarations(param_scope, CHECK_OK); | 4380 CheckConflictingVarDeclarations(param_scope, CHECK_OK); |
4383 } | 4381 } |
4384 init_block->statements()->Add(param_block, zone()); | 4382 init_block->statements()->Add(param_block, zone()); |
4385 } | 4383 } |
4386 } | 4384 } |
4387 return init_block; | 4385 return init_block; |
4388 } | 4386 } |
4389 | 4387 |
4390 Block* Parser::BuildRejectPromiseOnException(Block* block) { | 4388 Block* Parser::BuildRejectPromiseOnException(Block* inner_block, bool* ok) { |
4391 // try { <block> } catch (error) { return Promise.reject(error); } | 4389 // var .promise = %CreatePromise(); |
4392 Block* try_block = block; | 4390 // var .debug_is_active = %_DebugIsActive(); |
| 4391 // if (.debug_is_active) %DebugPushPromise(.promise); |
| 4392 // try { |
| 4393 // <inner_block> |
| 4394 // } catch (.catch) { |
| 4395 // %RejectPromise(.promise, .catch); |
| 4396 // return .promise; |
| 4397 // } finally { |
| 4398 // if (.debug_is_active) %DebugPopPromise(); |
| 4399 // } |
| 4400 Block* result = factory()->NewBlock(nullptr, 4, true, kNoSourcePosition); |
| 4401 |
| 4402 // var .promise = %CreatePromise(); |
| 4403 Statement* set_promise; |
| 4404 { |
| 4405 DeclareVariable(ast_value_factory()->dot_promise_string(), VAR, |
| 4406 kNoSourcePosition, CHECK_OK); |
| 4407 Expression* create_promise = factory()->NewCallRuntime( |
| 4408 Context::PROMISE_CREATE_INDEX, |
| 4409 new (zone()) ZoneList<Expression*>(0, zone()), kNoSourcePosition); |
| 4410 Assignment* assign_promise = factory()->NewAssignment( |
| 4411 Token::INIT, BuildDotPromise(), create_promise, kNoSourcePosition); |
| 4412 set_promise = |
| 4413 factory()->NewExpressionStatement(assign_promise, kNoSourcePosition); |
| 4414 } |
| 4415 result->statements()->Add(set_promise, zone()); |
| 4416 |
| 4417 // var .debug_is_active = %_DebugIsActive(); |
| 4418 Statement* set_debug_is_active; |
| 4419 { |
| 4420 DeclareVariable(ast_value_factory()->dot_debug_is_active_string(), VAR, |
| 4421 kNoSourcePosition, CHECK_OK); |
| 4422 Expression* debug_is_active = factory()->NewCallRuntime( |
| 4423 Runtime::kInlineDebugIsActive, |
| 4424 new (zone()) ZoneList<Expression*>(0, zone()), kNoSourcePosition); |
| 4425 Assignment* assign_debug_is_active = |
| 4426 factory()->NewAssignment(Token::INIT, BuildDotDebugIsActive(), |
| 4427 debug_is_active, kNoSourcePosition); |
| 4428 set_debug_is_active = factory()->NewExpressionStatement( |
| 4429 assign_debug_is_active, kNoSourcePosition); |
| 4430 } |
| 4431 result->statements()->Add(set_debug_is_active, zone()); |
| 4432 |
| 4433 // if (.debug_is_active) %DebugPushPromise(.promise); |
| 4434 Statement* conditionally_debug_push_promise; |
| 4435 { |
| 4436 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); |
| 4437 args->Add(BuildDotPromise(), zone()); |
| 4438 Expression* call_push_promise = factory()->NewCallRuntime( |
| 4439 Runtime::kDebugPushPromise, args, kNoSourcePosition); |
| 4440 Statement* debug_push_promise = |
| 4441 factory()->NewExpressionStatement(call_push_promise, kNoSourcePosition); |
| 4442 conditionally_debug_push_promise = factory()->NewIfStatement( |
| 4443 BuildDotDebugIsActive(), debug_push_promise, |
| 4444 factory()->NewEmptyStatement(kNoSourcePosition), kNoSourcePosition); |
| 4445 } |
| 4446 result->statements()->Add(conditionally_debug_push_promise, zone()); |
| 4447 |
| 4448 // catch (.catch) { return %RejectPromise(.promise, .catch), .promise } |
4393 Scope* catch_scope = NewScope(CATCH_SCOPE); | 4449 Scope* catch_scope = NewScope(CATCH_SCOPE); |
4394 catch_scope->set_is_hidden(); | 4450 catch_scope->set_is_hidden(); |
4395 Variable* catch_variable = | 4451 Variable* catch_variable = |
4396 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, | 4452 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, |
4397 kCreatedInitialized, Variable::NORMAL); | 4453 kCreatedInitialized, Variable::NORMAL); |
4398 Block* catch_block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); | 4454 Block* catch_block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); |
4399 | 4455 |
4400 Expression* promise_reject = BuildPromiseReject( | 4456 Expression* promise_reject = BuildRejectPromise( |
4401 factory()->NewVariableProxy(catch_variable), kNoSourcePosition); | 4457 factory()->NewVariableProxy(catch_variable), kNoSourcePosition); |
4402 | |
4403 ReturnStatement* return_promise_reject = | 4458 ReturnStatement* return_promise_reject = |
4404 factory()->NewReturnStatement(promise_reject, kNoSourcePosition); | 4459 factory()->NewReturnStatement(promise_reject, kNoSourcePosition); |
4405 catch_block->statements()->Add(return_promise_reject, zone()); | 4460 catch_block->statements()->Add(return_promise_reject, zone()); |
| 4461 |
4406 TryStatement* try_catch_statement = factory()->NewTryCatchStatement( | 4462 TryStatement* try_catch_statement = factory()->NewTryCatchStatement( |
4407 try_block, catch_scope, catch_variable, catch_block, kNoSourcePosition); | 4463 inner_block, catch_scope, catch_variable, catch_block, kNoSourcePosition); |
4408 | 4464 |
4409 block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); | 4465 // There is no TryCatchFinally node, so wrap it in an outer try/finally |
4410 block->statements()->Add(try_catch_statement, zone()); | 4466 Block* outer_try_block = |
4411 return block; | 4467 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); |
| 4468 outer_try_block->statements()->Add(try_catch_statement, zone()); |
| 4469 |
| 4470 // finally { if (.debug_is_active) %DebugPopPromise(); } |
| 4471 Block* finally_block = |
| 4472 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); |
| 4473 { |
| 4474 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(0, zone()); |
| 4475 Expression* call_pop_promise = factory()->NewCallRuntime( |
| 4476 Runtime::kDebugPopPromise, args, kNoSourcePosition); |
| 4477 Statement* debug_pop_promise = |
| 4478 factory()->NewExpressionStatement(call_pop_promise, kNoSourcePosition); |
| 4479 Statement* conditionally_debug_pop_promise = factory()->NewIfStatement( |
| 4480 BuildDotDebugIsActive(), debug_pop_promise, |
| 4481 factory()->NewEmptyStatement(kNoSourcePosition), kNoSourcePosition); |
| 4482 finally_block->statements()->Add(conditionally_debug_pop_promise, zone()); |
| 4483 } |
| 4484 |
| 4485 Statement* try_finally_statement = factory()->NewTryFinallyStatement( |
| 4486 outer_try_block, finally_block, kNoSourcePosition); |
| 4487 |
| 4488 result->statements()->Add(try_finally_statement, zone()); |
| 4489 return result; |
4412 } | 4490 } |
4413 | 4491 |
4414 Expression* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) { | 4492 Expression* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) { |
4415 DCHECK_NOT_NULL(function_state_->generator_object_variable()); | 4493 DCHECK_NOT_NULL(function_state_->generator_object_variable()); |
4416 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); | 4494 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); |
4417 args->Add(factory()->NewThisFunction(pos), zone()); | 4495 args->Add(factory()->NewThisFunction(pos), zone()); |
4418 args->Add(IsArrowFunction(kind) ? GetLiteralUndefined(pos) | 4496 args->Add(IsArrowFunction(kind) ? GetLiteralUndefined(pos) |
4419 : ThisExpression(kNoSourcePosition), | 4497 : ThisExpression(kNoSourcePosition), |
4420 zone()); | 4498 zone()); |
4421 return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args, | 4499 return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args, |
4422 pos); | 4500 pos); |
4423 } | 4501 } |
4424 | 4502 |
4425 Expression* Parser::BuildPromiseResolve(Expression* value, int pos) { | 4503 Expression* Parser::BuildResolvePromise(Expression* value, int pos) { |
4426 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); | 4504 // %ResolvePromise(.promise, value), .promise |
| 4505 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); |
| 4506 args->Add(BuildDotPromise(), zone()); |
4427 args->Add(value, zone()); | 4507 args->Add(value, zone()); |
4428 return factory()->NewCallRuntime(Context::PROMISE_CREATE_RESOLVED_INDEX, args, | 4508 Expression* call_runtime = |
4429 pos); | 4509 factory()->NewCallRuntime(Context::PROMISE_RESOLVE_INDEX, args, pos); |
| 4510 return factory()->NewBinaryOperation(Token::COMMA, call_runtime, |
| 4511 BuildDotPromise(), pos); |
4430 } | 4512 } |
4431 | 4513 |
4432 Expression* Parser::BuildPromiseReject(Expression* value, int pos) { | 4514 Expression* Parser::BuildRejectPromise(Expression* value, int pos) { |
4433 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); | 4515 // %RejectPromiseNoDebugEvent(.promise, value, true), .promise |
| 4516 // The NoDebugEvent variant disables the additional debug event for the |
| 4517 // rejection since a debug event already happened for the exception that got |
| 4518 // us here. |
| 4519 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); |
| 4520 args->Add(BuildDotPromise(), zone()); |
4434 args->Add(value, zone()); | 4521 args->Add(value, zone()); |
4435 return factory()->NewCallRuntime(Context::PROMISE_CREATE_REJECTED_INDEX, args, | 4522 Expression* call_runtime = factory()->NewCallRuntime( |
4436 pos); | 4523 Context::REJECT_PROMISE_NO_DEBUG_EVENT_INDEX, args, pos); |
| 4524 return factory()->NewBinaryOperation(Token::COMMA, call_runtime, |
| 4525 BuildDotPromise(), pos); |
| 4526 } |
| 4527 |
| 4528 VariableProxy* Parser::BuildDotPromise() { |
| 4529 return NewUnresolved(ast_value_factory()->dot_promise_string(), VAR); |
| 4530 } |
| 4531 |
| 4532 VariableProxy* Parser::BuildDotDebugIsActive() { |
| 4533 return NewUnresolved(ast_value_factory()->dot_debug_is_active_string(), VAR); |
4437 } | 4534 } |
4438 | 4535 |
4439 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( | 4536 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
4440 const AstRawString* function_name, int pos, | 4537 const AstRawString* function_name, int pos, |
4441 const ParserFormalParameters& parameters, FunctionKind kind, | 4538 const ParserFormalParameters& parameters, FunctionKind kind, |
4442 FunctionLiteral::FunctionType function_type, bool* ok) { | 4539 FunctionLiteral::FunctionType function_type, bool* ok) { |
4443 // Everything inside an eagerly parsed function will be parsed eagerly | 4540 // Everything inside an eagerly parsed function will be parsed eagerly |
4444 // (see comment above). | 4541 // (see comment above). |
4445 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | 4542 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); |
4446 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); | 4543 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4552 DCHECK_EQ(function_scope, inner_scope->outer_scope()); | 4649 DCHECK_EQ(function_scope, inner_scope->outer_scope()); |
4553 DCHECK_EQ(body, inner_block->statements()); | 4650 DCHECK_EQ(body, inner_block->statements()); |
4554 SetLanguageMode(function_scope, inner_scope->language_mode()); | 4651 SetLanguageMode(function_scope, inner_scope->language_mode()); |
4555 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); | 4652 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); |
4556 | 4653 |
4557 if (is_sloppy(inner_scope->language_mode())) { | 4654 if (is_sloppy(inner_scope->language_mode())) { |
4558 InsertSloppyBlockFunctionVarBindings(inner_scope, function_scope, | 4655 InsertSloppyBlockFunctionVarBindings(inner_scope, function_scope, |
4559 CHECK_OK); | 4656 CHECK_OK); |
4560 } | 4657 } |
4561 | 4658 |
| 4659 // TODO(littledan): Merge the two rejection blocks into one |
4562 if (IsAsyncFunction(kind)) { | 4660 if (IsAsyncFunction(kind)) { |
4563 init_block = BuildRejectPromiseOnException(init_block); | 4661 init_block = BuildRejectPromiseOnException(init_block, CHECK_OK); |
4564 } | 4662 } |
4565 | 4663 |
4566 DCHECK_NOT_NULL(init_block); | 4664 DCHECK_NOT_NULL(init_block); |
4567 | 4665 |
4568 inner_scope->set_end_position(scanner()->location().end_pos); | 4666 inner_scope->set_end_position(scanner()->location().end_pos); |
4569 if (inner_scope->FinalizeBlockScope() != nullptr) { | 4667 if (inner_scope->FinalizeBlockScope() != nullptr) { |
4570 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); | 4668 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); |
4571 InsertShadowingVarBindingInitializers(inner_block); | 4669 InsertShadowingVarBindingInitializers(inner_block); |
4572 } | 4670 } |
4573 inner_scope = nullptr; | 4671 inner_scope = nullptr; |
(...skipping 2075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6649 node->Print(Isolate::Current()); | 6747 node->Print(Isolate::Current()); |
6650 } | 6748 } |
6651 #endif // DEBUG | 6749 #endif // DEBUG |
6652 | 6750 |
6653 #undef CHECK_OK | 6751 #undef CHECK_OK |
6654 #undef CHECK_OK_VOID | 6752 #undef CHECK_OK_VOID |
6655 #undef CHECK_FAILED | 6753 #undef CHECK_FAILED |
6656 | 6754 |
6657 } // namespace internal | 6755 } // namespace internal |
6658 } // namespace v8 | 6756 } // namespace v8 |
OLD | NEW |