Version 5.2.361.25 (cherry-pick)
Merged 0e14baf712955a1993f742647bb2adc293702b80
Rewrite scopes of non-simple default arguments
BUG=chromium:616386
LOG=N
R=littledan@chromium.org
Review URL: https://codereview.chromium.org/2102933002 .
Cr-Commit-Position: refs/branch-heads/5.2@{#31}
Cr-Branched-From: 2cd36d6d0439ddfbe84cd90e112dced85084ec95-refs/heads/5.2.361@{#1}
Cr-Branched-From: 3fef34e02388e07d46067c516320f1ff12304c8e-refs/heads/master@{#36332}
diff --git a/include/v8-version.h b/include/v8-version.h
index 15074fb..777cd2c 100644
--- a/include/v8-version.h
+++ b/include/v8-version.h
@@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 5
#define V8_MINOR_VERSION 2
#define V8_BUILD_NUMBER 361
-#define V8_PATCH_LEVEL 24
+#define V8_PATCH_LEVEL 25
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/parsing/parameter-initializer-rewriter.cc b/src/parsing/parameter-initializer-rewriter.cc
index cbbf8de..6362c63 100644
--- a/src/parsing/parameter-initializer-rewriter.cc
+++ b/src/parsing/parameter-initializer-rewriter.cc
@@ -90,6 +90,10 @@
if (proxy->is_resolved()) {
Variable* var = proxy->var();
if (var->mode() != TEMPORARY) return;
+ // For rewriting inside the same ClosureScope (e.g., putting default
+ // parameter values in their own inner scope in certain cases), refrain
+ // from invalidly moving temporaries to a block scope.
+ if (var->scope()->ClosureScope() == new_scope_->ClosureScope()) return;
int index = old_scope_->RemoveTemporary(var);
if (index >= 0) {
temps_.push_back(std::make_pair(var, index));
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
index b4e4176..1f267d3 100644
--- a/src/parsing/parser.cc
+++ b/src/parsing/parser.cc
@@ -4583,6 +4583,12 @@
param_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
param_block->set_scope(param_scope);
descriptor.hoist_scope = scope_;
+ // Pass the appropriate scope in so that PatternRewriter can appropriately
+ // rewrite inner initializers of the pattern to param_scope
+ descriptor.scope = param_scope;
+ // Rewrite the outer initializer to point to param_scope
+ RewriteParameterInitializerScope(stack_limit(), initial_value, scope_,
+ param_scope);
}
{
diff --git a/src/parsing/pattern-rewriter.cc b/src/parsing/pattern-rewriter.cc
index 91d7549..808c0c0 100644
--- a/src/parsing/pattern-rewriter.cc
+++ b/src/parsing/pattern-rewriter.cc
@@ -677,9 +677,29 @@
RelocInfo::kNoPosition);
}
+ // Two cases for scope rewriting the scope of default parameters:
+ // - Eagerly parsed arrow functions are initially parsed as having
+ // initializers in the enclosing scope, but when the arrow is encountered,
+ // need to be in the scope of the function.
+ // - When an extra declaration scope needs to be inserted to account for
+ // a sloppy eval in a default parameter or function body, the initializer
+ // needs to be in that new inner scope which was added after initial
+ // parsing.
+ // Each of these cases can be handled by rewriting the contents of the
+ // initializer to the current scope. The source scope is typically the outer
+ // scope when one case occurs; when both cases occur, both scopes need to
+ // be included as the outer scope. (Both rewritings still need to be done
+ // to account for lazily parsed arrow functions which hit the second case.)
+ // TODO(littledan): Remove the outer_scope parameter of
+ // RewriteParameterInitializerScope
if (IsBindingContext() &&
descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER &&
- scope()->is_arrow_scope()) {
+ (scope()->is_arrow_scope() || scope()->is_block_scope())) {
+ if (scope()->outer_scope()->is_arrow_scope() && scope()->is_block_scope()) {
+ RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
+ scope()->outer_scope()->outer_scope(),
+ scope());
+ }
RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
scope()->outer_scope(), scope());
}
diff --git a/test/mjsunit/regress/regress-616386.js b/test/mjsunit/regress/regress-616386.js
new file mode 100644
index 0000000..d462ab7
--- /dev/null
+++ b/test/mjsunit/regress/regress-616386.js
@@ -0,0 +1,10 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --no-lazy
+
+assertEquals(0, ((y = (function(a2) { bbbb = a2 }), bbbb = eval('1')) => {y(0); return bbbb})())
+assertEquals(0, (({y = (function(a2) { bbbb = a2 }), bbbb = eval('1')} = {}) => {y(0); return bbbb})())
+assertEquals(0, (function (y = (function(a2) { bbbb = a2 }), bbbb = eval('1')) {y(0); return bbbb})())
+assertEquals(0, (function ({y = (function(a2) { bbbb = a2 }), bbbb = eval('1')} = {}) {y(0); return bbbb})())