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 951 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
962 if (ok && is_strict(language_mode())) { | 962 if (ok && is_strict(language_mode())) { |
963 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); | 963 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); |
964 CheckDecimalLiteralWithLeadingZero(use_counts_, beg_pos, | 964 CheckDecimalLiteralWithLeadingZero(use_counts_, beg_pos, |
965 scanner()->location().end_pos); | 965 scanner()->location().end_pos); |
966 } | 966 } |
967 if (ok && is_sloppy(language_mode())) { | 967 if (ok && is_sloppy(language_mode())) { |
968 // TODO(littledan): Function bindings on the global object that modify | 968 // TODO(littledan): Function bindings on the global object that modify |
969 // pre-existing bindings should be made writable, enumerable and | 969 // pre-existing bindings should be made writable, enumerable and |
970 // nonconfigurable if possible, whereas this code will leave attributes | 970 // nonconfigurable if possible, whereas this code will leave attributes |
971 // unchanged if the property already exists. | 971 // unchanged if the property already exists. |
972 InsertSloppyBlockFunctionVarBindings(scope, &ok); | 972 InsertSloppyBlockFunctionVarBindings(scope, nullptr, &ok); |
973 } | 973 } |
974 if (ok) { | 974 if (ok) { |
975 CheckConflictingVarDeclarations(scope_, &ok); | 975 CheckConflictingVarDeclarations(scope_, &ok); |
976 } | 976 } |
977 | 977 |
978 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { | 978 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { |
979 if (body->length() != 1 || | 979 if (body->length() != 1 || |
980 !body->at(0)->IsExpressionStatement() || | 980 !body->at(0)->IsExpressionStatement() || |
981 !body->at(0)->AsExpressionStatement()-> | 981 !body->at(0)->AsExpressionStatement()-> |
982 expression()->IsFunctionLiteral()) { | 982 expression()->IsFunctionLiteral()) { |
(...skipping 3366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4349 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); | 4349 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); |
4350 ValidateFormalParameters(&formals_classifier, language_mode, | 4350 ValidateFormalParameters(&formals_classifier, language_mode, |
4351 allow_duplicate_parameters, CHECK_OK); | 4351 allow_duplicate_parameters, CHECK_OK); |
4352 | 4352 |
4353 if (is_strict(language_mode)) { | 4353 if (is_strict(language_mode)) { |
4354 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), | 4354 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), |
4355 CHECK_OK); | 4355 CHECK_OK); |
4356 CheckDecimalLiteralWithLeadingZero(use_counts_, scope->start_position(), | 4356 CheckDecimalLiteralWithLeadingZero(use_counts_, scope->start_position(), |
4357 scope->end_position()); | 4357 scope->end_position()); |
4358 } | 4358 } |
4359 if (is_sloppy(language_mode)) { | |
4360 InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK); | |
4361 } | |
4362 CheckConflictingVarDeclarations(scope, CHECK_OK); | 4359 CheckConflictingVarDeclarations(scope, CHECK_OK); |
4363 | 4360 |
4364 if (body) { | 4361 if (body) { |
4365 // If body can be inspected, rewrite queued destructuring assignments | 4362 // If body can be inspected, rewrite queued destructuring assignments |
4366 ParserTraits::RewriteDestructuringAssignments(); | 4363 ParserTraits::RewriteDestructuringAssignments(); |
4367 } | 4364 } |
4368 has_duplicate_parameters = | 4365 has_duplicate_parameters = |
4369 !formals_classifier.is_valid_formal_parameter_list_without_duplicates(); | 4366 !formals_classifier.is_valid_formal_parameter_list_without_duplicates(); |
4370 } | 4367 } |
4371 | 4368 |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4800 | 4797 |
4801 Expect(Token::RBRACE, CHECK_OK); | 4798 Expect(Token::RBRACE, CHECK_OK); |
4802 scope_->set_end_position(scanner()->location().end_pos); | 4799 scope_->set_end_position(scanner()->location().end_pos); |
4803 | 4800 |
4804 if (!parameters.is_simple) { | 4801 if (!parameters.is_simple) { |
4805 DCHECK_NOT_NULL(inner_scope); | 4802 DCHECK_NOT_NULL(inner_scope); |
4806 DCHECK_EQ(body, inner_block->statements()); | 4803 DCHECK_EQ(body, inner_block->statements()); |
4807 SetLanguageMode(scope_, inner_scope->language_mode()); | 4804 SetLanguageMode(scope_, inner_scope->language_mode()); |
4808 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); | 4805 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); |
4809 | 4806 |
| 4807 if (is_sloppy(inner_scope->language_mode())) { |
| 4808 InsertSloppyBlockFunctionVarBindings( |
| 4809 inner_scope, inner_scope->outer_scope(), CHECK_OK); |
| 4810 } |
| 4811 |
4810 if (IsAsyncFunction(kind)) { | 4812 if (IsAsyncFunction(kind)) { |
4811 init_block = BuildRejectPromiseOnException(init_block); | 4813 init_block = BuildRejectPromiseOnException(init_block); |
4812 } | 4814 } |
4813 | 4815 |
4814 DCHECK_NOT_NULL(init_block); | 4816 DCHECK_NOT_NULL(init_block); |
4815 | 4817 |
4816 inner_scope->set_end_position(scanner()->location().end_pos); | 4818 inner_scope->set_end_position(scanner()->location().end_pos); |
4817 inner_scope = inner_scope->FinalizeBlockScope(); | 4819 inner_scope = inner_scope->FinalizeBlockScope(); |
4818 if (inner_scope != nullptr) { | 4820 if (inner_scope != nullptr) { |
4819 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); | 4821 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); |
4820 InsertShadowingVarBindingInitializers(inner_block); | 4822 InsertShadowingVarBindingInitializers(inner_block); |
4821 } | 4823 } |
4822 | 4824 |
4823 result->Add(init_block, zone()); | 4825 result->Add(init_block, zone()); |
4824 result->Add(inner_block, zone()); | 4826 result->Add(inner_block, zone()); |
| 4827 } else { |
| 4828 if (is_sloppy(inner_scope->language_mode())) { |
| 4829 InsertSloppyBlockFunctionVarBindings(inner_scope, nullptr, CHECK_OK); |
| 4830 } |
4825 } | 4831 } |
4826 | 4832 |
4827 if (function_type == FunctionLiteral::kNamedExpression) { | 4833 if (function_type == FunctionLiteral::kNamedExpression) { |
4828 // Now that we know the language mode, we can create the const assignment | 4834 // Now that we know the language mode, we can create the const assignment |
4829 // in the previously reserved spot. | 4835 // in the previously reserved spot. |
4830 // NOTE: We create a proxy and resolve it here so that in the | 4836 // NOTE: We create a proxy and resolve it here so that in the |
4831 // future we can change the AST to only refer to VariableProxies | 4837 // future we can change the AST to only refer to VariableProxies |
4832 // instead of Variables and Proxies as is the case now. | 4838 // instead of Variables and Proxies as is the case now. |
4833 VariableMode fvar_mode = is_strict(language_mode()) ? CONST : CONST_LEGACY; | 4839 VariableMode fvar_mode = is_strict(language_mode()) ? CONST : CONST_LEGACY; |
4834 Variable* fvar = new (zone()) | 4840 Variable* fvar = new (zone()) |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5101 VariableProxy* to = inner_scope->NewUnresolved(factory(), name); | 5107 VariableProxy* to = inner_scope->NewUnresolved(factory(), name); |
5102 VariableProxy* from = factory()->NewVariableProxy(parameter); | 5108 VariableProxy* from = factory()->NewVariableProxy(parameter); |
5103 Expression* assignment = factory()->NewAssignment( | 5109 Expression* assignment = factory()->NewAssignment( |
5104 Token::ASSIGN, to, from, RelocInfo::kNoPosition); | 5110 Token::ASSIGN, to, from, RelocInfo::kNoPosition); |
5105 Statement* statement = factory()->NewExpressionStatement( | 5111 Statement* statement = factory()->NewExpressionStatement( |
5106 assignment, RelocInfo::kNoPosition); | 5112 assignment, RelocInfo::kNoPosition); |
5107 inner_block->statements()->InsertAt(0, statement, zone()); | 5113 inner_block->statements()->InsertAt(0, statement, zone()); |
5108 } | 5114 } |
5109 } | 5115 } |
5110 | 5116 |
5111 | 5117 void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, |
5112 void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, bool* ok) { | 5118 Scope* complex_params_scope, |
| 5119 bool* ok) { |
5113 // For each variable which is used as a function declaration in a sloppy | 5120 // For each variable which is used as a function declaration in a sloppy |
5114 // block, | 5121 // block, |
5115 DCHECK(scope->is_declaration_scope()); | 5122 DCHECK(scope->is_declaration_scope()); |
5116 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map(); | 5123 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map(); |
5117 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { | 5124 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { |
5118 AstRawString* name = static_cast<AstRawString*>(p->key); | 5125 AstRawString* name = static_cast<AstRawString*>(p->key); |
5119 // If the variable wouldn't conflict with a lexical declaration, | 5126 |
5120 Variable* var = scope->LookupLocal(name); | 5127 // If the variable wouldn't conflict with a lexical declaration |
5121 if (var == nullptr || !IsLexicalVariableMode(var->mode())) { | 5128 // or parameter, |
| 5129 |
| 5130 // Check if there's a conflict with a parameter. |
| 5131 // This depends on the fact that functions always have a scope solely to |
| 5132 // hold complex parameters, and the names local to that scope are |
| 5133 // precisely the names of the parameters. IsDeclaredParameter(name) does |
| 5134 // not hold for names declared by complex parameters, nor are those |
| 5135 // bindings necessarily declared lexically, so we have to check for them |
| 5136 // explicitly. On the other hand, if there are not complex parameters, |
| 5137 // it is sufficient to just check IsDeclaredParameter. |
| 5138 if (complex_params_scope != nullptr) { |
| 5139 if (complex_params_scope->LookupLocal(name) != nullptr) { |
| 5140 continue; |
| 5141 } |
| 5142 } else { |
| 5143 if (scope->IsDeclaredParameter(name)) { |
| 5144 continue; |
| 5145 } |
| 5146 } |
| 5147 |
| 5148 bool var_created = false; |
| 5149 |
| 5150 // Write in assignments to var for each block-scoped function declaration |
| 5151 auto delegates = static_cast<SloppyBlockFunctionMap::Vector*>(p->value); |
| 5152 for (SloppyBlockFunctionStatement* delegate : *delegates) { |
| 5153 // Check if there's a conflict with a lexical declaration |
| 5154 Scope* outer_scope = scope->outer_scope(); |
| 5155 Scope* query_scope = delegate->scope()->outer_scope(); |
| 5156 Variable* var = nullptr; |
| 5157 bool should_hoist = true; |
| 5158 |
| 5159 // Note that we perform this loop for each delegate named 'name', |
| 5160 // which may duplicate work if those delegates share scopes. |
| 5161 // It is not sufficient to just do a Lookup on query_scope: for |
| 5162 // example, that does not prevent hoisting of the function in |
| 5163 // `{ let e; try {} catch (e) { function e(){} } }` |
| 5164 do { |
| 5165 var = query_scope->LookupLocal(name); |
| 5166 if (var != nullptr && IsLexicalVariableMode(var->mode())) { |
| 5167 should_hoist = false; |
| 5168 break; |
| 5169 } |
| 5170 query_scope = query_scope->outer_scope(); |
| 5171 } while (query_scope != outer_scope); |
| 5172 |
| 5173 if (!should_hoist) continue; |
| 5174 |
5122 // Declare a var-style binding for the function in the outer scope | 5175 // Declare a var-style binding for the function in the outer scope |
5123 VariableProxy* proxy = scope->NewUnresolved(factory(), name); | 5176 if (!var_created) { |
5124 Declaration* declaration = factory()->NewVariableDeclaration( | 5177 var_created = true; |
5125 proxy, VAR, scope, RelocInfo::kNoPosition); | 5178 VariableProxy* proxy = scope->NewUnresolved(factory(), name); |
5126 Declare(declaration, DeclarationDescriptor::NORMAL, true, ok, scope); | 5179 Declaration* declaration = factory()->NewVariableDeclaration( |
5127 DCHECK(ok); // Based on the preceding check, this should not fail | 5180 proxy, VAR, scope, RelocInfo::kNoPosition); |
5128 if (!ok) return; | 5181 Declare(declaration, DeclarationDescriptor::NORMAL, true, ok, scope); |
| 5182 DCHECK(ok); // Based on the preceding check, this should not fail |
| 5183 if (!ok) return; |
| 5184 } |
5129 | 5185 |
5130 // Write in assignments to var for each block-scoped function declaration | 5186 // Read from the local lexical scope and write to the function scope |
5131 auto delegates = static_cast<SloppyBlockFunctionMap::Vector*>(p->value); | 5187 VariableProxy* to = scope->NewUnresolved(factory(), name); |
5132 for (SloppyBlockFunctionStatement* delegate : *delegates) { | 5188 VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name); |
5133 // Read from the local lexical scope and write to the function scope | 5189 Expression* assignment = factory()->NewAssignment(Token::ASSIGN, to, from, |
5134 VariableProxy* to = scope->NewUnresolved(factory(), name); | 5190 RelocInfo::kNoPosition); |
5135 VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name); | 5191 Statement* statement = |
5136 Expression* assignment = factory()->NewAssignment( | 5192 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
5137 Token::ASSIGN, to, from, RelocInfo::kNoPosition); | 5193 delegate->set_statement(statement); |
5138 Statement* statement = factory()->NewExpressionStatement( | |
5139 assignment, RelocInfo::kNoPosition); | |
5140 delegate->set_statement(statement); | |
5141 } | |
5142 } | 5194 } |
5143 } | 5195 } |
5144 } | 5196 } |
5145 | 5197 |
5146 | 5198 |
5147 // ---------------------------------------------------------------------------- | 5199 // ---------------------------------------------------------------------------- |
5148 // Parser support | 5200 // Parser support |
5149 | 5201 |
5150 bool Parser::TargetStackContainsLabel(const AstRawString* label) { | 5202 bool Parser::TargetStackContainsLabel(const AstRawString* label) { |
5151 for (Target* t = target_stack_; t != NULL; t = t->previous()) { | 5203 for (Target* t = target_stack_; t != NULL; t = t->previous()) { |
(...skipping 1824 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6976 try_block, target); | 7028 try_block, target); |
6977 final_loop = target; | 7029 final_loop = target; |
6978 } | 7030 } |
6979 | 7031 |
6980 return final_loop; | 7032 return final_loop; |
6981 } | 7033 } |
6982 | 7034 |
6983 | 7035 |
6984 } // namespace internal | 7036 } // namespace internal |
6985 } // namespace v8 | 7037 } // namespace v8 |
OLD | NEW |