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) {
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, node);
walk_defuns(tw, fn);
}
return true;
});
def(AST_If, function(tw) {
@@ -4512,7 +4534,6 @@ 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;
@@ -4523,7 +4544,6 @@ merge(Compressor.prototype, {
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())) {
props.forEach(function(prop) {

View File

@@ -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"
}

View File

@@ -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"
}