From 358faaacaaa502d031cb4e195ab7601edcd5e44d Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Wed, 4 Jan 2023 07:17:04 +0200 Subject: [PATCH] fix corner case in `merge_vars` (#5771) fixes #5770 --- lib/compress.js | 32 +++++++++++++++------- test/compress/merge_vars.js | 53 +++++++++++++++++++++++++++++++++++++ test/reduce.js | 12 +++++++-- 3 files changed, 86 insertions(+), 11 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 034a9e03576..39a1da6ac19 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -6648,36 +6648,50 @@ Compressor.prototype.compress = function(node) { function walk_cond(condition, consequent, alternative) { var save = segment; - var segments = [ save, save ]; + var segments = scan_branches(condition, consequent, alternative); + if (consequent) { + segment = segments[0]; + pop(); + if (segment !== save) return; + } + if (alternative) { + segment = segments[1]; + pop(); + if (segment !== save) return; + } + segment = save; + } + + function scan_branches(condition, consequent, alternative) { + var segments = [ segment, segment ]; if (condition instanceof AST_Binary) switch (condition.operator) { case "&&": - segments[0] = walk_cond(condition.left, condition.right)[0]; + segments[0] = scan_branches(condition.left, condition.right)[0]; break; case "||": case "??": - segments[1] = walk_cond(condition.left, null, condition.right)[1]; + segments[1] = scan_branches(condition.left, null, condition.right)[1]; break; default: condition.walk(tw); break; } else if (condition instanceof AST_Conditional) { - walk_cond(condition.condition, condition.consequent, condition.alternative); + scan_branches(condition.condition, condition.consequent, condition.alternative); } else { condition.walk(tw); } - segment = segments[0]; if (consequent) { + segment = segments[0]; push(); consequent.walk(tw); + segments[0] = segment; } - segments[0] = segment; - segment = segments[1]; if (alternative) { + segment = segments[1]; push(); alternative.walk(tw); + segments[1] = segment; } - segments[1] = segment; - segment = save; return segments; } }); diff --git a/test/compress/merge_vars.js b/test/compress/merge_vars.js index e7b1be3a836..58563083103 100644 --- a/test/compress/merge_vars.js +++ b/test/compress/merge_vars.js @@ -3889,3 +3889,56 @@ issue_5714: { "42", ] } + +issue_5770_1: { + options = { + dead_code: true, + loops: true, + merge_vars: true, + toplevel: true, + } + input: { + L: do { + if (console) + for (var a = "FAIL 1"; a; a--) + continue L; + var b = "FAIL 2"; + } while (console.log(b || "PASS")); + } + expect: { + L: do { + if (console) { + var a = "FAIL 1"; + if (a) + continue L; + } + var b = "FAIL 2"; + } while (console.log(b || "PASS")); + } + expect_stdout: "PASS" +} + +issue_5770_2: { + options = { + conditionals: true, + dead_code: true, + if_return: true, + loops: true, + merge_vars: true, + toplevel: true, + } + input: { + L: do { + for (var a = "FAIL 1"; a; a--) + continue L; + var b = "FAIL 2"; + } while (console.log(b || "PASS")); + } + expect: { + L: do { + var a = "FAIL 1"; + var b; + } while (a || (b = "FAIL 2"), console.log(b || "PASS")); + } + expect_stdout: "PASS" +} diff --git a/test/reduce.js b/test/reduce.js index afb9f89b701..10a0086bf50 100644 --- a/test/reduce.js +++ b/test/reduce.js @@ -363,9 +363,17 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options) node.condition, node.body, node.alternative, - ][ (node.start._permute * steps | 0) % 3 ]; + node, + ][ (node.start._permute * steps | 0) % 4 ]; node.start._permute += step; - if (expr) { + if (expr === node) { + if (node.alternative) { + expr = node.clone(); + expr.alternative = null; + CHANGED = true; + return expr; + } + } else if (expr) { // replace if statement with its condition, then block or else block CHANGED = true; return to_statement(expr);