From: Alex Lam S.L Date: Sat, 20 Apr 2019 18:16:05 +0000 (+0800) Subject: fix corner cases in `functions` (#3372) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=c719552317a4ec14b04226cc0440d25b4028f09c;p=UglifyJS.git fix corner cases in `functions` (#3372) fixes #3371 --- diff --git a/lib/compress.js b/lib/compress.js index b0f1bfba..2fd36095 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -114,7 +114,7 @@ function Compressor(options, false_by_default) { }; } else if (Array.isArray(pure_funcs)) { this.pure_funcs = function(node) { - return pure_funcs.indexOf(node.expression.print_to_string()) < 0; + return !member(node.expression.print_to_string(), pure_funcs); }; } else { this.pure_funcs = return_true; @@ -131,7 +131,7 @@ function Compressor(options, false_by_default) { top_retain = top_retain.split(/,/); } this.top_retain = function(def) { - return top_retain.indexOf(def.name) >= 0; + return member(def.name, top_retain); }; } var toplevel = this.options["toplevel"]; @@ -1711,7 +1711,7 @@ merge(Compressor.prototype, { CHANGED = true; statements.splice(i, 1); } else if (stat instanceof AST_Directive) { - if (seen_dirs.indexOf(stat.value) < 0) { + if (!member(stat.value, seen_dirs)) { i++; seen_dirs.push(stat.value); } else { @@ -2853,7 +2853,7 @@ merge(Compressor.prototype, { var fixed = this.fixed_value(); if (!fixed) return this; var value; - if (cached.indexOf(fixed) >= 0) { + if (member(fixed, cached)) { value = fixed._eval(); } else { this._eval = return_this; @@ -3638,11 +3638,16 @@ merge(Compressor.prototype, { var defun = make_node(AST_Defun, def, def.value); defun.name = make_node(AST_SymbolDefun, def.name, def.name); var name_def = def.name.scope.resolve().def_function(defun.name); - if (def.value.name) def.value.name.definition().references.forEach(function(ref) { - ref.name = name_def.name; - ref.thedef = name_def; - ref.reference({}); - }); + if (def.value.name) { + var old_def = def.value.name.definition(); + def.value.walk(new TreeWalker(function(node) { + if (node instanceof AST_SymbolRef && node.definition() === old_def) { + node.name = name_def.name; + node.thedef = name_def; + node.reference({}); + } + })); + } body.push(defun); } else { if (side_effects.length > 0) { @@ -3703,6 +3708,7 @@ merge(Compressor.prototype, { // https://github.com/mishoo/UglifyJS2/issues/44 // https://github.com/mishoo/UglifyJS2/issues/1830 // https://github.com/mishoo/UglifyJS2/issues/1838 + // https://github.com/mishoo/UglifyJS2/issues/3371 // that's an invalid AST. // We fix it at this stage by moving the `var` outside the `for`. if (node instanceof AST_For) { @@ -3713,7 +3719,15 @@ merge(Compressor.prototype, { node.init = block.body.pop(); block.body.push(node); } - if (node.init instanceof AST_SimpleStatement) { + if (node.init instanceof AST_Defun) { + if (!block) { + block = make_node(AST_BlockStatement, node, { + body: [ node ] + }); + } + block.body.splice(-1, 0, node.init); + node.init = null; + } else if (node.init instanceof AST_SimpleStatement) { node.init = node.init.body; } else if (is_empty(node.init)) { node.init = null; diff --git a/test/compress/functions.js b/test/compress/functions.js index 64f3bbcc..983d7068 100644 --- a/test/compress/functions.js +++ b/test/compress/functions.js @@ -3012,3 +3012,32 @@ issue_3366: { } expect_stdout: "PASS" } + +issue_3371: { + options = { + functions: true, + inline: true, + reduce_vars: true, + side_effects: true, + unused: true, + } + input: { + (function() { + var a = function f() { + (function() { + console.log(typeof f); + })(); + }; + while (a()); + })(); + } + expect: { + (function() { + function a() { + console.log(typeof a); + } + while (a()); + })(); + } + expect_stdout: "function" +} diff --git a/test/compress/loops.js b/test/compress/loops.js index 3fa78338..137fd9da 100644 --- a/test/compress/loops.js +++ b/test/compress/loops.js @@ -646,3 +646,30 @@ issue_2904: { } expect_stdout: "1" } + +issue_3371: { + options = { + functions: true, + join_vars: true, + loops: true, + reduce_vars: true, + unused: true, + } + input: { + (function() { + var a = function() { + console.log("PASS"); + }; + while (a()); + })(); + } + expect: { + (function() { + function a() { + console.log("PASS"); + } + for (; a(); ); + })(); + } + expect_stdout: "PASS" +}