Skip to content

Commit 6a3fe9d

Browse files
authored
fix corner cases in reduce_vars (#5097)
fixes #5096
1 parent ec7fadc commit 6a3fe9d

File tree

3 files changed

+191
-28
lines changed

3 files changed

+191
-28
lines changed

lib/compress.js

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -884,15 +884,12 @@ merge(Compressor.prototype, {
884884
}
885885
if (ld && right instanceof AST_LambdaExpression) {
886886
walk_assign();
887-
if (ld.escaped.length) {
888-
right.walk(tw);
889-
} else {
890-
right.parent_scope.resolve().fn_defs.push(right);
891-
right.safe_ids = null;
892-
if (!node.write_only) mark_fn_def(tw, ld, right);
893-
}
887+
right.parent_scope.resolve().fn_defs.push(right);
888+
right.safe_ids = null;
889+
if (!ld.fixed || !node.write_only) mark_fn_def(tw, ld, right);
894890
return true;
895-
} else if (scan) {
891+
}
892+
if (scan) {
896893
right.walk(tw);
897894
walk_assign();
898895
return true;
@@ -1397,31 +1394,38 @@ merge(Compressor.prototype, {
13971394
var node = this;
13981395
var value = node.value;
13991396
if (value instanceof AST_LambdaExpression && node.name instanceof AST_SymbolDeclaration) {
1397+
walk_defn();
14001398
value.parent_scope.resolve().fn_defs.push(value);
14011399
value.safe_ids = null;
1400+
var ld = node.name.definition();
1401+
if (!ld.fixed) mark_fn_def(tw, ld, value);
14021402
} else if (value) {
14031403
value.walk(tw);
1404-
} else if (!(tw.parent() instanceof AST_Let)) {
1405-
return;
1404+
walk_defn();
1405+
} else if (tw.parent() instanceof AST_Let) {
1406+
walk_defn();
14061407
}
1407-
scan_declaration(tw, compressor, node.name, function() {
1408-
return node.value || make_node(AST_Undefined, node);
1409-
}, function(name, fixed) {
1410-
var d = name.definition();
1411-
if (fixed && safe_to_assign(tw, d, true)) {
1412-
mark(tw, d);
1413-
tw.loop_ids[d.id] = tw.in_loop;
1414-
d.fixed = fixed;
1415-
d.fixed.assigns = [ node ];
1416-
if (name instanceof AST_SymbolConst && d.redefined()
1417-
|| !(can_drop_symbol(name) || is_safe_lexical(d))) {
1418-
d.single_use = false;
1419-
}
1420-
} else {
1421-
d.fixed = false;
1422-
}
1423-
});
14241408
return true;
1409+
1410+
function walk_defn() {
1411+
scan_declaration(tw, compressor, node.name, function() {
1412+
return node.value || make_node(AST_Undefined, node);
1413+
}, function(name, fixed) {
1414+
var d = name.definition();
1415+
if (fixed && safe_to_assign(tw, d, true)) {
1416+
mark(tw, d);
1417+
tw.loop_ids[d.id] = tw.in_loop;
1418+
d.fixed = fixed;
1419+
d.fixed.assigns = [ node ];
1420+
if (name instanceof AST_SymbolConst && d.redefined()
1421+
|| !(can_drop_symbol(name) || is_safe_lexical(d))) {
1422+
d.single_use = false;
1423+
}
1424+
} else {
1425+
d.fixed = false;
1426+
}
1427+
});
1428+
}
14251429
});
14261430
def(AST_While, function(tw, descend) {
14271431
var save_loop = tw.in_loop;

test/compress/arrows.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ reduce_iife_3: {
556556
node_version: ">=4"
557557
}
558558

559-
reduce_lambda: {
559+
reduce_lambda_1: {
560560
options = {
561561
evaluate: true,
562562
reduce_vars: true,
@@ -588,6 +588,43 @@ reduce_lambda: {
588588
node_version: ">=4"
589589
}
590590

591+
reduce_lambda_2: {
592+
options = {
593+
evaluate: true,
594+
passes: 2,
595+
reduce_vars: true,
596+
side_effects: true,
597+
unused: true,
598+
}
599+
input: {
600+
(function(f, a, b) {
601+
f = () => {
602+
console.log(a, b);
603+
};
604+
a = "foo", b = 42;
605+
f();
606+
b = "bar";
607+
f();
608+
})();
609+
}
610+
expect: {
611+
(function(f, a, b) {
612+
f = () => {
613+
console.log("foo", b);
614+
};
615+
b = 42;
616+
f();
617+
b = "bar";
618+
f();
619+
})();
620+
}
621+
expect_stdout: [
622+
"foo 42",
623+
"foo bar",
624+
]
625+
node_version: ">=4"
626+
}
627+
591628
single_use_recursive: {
592629
options = {
593630
reduce_vars: true,

test/compress/functions.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6413,3 +6413,125 @@ issue_5067: {
64136413
}
64146414
expect: {}
64156415
}
6416+
6417+
issue_5096_1: {
6418+
options = {
6419+
evaluate: true,
6420+
passes: 2,
6421+
reduce_vars: true,
6422+
side_effects: true,
6423+
toplevel: true,
6424+
}
6425+
input: {
6426+
var a, b = "FAIL", c = 1;
6427+
do {
6428+
a && a();
6429+
a = function() {
6430+
b = "PASS";
6431+
};
6432+
} while (c--);
6433+
console.log(b);
6434+
}
6435+
expect: {
6436+
var a, b = "FAIL", c = 1;
6437+
do {
6438+
a && a();
6439+
a = function() {
6440+
b = "PASS";
6441+
};
6442+
} while (c--);
6443+
console.log(b);
6444+
}
6445+
expect_stdout: "PASS"
6446+
}
6447+
6448+
issue_5096_2: {
6449+
options = {
6450+
passes: 2,
6451+
reduce_vars: true,
6452+
side_effects: true,
6453+
toplevel: true,
6454+
unused: true,
6455+
}
6456+
input: {
6457+
var a, b = "FAIL", c = 1;
6458+
do {
6459+
a && a();
6460+
a = function() {
6461+
b = "PASS";
6462+
};
6463+
} while (c--);
6464+
console.log(b);
6465+
}
6466+
expect: {
6467+
var a, b = "FAIL", c = 1;
6468+
do {
6469+
a && a();
6470+
a = function() {
6471+
b = "PASS";
6472+
};
6473+
} while (c--);
6474+
console.log(b);
6475+
}
6476+
expect_stdout: "PASS"
6477+
}
6478+
6479+
issue_5096_3: {
6480+
options = {
6481+
evaluate: true,
6482+
reduce_vars: true,
6483+
side_effects: true,
6484+
toplevel: true,
6485+
}
6486+
input: {
6487+
var b = "FAIL", c = 1;
6488+
do {
6489+
a && a();
6490+
var a = function() {
6491+
b = "PASS";
6492+
};
6493+
} while (c--);
6494+
console.log(b);
6495+
}
6496+
expect: {
6497+
var b = "FAIL", c = 1;
6498+
do {
6499+
a && a();
6500+
var a = function() {
6501+
b = "PASS";
6502+
};
6503+
} while (c--);
6504+
console.log(b);
6505+
}
6506+
expect_stdout: "PASS"
6507+
}
6508+
6509+
issue_5096_4: {
6510+
options = {
6511+
reduce_vars: true,
6512+
side_effects: true,
6513+
toplevel: true,
6514+
unused: true,
6515+
}
6516+
input: {
6517+
var b = "FAIL", c = 1;
6518+
do {
6519+
a && a();
6520+
var a = function() {
6521+
b = "PASS";
6522+
};
6523+
} while (c--);
6524+
console.log(b);
6525+
}
6526+
expect: {
6527+
var b = "FAIL", c = 1;
6528+
do {
6529+
a && a();
6530+
var a = function() {
6531+
b = "PASS";
6532+
};
6533+
} while (c--);
6534+
console.log(b);
6535+
}
6536+
expect_stdout: "PASS"
6537+
}

0 commit comments

Comments
 (0)