fix corner cases in reduce_vars & unused (#3955)
fixes #3953 fixes #3956 fixes #3957
This commit is contained in:
@@ -495,6 +495,12 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function to_value(def, sym, fixed) {
|
||||||
|
if (fixed instanceof AST_Node) return fixed;
|
||||||
|
if (typeof fixed == "function") return fixed();
|
||||||
|
return make_node(AST_Undefined, sym);
|
||||||
|
}
|
||||||
|
|
||||||
function ref_once(compressor, def) {
|
function ref_once(compressor, def) {
|
||||||
return compressor.option("unused")
|
return compressor.option("unused")
|
||||||
&& !def.scope.pinned()
|
&& !def.scope.pinned()
|
||||||
@@ -576,8 +582,9 @@ merge(Compressor.prototype, {
|
|||||||
var eq = node.operator == "=";
|
var eq = node.operator == "=";
|
||||||
var value = eq ? node.right : node;
|
var value = eq ? node.right : node;
|
||||||
if (is_modified(compressor, tw, node, value, 0)) return;
|
if (is_modified(compressor, tw, node, value, 0)) return;
|
||||||
|
var safe = eq || safe_to_read(tw, d);
|
||||||
node.right.walk(tw);
|
node.right.walk(tw);
|
||||||
if ((eq || safe_to_read(tw, d)) && safe_to_assign(tw, d)) {
|
if (safe && safe_to_assign(tw, d)) {
|
||||||
push_ref(d, sym);
|
push_ref(d, sym);
|
||||||
mark(tw, d);
|
mark(tw, d);
|
||||||
if (eq) {
|
if (eq) {
|
||||||
@@ -587,9 +594,8 @@ merge(Compressor.prototype, {
|
|||||||
return node.right;
|
return node.right;
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
if (fixed == null) fixed = make_node(AST_Undefined, d.orig[0]);
|
|
||||||
sym.fixed = d.fixed = function() {
|
sym.fixed = d.fixed = function() {
|
||||||
var value = fixed instanceof AST_Node ? fixed : fixed();
|
var value = to_value(d, sym, fixed);
|
||||||
return value && make_node(AST_Binary, node, {
|
return value && make_node(AST_Binary, node, {
|
||||||
operator: node.operator.slice(0, -1),
|
operator: node.operator.slice(0, -1),
|
||||||
left: value,
|
left: value,
|
||||||
@@ -597,7 +603,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
sym.fixed.assigns = eq || !fixed.assigns ? [] : fixed.assigns.slice();
|
sym.fixed.assigns = eq || !fixed || !fixed.assigns ? [] : fixed.assigns.slice();
|
||||||
sym.fixed.assigns.push(node);
|
sym.fixed.assigns.push(node);
|
||||||
} else {
|
} else {
|
||||||
sym.walk(tw);
|
sym.walk(tw);
|
||||||
@@ -740,8 +746,8 @@ merge(Compressor.prototype, {
|
|||||||
fn.argnames.forEach(function(arg, i) {
|
fn.argnames.forEach(function(arg, i) {
|
||||||
var d = arg.definition();
|
var d = arg.definition();
|
||||||
if (d.fixed === undefined && (!fn.uses_arguments || tw.has_directive("use strict"))) {
|
if (d.fixed === undefined && (!fn.uses_arguments || tw.has_directive("use strict"))) {
|
||||||
tw.loop_ids[d.id] = tw.in_loop;
|
|
||||||
mark(tw, d);
|
mark(tw, d);
|
||||||
|
tw.loop_ids[d.id] = tw.in_loop;
|
||||||
var value = iife.args[i];
|
var value = iife.args[i];
|
||||||
d.fixed = function() {
|
d.fixed = function() {
|
||||||
var j = fn.argnames.indexOf(arg);
|
var j = fn.argnames.indexOf(arg);
|
||||||
@@ -870,9 +876,8 @@ merge(Compressor.prototype, {
|
|||||||
if (safe_to_read(tw, d) && safe_to_assign(tw, d)) {
|
if (safe_to_read(tw, d) && safe_to_assign(tw, d)) {
|
||||||
push_ref(d, exp);
|
push_ref(d, exp);
|
||||||
mark(tw, d);
|
mark(tw, d);
|
||||||
if (fixed == null) fixed = make_node(AST_Undefined, d.orig[0]);
|
|
||||||
d.fixed = function() {
|
d.fixed = function() {
|
||||||
var value = fixed instanceof AST_Node ? fixed : fixed();
|
var value = to_value(d, exp, fixed);
|
||||||
return value && make_node(AST_Binary, node, {
|
return value && make_node(AST_Binary, node, {
|
||||||
operator: node.operator.slice(0, -1),
|
operator: node.operator.slice(0, -1),
|
||||||
left: make_node(AST_UnaryPrefix, node, {
|
left: make_node(AST_UnaryPrefix, node, {
|
||||||
@@ -884,19 +889,19 @@ merge(Compressor.prototype, {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
d.fixed.assigns = fixed.assigns ? fixed.assigns.slice() : [];
|
d.fixed.assigns = fixed && fixed.assigns ? fixed.assigns.slice() : [];
|
||||||
d.fixed.assigns.push(node);
|
d.fixed.assigns.push(node);
|
||||||
if (node instanceof AST_UnaryPrefix) {
|
if (node instanceof AST_UnaryPrefix) {
|
||||||
exp.fixed = d.fixed;
|
exp.fixed = d.fixed;
|
||||||
} else {
|
} else {
|
||||||
exp.fixed = function() {
|
exp.fixed = function() {
|
||||||
var value = fixed instanceof AST_Node ? fixed : fixed();
|
var value = to_value(d, exp, fixed);
|
||||||
return value && make_node(AST_UnaryPrefix, node, {
|
return value && make_node(AST_UnaryPrefix, node, {
|
||||||
operator: "+",
|
operator: "+",
|
||||||
expression: value
|
expression: value
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exp.fixed.assigns = fixed.assigns;
|
exp.fixed.assigns = fixed && fixed.assigns;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
exp.walk(tw);
|
exp.walk(tw);
|
||||||
@@ -4429,6 +4434,7 @@ merge(Compressor.prototype, {
|
|||||||
if (!drop_vars || sym.id in in_use_ids) {
|
if (!drop_vars || sym.id in in_use_ids) {
|
||||||
if (def.value && indexOf_assign(sym, def) < 0) {
|
if (def.value && indexOf_assign(sym, def) < 0) {
|
||||||
def.value = def.value.drop_side_effect_free(compressor);
|
def.value = def.value.drop_side_effect_free(compressor);
|
||||||
|
if (def.value) def.value.tail_node().write_only = false;
|
||||||
}
|
}
|
||||||
var old_def, var_defs = var_defs_by_id.get(sym.id);
|
var old_def, var_defs = var_defs_by_id.get(sym.id);
|
||||||
if (!def.value) {
|
if (!def.value) {
|
||||||
|
|||||||
@@ -2652,3 +2652,41 @@ issue_3951: {
|
|||||||
"0",
|
"0",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3956: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
function f(b) {
|
||||||
|
console.log(b);
|
||||||
|
a = 1;
|
||||||
|
}
|
||||||
|
var c = f(c += 0);
|
||||||
|
(function(d) {
|
||||||
|
console.log(d);
|
||||||
|
})(console.log(a) ^ 1, c);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c, d;
|
||||||
|
c += 0,
|
||||||
|
console.log(NaN),
|
||||||
|
d = 1 ^ console.log(1),
|
||||||
|
console.log(d);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"NaN",
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -2715,3 +2715,23 @@ issue_3944: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "false"
|
expect_stdout: "false"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3953: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
(a += 0 * (a = 0)) && console.log("PASS");
|
||||||
|
}
|
||||||
|
f(1);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
(a += 0 * (a = 0)) && console.log("PASS");
|
||||||
|
}
|
||||||
|
f(1);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -7273,3 +7273,53 @@ local_assignment_loop: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3957_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
while (a += console.log(a = 0))
|
||||||
|
a = 0;
|
||||||
|
}
|
||||||
|
f("FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
while (a += console.log(a = 0))
|
||||||
|
a = 0;
|
||||||
|
}
|
||||||
|
f("FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3957_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
while (a += console.log(a = 0))
|
||||||
|
a = 0;
|
||||||
|
}
|
||||||
|
f("FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
while (a += console.log(a = 0))
|
||||||
|
a = 0;
|
||||||
|
}
|
||||||
|
f("FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user