diff --git a/lib/compress.js b/lib/compress.js index 42bb6a77..5ab9a841 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -8156,12 +8156,12 @@ Compressor.prototype.compress = function(node) { var self = this; var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false; var defs_by_id = Object.create(null); - self.transform(new TreeTransformer(function(node, descend) { + var tt = new TreeTransformer(function(node, descend) { if (node instanceof AST_Assign) { if (node.operator != "=") return; if (!node.write_only) return; if (!can_hoist(node.left, node.right, 1)) return; - descend(node, this); + descend(node, tt); var defs = new Dictionary(); var assignments = []; var decls = []; @@ -8185,15 +8185,20 @@ Compressor.prototype.compress = function(node) { }); defs.value = node.right; defs_by_id[node.left.definition().id] = defs; - self.body.splice(self.body.indexOf(this.stack[1]) + 1, 0, make_node(AST_Var, node, { + self.body.splice(self.body.indexOf(tt.stack[1]) + 1, 0, make_node(AST_Var, node, { definitions: decls, })); return make_sequence(node, assignments); } - if (node instanceof AST_Scope) return node === self ? undefined : node; + if (node instanceof AST_Scope) { + if (node === self) return; + var parent = tt.parent(); + if (parent.TYPE == "Call" && parent.expression === node) return; + return node; + } if (node instanceof AST_VarDef) { if (!can_hoist(node.name, node.value, 0)) return; - descend(node, this); + descend(node, tt); var defs = new Dictionary(); var var_defs = []; var decl = node.clone(); @@ -8215,7 +8220,8 @@ Compressor.prototype.compress = function(node) { defs.set(key, new_var.definition()); return new_var; } - })); + }); + self.transform(tt); self.transform(new TreeTransformer(function(node, descend) { if (node instanceof AST_PropAccess) { if (!(node.expression instanceof AST_SymbolRef)) return; @@ -8245,6 +8251,7 @@ Compressor.prototype.compress = function(node) { if (def.assignments != count) return; if (def.references.length - def.replaced == count) return; if (def.single_use) return; + if (self.find_variable(sym.name) !== def) return; if (top_retain(def)) return; if (sym.fixed_value() !== right) return; var fixed = sym.fixed || def.fixed; diff --git a/test/compress/hoist_props.js b/test/compress/hoist_props.js index 31c8439a..60b4d6d2 100644 --- a/test/compress/hoist_props.js +++ b/test/compress/hoist_props.js @@ -1176,3 +1176,30 @@ issue_5182: { "42", ] } + +issue_5441: { + options = { + hoist_props: true, + passes: 2, + reduce_vars: true, + side_effects: true, + } + input: { + console.log(function(a) { + (function() { + a = { p: this }; + })(); + return typeof a; + }()); + } + expect: { + console.log(function(a) { + (function() { + a_p = this; + })(); + var a_p; + return typeof {}; + }()); + } + expect_stdout: "object" +} diff --git a/test/compress/varify.js b/test/compress/varify.js index 0bc9ada2..75f6ec67 100644 --- a/test/compress/varify.js +++ b/test/compress/varify.js @@ -111,7 +111,7 @@ hoist_props_const: { } } expect: { - var o = 0, o_p = "PASS"; + var o, o_p = "PASS"; console.log(o_p); } expect_stdout: "PASS"