From 6fa3fbeae84200c90ff47dde03545742a861be17 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Mon, 29 Jan 2018 15:13:25 +0800 Subject: [PATCH] compress chained compound assignments (#2850) --- lib/compress.js | 63 ++++++++++++++++++----- test/compress/collapse_vars.js | 11 ++-- test/compress/reduce_vars.js | 94 ++++++++++++++++++++++++++-------- 3 files changed, 125 insertions(+), 43 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 07128aff..81af151b 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -320,6 +320,7 @@ merge(Compressor.prototype, { function reset_def(compressor, def) { def.assignments = 0; + def.chained = false; def.direct_access = false; def.escaped = false; if (def.scope.uses_eval || def.scope.uses_with) { @@ -485,19 +486,27 @@ merge(Compressor.prototype, { }); def(AST_Assign, function(tw) { var node = this; - if (node.operator != "=" || !(node.left instanceof AST_SymbolRef)) return; + if (!(node.left instanceof AST_SymbolRef)) return; var d = node.left.definition(); - if (safe_to_assign(tw, d, node.right)) { - d.references.push(node.left); - d.assignments++; - d.fixed = function() { - return node.right; - }; - mark(tw, d, false); - node.right.walk(tw); - mark(tw, d, true); - return true; - } + var fixed = d.fixed; + if (!fixed && node.operator != "=") return; + if (!safe_to_assign(tw, d, node.right)) return; + d.references.push(node.left); + d.assignments++; + if (node.operator != "=") d.chained = true; + d.fixed = node.operator == "=" ? function() { + return node.right; + } : function() { + return make_node(AST_Binary, node, { + operator: node.operator.slice(0, -1), + left: fixed instanceof AST_Node ? fixed : fixed(), + right: node.right + }); + }; + mark(tw, d, false); + node.right.walk(tw); + mark(tw, d, true); + return true; }); def(AST_Binary, function(tw) { if (!lazy_op(this.operator)) return; @@ -672,6 +681,32 @@ merge(Compressor.prototype, { if (this.bfinally) this.bfinally.walk(tw); return true; }); + def(AST_Unary, function(tw, descend) { + var node = this; + if (node.operator != "++" && node.operator != "--") return; + if (!(node.expression instanceof AST_SymbolRef)) return; + var d = node.expression.definition(); + var fixed = d.fixed; + if (!fixed) return; + if (!safe_to_assign(tw, d, true)) return; + d.references.push(node.expression); + d.assignments++; + d.chained = true; + d.fixed = function() { + return make_node(AST_Binary, node, { + operator: node.operator.slice(0, -1), + left: make_node(AST_UnaryPrefix, node, { + operator: "+", + expression: fixed instanceof AST_Node ? fixed : fixed() + }), + right: make_node(AST_Number, node, { + value: 1 + }) + }); + }; + mark(tw, d, true); + return true; + }); def(AST_VarDef, function(tw, descend) { var node = this; var d = node.name.definition(); @@ -2946,7 +2981,7 @@ merge(Compressor.prototype, { if (def.value.has_side_effects(compressor)) { def.value.walk(tw); } - if (def.name.fixed_value() === def.value) { + if (!node_def.chained && def.name.fixed_value() === def.value) { fixed_ids[node_def.id] = def; } } @@ -3164,7 +3199,7 @@ merge(Compressor.prototype, { && self.variables.get(sym.name) === (node_def = sym.definition())) { if (node instanceof AST_Assign) { node.right.walk(tw); - if (node.left.fixed_value() === node.right) { + if (!node_def.chained && node.left.fixed_value() === node.right) { fixed_ids[node_def.id] = node; } } diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js index 970f822e..4172b33b 100644 --- a/test/compress/collapse_vars.js +++ b/test/compress/collapse_vars.js @@ -52,13 +52,8 @@ collapse_vars_side_effects_1: { console.log.bind(console)(s.charAt(i++), s.charAt(i++), s.charAt(i++), 7); } function f2() { - var log = console.log.bind(console), - s = "abcdef", - i = 2, - x = s.charAt(i++), - y = s.charAt(i++), - z = s.charAt(i++); - log(x, i, y, z, 7); + var s = "abcdef", i = 2; + console.log.bind(console)(s.charAt(i++), 5, s.charAt(i++), s.charAt(i++), 7); } function f3() { var s = "abcdef", @@ -72,7 +67,7 @@ collapse_vars_side_effects_1: { var i = 10, x = i += 2, y = i += 3; - console.log.bind(console)(x, i += 4, y, i); + console.log.bind(console)(x, i += 4, y, 19); } f1(), f2(), f3(), f4(); } diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 4009c35b..2231587d 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -76,14 +76,12 @@ modified: { console.log(a + 1); console.log(b + 1); } - function f1() { var a = 1, b = 2; --b; console.log(a + 1); console.log(b + 1); } - function f2() { var a = 1, b = 2, c = 3; b = c; @@ -92,7 +90,6 @@ modified: { console.log(a + c); console.log(a + b + c); } - function f3() { var a = 1, b = 2, c = 3; b *= c; @@ -101,7 +98,6 @@ modified: { console.log(a + c); console.log(a + b + c); } - function f4() { var a = 1, b = 2, c = 3; if (a) { @@ -114,28 +110,26 @@ modified: { console.log(a + c); console.log(a + b + c); } - function f5(a) { B = a; - console.log(A ? 'yes' : 'no'); - console.log(B ? 'yes' : 'no'); + console.log(typeof A ? "yes" : "no"); + console.log(typeof B ? "yes" : "no"); } + f0(), f1(), f2(), f3(), f4(), f5(); } expect: { function f0() { var b = 2; b++; console.log(2); - console.log(b + 1); + console.log(4); } - function f1() { var b = 2; --b; console.log(2); - console.log(b + 1); + console.log(2); } - function f2() { 3; console.log(4); @@ -143,16 +137,14 @@ modified: { console.log(4); console.log(7); } - function f3() { var b = 2; b *= 3; - console.log(1 + b); - console.log(b + 3); + console.log(7); + console.log(9); console.log(4); - console.log(1 + b + 3); + console.log(10); } - function f4() { var b = 2, c = 3; b = c; @@ -161,13 +153,33 @@ modified: { console.log(1 + c); console.log(1 + b + c); } - function f5(a) { B = a; - console.log(A ? 'yes' : 'no'); - console.log(B ? 'yes' : 'no'); + console.log(typeof A ? "yes" : "no"); + console.log(typeof B ? "yes" : "no"); } + f0(), f1(), f2(), f3(), f4(), f5(); } + expect_stdout: [ + "2", + "4", + "2", + "2", + "4", + "6", + "4", + "7", + "7", + "9", + "4", + "10", + "4", + "6", + "4", + "7", + "yes", + "yes", + ] } unsafe_evaluate: { @@ -745,7 +757,7 @@ iife: { expect: { !function(a, b, c) { b++; - console.log(0, 1 * b, 5); + console.log(0, 3, 5); }(1, 2, 3); } expect_stdout: true @@ -766,7 +778,7 @@ iife_new: { expect: { var A = new function(a, b, c) { b++; - console.log(0, 1 * b, 5); + console.log(0, 3, 5); }(1, 2, 3); } expect_stdout: true @@ -5383,3 +5395,43 @@ issue_2836: { } expect_stdout: "PASS" } + +lvalues_def_1: { + options = { + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + var b = 1; + var a = b++, b = NaN; + console.log(a, b); + } + expect: { + var b = 1; + var a = b++; + b = NaN; + console.log(a, b); + } + expect_stdout: "1 NaN" +} + +lvalues_def_2: { + options = { + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + var b = 1; + var a = b += 1, b = NaN; + console.log(a, b); + } + expect: { + var b = 1; + var a = b += 1; + b = NaN; + console.log(a, b); + } + expect_stdout: "2 NaN" +} -- 2.34.1