enhance collapse_vars (#3801)
This commit is contained in:
@@ -1122,7 +1122,10 @@ merge(Compressor.prototype, {
|
|||||||
function collapse(statements, compressor) {
|
function collapse(statements, compressor) {
|
||||||
if (scope.pinned()) return statements;
|
if (scope.pinned()) return statements;
|
||||||
var args;
|
var args;
|
||||||
|
var assignments = Object.create(null);
|
||||||
var candidates = [];
|
var candidates = [];
|
||||||
|
var declare_only = Object.create(null);
|
||||||
|
var force_single;
|
||||||
var stat_index = statements.length;
|
var stat_index = statements.length;
|
||||||
var scanner = new TreeTransformer(function(node, descend) {
|
var scanner = new TreeTransformer(function(node, descend) {
|
||||||
if (abort) return node;
|
if (abort) return node;
|
||||||
@@ -1255,7 +1258,6 @@ merge(Compressor.prototype, {
|
|||||||
// Skip (non-executed) functions and (leading) default case in switch statements
|
// Skip (non-executed) functions and (leading) default case in switch statements
|
||||||
if (node instanceof AST_Default || node instanceof AST_Scope) return node;
|
if (node instanceof AST_Default || node instanceof AST_Scope) return node;
|
||||||
}, patch_sequence);
|
}, patch_sequence);
|
||||||
var force_single;
|
|
||||||
while (--stat_index >= 0) {
|
while (--stat_index >= 0) {
|
||||||
// Treat parameters as collapsible in IIFE, i.e.
|
// Treat parameters as collapsible in IIFE, i.e.
|
||||||
// function(a, b){ ... }(x());
|
// function(a, b){ ... }(x());
|
||||||
@@ -1264,7 +1266,6 @@ merge(Compressor.prototype, {
|
|||||||
if (stat_index == 0 && compressor.option("unused")) extract_args();
|
if (stat_index == 0 && compressor.option("unused")) extract_args();
|
||||||
// Find collapsible assignments
|
// Find collapsible assignments
|
||||||
var hit_stack = [];
|
var hit_stack = [];
|
||||||
var declare_only = Object.create(null);
|
|
||||||
extract_candidates(statements[stat_index]);
|
extract_candidates(statements[stat_index]);
|
||||||
while (candidates.length > 0) {
|
while (candidates.length > 0) {
|
||||||
hit_stack = candidates.pop();
|
hit_stack = candidates.pop();
|
||||||
@@ -1501,6 +1502,9 @@ merge(Compressor.prototype, {
|
|||||||
candidates.push(hit_stack.slice());
|
candidates.push(hit_stack.slice());
|
||||||
extract_candidates(expr.left);
|
extract_candidates(expr.left);
|
||||||
extract_candidates(expr.right);
|
extract_candidates(expr.right);
|
||||||
|
if (expr.left instanceof AST_SymbolRef) {
|
||||||
|
assignments[expr.left.name] = (assignments[expr.left.name] || 0) + 1;
|
||||||
|
}
|
||||||
} else if (expr instanceof AST_Binary) {
|
} else if (expr instanceof AST_Binary) {
|
||||||
extract_candidates(expr.left);
|
extract_candidates(expr.left);
|
||||||
extract_candidates(expr.right);
|
extract_candidates(expr.right);
|
||||||
@@ -1740,14 +1744,13 @@ merge(Compressor.prototype, {
|
|||||||
if (expr instanceof AST_VarDef) {
|
if (expr instanceof AST_VarDef) {
|
||||||
var def = expr.name.definition();
|
var def = expr.name.definition();
|
||||||
if (!member(expr.name, def.orig)) return;
|
if (!member(expr.name, def.orig)) return;
|
||||||
var referenced = def.references.length - def.replaced;
|
var declared = def.orig.length - def.eliminated - (declare_only[def.name] || 0);
|
||||||
var declared = def.orig.length - def.eliminated;
|
var referenced = def.references.length - def.replaced - (assignments[def.name] || 0);
|
||||||
declared -= declare_only[def.name] || 0;
|
|
||||||
if (declared > 1 && !(expr.name instanceof AST_SymbolFunarg)) {
|
if (declared > 1 && !(expr.name instanceof AST_SymbolFunarg)) {
|
||||||
mangleable_var(expr.value);
|
mangleable_var(expr.value);
|
||||||
return make_node(AST_SymbolRef, expr.name, expr.name);
|
return make_node(AST_SymbolRef, expr.name, expr.name);
|
||||||
}
|
}
|
||||||
if (referenced > 1 ? mangleable_var(expr.value) : !compressor.exposed(def)) {
|
if (mangleable_var(expr.value) || referenced == 1 && !compressor.exposed(def)) {
|
||||||
return make_node(AST_SymbolRef, expr.name, expr.name);
|
return make_node(AST_SymbolRef, expr.name, expr.name);
|
||||||
}
|
}
|
||||||
} else if (expr instanceof AST_Assign) {
|
} else if (expr instanceof AST_Assign) {
|
||||||
@@ -1871,6 +1874,7 @@ merge(Compressor.prototype, {
|
|||||||
found = true;
|
found = true;
|
||||||
if (node instanceof AST_VarDef) {
|
if (node instanceof AST_VarDef) {
|
||||||
node.value = null;
|
node.value = null;
|
||||||
|
declare_only[node.name.name] = (declare_only[node.name.name] || 0) + 1;
|
||||||
if (value_def) value_def.replaced++;
|
if (value_def) value_def.replaced++;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -803,8 +803,7 @@ collapse_vars_assignment: {
|
|||||||
expect: {
|
expect: {
|
||||||
function log(x) { return console.log(x), x; }
|
function log(x) { return console.log(x), x; }
|
||||||
function f0(c) {
|
function f0(c) {
|
||||||
var a = 3 / c;
|
return 3 / c;
|
||||||
return a = a;
|
|
||||||
}
|
}
|
||||||
function f1(c) {
|
function f1(c) {
|
||||||
return 1 - 3 / c;
|
return 1 - 3 / c;
|
||||||
@@ -2205,8 +2204,8 @@ var_defs: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var f1 = function(x, y) {
|
var f1 = function(x, y) {
|
||||||
var r = x + y, a = r * r - r, b = 7;
|
var r = x + y, z = r * r - r, b = 7;
|
||||||
console.log(a + b);
|
console.log(z + b);
|
||||||
};
|
};
|
||||||
f1("1", 0);
|
f1("1", 0);
|
||||||
}
|
}
|
||||||
@@ -2665,8 +2664,8 @@ double_def_1: {
|
|||||||
a();
|
a();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a;
|
var a = x;
|
||||||
(a = (a = x) && y)();
|
(a = a && y)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7921,3 +7920,37 @@ var_value_def: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mangleable_var: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var b = a(), c = a(), d = b;
|
||||||
|
return c.p(c, d);
|
||||||
|
}
|
||||||
|
console.log(f(function() {
|
||||||
|
return {
|
||||||
|
p: function() {
|
||||||
|
return "PASS"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
var b = a(), c = a();
|
||||||
|
return c.p(c, b);
|
||||||
|
}
|
||||||
|
console.log(f(function() {
|
||||||
|
return {
|
||||||
|
p: function() {
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user