From 4bd36dc8da23ad31eba45376e861784ba8568379 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Wed, 13 Nov 2019 21:44:44 +0800 Subject: [PATCH] enhance `unused` (#3584) --- lib/compress.js | 81 +++++++++++++++++++++--------------- test/compress/drop-unused.js | 46 +++++++++++++------- test/compress/functions.js | 2 +- 3 files changed, 78 insertions(+), 51 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 92e8d3a3..e97427bc 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -3727,10 +3727,20 @@ merge(Compressor.prototype, { }); } if (value) { - props.push(value); - return maintain_this_binding(compressor, parent, node, make_sequence(node, props.map(function(prop) { - return prop.transform(tt); - }))); + if (parent instanceof AST_Sequence && parent.tail_node() !== node) { + value = value.drop_side_effect_free(compressor); + } + if (value) props.push(value); + switch (props.length) { + case 0: + return MAP.skip; + case 1: + return maintain_this_binding(compressor, parent, node, props[0].transform(tt)); + default: + return make_sequence(node, props.map(function(prop) { + return prop.transform(tt); + })); + } } } } @@ -3874,37 +3884,10 @@ merge(Compressor.prototype, { }); } } - // certain combination of unused name + side effect leads to: - // https://github.com/mishoo/UglifyJS2/issues/44 - // https://github.com/mishoo/UglifyJS2/issues/1830 - // https://github.com/mishoo/UglifyJS2/issues/1838 - // https://github.com/mishoo/UglifyJS2/issues/3371 - // that's an invalid AST. - // We fix it at this stage by moving the `var` outside the `for`. - if (node instanceof AST_For) { - descend(node, this); - var block; - if (node.init instanceof AST_BlockStatement) { - block = node.init; - node.init = block.body.pop(); - block.body.push(node); - } - if (node.init instanceof AST_Defun) { - if (!block) { - block = make_node(AST_BlockStatement, node, { - body: [ node ] - }); - } - block.body.splice(-1, 0, node.init); - node.init = null; - } else if (node.init instanceof AST_SimpleStatement) { - node.init = node.init.body; - } else if (is_empty(node.init)) { - node.init = null; - } - return !block ? node : in_list ? MAP.splice(block.body) : block; - } if (node instanceof AST_LabeledStatement && node.body instanceof AST_For) { + // Certain combination of unused name + side effect leads to invalid AST: + // https://github.com/mishoo/UglifyJS2/issues/1830 + // We fix it at this stage by moving the label inwards, back to the `for`. descend(node, this); if (node.body instanceof AST_BlockStatement) { var block = node.body; @@ -3934,6 +3917,36 @@ merge(Compressor.prototype, { col : sym.start.col }; } + }, function(node, in_list) { + if (node instanceof AST_For) { + // Certain combination of unused name + side effect leads to invalid AST: + // https://github.com/mishoo/UglifyJS2/issues/44 + // https://github.com/mishoo/UglifyJS2/issues/1838 + // https://github.com/mishoo/UglifyJS2/issues/3371 + // We fix it at this stage by moving the `var` outside the `for`. + var block; + if (node.init instanceof AST_BlockStatement) { + block = node.init; + node.init = block.body.pop(); + block.body.push(node); + } + if (node.init instanceof AST_Defun) { + if (!block) { + block = make_node(AST_BlockStatement, node, { + body: [ node ] + }); + } + block.body.splice(-1, 0, node.init); + node.init = null; + } else if (node.init instanceof AST_SimpleStatement) { + node.init = node.init.body; + } else if (is_empty(node.init)) { + node.init = null; + } + return !block ? node : in_list ? MAP.splice(block.body) : block; + } else if (node instanceof AST_Sequence) { + if (node.expressions.length == 1) return node.expressions[0]; + } }); tt.push(compressor.parent()); self.transform(tt); diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js index 7cb2e899..297fa01a 100644 --- a/test/compress/drop-unused.js +++ b/test/compress/drop-unused.js @@ -1019,14 +1019,21 @@ delete_assign_1: { console.log(delete (a = 0 / 0)); } expect: { - console.log((void 0, !0)); - console.log((void 0, !0)); - console.log((1 / 0, !0)); - console.log((1 / 0, !0)); - console.log((NaN, !0)); - console.log((NaN, !0)); + console.log(!0); + console.log(!0); + console.log(!0); + console.log(!0); + console.log(!0); + console.log(!0); } - expect_stdout: true + expect_stdout: [ + "true", + "true", + "true", + "true", + "true", + "true", + ] } delete_assign_2: { @@ -1047,14 +1054,21 @@ delete_assign_2: { console.log(delete (a = 0 / 0)); } expect: { - console.log((void 0, !0)); - console.log((void 0, !0)); - console.log((Infinity, !0)); - console.log((1 / 0, !0)); - console.log((NaN, !0)); - console.log((NaN, !0)); + console.log(!0); + console.log(!0); + console.log(!0); + console.log(!0); + console.log(!0); + console.log(!0); } - expect_stdout: true + expect_stdout: [ + "true", + "true", + "true", + "true", + "true", + "true", + ] } drop_var: { @@ -1635,7 +1649,7 @@ double_assign_2: { } expect: { for (var i = 0; i < 2; i++) - void 0, a = {}, console.log(a); + a = {}, console.log(a); var a; } } @@ -1716,7 +1730,7 @@ issue_2768: { } expect: { var a = "FAIL"; - var c = (d = a, 0, void (d && (a = "PASS"))); + var c = (d = a, void (d && (a = "PASS"))); var d; console.log(a, typeof c); } diff --git a/test/compress/functions.js b/test/compress/functions.js index e36176bd..6c86c1c5 100644 --- a/test/compress/functions.js +++ b/test/compress/functions.js @@ -2346,7 +2346,7 @@ issue_3274: { } expect: { (function() { - for (var c; void 0, (c = 1..p) != c;) + for (var c; (c = 1..p) != c;) console.log("FAIL"); console.log("PASS"); })(); -- 2.34.1