From e04429350f4eff1299afe84967d15093abc091ff Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Thu, 13 May 2021 02:26:57 +0100 Subject: [PATCH] fix corner case in `ie8` (#4929) fixes #4928 --- lib/compress.js | 36 +++++++++++++++-------- test/compress/ie8.js | 50 ++++++++++++++++++++++++++++++++ test/compress/optional-chains.js | 22 ++++++++++++++ 3 files changed, 96 insertions(+), 12 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 9d83fc09..38e76620 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -6092,6 +6092,30 @@ merge(Compressor.prototype, { }); tw.directives = Object.create(compressor.directives); self.walk(tw); + var drop_fn_name = compressor.option("keep_fnames") ? return_false : compressor.option("ie8") ? function(def) { + return !compressor.exposed(def) && def.references.length == def.replaced; + } : function(def) { + if (!(def.id in in_use_ids)) return true; + if (def.orig.length < 2) return false; + // function argument will always overshadow its name + if (def.orig[1] instanceof AST_SymbolFunarg) return true; + // retain if referenced within destructured object of argument + return all(def.references, function(ref) { + return !ref.in_arg; + }); + }; + if (compressor.option("ie8")) initializations.each(function(init, id) { + if (id in in_use_ids) return; + init.forEach(function(init) { + init.walk(new TreeWalker(function(node) { + if (node instanceof AST_Function && node.name && !drop_fn_name(node.name.definition())) { + node.walk(tw); + return true; + } + if (node instanceof AST_Scope) return true; + })); + }); + }); // pass 2: for every used symbol we need to walk its // initialization code to figure out if it uses other // symbols (that may not be in_use). @@ -6129,18 +6153,6 @@ merge(Compressor.prototype, { delete assign_in_use[id]; } }); - var drop_fn_name = compressor.option("keep_fnames") ? return_false : compressor.option("ie8") ? function(def) { - return !compressor.exposed(def) && def.references.length == def.replaced; - } : function(def) { - if (!(def.id in in_use_ids)) return true; - if (def.orig.length < 2) return false; - // function argument will always overshadow its name - if (def.orig[1] instanceof AST_SymbolFunarg) return true; - // retain if referenced within destructured object of argument - return all(def.references, function(ref) { - return !ref.in_arg; - }); - }; // pass 3: we should drop declarations not in_use var trim_defns = []; var unused_fn_names = []; diff --git a/test/compress/ie8.js b/test/compress/ie8.js index 23532968..3221c92a 100644 --- a/test/compress/ie8.js +++ b/test/compress/ie8.js @@ -2947,3 +2947,53 @@ issue_4729: { } expect_stdout: "PASS" } + +issue_4928_1: { + options = { + ie8: true, + toplevel: true, + unused: true, + } + input: { + var a = function f() { + f(a); + }; + console.log(typeof f); + } + expect: { + var a = function f() { + f(a); + }; + console.log(typeof f); + } + expect_stdout: "undefined" +} + +issue_4928_2: { + options = { + ie8: true, + toplevel: true, + unused: true, + } + input: { + switch (42) { + case console: + var a = function f() { + f(a); + }; + case 42: + var a = console.log("PASS"); + } + } + expect: { + switch (42) { + case console: + var a = function f() { + f(a); + }; + case 42: + a = console.log("PASS"); + } + } + expect_stdout: "PASS" +} diff --git a/test/compress/optional-chains.js b/test/compress/optional-chains.js index 43033c92..7f61263c 100644 --- a/test/compress/optional-chains.js +++ b/test/compress/optional-chains.js @@ -253,3 +253,25 @@ issue_4906: { expect_stdout: "PASS" node_version: ">=14" } + +issue_4928: { + options = { + ie8: true, + toplevel: true, + unused: true, + } + input: { + var a = a?.[function f() { + f(a); + }]; + console.log(typeof f); + } + expect: { + var a = a?.[function f() { + f(a); + }]; + console.log(typeof f); + } + expect_stdout: "undefined" + node_version: ">=14" +}