enhance collapse_vars (#3616)
This commit is contained in:
@@ -1147,7 +1147,7 @@ merge(Compressor.prototype, {
|
||||
&& (scan_lhs && lhs.equivalent_to(node)
|
||||
|| scan_rhs && (hit_rhs = scan_rhs(node, this)))) {
|
||||
if (stop_if_hit && (hit_rhs || !lhs_local || !replace_all)) {
|
||||
abort = true;
|
||||
if (!hit_rhs || !value_def) abort = true;
|
||||
return node;
|
||||
}
|
||||
if (is_lhs(node, parent)) {
|
||||
@@ -1541,14 +1541,27 @@ merge(Compressor.prototype, {
|
||||
function find_stop(node, level) {
|
||||
var parent = scanner.parent(level);
|
||||
if (parent instanceof AST_Array) return value_def ? find_stop(parent, level + 1) : node;
|
||||
if (parent instanceof AST_Assign) return node;
|
||||
if (parent instanceof AST_Binary) {
|
||||
if (!value_def || parent.left !== node) return node;
|
||||
if (parent instanceof AST_Assign) {
|
||||
if (!value_def) return node;
|
||||
if (lhs.equivalent_to(parent.left)) return node;
|
||||
if (get_rvalue(candidate).equivalent_to(parent.left)) return node;
|
||||
return find_stop(parent, level + 1);
|
||||
}
|
||||
if (parent instanceof AST_Call) return node;
|
||||
if (parent instanceof AST_Binary) {
|
||||
if (!value_def) return node;
|
||||
if (lazy_op[parent.operator] && parent.left !== node) {
|
||||
var grandparent = scanner.parent(level + 1);
|
||||
if (!(grandparent instanceof AST_Binary)) return node;
|
||||
if (grandparent.operator != parent.operator) return node;
|
||||
}
|
||||
return find_stop(parent, level + 1);
|
||||
}
|
||||
if (parent instanceof AST_Call) return value_def ? parent : node;
|
||||
if (parent instanceof AST_Case) return node;
|
||||
if (parent instanceof AST_Conditional) return node;
|
||||
if (parent instanceof AST_Conditional) {
|
||||
if (!value_def || parent.condition !== node) return node;
|
||||
return find_stop(parent, level + 1);
|
||||
}
|
||||
if (parent instanceof AST_Definitions) return find_stop_unused(parent, level + 1);
|
||||
if (parent instanceof AST_Exit) return node;
|
||||
if (parent instanceof AST_If) return node;
|
||||
@@ -1562,7 +1575,10 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
if (parent instanceof AST_SimpleStatement) return find_stop_unused(parent, level + 1);
|
||||
if (parent instanceof AST_Switch) return node;
|
||||
if (parent instanceof AST_Unary) return node;
|
||||
if (parent instanceof AST_Unary) {
|
||||
if (parent.operator == "delete") return node;
|
||||
return value_def ? find_stop(parent, level + 1) : node;
|
||||
}
|
||||
if (parent instanceof AST_VarDef) return node;
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -6965,3 +6965,330 @@ setter_side_effect: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
substitution_assign: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f1(a, b) {
|
||||
f1 = b = a;
|
||||
console.log(a, b);
|
||||
}
|
||||
function f2(a, b) {
|
||||
a = 1 + (b = a);
|
||||
console.log(a, b);
|
||||
}
|
||||
function f3(a, b) {
|
||||
b = 1 + (b = a);
|
||||
console.log(a, b);
|
||||
}
|
||||
f1(42, "foo");
|
||||
f2(42, "foo");
|
||||
f3(42, "foo");
|
||||
}
|
||||
expect: {
|
||||
function f1(a, b) {
|
||||
f1 = a;
|
||||
console.log(a, a);
|
||||
}
|
||||
function f2(a, b) {
|
||||
a = 1 + (b = a);
|
||||
console.log(a, b);
|
||||
}
|
||||
function f3(a, b) {
|
||||
b = 1 + (b = a);
|
||||
console.log(a, b);
|
||||
}
|
||||
f1(42, "foo");
|
||||
f2(42, "foo");
|
||||
f3(42, "foo");
|
||||
}
|
||||
expect_stdout: [
|
||||
"42 42",
|
||||
"43 42",
|
||||
"42 43",
|
||||
]
|
||||
}
|
||||
|
||||
substitution_arithmetic: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f1(a, b) {
|
||||
console.log((b = a) + a, b);
|
||||
}
|
||||
function f2(a, b) {
|
||||
console.log(a - (b = a), b);
|
||||
}
|
||||
function f3(a, b) {
|
||||
console.log(a / (b = a) + b, b);
|
||||
}
|
||||
f1(42, "foo");
|
||||
f2(42, "foo");
|
||||
f3(42, "foo");
|
||||
}
|
||||
expect: {
|
||||
function f1(a, b) {
|
||||
console.log(a + a, a);
|
||||
}
|
||||
function f2(a, b) {
|
||||
console.log(a - a, a);
|
||||
}
|
||||
function f3(a, b) {
|
||||
console.log(a / a + a, a);
|
||||
}
|
||||
f1(42, "foo");
|
||||
f2(42, "foo");
|
||||
f3(42, "foo");
|
||||
}
|
||||
expect_stdout: [
|
||||
"84 42",
|
||||
"0 42",
|
||||
"43 42",
|
||||
]
|
||||
}
|
||||
|
||||
substitution_logical_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f1(a, b) {
|
||||
console.log((b = a) && a, b);
|
||||
}
|
||||
function f2(a, b) {
|
||||
console.log(a && (b = a), b);
|
||||
}
|
||||
f1(42, "foo");
|
||||
f1(null, true);
|
||||
f2(42, "foo");
|
||||
f2(null, true);
|
||||
}
|
||||
expect: {
|
||||
function f1(a, b) {
|
||||
console.log(a && a, a);
|
||||
}
|
||||
function f2(a, b) {
|
||||
console.log(a && (b = a), b);
|
||||
}
|
||||
f1(42, "foo");
|
||||
f1(null, true);
|
||||
f2(42, "foo");
|
||||
f2(null, true);
|
||||
}
|
||||
expect_stdout: [
|
||||
"42 42",
|
||||
"null null",
|
||||
"42 42",
|
||||
"null true"
|
||||
]
|
||||
}
|
||||
|
||||
substitution_logical_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f1(a, b) {
|
||||
console.log((b = a) && a && b);
|
||||
}
|
||||
function f2(a, b) {
|
||||
console.log((b = a) && a || b);
|
||||
}
|
||||
function f3(a, b) {
|
||||
console.log((b = a) || a && b);
|
||||
}
|
||||
function f4(a, b) {
|
||||
console.log((b = a) || a || b);
|
||||
}
|
||||
f1(42, "foo");
|
||||
f1(null, true);
|
||||
f2(42, "foo");
|
||||
f2(null, true);
|
||||
f3(42, "foo");
|
||||
f3(null, true);
|
||||
f4(42, "foo");
|
||||
f4(null, true);
|
||||
}
|
||||
expect: {
|
||||
function f1(a, b) {
|
||||
console.log(a && a && a);
|
||||
}
|
||||
function f2(a, b) {
|
||||
console.log(a && a || a);
|
||||
}
|
||||
function f3(a, b) {
|
||||
console.log(a || a && a);
|
||||
}
|
||||
function f4(a, b) {
|
||||
console.log(a || a || a);
|
||||
}
|
||||
f1(42, "foo");
|
||||
f1(null, true);
|
||||
f2(42, "foo");
|
||||
f2(null, true);
|
||||
f3(42, "foo");
|
||||
f3(null, true);
|
||||
f4(42, "foo");
|
||||
f4(null, true);
|
||||
}
|
||||
expect_stdout: [
|
||||
"42",
|
||||
"null",
|
||||
"42",
|
||||
"null",
|
||||
"42",
|
||||
"null",
|
||||
"42",
|
||||
"null",
|
||||
]
|
||||
}
|
||||
|
||||
substitution_logical_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f1(a, b) {
|
||||
console.log(a && (b = a) && b);
|
||||
}
|
||||
function f2(a, b) {
|
||||
console.log(a && (b = a) || b);
|
||||
}
|
||||
function f3(a, b) {
|
||||
console.log(a || (b = a) && b);
|
||||
}
|
||||
function f4(a, b) {
|
||||
console.log(a || (b = a) || b);
|
||||
}
|
||||
f1(42, "foo");
|
||||
f1(null, true);
|
||||
f2(42, "foo");
|
||||
f2(null, true);
|
||||
f3(42, "foo");
|
||||
f3(null, true);
|
||||
f4(42, "foo");
|
||||
f4(null, true);
|
||||
}
|
||||
expect: {
|
||||
function f1(a, b) {
|
||||
console.log(a && a && a);
|
||||
}
|
||||
function f2(a, b) {
|
||||
console.log(a && (b = a) || b);
|
||||
}
|
||||
function f3(a, b) {
|
||||
console.log(a || a && a);
|
||||
}
|
||||
function f4(a, b) {
|
||||
console.log(a || a || a);
|
||||
}
|
||||
f1(42, "foo");
|
||||
f1(null, true);
|
||||
f2(42, "foo");
|
||||
f2(null, true);
|
||||
f3(42, "foo");
|
||||
f3(null, true);
|
||||
f4(42, "foo");
|
||||
f4(null, true);
|
||||
}
|
||||
expect_stdout: [
|
||||
"42",
|
||||
"null",
|
||||
"42",
|
||||
"true",
|
||||
"42",
|
||||
"null",
|
||||
"42",
|
||||
"null",
|
||||
]
|
||||
}
|
||||
|
||||
substitution_conditional: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f1(a, b) {
|
||||
console.log((b = a) ? a : b, a, b);
|
||||
}
|
||||
function f2(a, b) {
|
||||
console.log(a ? b = a : b, a, b);
|
||||
}
|
||||
function f3(a, b) {
|
||||
console.log(a ? a : b = a, a, b);
|
||||
}
|
||||
f1("foo", "bar");
|
||||
f1(null, true);
|
||||
f2("foo", "bar");
|
||||
f2(null, true);
|
||||
f3("foo", "bar");
|
||||
f3(null, true);
|
||||
}
|
||||
expect: {
|
||||
function f1(a, b) {
|
||||
console.log(a ? a : a, a, a);
|
||||
}
|
||||
function f2(a, b) {
|
||||
console.log(a ? b = a : b, a, b);
|
||||
}
|
||||
function f3(a, b) {
|
||||
console.log(a ? a : b = a, a, b);
|
||||
}
|
||||
f1("foo", "bar");
|
||||
f1(null, true);
|
||||
f2("foo", "bar");
|
||||
f2(null, true);
|
||||
f3("foo", "bar");
|
||||
f3(null, true);
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo foo foo",
|
||||
"null null null",
|
||||
"foo foo foo",
|
||||
"true null true",
|
||||
"foo foo bar",
|
||||
"null null null",
|
||||
]
|
||||
}
|
||||
|
||||
substitution_unary: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f1(a, b) {
|
||||
console.log(typeof (b = a), a, b);
|
||||
}
|
||||
function f2(a, b) {
|
||||
console.log(void (b = a), a, b);
|
||||
}
|
||||
function f3(a, b) {
|
||||
console.log(delete (b = a), a, b);
|
||||
}
|
||||
f1(42, "foo");
|
||||
f2(42, "foo");
|
||||
f3(42, "foo");
|
||||
}
|
||||
expect: {
|
||||
function f1(a, b) {
|
||||
console.log(typeof a, a, a);
|
||||
}
|
||||
function f2(a, b) {
|
||||
console.log(void a, a, a);
|
||||
}
|
||||
function f3(a, b) {
|
||||
console.log(delete (b = a), a, b);
|
||||
}
|
||||
f1(42, "foo");
|
||||
f2(42, "foo");
|
||||
f3(42, "foo");
|
||||
}
|
||||
expect_stdout: [
|
||||
"number 42 42",
|
||||
"undefined 42 42",
|
||||
"true 42 42",
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user