From: Alex Lam S.L Date: Sun, 3 May 2020 14:52:43 +0000 (+0100) Subject: enhance `reduce_vars` (#3843) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=ac429dc8e1a3d49af8fd3627449bd22ffd781f20;p=UglifyJS.git enhance `reduce_vars` (#3843) --- diff --git a/lib/compress.js b/lib/compress.js index 394184bc..8b6c38dd 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -607,7 +607,13 @@ merge(Compressor.prototype, { def(AST_Call, function(tw, descend) { tw.find_parent(AST_Scope).may_call_this(); var exp = this.expression; - if (exp instanceof AST_SymbolRef) { + if (exp instanceof AST_Function) { + this.args.forEach(function(arg) { + arg.walk(tw); + }); + exp.walk(tw); + return true; + } else if (exp instanceof AST_SymbolRef) { var def = exp.definition(); if (this.TYPE == "Call" && tw.in_boolean_context()) def.bool_fn++; if (!(def.fixed instanceof AST_Defun)) return; @@ -706,23 +712,20 @@ merge(Compressor.prototype, { return true; }); def(AST_Function, function(tw, descend, compressor) { - var node = this; - node.inlined = false; - push(tw); - reset_variables(tw, compressor, node); + var fn = this; + fn.inlined = false; var iife; - if (!node.name - && (iife = tw.parent()) instanceof AST_Call - && iife.expression === node) { + if (!fn.name && (iife = tw.parent()) instanceof AST_Call && iife.expression === fn) { + reset_variables(tw, compressor, fn); // Virtually turn IIFE parameters into variable definitions: // (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})() // So existing transformation rules can work on them. - node.argnames.forEach(function(arg, i) { + fn.argnames.forEach(function(arg, i) { var d = arg.definition(); - if (d.fixed === undefined && (!node.uses_arguments || tw.has_directive("use strict"))) { + if (d.fixed === undefined && (!fn.uses_arguments || tw.has_directive("use strict"))) { var value = iife.args[i]; d.fixed = function() { - var j = node.argnames.indexOf(arg); + var j = fn.argnames.indexOf(arg); if (j < 0) return value; return iife.args[j] || make_node(AST_Undefined, iife); }; @@ -732,10 +735,29 @@ merge(Compressor.prototype, { d.fixed = false; } }); + var has_return = false; + var visit = tw.visit; + tw.visit = function(node, descend) { + var ret = visit.call(tw, node, descend); + if (!has_return && node instanceof AST_Return && tw.find_parent(AST_Scope) === fn) { + has_return = true; + push(tw); + } + return ret; + }; + descend(); + tw.visit = visit; + var safe_ids = tw.safe_ids; + pop(tw); + walk_defuns(tw, fn); + if (!has_return) tw.safe_ids = safe_ids; + } else { + push(tw); + reset_variables(tw, compressor, fn); + descend(); + pop(tw); + walk_defuns(tw, fn); } - descend(); - pop(tw); - walk_defuns(tw, node); return true; }); def(AST_If, function(tw) { @@ -4512,17 +4534,15 @@ merge(Compressor.prototype, { } function scan_ref_scoped(node, descend, init) { - if (scope === self) { - if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) { - var node_def = node.left.definition(); - if (node.operator != "=") chained[node_def.id] = true; - match_assigns(node_def, node); - } - if (node instanceof AST_Unary && node.expression instanceof AST_SymbolRef) { - var node_def = node.expression.definition(); - chained[node_def.id] = true; - match_assigns(node_def, node); - } + if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) { + var node_def = node.left.definition(); + if (node.operator != "=") chained[node_def.id] = true; + match_assigns(node_def, node); + } + if (node instanceof AST_Unary && node.expression instanceof AST_SymbolRef) { + var node_def = node.expression.definition(); + chained[node_def.id] = true; + match_assigns(node_def, node); } var node_def, props = [], sym = assign_as_unused(node, props); if (sym && self.variables.get(sym.name) === (node_def = sym.definition())) { diff --git a/test/compress/issue-1656.js b/test/compress/issue-1656.js index e44e2094..146ec609 100644 --- a/test/compress/issue-1656.js +++ b/test/compress/issue-1656.js @@ -35,11 +35,7 @@ f7: { console.log(a, b); } expect_exact: [ - "var b = 10;", - "", - "!function() {", - " b = 100;", - "}(), console.log(100, b);", + "console.log(100, 100);", ] - expect_stdout: true + expect_stdout: "100 100" } diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 8cc301cc..6cc575f1 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -6976,3 +6976,33 @@ issue_3774: { } expect_stdout: "PASS" } + +flatten_iife: { + options = { + reduce_vars: true, + side_effects: true, + toplevel: true, + unused: true, + } + input: { + var a = "FAIL"; + while (!console); + a++; + (function() { + while (!console); + a = "PASS"; + })(); + console.log(a); + } + expect: { + var a; + while (!console); + 0; + (function() { + while (!console); + a = "PASS"; + })(); + console.log(a); + } + expect_stdout: "PASS" +}