enhance reduce_vars (#5636)
This commit is contained in:
@@ -621,8 +621,10 @@ Compressor.prototype.compress = function(node) {
|
||||
scope.may_call_this = undefined;
|
||||
}
|
||||
|
||||
function push(tw) {
|
||||
tw.safe_ids = Object.create(tw.safe_ids);
|
||||
function push(tw, sequential) {
|
||||
var safe_ids = Object.create(tw.safe_ids);
|
||||
if (!sequential) safe_ids.seq = {};
|
||||
tw.safe_ids = safe_ids;
|
||||
}
|
||||
|
||||
function pop(tw) {
|
||||
@@ -643,7 +645,14 @@ Compressor.prototype.compress = function(node) {
|
||||
var safe = tw.safe_ids[def.id];
|
||||
if (safe) {
|
||||
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 (is_arguments(def)) 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
if (node instanceof AST_DefaultValue) {
|
||||
reset_flags(node);
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
node.value.walk(tw);
|
||||
pop(tw);
|
||||
var save = fixed;
|
||||
@@ -899,14 +908,15 @@ Compressor.prototype.compress = function(node) {
|
||||
var fn = this;
|
||||
fn.inlined = false;
|
||||
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;
|
||||
fn.walk(new TreeWalker(function(node) {
|
||||
if (hit) return aborts = true;
|
||||
if (node instanceof AST_Return) return hit = true;
|
||||
if (node instanceof AST_Scope && node !== fn) return true;
|
||||
}));
|
||||
if (aborts) push(tw);
|
||||
if (aborts) push(tw, sequential);
|
||||
reset_variables(tw, compressor, fn);
|
||||
// Virtually turn IIFE parameters into variable definitions:
|
||||
// (function(a,b) {...})(c,d) ---> (function() {var a=c,b=d; ...})()
|
||||
@@ -991,7 +1001,7 @@ Compressor.prototype.compress = function(node) {
|
||||
return walk_lazy();
|
||||
}
|
||||
var safe = safe_to_read(tw, ld);
|
||||
if (lazy) push(tw);
|
||||
if (lazy) push(tw, true);
|
||||
right.walk(tw);
|
||||
if (lazy) pop(tw);
|
||||
if (safe && !left.in_arg && safe_to_assign(tw, ld)) {
|
||||
@@ -1073,7 +1083,7 @@ Compressor.prototype.compress = function(node) {
|
||||
function walk_lazy() {
|
||||
if (!lazy) return;
|
||||
left.walk(tw);
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
right.walk(tw);
|
||||
pop(tw);
|
||||
return true;
|
||||
@@ -1082,7 +1092,7 @@ Compressor.prototype.compress = function(node) {
|
||||
def(AST_Binary, function(tw) {
|
||||
if (!lazy_op[this.operator]) return;
|
||||
this.left.walk(tw);
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
this.right.walk(tw);
|
||||
pop(tw);
|
||||
return true;
|
||||
@@ -1112,7 +1122,7 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
exp.walk(tw);
|
||||
var optional = node.optional;
|
||||
if (optional) push(tw);
|
||||
if (optional) push(tw, true);
|
||||
node.args.forEach(function(arg) {
|
||||
arg.walk(tw);
|
||||
});
|
||||
@@ -1182,7 +1192,7 @@ Compressor.prototype.compress = function(node) {
|
||||
});
|
||||
def(AST_ClassInitBlock, function(tw, descend, compressor) {
|
||||
var node = this;
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
reset_variables(tw, compressor, node);
|
||||
descend();
|
||||
pop_scope(tw, node);
|
||||
@@ -1190,19 +1200,19 @@ Compressor.prototype.compress = function(node) {
|
||||
});
|
||||
def(AST_Conditional, function(tw) {
|
||||
this.condition.walk(tw);
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
this.consequent.walk(tw);
|
||||
pop(tw);
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
this.alternative.walk(tw);
|
||||
pop(tw);
|
||||
return true;
|
||||
});
|
||||
def(AST_DefaultValue, function(tw) {
|
||||
this.name.walk(tw);
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
this.value.walk(tw);
|
||||
pop(tw);
|
||||
this.name.walk(tw);
|
||||
return true;
|
||||
});
|
||||
def(AST_Do, function(tw) {
|
||||
@@ -1274,18 +1284,18 @@ Compressor.prototype.compress = function(node) {
|
||||
});
|
||||
def(AST_If, function(tw) {
|
||||
this.condition.walk(tw);
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
this.body.walk(tw);
|
||||
pop(tw);
|
||||
if (this.alternative) {
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
this.alternative.walk(tw);
|
||||
pop(tw);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
def(AST_LabeledStatement, function(tw) {
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
this.body.walk(tw);
|
||||
pop(tw);
|
||||
return true;
|
||||
@@ -1319,7 +1329,7 @@ Compressor.prototype.compress = function(node) {
|
||||
def(AST_Sub, function(tw) {
|
||||
if (!this.optional) return;
|
||||
this.expression.walk(tw);
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
this.property.walk(tw);
|
||||
pop(tw);
|
||||
return true;
|
||||
@@ -1334,7 +1344,7 @@ Compressor.prototype.compress = function(node) {
|
||||
branch.expression.walk(tw);
|
||||
if (first) {
|
||||
first = false;
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
}
|
||||
})
|
||||
if (!first) pop(tw);
|
||||
@@ -1342,7 +1352,7 @@ Compressor.prototype.compress = function(node) {
|
||||
return true;
|
||||
});
|
||||
def(AST_SwitchBranch, function(tw) {
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
walk_body(this, tw);
|
||||
pop(tw);
|
||||
return true;
|
||||
@@ -1452,7 +1462,7 @@ Compressor.prototype.compress = function(node) {
|
||||
node.globals.each(function(def) {
|
||||
reset_def(tw, compressor, def);
|
||||
});
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
reset_variables(tw, compressor, node);
|
||||
descend();
|
||||
pop_scope(tw, node);
|
||||
@@ -1461,11 +1471,11 @@ Compressor.prototype.compress = function(node) {
|
||||
def(AST_Try, function(tw, descend, compressor) {
|
||||
var node = this;
|
||||
reset_block_variables(tw, compressor, node);
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
walk_body(node, tw);
|
||||
pop(tw);
|
||||
if (node.bcatch) {
|
||||
push(tw);
|
||||
push(tw, true);
|
||||
node.bcatch.walk(tw);
|
||||
pop(tw);
|
||||
}
|
||||
@@ -1590,6 +1600,7 @@ Compressor.prototype.compress = function(node) {
|
||||
// - `push()` & `pop()` when visiting conditional branches
|
||||
// - backup & restore via `save_ids` when visiting out-of-order sections
|
||||
tw.safe_ids = Object.create(null);
|
||||
tw.safe_ids.seq = {};
|
||||
this.walk(tw);
|
||||
});
|
||||
|
||||
@@ -3524,6 +3535,7 @@ Compressor.prototype.compress = function(node) {
|
||||
stat.alternative = make_node(AST_BlockStatement, stat, {
|
||||
body: as_statement_array(stat.alternative).concat(extract_functions(merge_jump, jump)),
|
||||
});
|
||||
adjust_refs(ab.value, merge_jump);
|
||||
statements[i] = stat;
|
||||
statements[i] = stat.transform(compressor);
|
||||
continue;
|
||||
@@ -3563,6 +3575,7 @@ Compressor.prototype.compress = function(node) {
|
||||
stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
|
||||
body: as_statement_array_with_return(stat.alternative, alt),
|
||||
});
|
||||
adjust_refs(alt.value, merge_jump);
|
||||
statements[i] = stat;
|
||||
statements[i] = stat.transform(compressor);
|
||||
continue;
|
||||
@@ -3776,6 +3789,37 @@ Compressor.prototype.compress = function(node) {
|
||||
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) {
|
||||
declare_only = true;
|
||||
for (var j = i; ++j < statements.length;) {
|
||||
|
||||
Reference in New Issue
Block a user