enhance dead_code (#3990)
This commit is contained in:
@@ -571,7 +571,14 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
def(AST_Assign, function(tw, descend, compressor) {
|
||||
var node = this;
|
||||
var eq = node.operator == "=";
|
||||
var sym = node.left;
|
||||
if (eq && sym.equivalent_to(node.right) && !sym.has_side_effects(compressor)) {
|
||||
node.right.walk(tw);
|
||||
walk_prop(sym);
|
||||
node.__drop = true;
|
||||
return true;
|
||||
}
|
||||
if (!(sym instanceof AST_SymbolRef)) {
|
||||
mark_assignment_to_arguments(sym);
|
||||
return;
|
||||
@@ -579,7 +586,6 @@ merge(Compressor.prototype, {
|
||||
var d = sym.definition();
|
||||
d.assignments++;
|
||||
var fixed = d.fixed;
|
||||
var eq = node.operator == "=";
|
||||
var value = eq ? node.right : node;
|
||||
if (is_modified(compressor, tw, node, value, 0)) return;
|
||||
var safe = eq || safe_to_read(tw, d);
|
||||
@@ -609,6 +615,21 @@ merge(Compressor.prototype, {
|
||||
d.fixed = false;
|
||||
}
|
||||
return true;
|
||||
|
||||
function walk_prop(node) {
|
||||
if (node instanceof AST_Dot) {
|
||||
walk_prop(node.expression);
|
||||
} else if (node instanceof AST_Sub) {
|
||||
walk_prop(node.expression);
|
||||
node.property.walk(tw);
|
||||
} else if (node instanceof AST_SymbolRef) {
|
||||
var d = node.definition();
|
||||
push_ref(d, node);
|
||||
node.fixed = d.fixed;
|
||||
} else {
|
||||
node.walk(tw);
|
||||
}
|
||||
}
|
||||
});
|
||||
def(AST_Binary, function(tw) {
|
||||
if (!lazy_op[this.operator]) return;
|
||||
@@ -7843,8 +7864,15 @@ merge(Compressor.prototype, {
|
||||
if (compressor.option("dead_code")) {
|
||||
if (self.left instanceof AST_PropAccess) {
|
||||
if (self.operator == "=") {
|
||||
if (self.left.equivalent_to(self.right)
|
||||
&& (self.left instanceof AST_Dot || !self.left.property.has_side_effects(compressor))) {
|
||||
if (self.__drop) {
|
||||
var props = [];
|
||||
flatten(self.left, props);
|
||||
flatten(self.right, props);
|
||||
return props.length == 0 ? make_node(AST_Number, self, {
|
||||
value: 0
|
||||
}) : make_sequence(self, props).optimize(compressor);
|
||||
}
|
||||
if (self.left.equivalent_to(self.right) && !self.left.has_side_effects(compressor)) {
|
||||
return self.right;
|
||||
}
|
||||
var exp = self.left.expression;
|
||||
@@ -7934,6 +7962,11 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
return try_evaluate(compressor, self);
|
||||
|
||||
function flatten(node, props) {
|
||||
if (!(node.expression instanceof AST_SymbolRef)) props.push(node.expression);
|
||||
if (node instanceof AST_Sub) props.push(node.property);
|
||||
}
|
||||
|
||||
function in_try(level, node) {
|
||||
var right = self.right;
|
||||
self.right = make_node(AST_Null, right);
|
||||
|
||||
@@ -1169,29 +1169,131 @@ redundant_assignments: {
|
||||
expect_stdout: "PASS PASS"
|
||||
}
|
||||
|
||||
self_assignments: {
|
||||
self_assignments_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
var a = "PASS", b = 0, l = [ "FAIL", "PASS" ], o = { p: "PASS" };
|
||||
var a = "PASS";
|
||||
a = a;
|
||||
l[0] = l[0];
|
||||
l[b] = l[b];
|
||||
l[b++] = l[b++];
|
||||
o.p = o.p;
|
||||
console.log(a, b, l[0], o.p);
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "PASS", b = 0, l = [ "FAIL", "PASS" ], o = { p: "PASS" };
|
||||
var a = "PASS";
|
||||
a;
|
||||
l[0];
|
||||
l[b];
|
||||
l[b++] = l[b++];
|
||||
o.p;
|
||||
console.log(a, b, l[0], o.p);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS 2 PASS PASS"
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
self_assignments_2: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = "q", o = {
|
||||
p: "PASS",
|
||||
};
|
||||
o.p = o.p;
|
||||
o[a] = o[a];
|
||||
console.log(o.p, o[a]);
|
||||
}
|
||||
expect: {
|
||||
var a = "q", o = {
|
||||
p: "PASS",
|
||||
};
|
||||
console.log(o.p, o[a]);
|
||||
}
|
||||
expect_stdout: "PASS undefined"
|
||||
}
|
||||
|
||||
self_assignments_3: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = "q", o = {
|
||||
p: "FAIL",
|
||||
get q() {
|
||||
return "PASS";
|
||||
},
|
||||
set q(v) {
|
||||
this.p = v;
|
||||
},
|
||||
};
|
||||
o.p = o.p;
|
||||
o[a] = o[a];
|
||||
console.log(o.p, o[a]);
|
||||
}
|
||||
expect: {
|
||||
var a = "q", o = {
|
||||
p: "FAIL",
|
||||
get q() {
|
||||
return "PASS";
|
||||
},
|
||||
set q(v) {
|
||||
this.p = v;
|
||||
},
|
||||
};
|
||||
o.p = o.p;
|
||||
o[a] = o[a];
|
||||
console.log(o.p, o[a]);
|
||||
}
|
||||
expect_stdout: "PASS PASS"
|
||||
}
|
||||
|
||||
self_assignments_4: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var i = 0, l = [ "PASS" ];
|
||||
l[0] = l[0];
|
||||
l[i] = l[i];
|
||||
console.log(l[0], i);
|
||||
}
|
||||
expect: {
|
||||
var i = 0, l = [ "PASS" ];
|
||||
console.log(l[0], i);
|
||||
}
|
||||
expect_stdout: "PASS 0"
|
||||
}
|
||||
|
||||
self_assignments_5: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
passes: 3,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var i = 0, l = [ "FAIL", "PASS" ];
|
||||
l[0] = l[0];
|
||||
l[i] = l[i];
|
||||
l[i++] = l[i++];
|
||||
console.log(l[0], i);
|
||||
}
|
||||
expect: {
|
||||
var i = 0, l = [ "FAIL", "PASS" ];
|
||||
l[0] = l[1];
|
||||
console.log(l[0], 2);
|
||||
}
|
||||
expect_stdout: "PASS 2"
|
||||
}
|
||||
|
||||
issue_3967: {
|
||||
|
||||
Reference in New Issue
Block a user