enhance reduce_vars (#5636)
This commit is contained in:
@@ -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;) {
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user