From 53b57ee57e3d00792f70685e6b4531e6d990ca27 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sat, 1 May 2021 17:19:56 +0100 Subject: [PATCH] enhance `reduce_vars` & `unused` (#4890) --- lib/compress.js | 26 +++--- test/compress/functions.js | 170 ++++++++++++++++++++++++++++++++++++- test/compress/ie8.js | 4 +- 3 files changed, 184 insertions(+), 16 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 9201d890c8..f4aa62d44a 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -610,6 +610,11 @@ merge(Compressor.prototype, { function is_immutable(value) { if (!value) return false; + if (value instanceof AST_Assign) { + var op = value.operator; + return op == "=" ? is_immutable(value.right) : !lazy_op[op.slice(0, -1)]; + } + if (value instanceof AST_Sequence) return is_immutable(value.tail_node()); return value.is_constant() || is_lambda(value) || value instanceof AST_ObjectIdentity; } @@ -901,6 +906,7 @@ merge(Compressor.prototype, { function walk_assign() { right.walk(tw); + var modified = is_modified(compressor, tw, node, right, 0, is_immutable(right), recursive_ref(tw, d)); scan_declaration(tw, compressor, left, function() { return node.right; }, function(sym, fixed, walk) { @@ -911,10 +917,7 @@ merge(Compressor.prototype, { } var d = sym.definition(); d.assignments++; - if (fixed - && !is_modified(compressor, tw, node, right, 0, is_immutable(right), recursive_ref(tw, d)) - && !sym.in_arg - && safe_to_assign(tw, d)) { + if (fixed && !modified && !sym.in_arg && safe_to_assign(tw, d)) { push_ref(d, sym); mark(tw, d); if (d.single_use && left instanceof AST_Destructured) d.single_use = false; @@ -6299,18 +6302,13 @@ merge(Compressor.prototype, { var drop_sym = is_var ? can_drop_symbol(def.name) : is_safe_lexical(sym); if (!drop_sym || !drop_vars || sym.id in in_use_ids) { if (value && indexOf_assign(sym, def) < 0) { - var write_only = value.write_only; value = value.drop_side_effect_free(compressor); - if (def.value !== value) { - if (value) { - AST_Node.warn("Side effects in last use of variable {name} [{file}:{line},{col}]", template(def.name)); - side_effects.push(value); - } - value = null; - trim_defns.push(def); - } else if (value.write_only !== write_only) { - value.write_only = write_only; + if (value) { + AST_Node.warn("Side effects in last use of variable {name} [{file}:{line},{col}]", template(def.name)); + side_effects.push(value); } + value = null; + trim_defns.push(def); } var old_def; if (!value && !(node instanceof AST_Let)) { diff --git a/test/compress/functions.js b/test/compress/functions.js index a9a3b8f611..5713a37b44 100644 --- a/test/compress/functions.js +++ b/test/compress/functions.js @@ -6013,7 +6013,7 @@ issue_4823: { console.log(typeof function() { { function f() {} - arguments = f(); + f(); var arguments = function() {}; } return f && arguments; @@ -6040,3 +6040,171 @@ drop_unused_self_reference: { } expect_stdout: "PASS" } + +reduce_cross_reference_1: { + options = { + passes: 3, + pure_getters: "strict", + reduce_vars: true, + sequences: true, + side_effects: true, + unused: true, + } + input: { + (function(a, b) { + a = b = function() {}; + a.p = a; + b = a = function() {}; + b.q = b; + })(); + } + expect: {} + expect_stdout: true +} + +reduce_cross_reference_1_toplevel: { + options = { + passes: 2, + pure_getters: "strict", + reduce_vars: true, + sequences: true, + side_effects: true, + toplevel: true, + unused: true, + } + input: { + var a = b = function() {}; + a.p = a; + var b = a = function() {}; + b.q = b; + } + expect: {} + expect_stdout: true +} + +reduce_cross_reference_2: { + options = { + collapse_vars: true, + passes: 3, + pure_getters: "strict", + reduce_vars: true, + sequences: true, + side_effects: true, + unused: true, + } + input: { + (function(a, b) { + a = b = function() {}; + b.p = a; + b = a = function() {}; + a.q = b; + })(); + } + expect: {} + expect_stdout: true +} + +reduce_cross_reference_2_toplevel: { + options = { + collapse_vars: true, + passes: 2, + pure_getters: "strict", + reduce_vars: true, + sequences: true, + side_effects: true, + toplevel: true, + unused: true, + } + input: { + var a = b = function() {}; + b.p = a; + var b = a = function() {}; + a.q = b; + } + expect: {} + expect_stdout: true +} + +reduce_cross_reference_3: { + options = { + collapse_vars: true, + passes: 3, + pure_getters: "strict", + reduce_vars: true, + sequences: true, + side_effects: true, + unused: true, + } + input: { + (function(a, b) { + a = b = function() {}; + a.p = b; + b = a = function() {}; + b.q = a; + })(); + } + expect: {} + expect_stdout: true +} + +reduce_cross_reference_3_toplevel: { + options = { + collapse_vars: true, + passes: 2, + pure_getters: "strict", + reduce_vars: true, + sequences: true, + side_effects: true, + toplevel: true, + unused: true, + } + input: { + var a = b = function() {}; + a.p = b; + var b = a = function() {}; + b.q = a; + } + expect: {} + expect_stdout: true +} + +reduce_cross_reference_4: { + options = { + passes: 3, + pure_getters: "strict", + reduce_vars: true, + sequences: true, + side_effects: true, + unused: true, + } + input: { + (function(a, b) { + a = b = function() {}; + b.p = b; + b = a = function() {}; + a.q = a; + })(); + } + expect: {} + expect_stdout: true +} + +reduce_cross_reference_4_toplevel: { + options = { + passes: 2, + pure_getters: "strict", + reduce_vars: true, + sequences: true, + side_effects: true, + toplevel: true, + unused: true, + } + input: { + var a = b = function() {}; + b.p = b; + var b = a = function() {}; + a.q = a; + } + expect: {} + expect_stdout: true +} diff --git a/test/compress/ie8.js b/test/compress/ie8.js index a1daa59c81..2353296891 100644 --- a/test/compress/ie8.js +++ b/test/compress/ie8.js @@ -2653,7 +2653,9 @@ issue_4019: { try { console.log("FAIL"); } catch (o) {} - }, o = (console.log(o.length), ++o); + }; + console.log(o.length), + ++o; } expect_stdout: "0" }