Skip to content

Commit c947d44

Browse files
committed
deps: cherry-pick 0e14baf712 from V8 upstream
Original commit message: Rewrite scopes of non-simple default arguments Default parameters have additional declaration block scopes inserted around them when something in the function scope calls eval. This patch sets the parent scope of the expressions introduced due to those defaults to the new block scope. R=adamk BUG=chromium:616386 Review-Url: https://codereview.chromium.org/2077283004 Cr-Commit-Position: refs/heads/master@{#37198} PR-URL: nodejs-private/node-private#80 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
1 parent cae9eb3 commit c947d44

File tree

4 files changed

+41
-1
lines changed

4 files changed

+41
-1
lines changed

deps/v8/src/parsing/parameter-initializer-rewriter.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ void Rewriter::VisitVariableProxy(VariableProxy* proxy) {
6363
if (proxy->is_resolved()) {
6464
Variable* var = proxy->var();
6565
if (var->mode() != TEMPORARY) return;
66+
// For rewriting inside the same ClosureScope (e.g., putting default
67+
// parameter values in their own inner scope in certain cases), refrain
68+
// from invalidly moving temporaries to a block scope.
69+
if (var->scope()->ClosureScope() == new_scope_->ClosureScope()) return;
6670
if (old_scope_->RemoveTemporary(var)) {
6771
var->set_scope(new_scope_);
6872
new_scope_->AddTemporary(var);

deps/v8/src/parsing/parser.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4479,6 +4479,12 @@ Block* Parser::BuildParameterInitializationBlock(
44794479
param_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
44804480
param_block->set_scope(param_scope);
44814481
descriptor.hoist_scope = scope_;
4482+
// Pass the appropriate scope in so that PatternRewriter can appropriately
4483+
// rewrite inner initializers of the pattern to param_scope
4484+
descriptor.scope = param_scope;
4485+
// Rewrite the outer initializer to point to param_scope
4486+
RewriteParameterInitializerScope(stack_limit(), initial_value, scope_,
4487+
param_scope);
44824488
}
44834489

44844490
{

deps/v8/src/parsing/pattern-rewriter.cc

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,9 +668,29 @@ void Parser::PatternRewriter::VisitAssignment(Assignment* node) {
668668
RelocInfo::kNoPosition);
669669
}
670670

671+
// Two cases for scope rewriting the scope of default parameters:
672+
// - Eagerly parsed arrow functions are initially parsed as having
673+
// initializers in the enclosing scope, but when the arrow is encountered,
674+
// need to be in the scope of the function.
675+
// - When an extra declaration scope needs to be inserted to account for
676+
// a sloppy eval in a default parameter or function body, the initializer
677+
// needs to be in that new inner scope which was added after initial
678+
// parsing.
679+
// Each of these cases can be handled by rewriting the contents of the
680+
// initializer to the current scope. The source scope is typically the outer
681+
// scope when one case occurs; when both cases occur, both scopes need to
682+
// be included as the outer scope. (Both rewritings still need to be done
683+
// to account for lazily parsed arrow functions which hit the second case.)
684+
// TODO(littledan): Remove the outer_scope parameter of
685+
// RewriteParameterInitializerScope
671686
if (IsBindingContext() &&
672687
descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER &&
673-
scope()->is_arrow_scope()) {
688+
(scope()->is_arrow_scope() || scope()->is_block_scope())) {
689+
if (scope()->outer_scope()->is_arrow_scope() && scope()->is_block_scope()) {
690+
RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
691+
scope()->outer_scope()->outer_scope(),
692+
scope());
693+
}
674694
RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
675695
scope()->outer_scope(), scope());
676696
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2016 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// Flags: --no-lazy
6+
7+
assertEquals(0, ((y = (function(a2) { bbbb = a2 }), bbbb = eval('1')) => {y(0); return bbbb})())
8+
assertEquals(0, (({y = (function(a2) { bbbb = a2 }), bbbb = eval('1')} = {}) => {y(0); return bbbb})())
9+
assertEquals(0, (function (y = (function(a2) { bbbb = a2 }), bbbb = eval('1')) {y(0); return bbbb})())
10+
assertEquals(0, (function ({y = (function(a2) { bbbb = a2 }), bbbb = eval('1')} = {}) {y(0); return bbbb})())

0 commit comments

Comments
 (0)