From 2a49760032dea89032d6bc82dabab5e9e53bb310 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Wed, 3 Mar 2021 10:47:17 +0000 Subject: [PATCH] enhance `side_effects` (#4727) --- lib/compress.js | 61 +++++++++++++++++++++------------- test/compress/collapse_vars.js | 10 +++--- test/compress/issue-281.js | 20 +++++++---- test/compress/merge_vars.js | 4 +-- test/compress/reduce_vars.js | 6 ++-- test/compress/sequences.js | 8 ++--- 6 files changed, 65 insertions(+), 44 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 1b22d861..99e67b91 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -4797,9 +4797,15 @@ merge(Compressor.prototype, { || this.right.has_side_effects(compressor); }); def(AST_Binary, function(compressor) { - return this.left.has_side_effects(compressor) - || this.right.has_side_effects(compressor) - || this.operator == "in" && !is_object(this.right); + var lhs = this.left; + if (lhs.has_side_effects(compressor)) return true; + var rhs = this.right; + var op = this.operator; + if (!rhs.has_side_effects(compressor)) return op == "in" && !is_object(rhs); + if (op == "&&" && rhs instanceof AST_PropAccess && lhs.equivalent_to(rhs.expression)) { + return rhs instanceof AST_Sub && rhs.property.has_side_effects(compressor); + } + return true; }); def(AST_Block, function(compressor) { return any(this.body, compressor); @@ -7208,33 +7214,42 @@ merge(Compressor.prototype, { return node; }); def(AST_Binary, function(compressor, first_in_statement) { - if (this.operator == "in" && !is_object(this.right)) { - var left = this.left.drop_side_effect_free(compressor, first_in_statement); - if (left === this.left) return this; + var left = this.left; + var right = this.right; + var op = this.operator; + if (op == "in" && !is_object(right)) { + var lhs = left.drop_side_effect_free(compressor, first_in_statement); + if (lhs === left) return this; var node = this.clone(); - node.left = left || make_node(AST_Number, this.left, { - value: 0 - }); + node.left = lhs || make_node(AST_Number, left, { value: 0 }); return node; } - var right = this.right.drop_side_effect_free(compressor, first_in_statement); - if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement); - if (lazy_op[this.operator] && !(right instanceof AST_Function)) { + var rhs = right.drop_side_effect_free(compressor, first_in_statement); + if (!rhs) return left.drop_side_effect_free(compressor, first_in_statement); + if (lazy_op[op] && !(rhs instanceof AST_Function)) { var node = this; - if (right !== node.right) { - node = this.clone(); - node.right = right.drop_side_effect_free(compressor); - } - if (this.operator == "??") return node; + if (op == "&&" + && rhs instanceof AST_PropAccess + && left.equivalent_to(rhs.expression) + && !left.has_side_effects(compressor)) { + var prop = rhs instanceof AST_Sub && rhs.property.drop_side_effect_free(compressor); + if (!prop) return left.drop_side_effect_free(compressor, first_in_statement); + node = node.clone(); + node.right = prop; + } else if (rhs !== right) { + node = node.clone(); + node.right = rhs.drop_side_effect_free(compressor); + } + if (op == "??") return node; return (first_in_statement ? best_of_statement : best_of_expression)(node, make_node(AST_Binary, this, { - operator: node.operator == "&&" ? "||" : "&&", - left: node.left.negate(compressor, first_in_statement), - right: node.right + operator: op == "&&" ? "||" : "&&", + left: left.negate(compressor, first_in_statement), + right: node.right, })); } else { - var left = this.left.drop_side_effect_free(compressor, first_in_statement); - if (!left) return right; - return make_sequence(this, [ left, right.drop_side_effect_free(compressor) ]); + var lhs = left.drop_side_effect_free(compressor, first_in_statement); + if (!lhs) return rhs; + return make_sequence(this, [ lhs, rhs.drop_side_effect_free(compressor) ]); } }); def(AST_Call, function(compressor, first_in_statement) { diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js index fe963b4a..c0a545c5 100644 --- a/test/compress/collapse_vars.js +++ b/test/compress/collapse_vars.js @@ -2863,7 +2863,7 @@ lvalues_def: { expect: { var a = 0, b = 1; a = b++, b = +void 0; - a && a[a++]; + a && a++; console.log(a, b); } expect_stdout: true @@ -5098,7 +5098,7 @@ issue_2878: { } b = f2(); a = 1; - b && b.b; + b && b[console]; f2(); })(); console.log(c); @@ -5111,7 +5111,7 @@ issue_2878: { } b = f2(), a = 1, - b && b.b, + b && console, f2(); })(), console.log(c); @@ -6546,7 +6546,7 @@ issue_3520: { (function f() { c = 0; var i = void 0; - var f = f && f[i]; + var f = f && f[console && i]; })(); a += b; c && b++; @@ -6560,7 +6560,7 @@ issue_3520: { for (var i = 2; --i >= 0;) { (function() { c = 0; - var f = f && f[void 0]; + var f = f && f[console && void 0]; })(); a += b; c && b++; diff --git a/test/compress/issue-281.js b/test/compress/issue-281.js index 1c339bcd..797f7d9b 100644 --- a/test/compress/issue-281.js +++ b/test/compress/issue-281.js @@ -463,15 +463,19 @@ drop_fargs: { var a = 1; !function(a_1) { a++; - }(a++ + (a && a.var)); + }(a++ + (a && console.log(a))); console.log(a); } expect: { var a = 1; - ++a && a.var, a++; + ++a && console.log(a), + a++; console.log(a); } - expect_stdout: "3" + expect_stdout: [ + "2", + "3", + ] } keep_fargs: { @@ -486,13 +490,17 @@ keep_fargs: { var a = 1; !function(a_1) { a++; - }(a++ + (a && a.var)); + }(a++ + (a && console.log(a))); console.log(a); } expect: { var a = 1; - ++a && a.var, a++; + ++a && console.log(a), + a++; console.log(a); } - expect_stdout: "3" + expect_stdout: [ + "2", + "3", + ] } diff --git a/test/compress/merge_vars.js b/test/compress/merge_vars.js index c45f8353..667cacf8 100644 --- a/test/compress/merge_vars.js +++ b/test/compress/merge_vars.js @@ -2723,7 +2723,7 @@ issue_4135: { var c = function() { var d = 0; function f() { - d && d.p; + d && d[console]; } f(); this; @@ -2735,7 +2735,7 @@ issue_4135: { 0; a++; if (!a) - c = (a++, c = 0, void (c && c.p)); + c = (a++, c = 0, void (c && console)); var c; console.log(a, -1, c); } diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 5ae0884b..110f046a 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -2554,7 +2554,7 @@ side_effects_assign: { console.log(a); } expect: { - var a = typeof void (a && a.in); + var a = "undefined"; console.log(a); } expect_stdout: "undefined" @@ -2595,9 +2595,7 @@ pure_getters_2: { var a; var a = a && a.b; } - expect: { - var a = a && a.b; - } + expect: {} } pure_getters_3: { diff --git a/test/compress/sequences.js b/test/compress/sequences.js index b8190366..a9dbc707 100644 --- a/test/compress/sequences.js +++ b/test/compress/sequences.js @@ -745,12 +745,12 @@ issue_2062: { } input: { var a = 1; - if ([ a || a++ + a--, a++ + a--, a && a.var ]); + if ([ a || a++ + a--, a++ + a--, a && a[console] ]); console.log(a); } expect: { var a = 1; - a || (a++, a--), a++, --a && a.var; + a || (a++, a--), a++, --a && console; console.log(a); } expect_stdout: "1" @@ -1088,7 +1088,7 @@ issue_3490_1: { if ({ 3: function() { var a; - return (a && a.p) < this; + return (a && a[console]) < this; }(), }) c = "PASS"; if (b) while ("" == typeof d); @@ -1098,7 +1098,7 @@ issue_3490_1: { var b = 42, c = "FAIL"; if (function() { var a; - a && a.p; + a && console; }(), c = "PASS", b) while ("" == typeof d); console.log(c, b); } -- 2.34.1