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 2498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2509 // ES6 14.6.1 Static Semantics: IsInTailPosition | 2509 // ES6 14.6.1 Static Semantics: IsInTailPosition |
2510 function_state_->AddImplicitTailCallExpression(return_value); | 2510 function_state_->AddImplicitTailCallExpression(return_value); |
2511 } | 2511 } |
2512 } | 2512 } |
2513 } | 2513 } |
2514 ExpectSemicolon(CHECK_OK); | 2514 ExpectSemicolon(CHECK_OK); |
2515 | 2515 |
2516 if (is_generator()) { | 2516 if (is_generator()) { |
2517 return_value = BuildIteratorResult(return_value, true); | 2517 return_value = BuildIteratorResult(return_value, true); |
2518 } else if (is_async_function()) { | 2518 } else if (is_async_function()) { |
2519 return_value = BuildPromiseResolve(return_value, return_value->position()); | 2519 return_value = BuildResolvePromise(return_value, return_value->position()); |
2520 } | 2520 } |
2521 | 2521 |
2522 result = factory()->NewReturnStatement(return_value, loc.beg_pos); | 2522 result = factory()->NewReturnStatement(return_value, loc.beg_pos); |
2523 | 2523 |
2524 DeclarationScope* decl_scope = GetDeclarationScope(); | 2524 DeclarationScope* decl_scope = GetDeclarationScope(); |
2525 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { | 2525 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { |
2526 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); | 2526 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); |
2527 *ok = false; | 2527 *ok = false; |
2528 return NULL; | 2528 return NULL; |
2529 } | 2529 } |
(...skipping 1309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3839 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest); | 3839 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest); |
3840 } | 3840 } |
3841 | 3841 |
3842 void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name, | 3842 void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name, |
3843 Scope* scope, ZoneList<Statement*>* body, | 3843 Scope* scope, ZoneList<Statement*>* body, |
3844 ExpressionClassifier* classifier, | 3844 ExpressionClassifier* classifier, |
3845 FunctionKind kind, | 3845 FunctionKind kind, |
3846 FunctionBodyType body_type, | 3846 FunctionBodyType body_type, |
3847 bool accept_IN, int pos, bool* ok) { | 3847 bool accept_IN, int pos, bool* ok) { |
3848 // function async_function() { | 3848 // function async_function() { |
3849 // try { | 3849 // .generator_object = %CreateGeneratorObject(); |
3850 // .generator_object = %CreateGeneratorObject(); | 3850 // BuildRejectPromiseOnException({ |
3851 // ... function body ... | 3851 // ... function body ... |
3852 // } catch (e) { | 3852 // return %ResolvePromise(.promise, expr), .promise; |
3853 // return Promise.reject(e); | 3853 // }) |
3854 // } | |
3855 // } | 3854 // } |
3856 scope->ForceContextAllocation(); | 3855 scope->ForceContextAllocation(); |
3857 Variable* temp = | 3856 Variable* temp = |
3858 NewTemporary(ast_value_factory()->dot_generator_object_string()); | 3857 NewTemporary(ast_value_factory()->dot_generator_object_string()); |
3859 function_state_->set_generator_object_variable(temp); | 3858 function_state_->set_generator_object_variable(temp); |
3860 | 3859 |
3861 Expression* init_generator_variable = factory()->NewAssignment( | 3860 Expression* init_generator_variable = factory()->NewAssignment( |
3862 Token::INIT, factory()->NewVariableProxy(temp), | 3861 Token::INIT, factory()->NewVariableProxy(temp), |
3863 BuildCreateJSGeneratorObject(pos, kind), kNoSourcePosition); | 3862 BuildCreateJSGeneratorObject(pos, kind), kNoSourcePosition); |
3864 body->Add(factory()->NewExpressionStatement(init_generator_variable, | 3863 body->Add(factory()->NewExpressionStatement(init_generator_variable, |
3865 kNoSourcePosition), | 3864 kNoSourcePosition), |
3866 zone()); | 3865 zone()); |
3867 | 3866 |
3868 Block* try_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition); | 3867 Block* block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition); |
3869 | |
3870 ZoneList<Statement*>* inner_body = try_block->statements(); | |
3871 | 3868 |
3872 Expression* return_value = nullptr; | 3869 Expression* return_value = nullptr; |
3873 if (body_type == FunctionBodyType::kNormal) { | 3870 if (body_type == FunctionBodyType::kNormal) { |
3874 ParseStatementList(inner_body, Token::RBRACE, CHECK_OK_VOID); | 3871 ParseStatementList(block->statements(), Token::RBRACE, CHECK_OK_VOID); |
3875 return_value = factory()->NewUndefinedLiteral(kNoSourcePosition); | 3872 return_value = factory()->NewUndefinedLiteral(kNoSourcePosition); |
3876 } else { | 3873 } else { |
3877 return_value = | 3874 return_value = |
3878 ParseAssignmentExpression(accept_IN, classifier, CHECK_OK_VOID); | 3875 ParseAssignmentExpression(accept_IN, classifier, CHECK_OK_VOID); |
3879 RewriteNonPattern(classifier, CHECK_OK_VOID); | 3876 RewriteNonPattern(classifier, CHECK_OK_VOID); |
3880 } | 3877 } |
3881 | 3878 |
3882 return_value = BuildPromiseResolve(return_value, return_value->position()); | 3879 return_value = BuildResolvePromise(return_value, return_value->position()); |
3883 inner_body->Add( | 3880 block->statements()->Add( |
3884 factory()->NewReturnStatement(return_value, return_value->position()), | 3881 factory()->NewReturnStatement(return_value, return_value->position()), |
3885 zone()); | 3882 zone()); |
3886 body->Add(BuildRejectPromiseOnException(try_block), zone()); | 3883 block = BuildRejectPromiseOnException(block, CHECK_OK_VOID); |
3884 body->Add(block, zone()); | |
3887 scope->set_end_position(scanner()->location().end_pos); | 3885 scope->set_end_position(scanner()->location().end_pos); |
3888 } | 3886 } |
3889 | 3887 |
3890 DoExpression* Parser::ParseDoExpression(bool* ok) { | 3888 DoExpression* Parser::ParseDoExpression(bool* ok) { |
3891 // AssignmentExpression :: | 3889 // AssignmentExpression :: |
3892 // do '{' StatementList '}' | 3890 // do '{' StatementList '}' |
3893 int pos = peek_position(); | 3891 int pos = peek_position(); |
3894 | 3892 |
3895 Expect(Token::DO, CHECK_OK); | 3893 Expect(Token::DO, CHECK_OK); |
3896 Variable* result = NewTemporary(ast_value_factory()->dot_result_string()); | 3894 Variable* result = NewTemporary(ast_value_factory()->dot_result_string()); |
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4437 param_scope = block_state.FinalizedBlockScope(); | 4435 param_scope = block_state.FinalizedBlockScope(); |
4438 if (param_scope != nullptr) { | 4436 if (param_scope != nullptr) { |
4439 CheckConflictingVarDeclarations(param_scope, CHECK_OK); | 4437 CheckConflictingVarDeclarations(param_scope, CHECK_OK); |
4440 } | 4438 } |
4441 init_block->statements()->Add(param_block, zone()); | 4439 init_block->statements()->Add(param_block, zone()); |
4442 } | 4440 } |
4443 } | 4441 } |
4444 return init_block; | 4442 return init_block; |
4445 } | 4443 } |
4446 | 4444 |
4447 Block* Parser::BuildRejectPromiseOnException(Block* block) { | 4445 Block* Parser::BuildRejectPromiseOnException(Block* inner_block, bool* ok) { |
4448 // try { <block> } catch (error) { return Promise.reject(error); } | 4446 // var .promise = %CreatePromise(); |
4449 Block* try_block = block; | 4447 // var .debug_is_active = %_DebugIsActive(); |
4448 // if (.debug_is_active) %DebugPushPromise(.promise); | |
4449 // try { | |
4450 // <inner_block> | |
4451 // } catch (.catch) { | |
4452 // %RejectPromise(.promise, .catch); | |
4453 // return .promise; | |
4454 // } finally { | |
4455 // if (.debug_is_active) %DebugPopPromise(); | |
4456 // } | |
4457 Block* result = factory()->NewBlock(nullptr, 4, true, kNoSourcePosition); | |
4458 | |
4459 // var .promise = %CreatePromise(); | |
4460 Statement* set_promise; | |
4461 { | |
4462 DeclareVariable(ast_value_factory()->dot_promise_string(), VAR, | |
neis
2016/08/25 08:15:22
Please declare this CONST, not VAR.
Dan Ehrenberg
2016/08/25 14:23:34
I use VAR rather than CONST here so that if there
| |
4463 kNoSourcePosition, CHECK_OK); | |
4464 Expression* create_promise = factory()->NewCallRuntime( | |
4465 Context::PROMISE_CREATE_INDEX, | |
4466 new (zone()) ZoneList<Expression*>(0, zone()), kNoSourcePosition); | |
4467 Assignment* assign_promise = factory()->NewAssignment( | |
4468 Token::INIT, BuildDotPromise(), create_promise, kNoSourcePosition); | |
4469 set_promise = | |
4470 factory()->NewExpressionStatement(assign_promise, kNoSourcePosition); | |
4471 } | |
4472 result->statements()->Add(set_promise, zone()); | |
4473 | |
4474 // var .debug_is_active = %_DebugIsActive(); | |
4475 Statement* set_debug_is_active; | |
4476 { | |
4477 DeclareVariable(ast_value_factory()->dot_debug_is_active_string(), VAR, | |
4478 kNoSourcePosition, CHECK_OK); | |
4479 Expression* debug_is_active = factory()->NewCallRuntime( | |
4480 Runtime::kInlineDebugIsActive, | |
4481 new (zone()) ZoneList<Expression*>(0, zone()), kNoSourcePosition); | |
4482 Assignment* assign_debug_is_active = factory()->NewAssignment( | |
4483 Token::INIT, BuildDotDebugIsActive(), debug_is_active, kNoSourcePosition ); | |
4484 set_debug_is_active = factory()->NewExpressionStatement( | |
4485 assign_debug_is_active, kNoSourcePosition); | |
4486 } | |
4487 result->statements()->Add(set_debug_is_active, zone()); | |
4488 | |
4489 // if (.debug_is_active) %DebugPushPromise(.promise); | |
4490 Statement* conditionally_debug_push_promise; | |
4491 { | |
4492 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); | |
4493 args->Add(BuildDotPromise(), zone()); | |
4494 Expression* call_push_promise = factory()->NewCallRuntime( | |
4495 Runtime::kDebugPushPromise, args, kNoSourcePosition); | |
4496 Statement* debug_push_promise = | |
4497 factory()->NewExpressionStatement(call_push_promise, kNoSourcePosition); | |
4498 conditionally_debug_push_promise = factory()->NewIfStatement( | |
4499 BuildDotDebugIsActive(), debug_push_promise, | |
4500 factory()->NewEmptyStatement(kNoSourcePosition), kNoSourcePosition); | |
4501 } | |
4502 result->statements()->Add(conditionally_debug_push_promise, zone()); | |
4503 | |
4504 // catch (.catch) { return %RejectPromise(.promise, .catch), .promise } | |
4450 Scope* catch_scope = NewScope(CATCH_SCOPE); | 4505 Scope* catch_scope = NewScope(CATCH_SCOPE); |
4451 catch_scope->set_is_hidden(); | 4506 catch_scope->set_is_hidden(); |
4452 Variable* catch_variable = | 4507 Variable* catch_variable = |
4453 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, | 4508 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, |
4454 kCreatedInitialized, Variable::NORMAL); | 4509 kCreatedInitialized, Variable::NORMAL); |
4455 Block* catch_block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); | 4510 Block* catch_block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); |
4456 | 4511 |
4457 Expression* promise_reject = BuildPromiseReject( | 4512 Expression* promise_reject = BuildRejectPromise( |
4458 factory()->NewVariableProxy(catch_variable), kNoSourcePosition); | 4513 factory()->NewVariableProxy(catch_variable), kNoSourcePosition); |
4459 | |
4460 ReturnStatement* return_promise_reject = | 4514 ReturnStatement* return_promise_reject = |
4461 factory()->NewReturnStatement(promise_reject, kNoSourcePosition); | 4515 factory()->NewReturnStatement(promise_reject, kNoSourcePosition); |
4462 catch_block->statements()->Add(return_promise_reject, zone()); | 4516 catch_block->statements()->Add(return_promise_reject, zone()); |
4517 | |
4463 TryStatement* try_catch_statement = factory()->NewTryCatchStatement( | 4518 TryStatement* try_catch_statement = factory()->NewTryCatchStatement( |
4464 try_block, catch_scope, catch_variable, catch_block, kNoSourcePosition); | 4519 inner_block, catch_scope, catch_variable, catch_block, kNoSourcePosition); |
4465 | 4520 |
4466 block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); | 4521 // There is no TryCatchFinally node, so wrap it in an outer try/finally |
4467 block->statements()->Add(try_catch_statement, zone()); | 4522 Block* outer_try_block = |
4468 return block; | 4523 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); |
4524 outer_try_block->statements()->Add(try_catch_statement, zone()); | |
4525 | |
4526 // finally { if (.debug_is_active) %DebugPopPromise(); } | |
4527 Block* finally_block = | |
4528 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); | |
4529 { | |
4530 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(0, zone()); | |
4531 Expression* call_pop_promise = factory()->NewCallRuntime( | |
4532 Runtime::kDebugPopPromise, args, kNoSourcePosition); | |
4533 Statement* debug_pop_promise = | |
4534 factory()->NewExpressionStatement(call_pop_promise, kNoSourcePosition); | |
4535 Statement* conditionally_debug_pop_promise = factory()->NewIfStatement( | |
4536 BuildDotDebugIsActive(), debug_pop_promise, | |
4537 factory()->NewEmptyStatement(kNoSourcePosition), kNoSourcePosition); | |
4538 finally_block->statements()->Add(conditionally_debug_pop_promise, zone()); | |
4539 } | |
4540 | |
4541 Statement* try_finally_statement = factory()->NewTryFinallyStatement( | |
4542 outer_try_block, finally_block, kNoSourcePosition); | |
4543 | |
4544 result->statements()->Add(try_finally_statement, zone()); | |
4545 return result; | |
4469 } | 4546 } |
4470 | 4547 |
4471 Expression* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) { | 4548 Expression* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) { |
4472 DCHECK_NOT_NULL(function_state_->generator_object_variable()); | 4549 DCHECK_NOT_NULL(function_state_->generator_object_variable()); |
4473 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); | 4550 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); |
4474 args->Add(factory()->NewThisFunction(pos), zone()); | 4551 args->Add(factory()->NewThisFunction(pos), zone()); |
4475 args->Add(IsArrowFunction(kind) ? GetLiteralUndefined(pos) | 4552 args->Add(IsArrowFunction(kind) ? GetLiteralUndefined(pos) |
4476 : ThisExpression(kNoSourcePosition), | 4553 : ThisExpression(kNoSourcePosition), |
4477 zone()); | 4554 zone()); |
4478 return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args, | 4555 return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args, |
4479 pos); | 4556 pos); |
4480 } | 4557 } |
4481 | 4558 |
4482 Expression* Parser::BuildPromiseResolve(Expression* value, int pos) { | 4559 Expression* Parser::BuildResolvePromise(Expression* value, int pos) { |
4483 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); | 4560 // %ResolvePromise(.promise, value), .promise |
4561 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); | |
4562 args->Add(BuildDotPromise(), zone()); | |
4484 args->Add(value, zone()); | 4563 args->Add(value, zone()); |
4485 return factory()->NewCallRuntime(Context::PROMISE_CREATE_RESOLVED_INDEX, args, | 4564 Expression* call_runtime = |
4486 pos); | 4565 factory()->NewCallRuntime(Context::PROMISE_RESOLVE_INDEX, args, pos); |
4566 return factory()->NewBinaryOperation(Token::COMMA, call_runtime, | |
4567 BuildDotPromise(), pos); | |
4487 } | 4568 } |
4488 | 4569 |
4489 Expression* Parser::BuildPromiseReject(Expression* value, int pos) { | 4570 Expression* Parser::BuildRejectPromise(Expression* value, int pos) { |
4490 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); | 4571 // %RejectPromiseNoDebugEvent(.promise, value, true), .promise |
4572 // The NoDebugEvent variant disables the additional debug event for the | |
4573 // rejection since a debug event already happened for the exception that got | |
4574 // us here. | |
4575 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); | |
4576 args->Add(BuildDotPromise(), zone()); | |
4491 args->Add(value, zone()); | 4577 args->Add(value, zone()); |
4492 return factory()->NewCallRuntime(Context::PROMISE_CREATE_REJECTED_INDEX, args, | 4578 Expression* call_runtime = factory()->NewCallRuntime( |
4493 pos); | 4579 Context::REJECT_PROMISE_NO_DEBUG_EVENT_INDEX, args, pos); |
4580 return factory()->NewBinaryOperation(Token::COMMA, call_runtime, | |
4581 BuildDotPromise(), pos); | |
4582 } | |
4583 | |
4584 VariableProxy* Parser::BuildDotPromise() { | |
4585 return NewUnresolved(ast_value_factory()->dot_promise_string(), VAR); | |
4586 } | |
4587 | |
4588 VariableProxy* Parser::BuildDotDebugIsActive() { | |
4589 return NewUnresolved(ast_value_factory()->dot_debug_is_active_string(), VAR); | |
4494 } | 4590 } |
4495 | 4591 |
4496 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( | 4592 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
4497 const AstRawString* function_name, int pos, | 4593 const AstRawString* function_name, int pos, |
4498 const ParserFormalParameters& parameters, FunctionKind kind, | 4594 const ParserFormalParameters& parameters, FunctionKind kind, |
4499 FunctionLiteral::FunctionType function_type, bool* ok) { | 4595 FunctionLiteral::FunctionType function_type, bool* ok) { |
4500 // Everything inside an eagerly parsed function will be parsed eagerly | 4596 // Everything inside an eagerly parsed function will be parsed eagerly |
4501 // (see comment above). | 4597 // (see comment above). |
4502 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | 4598 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); |
4503 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); | 4599 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4609 DCHECK_EQ(function_scope, inner_scope->outer_scope()); | 4705 DCHECK_EQ(function_scope, inner_scope->outer_scope()); |
4610 DCHECK_EQ(body, inner_block->statements()); | 4706 DCHECK_EQ(body, inner_block->statements()); |
4611 SetLanguageMode(function_scope, inner_scope->language_mode()); | 4707 SetLanguageMode(function_scope, inner_scope->language_mode()); |
4612 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); | 4708 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); |
4613 | 4709 |
4614 if (is_sloppy(inner_scope->language_mode())) { | 4710 if (is_sloppy(inner_scope->language_mode())) { |
4615 InsertSloppyBlockFunctionVarBindings(inner_scope, function_scope, | 4711 InsertSloppyBlockFunctionVarBindings(inner_scope, function_scope, |
4616 CHECK_OK); | 4712 CHECK_OK); |
4617 } | 4713 } |
4618 | 4714 |
4715 // TODO(littledan): Merge the two rejection blocks into one | |
4619 if (IsAsyncFunction(kind)) { | 4716 if (IsAsyncFunction(kind)) { |
4620 init_block = BuildRejectPromiseOnException(init_block); | 4717 init_block = BuildRejectPromiseOnException(init_block, CHECK_OK); |
4621 } | 4718 } |
4622 | 4719 |
4623 DCHECK_NOT_NULL(init_block); | 4720 DCHECK_NOT_NULL(init_block); |
4624 | 4721 |
4625 inner_scope->set_end_position(scanner()->location().end_pos); | 4722 inner_scope->set_end_position(scanner()->location().end_pos); |
4626 if (inner_scope->FinalizeBlockScope() != nullptr) { | 4723 if (inner_scope->FinalizeBlockScope() != nullptr) { |
4627 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); | 4724 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); |
4628 InsertShadowingVarBindingInitializers(inner_block); | 4725 InsertShadowingVarBindingInitializers(inner_block); |
4629 } | 4726 } |
4630 inner_scope = nullptr; | 4727 inner_scope = nullptr; |
(...skipping 2092 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6723 node->Print(Isolate::Current()); | 6820 node->Print(Isolate::Current()); |
6724 } | 6821 } |
6725 #endif // DEBUG | 6822 #endif // DEBUG |
6726 | 6823 |
6727 #undef CHECK_OK | 6824 #undef CHECK_OK |
6728 #undef CHECK_OK_VOID | 6825 #undef CHECK_OK_VOID |
6729 #undef CHECK_FAILED | 6826 #undef CHECK_FAILED |
6730 | 6827 |
6731 } // namespace internal | 6828 } // namespace internal |
6732 } // namespace v8 | 6829 } // namespace v8 |
OLD | NEW |