From 53a243cacdd12054fb97cb8b6c454ac21653504c Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Tue, 30 Aug 2022 00:52:02 +0800 Subject: [PATCH] enhance `reduce_vars` --- lib/compress.js | 66 ++++++++++++++++++++------------- test/compress/collapse_vars.js | 5 +-- test/compress/default-values.js | 2 +- test/compress/drop-unused.js | 12 +++--- test/compress/hoist_vars.js | 2 +- test/compress/reduce_vars.js | 7 ++-- 6 files changed, 54 insertions(+), 40 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 14a36c24832..da962152abc 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -621,8 +621,14 @@ Compressor.prototype.compress = function(node) { scope.may_call_this = undefined; } - function push(tw) { - tw.safe_ids = Object.create(tw.safe_ids); + function push(tw, sequential) { + var safe_ids = Object.create(tw.safe_ids); + if (sequential) { + safe_ids.seq.push(safe_ids); + } else { + safe_ids.seq = [ safe_ids ]; + } + tw.safe_ids = safe_ids; } function pop(tw) { @@ -643,7 +649,14 @@ Compressor.prototype.compress = function(node) { var safe = tw.safe_ids[def.id]; if (safe) { var in_order = HOP(tw.safe_ids, def.id); - if (!in_order) safe.read = safe.read && safe.read !== tw.safe_ids ? true : tw.safe_ids; + if (!in_order) { + var seq = tw.safe_ids.seq; + if (!safe.read) { + safe.read = seq; + } else if (safe.read !== seq) { + safe.read = true; + } + } if (def.fixed == null) { if (is_arguments(def)) return false; if (def.global && def.name == "arguments") return false; @@ -684,7 +697,8 @@ Compressor.prototype.compress = function(node) { safe.assign = safe.assign && safe.assign !== tw.safe_ids ? true : tw.safe_ids; } if (def.fixed != null && safe.read) { - if (safe.read !== tw.safe_ids) return false; + if (safe.read === true) return false; + if (!member(tw.safe_ids, safe.read)) return false; if (tw.loop_ids[def.id] !== tw.in_loop) return false; } return safe_to_read(tw, def) && all(def.orig, function(sym) { @@ -810,7 +824,7 @@ Compressor.prototype.compress = function(node) { var scanner = new TreeWalker(function(node) { if (node instanceof AST_DefaultValue) { reset_flags(node); - push(tw); + push(tw, true); node.value.walk(tw); pop(tw); var save = fixed; @@ -899,14 +913,15 @@ Compressor.prototype.compress = function(node) { var fn = this; fn.inlined = false; var iife = tw.parent(); - var hit = is_async(fn) || is_generator(fn); + var sequential = !is_async(fn) && !is_generator(fn); + var hit = !sequential; var aborts = false; fn.walk(new TreeWalker(function(node) { if (hit) return aborts = true; if (node instanceof AST_Return) return hit = true; if (node instanceof AST_Scope && node !== fn) return true; })); - if (aborts) push(tw); + if (aborts) push(tw, sequential); reset_variables(tw, compressor, fn); // Virtually turn IIFE parameters into variable definitions: // (function(a,b) {...})(c,d) ---> (function() {var a=c,b=d; ...})() @@ -991,7 +1006,7 @@ Compressor.prototype.compress = function(node) { return walk_lazy(); } var safe = safe_to_read(tw, ld); - if (lazy) push(tw); + if (lazy) push(tw, true); right.walk(tw); if (lazy) pop(tw); if (safe && !left.in_arg && safe_to_assign(tw, ld)) { @@ -1073,7 +1088,7 @@ Compressor.prototype.compress = function(node) { function walk_lazy() { if (!lazy) return; left.walk(tw); - push(tw); + push(tw, true); right.walk(tw); pop(tw); return true; @@ -1082,7 +1097,7 @@ Compressor.prototype.compress = function(node) { def(AST_Binary, function(tw) { if (!lazy_op[this.operator]) return; this.left.walk(tw); - push(tw); + push(tw, true); this.right.walk(tw); pop(tw); return true; @@ -1112,7 +1127,7 @@ Compressor.prototype.compress = function(node) { } exp.walk(tw); var optional = node.optional; - if (optional) push(tw); + if (optional) push(tw, true); node.args.forEach(function(arg) { arg.walk(tw); }); @@ -1182,7 +1197,7 @@ Compressor.prototype.compress = function(node) { }); def(AST_ClassInitBlock, function(tw, descend, compressor) { var node = this; - push(tw); + push(tw, true); reset_variables(tw, compressor, node); descend(); pop_scope(tw, node); @@ -1190,19 +1205,19 @@ Compressor.prototype.compress = function(node) { }); def(AST_Conditional, function(tw) { this.condition.walk(tw); - push(tw); + push(tw, true); this.consequent.walk(tw); pop(tw); - push(tw); + push(tw, true); this.alternative.walk(tw); pop(tw); return true; }); def(AST_DefaultValue, function(tw) { - this.name.walk(tw); - push(tw); + push(tw, true); this.value.walk(tw); pop(tw); + this.name.walk(tw); return true; }); def(AST_Do, function(tw) { @@ -1274,18 +1289,18 @@ Compressor.prototype.compress = function(node) { }); def(AST_If, function(tw) { this.condition.walk(tw); - push(tw); + push(tw, true); this.body.walk(tw); pop(tw); if (this.alternative) { - push(tw); + push(tw, true); this.alternative.walk(tw); pop(tw); } return true; }); def(AST_LabeledStatement, function(tw) { - push(tw); + push(tw, true); this.body.walk(tw); pop(tw); return true; @@ -1319,7 +1334,7 @@ Compressor.prototype.compress = function(node) { def(AST_Sub, function(tw) { if (!this.optional) return; this.expression.walk(tw); - push(tw); + push(tw, true); this.property.walk(tw); pop(tw); return true; @@ -1334,7 +1349,7 @@ Compressor.prototype.compress = function(node) { branch.expression.walk(tw); if (first) { first = false; - push(tw); + push(tw, true); } }) if (!first) pop(tw); @@ -1342,7 +1357,7 @@ Compressor.prototype.compress = function(node) { return true; }); def(AST_SwitchBranch, function(tw) { - push(tw); + push(tw, true); walk_body(this, tw); pop(tw); return true; @@ -1452,7 +1467,7 @@ Compressor.prototype.compress = function(node) { node.globals.each(function(def) { reset_def(tw, compressor, def); }); - push(tw); + push(tw, true); reset_variables(tw, compressor, node); descend(); pop_scope(tw, node); @@ -1461,11 +1476,11 @@ Compressor.prototype.compress = function(node) { def(AST_Try, function(tw, descend, compressor) { var node = this; reset_block_variables(tw, compressor, node); - push(tw); + push(tw, true); walk_body(node, tw); pop(tw); if (node.bcatch) { - push(tw); + push(tw, true); node.bcatch.walk(tw); pop(tw); } @@ -1590,6 +1605,7 @@ Compressor.prototype.compress = function(node) { // - `push()` & `pop()` when visiting conditional branches // - backup & restore via `save_ids` when visiting out-of-order sections tw.safe_ids = Object.create(null); + tw.safe_ids.seq = [ tw.safe_ids ]; this.walk(tw); }); diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js index 0e19d579570..4c705abc242 100644 --- a/test/compress/collapse_vars.js +++ b/test/compress/collapse_vars.js @@ -9321,12 +9321,11 @@ issue_4874: { })(a = 42); } expect: { - var a; null; (function(b) { - for (var c in a && a[console.log("PASS")]) + for (var c in 42, 42[console.log("PASS")]) console; - })(a = 42); + })(); } expect_stdout: "PASS" } diff --git a/test/compress/default-values.js b/test/compress/default-values.js index 49b9b7fa803..ac2be8400d7 100644 --- a/test/compress/default-values.js +++ b/test/compress/default-values.js @@ -2505,7 +2505,7 @@ issue_5463: { var a, b, b; console.log("PASS") && ( b = a = void 0, - b = [a = FAIL] = a && a + b = [a = FAIL] = a ); } expect_stdout: "PASS" diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js index 1f4d2c921dd..fffa69419f3 100644 --- a/test/compress/drop-unused.js +++ b/test/compress/drop-unused.js @@ -1878,7 +1878,7 @@ issue_2846: { var c = function(a, b) { a = 0; b && b(a); - return a++; + return +a; }(); console.log(c); } @@ -2976,14 +2976,12 @@ issue_4025: { console.log(a, b, d); } expect: { - var c = 0; try { - console.log(c); + console.log(0); } finally { - var d = c + 1; - c = 0; + 0; } - console.log(1, 1, d); + console.log(1, 1, 1); } expect_stdout: [ "0", @@ -3696,7 +3694,7 @@ issue_5224: { (function() { var a = "FAIL 1"; null; - a = console.log(a); + console.log(a); })(function() { console.log(1 / 0); a; diff --git a/test/compress/hoist_vars.js b/test/compress/hoist_vars.js index cc24f5887a1..d0a73d49c56 100644 --- a/test/compress/hoist_vars.js +++ b/test/compress/hoist_vars.js @@ -624,7 +624,7 @@ issue_5411_2: { var b, c; b++; b = "PASS", - c = c && c[b]; + c; console.log(b); } expect_stdout: "PASS" diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 002202617dc..885887ede31 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -2488,7 +2488,7 @@ side_effects_assign: { console.log(a); } expect: { - var a = typeof void (a && a.in); + var a = "undefined"; console.log(a); } expect_stdout: "undefined" @@ -2530,7 +2530,8 @@ pure_getters_2: { var a = a && a.b; } expect: { - var a = a && a.b; + var a; + a && a.b; } } @@ -5424,7 +5425,7 @@ issue_2774: { get a() { var b; (b = true) && b.c; - b = void 0; + void 0; } }.a); }