aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/compress.js37
-rw-r--r--lib/scope.js35
-rw-r--r--test/compress/destructured.js29
3 files changed, 79 insertions, 22 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 4da13758..1bb6d542 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -4542,7 +4542,7 @@ merge(Compressor.prototype, {
var def = node.definition();
if (member(def.scope, scopes)) return true;
if (scope && !def.redefined()) {
- var scope_def = scope.find_variable(node);
+ var scope_def = scope.find_variable(node.name);
if (def.undeclared ? !scope_def : scope_def === def) {
result = "f";
return true;
@@ -4842,7 +4842,9 @@ merge(Compressor.prototype, {
if (!(ref instanceof AST_SymbolRef)) return;
var def = ref.definition();
var ldef = node.variables.get(ref.name);
- if (ldef && (ldef === def || def.undeclared || node.parent_scope.find_variable(ref) === def)) {
+ if (ldef && (ldef === def
+ || def.undeclared
+ || node.parent_scope.find_variable(ref.name) === def)) {
references[def.id] = false;
references[ldef.id] = false;
} else {
@@ -5468,7 +5470,7 @@ merge(Compressor.prototype, {
}) : def.value === def.name.fixed_value())
&& (!def.value.name || (old_def = def.value.name.definition()).assignments == 0
&& (old_def.name == def.name.name || all(old_def.references, function(ref) {
- return ref.scope.find_variable(def.name) === def.name.definition();
+ return ref.scope.find_variable(def.name.name) === def.name.definition();
})))
&& can_declare_defun()
&& can_rename(def.value, def.name.name)) {
@@ -5759,6 +5761,33 @@ merge(Compressor.prototype, {
if (init instanceof AST_SymbolRef) return init;
}
+ function find_variable(name) {
+ var level = 0;
+ var scope = self;
+ while (true) {
+ var in_arg = false;
+ do {
+ var parent = compressor.parent(level++);
+ if (parent instanceof AST_DestructuredKeyVal && parent.key === scope) {
+ var fn = compressor.parent(level + 1);
+ if (fn instanceof AST_Lambda) {
+ in_arg = fn.argnames.indexOf(compressor.parent(level)) >= 0;
+ level += 2;
+ scope = fn;
+ break;
+ }
+ }
+ if (!parent) return;
+ scope = parent;
+ } while (!(scope instanceof AST_BlockScope));
+ var def = scope.variables.get(name);
+ if (!def) continue;
+ if (!in_arg) return def;
+ var sym = def.orig[0];
+ if (sym instanceof AST_SymbolFunarg || sym instanceof AST_SymbolLambda) return def;
+ }
+ }
+
function scan_ref_scoped(node, descend, init) {
if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) {
var def = node.left.definition();
@@ -5807,7 +5836,7 @@ merge(Compressor.prototype, {
if (!sym) return;
var def = sym.definition();
if (def.scope !== self) {
- var d = self.find_variable(sym);
+ var d = find_variable(sym.name);
if ((d && d.redefined() || d) === def) return;
}
node.object.walk(tw);
diff --git a/lib/scope.js b/lib/scope.js
index 6c521bcc..ff0cb58c 100644
--- a/lib/scope.js
+++ b/lib/scope.js
@@ -190,7 +190,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
function entangle(defun, scope) {
if (defun === scope) return;
node.mark_enclosed(options);
- var def = scope.find_variable(node);
+ var def = scope.find_variable(node.name);
if (node.thedef === def) return;
node.thedef = def;
def.orig.push(node);
@@ -219,6 +219,21 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
if (node.label) node.label.thedef.references.push(node);
return true;
}
+ // ensure mangling works if `catch` reuses a scope variable
+ if (node instanceof AST_SymbolCatch) {
+ var def = node.definition().redefined();
+ if (def) for (var s = node.scope; s; s = s.parent_scope) {
+ push_uniq(s.enclosed, def);
+ if (s === def.scope) break;
+ }
+ return true;
+ }
+ // ensure compression works if `const` reuses a scope variable
+ if (node instanceof AST_SymbolConst) {
+ var redef = node.definition().redefined();
+ if (redef) redef.const_redefs = true;
+ return true;
+ }
if (node instanceof AST_SymbolRef) {
var name = node.name;
var sym = node.scope.find_variable(name);
@@ -258,21 +273,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
node.reference(options);
return true;
}
- // ensure mangling works if `catch` reuses a scope variable
- if (node instanceof AST_SymbolCatch) {
- var def = node.definition().redefined();
- if (def) for (var s = node.scope; s; s = s.parent_scope) {
- push_uniq(s.enclosed, def);
- if (s === def.scope) break;
- }
- return true;
- }
- // ensure compression works if `const` reuses a scope variable
- if (node instanceof AST_SymbolConst) {
- var redef = node.definition().redefined();
- if (redef) redef.const_redefs = true;
- return true;
- }
});
self.walk(tw);
@@ -390,9 +390,8 @@ AST_Symbol.DEFMETHOD("reference", function(options) {
});
AST_BlockScope.DEFMETHOD("find_variable", function(name) {
- if (name instanceof AST_Symbol) name = name.name;
return this.variables.get(name)
- || (this.parent_scope && this.parent_scope.find_variable(name));
+ || this.parent_scope && this.parent_scope.find_variable(name);
});
AST_BlockScope.DEFMETHOD("def_function", function(symbol, init) {
diff --git a/test/compress/destructured.js b/test/compress/destructured.js
index eb6834a4..82d02172 100644
--- a/test/compress/destructured.js
+++ b/test/compress/destructured.js
@@ -1777,3 +1777,32 @@ issue_4323: {
expect_stdout: "function"
node_version: ">=6"
}
+
+issue_4355: {
+ options = {
+ loops: true,
+ unused: true,
+ }
+ input: {
+ var a;
+ (function({
+ [function() {
+ for (a in "foo");
+ }()]: b,
+ }) {
+ var a;
+ })(0);
+ console.log(a);
+ }
+ expect: {
+ var a;
+ (function({
+ [function() {
+ for (a in "foo");
+ }()]: b,
+ }) {})(0);
+ console.log(a);
+ }
+ expect_stdout: "2"
+ node_version: ">=6"
+}