From fac0aa2b8aca8605835e604afe8b39903cc89b75 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L." Date: Fri, 26 Jul 2024 04:10:29 +0300 Subject: [PATCH] fix corner case in `reduce_vars` (#5893) fixes #5892 --- lib/compress.js | 27 ++++++-------- test/compress/functions.js | 3 +- test/compress/reduce_vars.js | 33 +++++++++++++++++ test/compress/switches.js | 71 ++++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 17 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 725ef91fc07..8e135e2df7e 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -641,7 +641,7 @@ Compressor.prototype.compress = function(node) { var defined_ids = Object.create(tw.defined_ids); var safe_ids = Object.create(tw.safe_ids); if (!sequential) { - defined_ids.seq = {}; + defined_ids.seq = Object.create(null); safe_ids.seq = {}; } tw.defined_ids = defined_ids; @@ -654,18 +654,22 @@ Compressor.prototype.compress = function(node) { } function access(tw, def) { - tw.defined_ids[def.id] = tw.defined_ids.seq; + var seq = tw.defined_ids.seq; + tw.defined_ids[def.id] = seq; + seq[def.id] = true; } function assign(tw, def) { - tw.assigned_ids[def.id] = tw.defined_ids.seq; - tw.defined_ids[def.id] = false; + var seq = tw.defined_ids.seq; + tw.assigned_ids[def.id] = seq; + seq[def.id] = false; } function safe_to_access(tw, def) { var seq = tw.defined_ids.seq; var defined = tw.defined_ids[def.id]; if (defined !== seq) return false; + if (!defined[def.id]) return false; var assigned = tw.assigned_ids[def.id]; return !assigned || assigned === seq; } @@ -1399,22 +1403,13 @@ Compressor.prototype.compress = function(node) { } }); if (!first) pop(tw); - var defined_ids = tw.defined_ids; - var safe_ids = tw.safe_ids; - node.body.forEach(function(branch) { - push(tw, true); - branch.walk(tw); - if (aborts(branch)) { - tw.defined_ids = defined_ids; - tw.safe_ids = safe_ids; - } - }); - tw.defined_ids = defined_ids; - tw.safe_ids = safe_ids; + walk_body(node, tw); return true; }); def(AST_SwitchBranch, function(tw) { + push(tw, true); walk_body(this, tw); + pop(tw); return true; }); def(AST_SymbolCatch, function() { diff --git a/test/compress/functions.js b/test/compress/functions.js index be9ede3d3fe..3d8fc477a1b 100644 --- a/test/compress/functions.js +++ b/test/compress/functions.js @@ -5737,8 +5737,9 @@ issue_3929: { (function() { switch (f) { default: + var abc = 0; case 0: - 0..p; + abc.p; } console.log(typeof f); })(); diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 36deccf0bcb..edd95bd009e 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -8460,3 +8460,36 @@ issue_5872_3: { } expect_stdout: "PASS" } + +issue_5892: { + options = { + pure_getters: "strict", + reduce_vars: true, + side_effects: true, + } + input: { + try { + var a = 42; + a.p; + if (console) + a = null; + a.q; + console.log("FAIL"); + } catch (e) { + console.log("PASS"); + } + } + expect: { + try { + var a = 42; + a.p; + if (console) + a = null; + a.q; + console.log("FAIL"); + } catch (e) { + console.log("PASS"); + } + } + expect_stdout: "PASS" +} diff --git a/test/compress/switches.js b/test/compress/switches.js index 2e23f3e3b55..681a919925e 100644 --- a/test/compress/switches.js +++ b/test/compress/switches.js @@ -1727,3 +1727,74 @@ issue_5890: { } expect_stdout: "PASS" } + +issue_5892_1: { + options = { + reduce_vars: true, + unused: true, + toplevel: true, + } + input: { + try { + switch (42) { + case null: + var a = "foo"; + default: + a.p; + } + console.log("FAIL"); + } catch (e) { + console.log("PASS"); + } + } + expect: { + try { + switch (42) { + case null: + var a = "foo"; + default: + a.p; + } + console.log("FAIL"); + } catch (e) { + console.log("PASS"); + } + } + expect_stdout: "PASS" +} + +issue_5892_2: { + options = { + pure_getters: "strict", + reduce_vars: true, + side_effects: true, + toplevel: true, + } + input: { + try { + switch (42) { + case null: + var a = "foo"; + default: + a.p; + } + console.log("FAIL"); + } catch (e) { + console.log("PASS"); + } + } + expect: { + try { + switch (42) { + case null: + var a = "foo"; + default: + a.p; + } + console.log("FAIL"); + } catch (e) { + console.log("PASS"); + } + } + expect_stdout: "PASS" +}