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 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
712 if (ok && is_strict(language_mode())) { | 712 if (ok && is_strict(language_mode())) { |
713 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); | 713 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); |
714 CheckDecimalLiteralWithLeadingZero(use_counts_, beg_pos, | 714 CheckDecimalLiteralWithLeadingZero(use_counts_, beg_pos, |
715 scanner()->location().end_pos); | 715 scanner()->location().end_pos); |
716 } | 716 } |
717 if (ok && is_sloppy(language_mode())) { | 717 if (ok && is_sloppy(language_mode())) { |
718 // TODO(littledan): Function bindings on the global object that modify | 718 // TODO(littledan): Function bindings on the global object that modify |
719 // pre-existing bindings should be made writable, enumerable and | 719 // pre-existing bindings should be made writable, enumerable and |
720 // nonconfigurable if possible, whereas this code will leave attributes | 720 // nonconfigurable if possible, whereas this code will leave attributes |
721 // unchanged if the property already exists. | 721 // unchanged if the property already exists. |
722 InsertSloppyBlockFunctionVarBindings(scope, nullptr, &ok); | 722 InsertSloppyBlockFunctionVarBindings(scope, &ok); |
723 } | 723 } |
724 if (ok) { | 724 if (ok) { |
725 CheckConflictingVarDeclarations(scope, &ok); | 725 CheckConflictingVarDeclarations(scope, &ok); |
726 } | 726 } |
727 | 727 |
728 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { | 728 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { |
729 if (body->length() != 1 || | 729 if (body->length() != 1 || |
730 !body->at(0)->IsExpressionStatement() || | 730 !body->at(0)->IsExpressionStatement() || |
731 !body->at(0)->AsExpressionStatement()-> | 731 !body->at(0)->AsExpressionStatement()-> |
732 expression()->IsFunctionLiteral()) { | 732 expression()->IsFunctionLiteral()) { |
(...skipping 889 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1622 VariableProxy* Parser::NewUnresolved(const AstRawString* name, int begin_pos, | 1622 VariableProxy* Parser::NewUnresolved(const AstRawString* name, int begin_pos, |
1623 int end_pos, Variable::Kind kind) { | 1623 int end_pos, Variable::Kind kind) { |
1624 return scope()->NewUnresolved(factory(), name, begin_pos, end_pos, kind); | 1624 return scope()->NewUnresolved(factory(), name, begin_pos, end_pos, kind); |
1625 } | 1625 } |
1626 | 1626 |
1627 VariableProxy* Parser::NewUnresolved(const AstRawString* name) { | 1627 VariableProxy* Parser::NewUnresolved(const AstRawString* name) { |
1628 return scope()->NewUnresolved(factory(), name, scanner()->location().beg_pos, | 1628 return scope()->NewUnresolved(factory(), name, scanner()->location().beg_pos, |
1629 scanner()->location().end_pos); | 1629 scanner()->location().end_pos); |
1630 } | 1630 } |
1631 | 1631 |
1632 InitializationFlag Parser::DefaultInitializationFlag(VariableMode mode) { | |
1633 DCHECK(IsDeclaredVariableMode(mode)); | |
1634 return mode == VAR ? kCreatedInitialized : kNeedsInitialization; | |
1635 } | |
1636 | |
1637 Declaration* Parser::DeclareVariable(const AstRawString* name, | 1632 Declaration* Parser::DeclareVariable(const AstRawString* name, |
1638 VariableMode mode, int pos, bool* ok) { | 1633 VariableMode mode, int pos, bool* ok) { |
1639 return DeclareVariable(name, mode, DefaultInitializationFlag(mode), pos, ok); | 1634 return DeclareVariable(name, mode, Variable::DefaultInitializationFlag(mode), |
| 1635 pos, ok); |
1640 } | 1636 } |
1641 | 1637 |
1642 Declaration* Parser::DeclareVariable(const AstRawString* name, | 1638 Declaration* Parser::DeclareVariable(const AstRawString* name, |
1643 VariableMode mode, InitializationFlag init, | 1639 VariableMode mode, InitializationFlag init, |
1644 int pos, bool* ok) { | 1640 int pos, bool* ok) { |
1645 DCHECK_NOT_NULL(name); | 1641 DCHECK_NOT_NULL(name); |
1646 Scope* scope = | 1642 Scope* scope = |
1647 IsLexicalVariableMode(mode) ? this->scope() : GetDeclarationScope(); | 1643 IsLexicalVariableMode(mode) ? this->scope() : GetDeclarationScope(); |
1648 VariableProxy* proxy = | 1644 VariableProxy* proxy = |
1649 scope->NewUnresolved(factory(), name, scanner()->location().beg_pos, | 1645 scope->NewUnresolved(factory(), name, scanner()->location().beg_pos, |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1791 // a script scope, or the initial scope of eval or another function. | 1787 // a script scope, or the initial scope of eval or another function. |
1792 VariableMode mode = | 1788 VariableMode mode = |
1793 (!scope()->is_declaration_scope() || scope()->is_module_scope()) ? LET | 1789 (!scope()->is_declaration_scope() || scope()->is_module_scope()) ? LET |
1794 : VAR; | 1790 : VAR; |
1795 VariableProxy* proxy = NewUnresolved(variable_name); | 1791 VariableProxy* proxy = NewUnresolved(variable_name); |
1796 Declaration* declaration = | 1792 Declaration* declaration = |
1797 factory()->NewFunctionDeclaration(proxy, fun, scope(), pos); | 1793 factory()->NewFunctionDeclaration(proxy, fun, scope(), pos); |
1798 Declare(declaration, DeclarationDescriptor::NORMAL, mode, kCreatedInitialized, | 1794 Declare(declaration, DeclarationDescriptor::NORMAL, mode, kCreatedInitialized, |
1799 CHECK_OK); | 1795 CHECK_OK); |
1800 if (names) names->Add(variable_name, zone()); | 1796 if (names) names->Add(variable_name, zone()); |
1801 EmptyStatement* empty = factory()->NewEmptyStatement(kNoSourcePosition); | |
1802 // Async functions don't undergo sloppy mode block scoped hoisting, and don't | 1797 // Async functions don't undergo sloppy mode block scoped hoisting, and don't |
1803 // allow duplicates in a block. Both are represented by the | 1798 // allow duplicates in a block. Both are represented by the |
1804 // sloppy_block_function_map. Don't add them to the map for async functions. | 1799 // sloppy_block_function_map. Don't add them to the map for async functions. |
1805 // Generators are also supposed to be prohibited; currently doing this behind | 1800 // Generators are also supposed to be prohibited; currently doing this behind |
1806 // a flag and UseCounting violations to assess web compatibility. | 1801 // a flag and UseCounting violations to assess web compatibility. |
1807 if (is_sloppy(language_mode()) && !scope()->is_declaration_scope() && | 1802 if (is_sloppy(language_mode()) && !scope()->is_declaration_scope() && |
1808 !is_async && !(allow_harmony_restrictive_generators() && is_generator)) { | 1803 !is_async && !(allow_harmony_restrictive_generators() && is_generator)) { |
1809 SloppyBlockFunctionStatement* delegate = | 1804 SloppyBlockFunctionStatement* delegate = |
1810 factory()->NewSloppyBlockFunctionStatement(empty, scope()); | 1805 factory()->NewSloppyBlockFunctionStatement(scope()); |
1811 DeclarationScope* target_scope = GetDeclarationScope(); | 1806 DeclarationScope* target_scope = GetDeclarationScope(); |
1812 target_scope->DeclareSloppyBlockFunction(variable_name, delegate); | 1807 target_scope->DeclareSloppyBlockFunction(variable_name, delegate); |
1813 return delegate; | 1808 return delegate; |
1814 } | 1809 } |
1815 return empty; | 1810 return factory()->NewEmptyStatement(kNoSourcePosition); |
1816 } | 1811 } |
1817 | 1812 |
1818 Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, | 1813 Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, |
1819 bool default_export, bool* ok) { | 1814 bool default_export, bool* ok) { |
1820 // ClassDeclaration :: | 1815 // ClassDeclaration :: |
1821 // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}' | 1816 // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}' |
1822 // 'class' ('extends' LeftHandExpression)? '{' ClassBody '}' | 1817 // 'class' ('extends' LeftHandExpression)? '{' ClassBody '}' |
1823 // | 1818 // |
1824 // The anonymous form is allowed iff [default_export] is true. | 1819 // The anonymous form is allowed iff [default_export] is true. |
1825 // | 1820 // |
(...skipping 2578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4404 | 4399 |
4405 if (!parameters.is_simple) { | 4400 if (!parameters.is_simple) { |
4406 DCHECK_NOT_NULL(inner_scope); | 4401 DCHECK_NOT_NULL(inner_scope); |
4407 DCHECK_EQ(function_scope, scope()); | 4402 DCHECK_EQ(function_scope, scope()); |
4408 DCHECK_EQ(function_scope, inner_scope->outer_scope()); | 4403 DCHECK_EQ(function_scope, inner_scope->outer_scope()); |
4409 DCHECK_EQ(body, inner_block->statements()); | 4404 DCHECK_EQ(body, inner_block->statements()); |
4410 SetLanguageMode(function_scope, inner_scope->language_mode()); | 4405 SetLanguageMode(function_scope, inner_scope->language_mode()); |
4411 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); | 4406 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); |
4412 | 4407 |
4413 if (is_sloppy(inner_scope->language_mode())) { | 4408 if (is_sloppy(inner_scope->language_mode())) { |
4414 InsertSloppyBlockFunctionVarBindings(inner_scope, function_scope, | 4409 InsertSloppyBlockFunctionVarBindings(inner_scope, CHECK_OK); |
4415 CHECK_OK); | |
4416 } | 4410 } |
4417 | 4411 |
4418 // TODO(littledan): Merge the two rejection blocks into one | 4412 // TODO(littledan): Merge the two rejection blocks into one |
4419 if (IsAsyncFunction(kind)) { | 4413 if (IsAsyncFunction(kind)) { |
4420 init_block = BuildRejectPromiseOnException(init_block, CHECK_OK); | 4414 init_block = BuildRejectPromiseOnException(init_block, CHECK_OK); |
4421 } | 4415 } |
4422 | 4416 |
4423 DCHECK_NOT_NULL(init_block); | 4417 DCHECK_NOT_NULL(init_block); |
4424 | 4418 |
4425 inner_scope->set_end_position(scanner()->location().end_pos); | 4419 inner_scope->set_end_position(scanner()->location().end_pos); |
4426 if (inner_scope->FinalizeBlockScope() != nullptr) { | 4420 if (inner_scope->FinalizeBlockScope() != nullptr) { |
4427 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); | 4421 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); |
4428 InsertShadowingVarBindingInitializers(inner_block); | 4422 InsertShadowingVarBindingInitializers(inner_block); |
4429 } | 4423 } |
4430 inner_scope = nullptr; | 4424 inner_scope = nullptr; |
4431 | 4425 |
4432 result->Add(init_block, zone()); | 4426 result->Add(init_block, zone()); |
4433 result->Add(inner_block, zone()); | 4427 result->Add(inner_block, zone()); |
4434 } else { | 4428 } else { |
4435 DCHECK_EQ(inner_scope, function_scope); | 4429 DCHECK_EQ(inner_scope, function_scope); |
4436 if (is_sloppy(function_scope->language_mode())) { | 4430 if (is_sloppy(function_scope->language_mode())) { |
4437 InsertSloppyBlockFunctionVarBindings(function_scope, nullptr, CHECK_OK); | 4431 InsertSloppyBlockFunctionVarBindings(function_scope, CHECK_OK); |
4438 } | 4432 } |
4439 } | 4433 } |
4440 | 4434 |
4441 if (function_type == FunctionLiteral::kNamedExpression) { | 4435 if (function_type == FunctionLiteral::kNamedExpression) { |
4442 // Now that we know the language mode, we can create the const assignment | 4436 // Now that we know the language mode, we can create the const assignment |
4443 // in the previously reserved spot. | 4437 // in the previously reserved spot. |
4444 DCHECK_EQ(function_scope, scope()); | 4438 DCHECK_EQ(function_scope, scope()); |
4445 Variable* fvar = function_scope->DeclareFunctionVar(function_name); | 4439 Variable* fvar = function_scope->DeclareFunctionVar(function_name); |
4446 VariableProxy* fproxy = factory()->NewVariableProxy(fvar); | 4440 VariableProxy* fproxy = factory()->NewVariableProxy(fvar); |
4447 result->Set(kFunctionNameAssignmentIndex, | 4441 result->Set(kFunctionNameAssignmentIndex, |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4514 scope()->SetScopeName(name); | 4508 scope()->SetScopeName(name); |
4515 #endif | 4509 #endif |
4516 | 4510 |
4517 VariableProxy* proxy = nullptr; | 4511 VariableProxy* proxy = nullptr; |
4518 if (name != nullptr) { | 4512 if (name != nullptr) { |
4519 proxy = NewUnresolved(name); | 4513 proxy = NewUnresolved(name); |
4520 // TODO(verwaest): declare via block_state. | 4514 // TODO(verwaest): declare via block_state. |
4521 Declaration* declaration = | 4515 Declaration* declaration = |
4522 factory()->NewVariableDeclaration(proxy, block_state.scope(), pos); | 4516 factory()->NewVariableDeclaration(proxy, block_state.scope(), pos); |
4523 Declare(declaration, DeclarationDescriptor::NORMAL, CONST, | 4517 Declare(declaration, DeclarationDescriptor::NORMAL, CONST, |
4524 DefaultInitializationFlag(CONST), CHECK_OK); | 4518 Variable::DefaultInitializationFlag(CONST), CHECK_OK); |
4525 } | 4519 } |
4526 | 4520 |
4527 Expression* extends = nullptr; | 4521 Expression* extends = nullptr; |
4528 if (Check(Token::EXTENDS)) { | 4522 if (Check(Token::EXTENDS)) { |
4529 block_state.set_start_position(scanner()->location().end_pos); | 4523 block_state.set_start_position(scanner()->location().end_pos); |
4530 ExpressionClassifier extends_classifier(this); | 4524 ExpressionClassifier extends_classifier(this); |
4531 extends = ParseLeftHandSideExpression(CHECK_OK); | 4525 extends = ParseLeftHandSideExpression(CHECK_OK); |
4532 CheckNoTailCallExpressions(CHECK_OK); | 4526 CheckNoTailCallExpressions(CHECK_OK); |
4533 RewriteNonPattern(CHECK_OK); | 4527 RewriteNonPattern(CHECK_OK); |
4534 impl()->AccumulateFormalParameterContainmentErrors(); | 4528 impl()->AccumulateFormalParameterContainmentErrors(); |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4716 VariableProxy* from = factory()->NewVariableProxy(parameter); | 4710 VariableProxy* from = factory()->NewVariableProxy(parameter); |
4717 Expression* assignment = | 4711 Expression* assignment = |
4718 factory()->NewAssignment(Token::ASSIGN, to, from, kNoSourcePosition); | 4712 factory()->NewAssignment(Token::ASSIGN, to, from, kNoSourcePosition); |
4719 Statement* statement = | 4713 Statement* statement = |
4720 factory()->NewExpressionStatement(assignment, kNoSourcePosition); | 4714 factory()->NewExpressionStatement(assignment, kNoSourcePosition); |
4721 inner_block->statements()->InsertAt(0, statement, zone()); | 4715 inner_block->statements()->InsertAt(0, statement, zone()); |
4722 } | 4716 } |
4723 } | 4717 } |
4724 | 4718 |
4725 void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope, | 4719 void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope, |
4726 Scope* complex_params_scope, | |
4727 bool* ok) { | 4720 bool* ok) { |
4728 // For each variable which is used as a function declaration in a sloppy | 4721 scope->HoistSloppyBlockFunctions(factory(), ok); |
4729 // block, | 4722 DCHECK(*ok); |
| 4723 if (!*ok) return; |
| 4724 |
4730 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map(); | 4725 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map(); |
4731 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { | 4726 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { |
4732 AstRawString* name = static_cast<AstRawString*>(p->key); | 4727 // Write in assignments to var for each block-scoped function declaration |
4733 | 4728 auto delegates = static_cast<SloppyBlockFunctionStatement*>(p->value); |
4734 // If the variable wouldn't conflict with a lexical declaration | 4729 for (SloppyBlockFunctionStatement* delegate = delegates; |
4735 // or parameter, | 4730 delegate != nullptr; delegate = delegate->next()) { |
4736 | 4731 if (delegate->to() == nullptr) { |
4737 // Check if there's a conflict with a parameter. | |
4738 // This depends on the fact that functions always have a scope solely to | |
4739 // hold complex parameters, and the names local to that scope are | |
4740 // precisely the names of the parameters. IsDeclaredParameter(name) does | |
4741 // not hold for names declared by complex parameters, nor are those | |
4742 // bindings necessarily declared lexically, so we have to check for them | |
4743 // explicitly. On the other hand, if there are not complex parameters, | |
4744 // it is sufficient to just check IsDeclaredParameter. | |
4745 if (complex_params_scope != nullptr) { | |
4746 if (complex_params_scope->LookupLocal(name) != nullptr) { | |
4747 continue; | 4732 continue; |
4748 } | 4733 } |
4749 } else { | 4734 Expression* assignment = factory()->NewAssignment( |
4750 if (scope->IsDeclaredParameter(name)) { | 4735 Token::ASSIGN, delegate->to(), delegate->from(), kNoSourcePosition); |
4751 continue; | |
4752 } | |
4753 } | |
4754 | |
4755 bool var_created = false; | |
4756 | |
4757 // Write in assignments to var for each block-scoped function declaration | |
4758 auto delegates = static_cast<SloppyBlockFunctionStatement*>(p->value); | |
4759 | |
4760 DeclarationScope* decl_scope = scope; | |
4761 while (decl_scope->is_eval_scope()) { | |
4762 decl_scope = decl_scope->outer_scope()->GetDeclarationScope(); | |
4763 } | |
4764 Scope* outer_scope = decl_scope->outer_scope(); | |
4765 | |
4766 for (SloppyBlockFunctionStatement* delegate = delegates; | |
4767 delegate != nullptr; delegate = delegate->next()) { | |
4768 // Check if there's a conflict with a lexical declaration | |
4769 Scope* query_scope = delegate->scope()->outer_scope(); | |
4770 Variable* var = nullptr; | |
4771 bool should_hoist = true; | |
4772 | |
4773 // Note that we perform this loop for each delegate named 'name', | |
4774 // which may duplicate work if those delegates share scopes. | |
4775 // It is not sufficient to just do a Lookup on query_scope: for | |
4776 // example, that does not prevent hoisting of the function in | |
4777 // `{ let e; try {} catch (e) { function e(){} } }` | |
4778 do { | |
4779 var = query_scope->LookupLocal(name); | |
4780 if (var != nullptr && IsLexicalVariableMode(var->mode())) { | |
4781 should_hoist = false; | |
4782 break; | |
4783 } | |
4784 query_scope = query_scope->outer_scope(); | |
4785 } while (query_scope != outer_scope); | |
4786 | |
4787 if (!should_hoist) continue; | |
4788 | |
4789 // Declare a var-style binding for the function in the outer scope | |
4790 if (!var_created) { | |
4791 var_created = true; | |
4792 VariableProxy* proxy = scope->NewUnresolved(factory(), name); | |
4793 Declaration* declaration = | |
4794 factory()->NewVariableDeclaration(proxy, scope, kNoSourcePosition); | |
4795 Declare(declaration, DeclarationDescriptor::NORMAL, VAR, | |
4796 DefaultInitializationFlag(VAR), ok, scope); | |
4797 DCHECK(*ok); // Based on the preceding check, this should not fail | |
4798 if (!*ok) return; | |
4799 } | |
4800 | |
4801 // Read from the local lexical scope and write to the function scope | |
4802 VariableProxy* to = scope->NewUnresolved(factory(), name); | |
4803 VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name); | |
4804 Expression* assignment = | |
4805 factory()->NewAssignment(Token::ASSIGN, to, from, kNoSourcePosition); | |
4806 Statement* statement = | 4736 Statement* statement = |
4807 factory()->NewExpressionStatement(assignment, kNoSourcePosition); | 4737 factory()->NewExpressionStatement(assignment, kNoSourcePosition); |
4808 delegate->set_statement(statement); | 4738 delegate->set_statement(statement); |
4809 } | 4739 } |
4810 } | 4740 } |
4811 } | 4741 } |
4812 | 4742 |
4813 | 4743 |
4814 // ---------------------------------------------------------------------------- | 4744 // ---------------------------------------------------------------------------- |
4815 // Parser support | 4745 // Parser support |
(...skipping 1674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6490 node->Print(Isolate::Current()); | 6420 node->Print(Isolate::Current()); |
6491 } | 6421 } |
6492 #endif // DEBUG | 6422 #endif // DEBUG |
6493 | 6423 |
6494 #undef CHECK_OK | 6424 #undef CHECK_OK |
6495 #undef CHECK_OK_VOID | 6425 #undef CHECK_OK_VOID |
6496 #undef CHECK_FAILED | 6426 #undef CHECK_FAILED |
6497 | 6427 |
6498 } // namespace internal | 6428 } // namespace internal |
6499 } // namespace v8 | 6429 } // namespace v8 |
OLD | NEW |