From: Alex Lam S.L Date: Wed, 7 Oct 2020 14:01:39 +0000 (+0100) Subject: fix corner case in `reduce_vars` (#4189) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=9c0feb69e5cdd3d491c6b0600fc964a41a774710;p=UglifyJS.git fix corner case in `reduce_vars` (#4189) fixes #4188 --- diff --git a/lib/compress.js b/lib/compress.js index 29cc82a9..fa1cc383 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -354,6 +354,13 @@ merge(Compressor.prototype, { return orig.length == 1 && orig[0] instanceof AST_SymbolFunarg; } + function cross_scope(def, sym) { + do { + if (def === sym) return false; + if (sym instanceof AST_Scope) return true; + } while (sym = sym.parent_scope); + } + (function(def) { def(AST_Node, noop); @@ -506,6 +513,7 @@ merge(Compressor.prototype, { function ref_once(compressor, def) { return compressor.option("unused") && !def.scope.pinned() + && def.single_use !== false && def.references.length - def.recursive_refs == 1; } @@ -840,11 +848,13 @@ merge(Compressor.prototype, { && d.orig[0] instanceof AST_SymbolDefun) { tw.loop_ids[d.id] = tw.in_loop; } - var value; - if (d.fixed === undefined || !safe_to_read(tw, d)) { + if (d.fixed === false) { + var redef = d.redefined(); + if (redef && cross_scope(d.scope, this.scope)) redef.single_use = false; + } else if (d.fixed === undefined || !safe_to_read(tw, d)) { d.fixed = false; } else if (d.fixed) { - value = this.fixed_value(); + var value = this.fixed_value(); var recursive = recursive_ref(tw, d); if (recursive) { d.recursive_refs++; @@ -5140,13 +5150,6 @@ merge(Compressor.prototype, { return rhs.right; } - function cross_scope(def, sym) { - do { - if (def === sym) return false; - if (sym instanceof AST_Scope) return true; - } while (sym = sym.parent_scope); - } - function scan_ref_scoped(node, descend, init) { if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) { var def = node.left.definition(); @@ -8310,13 +8313,6 @@ merge(Compressor.prototype, { return lhs instanceof AST_SymbolRef || lhs.TYPE === self.TYPE; } - function find_variable(compressor, name) { - var level = 0, node; - while (node = compressor.parent(level++)) { - if (node.variables) return node.find_variable(name); - } - } - OPT(AST_Undefined, function(self, compressor) { if (compressor.option("unsafe_undefined")) { var undef = find_scope(compressor).find_variable("undefined"); diff --git a/lib/scope.js b/lib/scope.js index 209ac235..ec2c1f6d 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -196,7 +196,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { var sym = node.scope.find_variable(name); if (!sym) { sym = self.def_global(node); - } else if (sym.scope instanceof AST_Lambda && name == "arguments") { + } else if (name == "arguments" && sym.scope instanceof AST_Lambda) { sym.scope.uses_arguments = true; } if (name == "eval") { diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 414d6646..ea3703c1 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -7535,3 +7535,69 @@ global_assign: { } expect_stdout: "PASS" } + +issue_4188_1: { + options = { + reduce_vars: true, + unused: true, + } + input: { + (function() { + try { + while (A) + var a = function() {}, b = a; + } catch (a) { + console.log(function() { + return typeof a; + }(), typeof b); + } + })(); + } + expect: { + (function() { + try { + while (A) + var a = function() {}, b = a; + } catch (a) { + console.log(function() { + return typeof a; + }(), typeof b); + } + })(); + } + expect_stdout: "object undefined" +} + +issue_4188_2: { + options = { + reduce_vars: true, + unused: true, + } + input: { + (function() { + try { + throw 42; + } catch (a) { + console.log(function() { + return typeof a; + }(), typeof b); + } + while (!console) + var a = function() {}, b = a; + })(); + } + expect: { + (function() { + try { + throw 42; + } catch (a) { + console.log(function() { + return typeof a; + }(), typeof b); + } + while (!console) + var a = function() {}, b = a; + })(); + } + expect_stdout: "number undefined" +}