Chromium Code Reviews| Index: src/parsing/pattern-rewriter.cc |
| diff --git a/src/parsing/pattern-rewriter.cc b/src/parsing/pattern-rewriter.cc |
| index 7f38053e549c6cd7f5eb673b88e5b7bc10739fc9..9ed69646ef5a229929eade51f31ec49991a8c2ed 100644 |
| --- a/src/parsing/pattern-rewriter.cc |
| +++ b/src/parsing/pattern-rewriter.cc |
| @@ -137,22 +137,31 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) { |
| factory()->NewVariableProxy(name, NORMAL_VARIABLE, pattern->position()); |
| Declaration* declaration = factory()->NewVariableDeclaration( |
| proxy, descriptor_->scope, descriptor_->declaration_pos); |
| + |
| + // When an extra declaration scope needs to be inserted to account for |
| + // a sloppy eval in a default parameter or function body, the parameter |
| + // needs to be declared in the function's scope, not in the varblock |
| + // scope which will be used for the initializer expression. |
| + Scope* outer_function_scope = nullptr; |
| + if (DeclaresParameterContainingSloppyEval()) { |
| + 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
|
| + } |
| Variable* var = parser_->Declare( |
| declaration, descriptor_->declaration_kind, descriptor_->mode, |
| Variable::DefaultInitializationFlag(descriptor_->mode), ok_, |
| - descriptor_->hoist_scope); |
| + outer_function_scope); |
| if (!*ok_) return; |
| DCHECK_NOT_NULL(var); |
| DCHECK(proxy->is_resolved()); |
| DCHECK(initializer_position_ != kNoSourcePosition); |
| var->set_initializer_position(initializer_position_); |
| - // TODO(adamk): This should probably be checking hoist_scope. |
| - // Move it to Parser::Declare() to make it easier to test |
| - // the right scope. |
| - Scope* declaration_scope = IsLexicalVariableMode(descriptor_->mode) |
| - ? descriptor_->scope |
| - : descriptor_->scope->GetDeclarationScope(); |
| + Scope* declaration_scope = |
| + outer_function_scope != nullptr |
| + ? outer_function_scope |
| + : (IsLexicalVariableMode(descriptor_->mode) |
| + ? descriptor_->scope |
| + : descriptor_->scope->GetDeclarationScope()); |
| if (declaration_scope->num_var() > kMaxNumFunctionLocals) { |
| parser_->ReportMessage(MessageTemplate::kTooManyVariables); |
| *ok_ = false; |
| @@ -321,20 +330,31 @@ void Parser::PatternRewriter::VisitRewritableExpression( |
| set_context(old_context); |
| } |
| +bool Parser::PatternRewriter::DeclaresParameterContainingSloppyEval() const { |
| + // Need to check for a binding context to make sure we have a descriptor. |
| + if (IsBindingContext() && |
| + // Only relevant for parameters. |
| + descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER && |
| + // And only when scope is a block scope; |
| + // without eval, it is a function scope. |
| + scope()->is_block_scope()) { |
| + DCHECK(scope()->calls_sloppy_eval()); |
| + DCHECK(scope()->is_declaration_scope()); |
| + 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
|
| + return true; |
| + } |
| + |
| + return false; |
| +} |
| + |
| // When an extra declaration scope needs to be inserted to account for |
| // a sloppy eval in a default parameter or function body, the expressions |
| // needs to be in that new inner scope which was added after initial |
| // parsing. |
| void Parser::PatternRewriter::RewriteParameterScopes(Expression* expr) { |
| - if (!IsBindingContext()) return; |
| - if (descriptor_->declaration_kind != DeclarationDescriptor::PARAMETER) return; |
| - if (!scope()->is_block_scope()) return; |
| - |
| - DCHECK(scope()->is_declaration_scope()); |
| - DCHECK(scope()->outer_scope()->is_function_scope()); |
| - DCHECK(scope()->calls_sloppy_eval()); |
| - |
| - ReparentParameterExpressionScope(parser_->stack_limit(), expr, scope()); |
| + if (DeclaresParameterContainingSloppyEval()) { |
| + ReparentParameterExpressionScope(parser_->stack_limit(), expr, scope()); |
| + } |
| } |
| void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern, |