| 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 |