enhance reduce_vars (#3843)

This commit is contained in:
Alex Lam S.L
2020-05-03 15:52:43 +01:00
committed by GitHub
parent 3766d5c962
commit ac429dc8e1
3 changed files with 77 additions and 31 deletions

View File

@@ -607,7 +607,13 @@ merge(Compressor.prototype, {
def(AST_Call, function(tw, descend) { def(AST_Call, function(tw, descend) {
tw.find_parent(AST_Scope).may_call_this(); tw.find_parent(AST_Scope).may_call_this();
var exp = this.expression; 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(); var def = exp.definition();
if (this.TYPE == "Call" && tw.in_boolean_context()) def.bool_fn++; if (this.TYPE == "Call" && tw.in_boolean_context()) def.bool_fn++;
if (!(def.fixed instanceof AST_Defun)) return; if (!(def.fixed instanceof AST_Defun)) return;
@@ -706,23 +712,20 @@ merge(Compressor.prototype, {
return true; return true;
}); });
def(AST_Function, function(tw, descend, compressor) { def(AST_Function, function(tw, descend, compressor) {
var node = this; var fn = this;
node.inlined = false; fn.inlined = false;
push(tw);
reset_variables(tw, compressor, node);
var iife; var iife;
if (!node.name if (!fn.name && (iife = tw.parent()) instanceof AST_Call && iife.expression === fn) {
&& (iife = tw.parent()) instanceof AST_Call reset_variables(tw, compressor, fn);
&& iife.expression === node) {
// Virtually turn IIFE parameters into variable definitions: // Virtually turn IIFE parameters into variable definitions:
// (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})() // (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})()
// So existing transformation rules can work on them. // So existing transformation rules can work on them.
node.argnames.forEach(function(arg, i) { fn.argnames.forEach(function(arg, i) {
var d = arg.definition(); 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]; var value = iife.args[i];
d.fixed = function() { d.fixed = function() {
var j = node.argnames.indexOf(arg); var j = fn.argnames.indexOf(arg);
if (j < 0) return value; if (j < 0) return value;
return iife.args[j] || make_node(AST_Undefined, iife); return iife.args[j] || make_node(AST_Undefined, iife);
}; };
@@ -732,10 +735,29 @@ merge(Compressor.prototype, {
d.fixed = false; 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; return true;
}); });
def(AST_If, function(tw) { def(AST_If, function(tw) {
@@ -4512,17 +4534,15 @@ merge(Compressor.prototype, {
} }
function scan_ref_scoped(node, descend, init) { function scan_ref_scoped(node, descend, init) {
if (scope === self) { if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) {
if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) { var node_def = node.left.definition();
var node_def = node.left.definition(); if (node.operator != "=") chained[node_def.id] = true;
if (node.operator != "=") chained[node_def.id] = true; match_assigns(node_def, node);
match_assigns(node_def, node); }
} if (node instanceof AST_Unary && node.expression instanceof AST_SymbolRef) {
if (node instanceof AST_Unary && node.expression instanceof AST_SymbolRef) { var node_def = node.expression.definition();
var node_def = node.expression.definition(); chained[node_def.id] = true;
chained[node_def.id] = true; match_assigns(node_def, node);
match_assigns(node_def, node);
}
} }
var node_def, props = [], sym = assign_as_unused(node, props); var node_def, props = [], sym = assign_as_unused(node, props);
if (sym && self.variables.get(sym.name) === (node_def = sym.definition())) { if (sym && self.variables.get(sym.name) === (node_def = sym.definition())) {

View File

@@ -35,11 +35,7 @@ f7: {
console.log(a, b); console.log(a, b);
} }
expect_exact: [ expect_exact: [
"var b = 10;", "console.log(100, 100);",
"",
"!function() {",
" b = 100;",
"}(), console.log(100, b);",
] ]
expect_stdout: true expect_stdout: "100 100"
} }

View File

@@ -6976,3 +6976,33 @@ issue_3774: {
} }
expect_stdout: "PASS" 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"
}