OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/ast/ast.h" | 5 #include "src/ast/ast.h" |
6 #include "src/messages.h" | 6 #include "src/messages.h" |
7 #include "src/objects-inl.h" | 7 #include "src/objects-inl.h" |
8 #include "src/parsing/parameter-initializer-rewriter.h" | 8 #include "src/parsing/parameter-initializer-rewriter.h" |
9 #include "src/parsing/parser.h" | 9 #include "src/parsing/parser.h" |
10 | 10 |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
130 // when the variable is encountered in the source. But the variable/constant | 130 // when the variable is encountered in the source. But the variable/constant |
131 // is declared (and set to 'undefined') upon entering the function within | 131 // is declared (and set to 'undefined') upon entering the function within |
132 // which the variable or constant is declared. Only function variables have | 132 // which the variable or constant is declared. Only function variables have |
133 // an initial value in the declaration (because they are initialized upon | 133 // an initial value in the declaration (because they are initialized upon |
134 // entering the function). | 134 // entering the function). |
135 const AstRawString* name = pattern->raw_name(); | 135 const AstRawString* name = pattern->raw_name(); |
136 VariableProxy* proxy = | 136 VariableProxy* proxy = |
137 factory()->NewVariableProxy(name, NORMAL_VARIABLE, pattern->position()); | 137 factory()->NewVariableProxy(name, NORMAL_VARIABLE, pattern->position()); |
138 Declaration* declaration = factory()->NewVariableDeclaration( | 138 Declaration* declaration = factory()->NewVariableDeclaration( |
139 proxy, descriptor_->scope, descriptor_->declaration_pos); | 139 proxy, descriptor_->scope, descriptor_->declaration_pos); |
140 | |
141 // When an extra declaration scope needs to be inserted to account for | |
142 // a sloppy eval in a default parameter or function body, the parameter | |
143 // needs to be declared in the function's scope, not in the varblock | |
144 // scope which will be used for the initializer expression. | |
145 Scope* outer_function_scope = nullptr; | |
146 if (DeclaresParameterContainingSloppyEval()) { | |
147 outer_function_scope = descriptor_->scope->outer_scope(); | |
neis
2017/02/01 08:55:24
Can you add a DCHECK here saying that it's a funct
adamk
2017/02/01 16:22:15
I could add another one, but it does feel kind of
| |
148 } | |
140 Variable* var = parser_->Declare( | 149 Variable* var = parser_->Declare( |
141 declaration, descriptor_->declaration_kind, descriptor_->mode, | 150 declaration, descriptor_->declaration_kind, descriptor_->mode, |
142 Variable::DefaultInitializationFlag(descriptor_->mode), ok_, | 151 Variable::DefaultInitializationFlag(descriptor_->mode), ok_, |
143 descriptor_->hoist_scope); | 152 outer_function_scope); |
144 if (!*ok_) return; | 153 if (!*ok_) return; |
145 DCHECK_NOT_NULL(var); | 154 DCHECK_NOT_NULL(var); |
146 DCHECK(proxy->is_resolved()); | 155 DCHECK(proxy->is_resolved()); |
147 DCHECK(initializer_position_ != kNoSourcePosition); | 156 DCHECK(initializer_position_ != kNoSourcePosition); |
148 var->set_initializer_position(initializer_position_); | 157 var->set_initializer_position(initializer_position_); |
149 | 158 |
150 // TODO(adamk): This should probably be checking hoist_scope. | 159 Scope* declaration_scope = |
151 // Move it to Parser::Declare() to make it easier to test | 160 outer_function_scope != nullptr |
152 // the right scope. | 161 ? outer_function_scope |
153 Scope* declaration_scope = IsLexicalVariableMode(descriptor_->mode) | 162 : (IsLexicalVariableMode(descriptor_->mode) |
154 ? descriptor_->scope | 163 ? descriptor_->scope |
155 : descriptor_->scope->GetDeclarationScope(); | 164 : descriptor_->scope->GetDeclarationScope()); |
156 if (declaration_scope->num_var() > kMaxNumFunctionLocals) { | 165 if (declaration_scope->num_var() > kMaxNumFunctionLocals) { |
157 parser_->ReportMessage(MessageTemplate::kTooManyVariables); | 166 parser_->ReportMessage(MessageTemplate::kTooManyVariables); |
158 *ok_ = false; | 167 *ok_ = false; |
159 return; | 168 return; |
160 } | 169 } |
161 if (names_) { | 170 if (names_) { |
162 names_->Add(name, zone()); | 171 names_->Add(name, zone()); |
163 } | 172 } |
164 | 173 |
165 // If there's no initializer, we're done. | 174 // If there's no initializer, we're done. |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
314 Expression* expr = factory()->NewDoExpression(block_, temp, pos); | 323 Expression* expr = factory()->NewDoExpression(block_, temp, pos); |
315 node->Rewrite(expr); | 324 node->Rewrite(expr); |
316 block_ = old_block; | 325 block_ = old_block; |
317 if (block_) { | 326 if (block_) { |
318 block_->statements()->Add(factory()->NewExpressionStatement(expr, pos), | 327 block_->statements()->Add(factory()->NewExpressionStatement(expr, pos), |
319 zone()); | 328 zone()); |
320 } | 329 } |
321 set_context(old_context); | 330 set_context(old_context); |
322 } | 331 } |
323 | 332 |
333 bool Parser::PatternRewriter::DeclaresParameterContainingSloppyEval() const { | |
334 // Need to check for a binding context to make sure we have a descriptor. | |
335 if (IsBindingContext() && | |
336 // Only relevant for parameters. | |
337 descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER && | |
338 // And only when scope is a block scope; | |
339 // without eval, it is a function scope. | |
340 scope()->is_block_scope()) { | |
341 DCHECK(scope()->calls_sloppy_eval()); | |
342 DCHECK(scope()->is_declaration_scope()); | |
343 DCHECK(scope()->outer_scope()->is_function_scope()); | |
neis
2017/02/01 08:55:24
Hmm I guess it's already here because scope() is a
adamk
2017/02/01 16:22:15
Another option would be to call this function some
neis
2017/02/01 16:26:41
I prefer the current version. It's okay with me if
| |
344 return true; | |
345 } | |
346 | |
347 return false; | |
348 } | |
349 | |
324 // When an extra declaration scope needs to be inserted to account for | 350 // When an extra declaration scope needs to be inserted to account for |
325 // a sloppy eval in a default parameter or function body, the expressions | 351 // a sloppy eval in a default parameter or function body, the expressions |
326 // needs to be in that new inner scope which was added after initial | 352 // needs to be in that new inner scope which was added after initial |
327 // parsing. | 353 // parsing. |
328 void Parser::PatternRewriter::RewriteParameterScopes(Expression* expr) { | 354 void Parser::PatternRewriter::RewriteParameterScopes(Expression* expr) { |
329 if (!IsBindingContext()) return; | 355 if (DeclaresParameterContainingSloppyEval()) { |
330 if (descriptor_->declaration_kind != DeclarationDescriptor::PARAMETER) return; | 356 ReparentParameterExpressionScope(parser_->stack_limit(), expr, scope()); |
331 if (!scope()->is_block_scope()) return; | 357 } |
332 | |
333 DCHECK(scope()->is_declaration_scope()); | |
334 DCHECK(scope()->outer_scope()->is_function_scope()); | |
335 DCHECK(scope()->calls_sloppy_eval()); | |
336 | |
337 ReparentParameterExpressionScope(parser_->stack_limit(), expr, scope()); | |
338 } | 358 } |
339 | 359 |
340 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern, | 360 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern, |
341 Variable** temp_var) { | 361 Variable** temp_var) { |
342 auto temp = *temp_var = CreateTempVar(current_value_); | 362 auto temp = *temp_var = CreateTempVar(current_value_); |
343 | 363 |
344 ZoneList<Expression*>* rest_runtime_callargs = nullptr; | 364 ZoneList<Expression*>* rest_runtime_callargs = nullptr; |
345 if (pattern->has_rest_property()) { | 365 if (pattern->has_rest_property()) { |
346 // non_rest_properties_count = pattern->properties()->length - 1; | 366 // non_rest_properties_count = pattern->properties()->length - 1; |
347 // args_length = 1 + non_rest_properties_count because we need to | 367 // args_length = 1 + non_rest_properties_count because we need to |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
746 NOT_A_PATTERN(TryFinallyStatement) | 766 NOT_A_PATTERN(TryFinallyStatement) |
747 NOT_A_PATTERN(UnaryOperation) | 767 NOT_A_PATTERN(UnaryOperation) |
748 NOT_A_PATTERN(VariableDeclaration) | 768 NOT_A_PATTERN(VariableDeclaration) |
749 NOT_A_PATTERN(WhileStatement) | 769 NOT_A_PATTERN(WhileStatement) |
750 NOT_A_PATTERN(WithStatement) | 770 NOT_A_PATTERN(WithStatement) |
751 NOT_A_PATTERN(Yield) | 771 NOT_A_PATTERN(Yield) |
752 | 772 |
753 #undef NOT_A_PATTERN | 773 #undef NOT_A_PATTERN |
754 } // namespace internal | 774 } // namespace internal |
755 } // namespace v8 | 775 } // namespace v8 |
OLD | NEW |