enhance reduce_vars (#5636)

This commit is contained in:
Alex Lam S.L
2022-08-30 09:00:43 +01:00
committed by GitHub
parent 15b608f74c
commit 10bc86ba10
7 changed files with 109 additions and 40 deletions

View File

@@ -621,8 +621,10 @@ Compressor.prototype.compress = function(node) {
scope.may_call_this = undefined; scope.may_call_this = undefined;
} }
function push(tw) { function push(tw, sequential) {
tw.safe_ids = Object.create(tw.safe_ids); var safe_ids = Object.create(tw.safe_ids);
if (!sequential) safe_ids.seq = {};
tw.safe_ids = safe_ids;
} }
function pop(tw) { function pop(tw) {
@@ -643,7 +645,14 @@ Compressor.prototype.compress = function(node) {
var safe = tw.safe_ids[def.id]; var safe = tw.safe_ids[def.id];
if (safe) { if (safe) {
var in_order = HOP(tw.safe_ids, def.id); var in_order = HOP(tw.safe_ids, def.id);
if (!in_order) safe.read = safe.read && safe.read !== tw.safe_ids ? true : tw.safe_ids; if (!in_order) {
var seq = tw.safe_ids.seq;
if (!safe.read) {
safe.read = seq;
} else if (safe.read !== seq) {
safe.read = true;
}
}
if (def.fixed == null) { if (def.fixed == null) {
if (is_arguments(def)) return false; if (is_arguments(def)) return false;
if (def.global && def.name == "arguments") return false; if (def.global && def.name == "arguments") return false;
@@ -684,7 +693,7 @@ Compressor.prototype.compress = function(node) {
safe.assign = safe.assign && safe.assign !== tw.safe_ids ? true : tw.safe_ids; safe.assign = safe.assign && safe.assign !== tw.safe_ids ? true : tw.safe_ids;
} }
if (def.fixed != null && safe.read) { if (def.fixed != null && safe.read) {
if (safe.read !== tw.safe_ids) return false; if (safe.read !== tw.safe_ids.seq) return false;
if (tw.loop_ids[def.id] !== tw.in_loop) return false; if (tw.loop_ids[def.id] !== tw.in_loop) return false;
} }
return safe_to_read(tw, def) && all(def.orig, function(sym) { return safe_to_read(tw, def) && all(def.orig, function(sym) {
@@ -810,7 +819,7 @@ Compressor.prototype.compress = function(node) {
var scanner = new TreeWalker(function(node) { var scanner = new TreeWalker(function(node) {
if (node instanceof AST_DefaultValue) { if (node instanceof AST_DefaultValue) {
reset_flags(node); reset_flags(node);
push(tw); push(tw, true);
node.value.walk(tw); node.value.walk(tw);
pop(tw); pop(tw);
var save = fixed; var save = fixed;
@@ -899,14 +908,15 @@ Compressor.prototype.compress = function(node) {
var fn = this; var fn = this;
fn.inlined = false; fn.inlined = false;
var iife = tw.parent(); var iife = tw.parent();
var hit = is_async(fn) || is_generator(fn); var sequential = !is_async(fn) && !is_generator(fn);
var hit = !sequential;
var aborts = false; var aborts = false;
fn.walk(new TreeWalker(function(node) { fn.walk(new TreeWalker(function(node) {
if (hit) return aborts = true; if (hit) return aborts = true;
if (node instanceof AST_Return) return hit = true; if (node instanceof AST_Return) return hit = true;
if (node instanceof AST_Scope && node !== fn) return true; if (node instanceof AST_Scope && node !== fn) return true;
})); }));
if (aborts) push(tw); if (aborts) push(tw, sequential);
reset_variables(tw, compressor, fn); reset_variables(tw, compressor, fn);
// 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; ...})()
@@ -991,7 +1001,7 @@ Compressor.prototype.compress = function(node) {
return walk_lazy(); return walk_lazy();
} }
var safe = safe_to_read(tw, ld); var safe = safe_to_read(tw, ld);
if (lazy) push(tw); if (lazy) push(tw, true);
right.walk(tw); right.walk(tw);
if (lazy) pop(tw); if (lazy) pop(tw);
if (safe && !left.in_arg && safe_to_assign(tw, ld)) { if (safe && !left.in_arg && safe_to_assign(tw, ld)) {
@@ -1073,7 +1083,7 @@ Compressor.prototype.compress = function(node) {
function walk_lazy() { function walk_lazy() {
if (!lazy) return; if (!lazy) return;
left.walk(tw); left.walk(tw);
push(tw); push(tw, true);
right.walk(tw); right.walk(tw);
pop(tw); pop(tw);
return true; return true;
@@ -1082,7 +1092,7 @@ Compressor.prototype.compress = function(node) {
def(AST_Binary, function(tw) { def(AST_Binary, function(tw) {
if (!lazy_op[this.operator]) return; if (!lazy_op[this.operator]) return;
this.left.walk(tw); this.left.walk(tw);
push(tw); push(tw, true);
this.right.walk(tw); this.right.walk(tw);
pop(tw); pop(tw);
return true; return true;
@@ -1112,7 +1122,7 @@ Compressor.prototype.compress = function(node) {
} }
exp.walk(tw); exp.walk(tw);
var optional = node.optional; var optional = node.optional;
if (optional) push(tw); if (optional) push(tw, true);
node.args.forEach(function(arg) { node.args.forEach(function(arg) {
arg.walk(tw); arg.walk(tw);
}); });
@@ -1182,7 +1192,7 @@ Compressor.prototype.compress = function(node) {
}); });
def(AST_ClassInitBlock, function(tw, descend, compressor) { def(AST_ClassInitBlock, function(tw, descend, compressor) {
var node = this; var node = this;
push(tw); push(tw, true);
reset_variables(tw, compressor, node); reset_variables(tw, compressor, node);
descend(); descend();
pop_scope(tw, node); pop_scope(tw, node);
@@ -1190,19 +1200,19 @@ Compressor.prototype.compress = function(node) {
}); });
def(AST_Conditional, function(tw) { def(AST_Conditional, function(tw) {
this.condition.walk(tw); this.condition.walk(tw);
push(tw); push(tw, true);
this.consequent.walk(tw); this.consequent.walk(tw);
pop(tw); pop(tw);
push(tw); push(tw, true);
this.alternative.walk(tw); this.alternative.walk(tw);
pop(tw); pop(tw);
return true; return true;
}); });
def(AST_DefaultValue, function(tw) { def(AST_DefaultValue, function(tw) {
this.name.walk(tw); push(tw, true);
push(tw);
this.value.walk(tw); this.value.walk(tw);
pop(tw); pop(tw);
this.name.walk(tw);
return true; return true;
}); });
def(AST_Do, function(tw) { def(AST_Do, function(tw) {
@@ -1274,18 +1284,18 @@ Compressor.prototype.compress = function(node) {
}); });
def(AST_If, function(tw) { def(AST_If, function(tw) {
this.condition.walk(tw); this.condition.walk(tw);
push(tw); push(tw, true);
this.body.walk(tw); this.body.walk(tw);
pop(tw); pop(tw);
if (this.alternative) { if (this.alternative) {
push(tw); push(tw, true);
this.alternative.walk(tw); this.alternative.walk(tw);
pop(tw); pop(tw);
} }
return true; return true;
}); });
def(AST_LabeledStatement, function(tw) { def(AST_LabeledStatement, function(tw) {
push(tw); push(tw, true);
this.body.walk(tw); this.body.walk(tw);
pop(tw); pop(tw);
return true; return true;
@@ -1319,7 +1329,7 @@ Compressor.prototype.compress = function(node) {
def(AST_Sub, function(tw) { def(AST_Sub, function(tw) {
if (!this.optional) return; if (!this.optional) return;
this.expression.walk(tw); this.expression.walk(tw);
push(tw); push(tw, true);
this.property.walk(tw); this.property.walk(tw);
pop(tw); pop(tw);
return true; return true;
@@ -1334,7 +1344,7 @@ Compressor.prototype.compress = function(node) {
branch.expression.walk(tw); branch.expression.walk(tw);
if (first) { if (first) {
first = false; first = false;
push(tw); push(tw, true);
} }
}) })
if (!first) pop(tw); if (!first) pop(tw);
@@ -1342,7 +1352,7 @@ Compressor.prototype.compress = function(node) {
return true; return true;
}); });
def(AST_SwitchBranch, function(tw) { def(AST_SwitchBranch, function(tw) {
push(tw); push(tw, true);
walk_body(this, tw); walk_body(this, tw);
pop(tw); pop(tw);
return true; return true;
@@ -1452,7 +1462,7 @@ Compressor.prototype.compress = function(node) {
node.globals.each(function(def) { node.globals.each(function(def) {
reset_def(tw, compressor, def); reset_def(tw, compressor, def);
}); });
push(tw); push(tw, true);
reset_variables(tw, compressor, node); reset_variables(tw, compressor, node);
descend(); descend();
pop_scope(tw, node); pop_scope(tw, node);
@@ -1461,11 +1471,11 @@ Compressor.prototype.compress = function(node) {
def(AST_Try, function(tw, descend, compressor) { def(AST_Try, function(tw, descend, compressor) {
var node = this; var node = this;
reset_block_variables(tw, compressor, node); reset_block_variables(tw, compressor, node);
push(tw); push(tw, true);
walk_body(node, tw); walk_body(node, tw);
pop(tw); pop(tw);
if (node.bcatch) { if (node.bcatch) {
push(tw); push(tw, true);
node.bcatch.walk(tw); node.bcatch.walk(tw);
pop(tw); pop(tw);
} }
@@ -1590,6 +1600,7 @@ Compressor.prototype.compress = function(node) {
// - `push()` & `pop()` when visiting conditional branches // - `push()` & `pop()` when visiting conditional branches
// - backup & restore via `save_ids` when visiting out-of-order sections // - backup & restore via `save_ids` when visiting out-of-order sections
tw.safe_ids = Object.create(null); tw.safe_ids = Object.create(null);
tw.safe_ids.seq = {};
this.walk(tw); this.walk(tw);
}); });
@@ -3524,6 +3535,7 @@ Compressor.prototype.compress = function(node) {
stat.alternative = make_node(AST_BlockStatement, stat, { stat.alternative = make_node(AST_BlockStatement, stat, {
body: as_statement_array(stat.alternative).concat(extract_functions(merge_jump, jump)), body: as_statement_array(stat.alternative).concat(extract_functions(merge_jump, jump)),
}); });
adjust_refs(ab.value, merge_jump);
statements[i] = stat; statements[i] = stat;
statements[i] = stat.transform(compressor); statements[i] = stat.transform(compressor);
continue; continue;
@@ -3563,6 +3575,7 @@ Compressor.prototype.compress = function(node) {
stat.alternative = make_node(AST_BlockStatement, stat.alternative, { stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
body: as_statement_array_with_return(stat.alternative, alt), body: as_statement_array_with_return(stat.alternative, alt),
}); });
adjust_refs(alt.value, merge_jump);
statements[i] = stat; statements[i] = stat;
statements[i] = stat.transform(compressor); statements[i] = stat.transform(compressor);
continue; continue;
@@ -3776,6 +3789,37 @@ Compressor.prototype.compress = function(node) {
return body; return body;
} }
function adjust_refs(value, mode) {
if (!mode) return;
if (!value) return;
switch (mode) {
case 4:
return;
case 3:
case 2:
value = value.tail_node();
}
var fixed_by_id = new Dictionary();
value.walk(new TreeWalker(function(node) {
if (!(node instanceof AST_SymbolRef)) return;
var def = node.definition();
if (def.scope.resolve() !== scope) return;
var fixed = node.fixed;
if (!fixed || !fixed_by_id.has(def.id)) {
fixed_by_id.set(def.id, fixed);
} else if (fixed_by_id.get(def.id) !== fixed) {
fixed_by_id.set(def.id, false);
}
}));
if (fixed_by_id.size() > 0) jump.value.walk(new TreeWalker(function(node) {
if (!(node instanceof AST_SymbolRef)) return;
var def = node.definition();
var fixed = node.fixed;
if (!fixed || !fixed_by_id.has(def.id)) return;
if (fixed_by_id.get(def.id) !== fixed) node.fixed = false;
}));
}
function next_index(i) { function next_index(i) {
declare_only = true; declare_only = true;
for (var j = i; ++j < statements.length;) { for (var j = i; ++j < statements.length;) {

View File

@@ -9321,12 +9321,11 @@ issue_4874: {
})(a = 42); })(a = 42);
} }
expect: { expect: {
var a;
null; null;
(function(b) { (function(b) {
for (var c in a && a[console.log("PASS")]) for (var c in 42, 42[console.log("PASS")])
console; console;
})(a = 42); })();
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }

View File

@@ -2505,7 +2505,7 @@ issue_5463: {
var a, b, b; var a, b, b;
console.log("PASS") && ( console.log("PASS") && (
b = a = void 0, b = a = void 0,
b = [a = FAIL] = a && a b = [a = FAIL] = a
); );
} }
expect_stdout: "PASS" expect_stdout: "PASS"

View File

@@ -1878,7 +1878,7 @@ issue_2846: {
var c = function(a, b) { var c = function(a, b) {
a = 0; a = 0;
b && b(a); b && b(a);
return a++; return +a;
}(); }();
console.log(c); console.log(c);
} }
@@ -2976,14 +2976,12 @@ issue_4025: {
console.log(a, b, d); console.log(a, b, d);
} }
expect: { expect: {
var c = 0;
try { try {
console.log(c); console.log(0);
} finally { } finally {
var d = c + 1; 0;
c = 0;
} }
console.log(1, 1, d); console.log(1, 1, 1);
} }
expect_stdout: [ expect_stdout: [
"0", "0",
@@ -3696,7 +3694,7 @@ issue_5224: {
(function() { (function() {
var a = "FAIL 1"; var a = "FAIL 1";
null; null;
a = console.log(a); console.log(a);
})(function() { })(function() {
console.log(1 / 0); console.log(1 / 0);
a; a;

View File

@@ -624,7 +624,7 @@ issue_5411_2: {
var b, c; var b, c;
b++; b++;
b = "PASS", b = "PASS",
c = c && c[b]; c;
console.log(b); console.log(b);
} }
expect_stdout: "PASS" expect_stdout: "PASS"

View File

@@ -1834,6 +1834,33 @@ switch_return_5: {
] ]
} }
merged_references: {
options = {
if_return: true,
reduce_vars: true,
unused: true,
}
input: {
var a, b = "PASS";
console.log(function(c) {
if (c = b)
return a || c;
c = FAIL;
return a || c;
}());
}
expect: {
var a, b = "PASS";
console.log(function(c) {
if (c = b);
else
c = FAIL;
return a || c;
}());
}
expect_stdout: "PASS"
}
issue_5583: { issue_5583: {
options = { options = {
conditionals: true, conditionals: true,

View File

@@ -2488,7 +2488,7 @@ side_effects_assign: {
console.log(a); console.log(a);
} }
expect: { expect: {
var a = typeof void (a && a.in); var a = "undefined";
console.log(a); console.log(a);
} }
expect_stdout: "undefined" expect_stdout: "undefined"
@@ -2530,7 +2530,8 @@ pure_getters_2: {
var a = a && a.b; var a = a && a.b;
} }
expect: { expect: {
var a = a && a.b; var a;
a && a.b;
} }
} }
@@ -5424,7 +5425,7 @@ issue_2774: {
get a() { get a() {
var b; var b;
(b = true) && b.c; (b = true) && b.c;
b = void 0; void 0;
} }
}.a); }.a);
} }