Commit 61c137c8 authored by nikolaos's avatar nikolaos Committed by Commit bot

Fix bug with re-scoping arrow function parameter initializers

When re-scoping arrow function parameter initializers, temporaries
should be moved from the closure of the old scope to the closure of
the new scope, if necessary.

R=adamk@chromium.org, rossberg@chromium.org
BUG=chromium:622663
LOG=N

Review-Url: https://codereview.chromium.org/2083083007
Cr-Commit-Position: refs/heads/master@{#37335}
parent 872c461b
......@@ -555,6 +555,11 @@ Variable* Scope::NewTemporary(const AstRawString* name) {
int Scope::RemoveTemporary(Variable* var) {
DCHECK_NOT_NULL(var);
// Temporaries are only placed in ClosureScopes.
DCHECK_EQ(ClosureScope(), this);
DCHECK_EQ(var->scope()->ClosureScope(), var->scope());
// If the temporary is not here, return quickly.
if (var->scope() != this) return -1;
// Most likely (always?) any temporary variable we want to remove
// was just added before, so we search backwards.
for (int i = temps_.length(); i-- > 0;) {
......
......@@ -216,7 +216,11 @@ class Scope: public ZoneObject {
// Adds a temporary variable in this scope's TemporaryScope. This is for
// adjusting the scope of temporaries used when desugaring parameter
// initializers.
void AddTemporary(Variable* var) { temps_.Add(var, zone()); }
void AddTemporary(Variable* var) {
// Temporaries are only placed in ClosureScopes.
DCHECK_EQ(ClosureScope(), this);
temps_.Add(var, zone());
}
// Adds the specific declaration node to the list of declarations in
// this scope. The declarations are processed as part of entering
......
......@@ -24,7 +24,9 @@ class Rewriter final : public AstExpressionVisitor {
Scope* new_scope)
: AstExpressionVisitor(stack_limit, initializer),
old_scope_(old_scope),
new_scope_(new_scope) {}
new_scope_(new_scope),
old_scope_closure_(old_scope->ClosureScope()),
new_scope_closure_(new_scope->ClosureScope()) {}
~Rewriter();
private:
......@@ -40,6 +42,8 @@ class Rewriter final : public AstExpressionVisitor {
Scope* old_scope_;
Scope* new_scope_;
Scope* old_scope_closure_;
Scope* new_scope_closure_;
std::vector<std::pair<Variable*, int>> temps_;
};
......@@ -55,8 +59,8 @@ Rewriter::~Rewriter() {
// Ensure that we add temporaries in the order they appeared in old_scope_.
std::sort(temps_.begin(), temps_.end(), LessThanSecond());
for (auto var_and_index : temps_) {
var_and_index.first->set_scope(new_scope_);
new_scope_->AddTemporary(var_and_index.first);
var_and_index.first->set_scope(new_scope_closure_);
new_scope_closure_->AddTemporary(var_and_index.first);
}
}
}
......@@ -90,11 +94,11 @@ void Rewriter::VisitVariableProxy(VariableProxy* proxy) {
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);
// Temporaries are only placed in ClosureScopes.
DCHECK_EQ(var->scope(), var->scope()->ClosureScope());
// If the temporary is already where it should be, return quickly.
if (var->scope() == new_scope_closure_) return;
int index = old_scope_closure_->RemoveTemporary(var);
if (index >= 0) {
temps_.push_back(std::make_pair(var, index));
}
......
+// 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
(function() {
try { (y = [...[]]) => {} } catch(_) {} // will core dump, if not fixed
})();
(function() {
try { ((y = [...[]]) => {})(); } catch(_) {} // will core dump, if not fixed,
// even without --no-lazy
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment