 Chromium Code Reviews
 Chromium Code Reviews Issue 2662183002:
  [parser] Remove hoist_scope from DeclarationDescriptor  (Closed)
    
  
    Issue 2662183002:
  [parser] Remove hoist_scope from DeclarationDescriptor  (Closed) 
  | 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 |