diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2020-12-24 09:02:18 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-24 17:02:18 +0800 |
commit | 18966945324786d29def134662221a068297161d (patch) | |
tree | 9cd23edc4262ff7ab0d8b32a9b315a9788abc56d | |
parent | 5f269cd57356fc4dbe7486dca22902d22695d499 (diff) | |
download | tracifyjs-18966945324786d29def134662221a068297161d.tar.gz tracifyjs-18966945324786d29def134662221a068297161d.zip |
fix & enhance `collapse_vars` (#4447)
fixes #4446
-rw-r--r-- | lib/compress.js | 50 | ||||
-rw-r--r-- | test/compress/collapse_vars.js | 4 | ||||
-rw-r--r-- | test/compress/default-values.js | 38 | ||||
-rw-r--r-- | test/compress/destructured.js | 18 | ||||
-rw-r--r-- | test/reduce.js | 14 | ||||
-rw-r--r-- | test/ufuzz/index.js | 26 | ||||
-rw-r--r-- | test/ufuzz/job.js | 2 |
7 files changed, 125 insertions, 27 deletions
diff --git a/lib/compress.js b/lib/compress.js index a611bf4a..29cd26b6 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1542,7 +1542,7 @@ merge(Compressor.prototype, { && (scan_lhs && lhs.equivalent_to(node) || scan_rhs && (hit_rhs = scan_rhs(node, this)))) { if (!can_replace || stop_if_hit && (hit_rhs || !lhs_local || !replace_all)) { - if (!hit_rhs || !value_def) abort = true; + if (!hit_rhs && !value_def) abort = true; return node; } if (is_lhs(node, parent)) { @@ -1595,14 +1595,28 @@ merge(Compressor.prototype, { can_replace = false; descend(node, scanner); can_replace = replace; - return node; + return signal_abort(node); + } + // Scan but don't replace inside destructuring LHS + if (node instanceof AST_Assign && node.left instanceof AST_Destructured) { + var replace = can_replace; + can_replace = false; + node.left = node.left.transform(scanner); + can_replace = replace; + node.right = node.right.transform(scanner); + return signal_abort(node); + } + // Scan but don't replace inside default value + if (node instanceof AST_DefaultValue) { + node.name = node.name.transform(scanner); + var replace = can_replace; + can_replace = false; + node.value = node.value.transform(scanner); + can_replace = replace; + return signal_abort(node); } return handle_custom_scan_order(node, scanner); - }, function(node) { - if (abort) return; - if (stop_after === node) abort = true; - if (stop_if_hit === node) stop_if_hit = null; - }); + }, signal_abort); var multi_replacer = new TreeTransformer(function(node) { if (abort) return node; // Skip nodes before `candidate` as quickly as possible @@ -1723,6 +1737,13 @@ merge(Compressor.prototype, { } } + function signal_abort(node) { + if (abort) return node; + if (stop_after === node) abort = true; + if (stop_if_hit === node) stop_if_hit = null; + return node; + } + function handle_custom_scan_order(node, tt) { if (!(node instanceof AST_BlockScope)) return; // Skip (non-executed) functions @@ -1760,6 +1781,13 @@ merge(Compressor.prototype, { } } + function is_direct_assignment(node, parent) { + if (parent instanceof AST_Assign) return parent.operator == "=" && parent.left === node; + if (parent instanceof AST_DefaultValue) return parent.name === node; + if (parent instanceof AST_DestructuredArray) return true; + if (parent instanceof AST_DestructuredKeyVal) return parent.value === node; + } + function should_stop(node, parent) { if (node === rvalue) return true; if (parent instanceof AST_For) return node !== parent.init; @@ -1773,7 +1801,7 @@ merge(Compressor.prototype, { } if (node instanceof AST_Debugger) return true; if (node instanceof AST_Defun) return funarg && lhs.name === node.name.name; - if (node instanceof AST_Destructured) return parent instanceof AST_Assign; + if (node instanceof AST_Destructured) return (in_try || !lhs_local) && parent instanceof AST_Assign; if (node instanceof AST_DestructuredKeyVal) return node.key instanceof AST_Node; if (node instanceof AST_DWLoop) return true; if (node instanceof AST_LoopControl) return true; @@ -1784,7 +1812,7 @@ merge(Compressor.prototype, { return !(parent instanceof AST_PropAccess && parent.expression === node) && is_arguments(node.definition()); } - } else if (parent instanceof AST_Assign && parent.operator == "=" && parent.left === node) { + } else if (is_direct_assignment(node, parent)) { return false; } if (!replace_all) return true; @@ -1864,9 +1892,7 @@ merge(Compressor.prototype, { } if (node instanceof AST_Spread) return true; if (node instanceof AST_SymbolRef) { - if (symbol_in_lvalues(node, parent)) { - return !(parent instanceof AST_Assign && parent.operator == "=" && parent.left === node); - } + if (symbol_in_lvalues(node, parent)) return !is_direct_assignment(node, parent); if (side_effects && may_modify(node)) return true; var def = node.definition(); return (in_try || def.scope.resolve() !== scope) && !can_drop_symbol(node); diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js index 17ee8d10..f630883a 100644 --- a/test/compress/collapse_vars.js +++ b/test/compress/collapse_vars.js @@ -4273,8 +4273,8 @@ issue_2436_14: { var b = {}; (function() { a && function(c, d) { - console.log(c, d); - }(b, a); + console.log(b, d); + }(0, a); })(); } expect_stdout: true diff --git a/test/compress/default-values.js b/test/compress/default-values.js index 64dad3cf..8b9b3a95 100644 --- a/test/compress/default-values.js +++ b/test/compress/default-values.js @@ -974,3 +974,41 @@ issue_4444: { expect_stdout: "PASS" node_version: ">=6" } + +issue_4446_1: { + options = { + collapse_vars: true, + } + input: { + a = 42; + [ b = 42 ] = [ "PASS" ]; + c = 42; + console.log(b, a); + } + expect: { + [ b = 42 ] = [ "PASS" ]; + c = a = 42; + console.log(b, a); + } + expect_stdout: "PASS 42" + node_version: ">=6" +} + +issue_4446_2: { + options = { + collapse_vars: true, + } + input: { + a = 42; + var [ b = 42 ] = [ "PASS" ]; + c = 42; + console.log(b, a); + } + expect: { + var [ b = 42 ] = [ "PASS" ]; + c = a = 42; + console.log(b, a); + } + expect_stdout: "PASS 42" + node_version: ">=6" +} diff --git a/test/compress/destructured.js b/test/compress/destructured.js index 5594658d..7fe2f0c8 100644 --- a/test/compress/destructured.js +++ b/test/compress/destructured.js @@ -2146,3 +2146,21 @@ issue_4436_undefined: { expect_stdout: true node_version: ">=6" } + +issue_4446: { + options = { + collapse_vars: true, + } + input: { + a = "PASS"; + var a = [ a[0] ] = [ a ]; + console.log(a[0]); + } + expect: { + a = "PASS"; + var a = [ a[0] ] = [ a ]; + console.log(a[0]); + } + expect_stdout: "PASS" + node_version: ">=6" +} diff --git a/test/reduce.js b/test/reduce.js index d0797f8a..f6b54141 100644 --- a/test/reduce.js +++ b/test/reduce.js @@ -153,6 +153,20 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options) node.left, node.right, ][ permute & 1 ]; + if (expr instanceof U.AST_Destructured) expr = expr.transform(new U.TreeTransformer(function(node, descend) { + if (node instanceof U.AST_DefaultValue) return new U.AST_Assign({ + operator: "=", + left: node.name.transform(this), + right: node.value, + start: {}, + }); + if (node instanceof U.AST_DestructuredKeyVal) return new U.AST_ObjectKeyVal(node); + if (node instanceof U.AST_Destructured) { + node = new (node instanceof U.AST_DestructuredArray ? U.AST_Array : U.AST_Object)(node); + descend(node, this); + } + return node; + })); CHANGED = true; return permute < 2 ? expr : wrap_with_console_log(expr); } diff --git a/test/ufuzz/index.js b/test/ufuzz/index.js index 1d247984..d4c83d88 100644 --- a/test/ufuzz/index.js +++ b/test/ufuzz/index.js @@ -1680,18 +1680,20 @@ function log(options) { } } errorln("//-------------------------------------------------------------"); - var reduce_options = JSON.parse(options); - reduce_options.validate = true; - var reduced = reduce_test(original_code, reduce_options, { - verbose: false, - }).code; - if (reduced) { - errorln(); - errorln("// reduced test case (output will differ)"); - errorln(); - errorln(reduced); - errorln(); - errorln("//-------------------------------------------------------------"); + if (!ok) { + var reduce_options = JSON.parse(options); + reduce_options.validate = true; + var reduced = reduce_test(original_code, reduce_options, { + verbose: false, + }).code; + if (reduced) { + errorln(); + errorln("// reduced test case (output will differ)"); + errorln(); + errorln(reduced); + errorln(); + errorln("//-------------------------------------------------------------"); + } } errorln("minify(options):"); errorln(JSON.stringify(JSON.parse(options), null, 2)); diff --git a/test/ufuzz/job.js b/test/ufuzz/job.js index 52c057e8..5cef23e9 100644 --- a/test/ufuzz/job.js +++ b/test/ufuzz/job.js @@ -70,7 +70,7 @@ function run() { function trap(data) { stderr += data; - if (~stderr.indexOf("\nminify(options):\n")) { + if (~stderr.indexOf("!!!!!! Failed... round ")) { process.exitCode = 1; child.stderr.removeListener("data", trap); } |