Skip to content

Commit 43ec350

Browse files
authored
fix corner case in conditionals (#5674)
fixes #5673
1 parent 63b04a6 commit 43ec350

File tree

2 files changed

+74
-27
lines changed

2 files changed

+74
-27
lines changed

Diff for: lib/compress.js

+32-27
Original file line numberDiff line numberDiff line change
@@ -1828,6 +1828,29 @@ Compressor.prototype.compress = function(node) {
18281828
return wrap ? make_sequence(orig, [ make_node(AST_Number, orig, { value: 0 }), val ]) : val;
18291829
}
18301830

1831+
function merge_expression(base, target, scope) {
1832+
var fixed_by_id = new Dictionary();
1833+
base.walk(new TreeWalker(function(node) {
1834+
if (!(node instanceof AST_SymbolRef)) return;
1835+
var def = node.definition();
1836+
if (scope && def.scope.resolve() !== scope) return;
1837+
var fixed = node.fixed;
1838+
if (!fixed || !fixed_by_id.has(def.id)) {
1839+
fixed_by_id.set(def.id, fixed);
1840+
} else if (fixed_by_id.get(def.id) !== fixed) {
1841+
fixed_by_id.set(def.id, false);
1842+
}
1843+
}));
1844+
if (fixed_by_id.size() > 0) target.walk(new TreeWalker(function(node) {
1845+
if (!(node instanceof AST_SymbolRef)) return;
1846+
var def = node.definition();
1847+
var fixed = node.fixed;
1848+
if (!fixed || !fixed_by_id.has(def.id)) return;
1849+
if (fixed_by_id.get(def.id) !== fixed) node.fixed = false;
1850+
}));
1851+
return target;
1852+
}
1853+
18311854
function merge_sequence(array, node) {
18321855
if (node instanceof AST_Sequence) {
18331856
[].push.apply(array, node.expressions);
@@ -3813,25 +3836,7 @@ Compressor.prototype.compress = function(node) {
38133836
case 2:
38143837
value = value.tail_node();
38153838
}
3816-
var fixed_by_id = new Dictionary();
3817-
value.walk(new TreeWalker(function(node) {
3818-
if (!(node instanceof AST_SymbolRef)) return;
3819-
var def = node.definition();
3820-
if (def.scope.resolve() !== scope) return;
3821-
var fixed = node.fixed;
3822-
if (!fixed || !fixed_by_id.has(def.id)) {
3823-
fixed_by_id.set(def.id, fixed);
3824-
} else if (fixed_by_id.get(def.id) !== fixed) {
3825-
fixed_by_id.set(def.id, false);
3826-
}
3827-
}));
3828-
if (fixed_by_id.size() > 0) jump.value.walk(new TreeWalker(function(node) {
3829-
if (!(node instanceof AST_SymbolRef)) return;
3830-
var def = node.definition();
3831-
var fixed = node.fixed;
3832-
if (!fixed || !fixed_by_id.has(def.id)) return;
3833-
if (fixed_by_id.get(def.id) !== fixed) node.fixed = false;
3834-
}));
3839+
merge_expression(value, jump.value, scope);
38353840
}
38363841

38373842
function next_index(i) {
@@ -12933,7 +12938,7 @@ Compressor.prototype.compress = function(node) {
1293312938
right: fuse(consequent, seq_tail, "condition"),
1293412939
}),
1293512940
consequent: seq_tail.consequent,
12936-
alternative: alternative,
12941+
alternative: merge_expression(seq_tail.alternative, alternative),
1293712942
});
1293812943
}
1293912944
// x ? (y ? a : b) : a ---> !x || y ? a : b
@@ -12945,7 +12950,7 @@ Compressor.prototype.compress = function(node) {
1294512950
operator: "||",
1294612951
right: fuse(consequent, seq_tail, "condition"),
1294712952
}),
12948-
consequent: alternative,
12953+
consequent: merge_expression(seq_tail.consequent, alternative),
1294912954
alternative: seq_tail.alternative,
1295012955
});
1295112956
}
@@ -12958,7 +12963,7 @@ Compressor.prototype.compress = function(node) {
1295812963
operator: "||",
1295912964
right: fuse(alternative, alt_tail, "condition"),
1296012965
}),
12961-
consequent: consequent,
12966+
consequent: merge_expression(consequent, alt_tail.consequent),
1296212967
alternative: alt_tail.alternative,
1296312968
});
1296412969
}
@@ -12972,7 +12977,7 @@ Compressor.prototype.compress = function(node) {
1297212977
right: fuse(alternative, alt_tail, "condition"),
1297312978
}),
1297412979
consequent: alt_tail.consequent,
12975-
alternative: consequent,
12980+
alternative: merge_expression(consequent, alt_tail.alternative),
1297612981
});
1297712982
}
1297812983
// x ? y && a : a ---> (!x || y) && a
@@ -12986,7 +12991,7 @@ Compressor.prototype.compress = function(node) {
1298612991
left: negated,
1298712992
right: fuse(consequent, seq_tail, "left"),
1298812993
}),
12989-
right: alternative,
12994+
right: merge_expression(seq_tail.right, alternative),
1299012995
}).optimize(compressor);
1299112996
}
1299212997
// x ? y || a : a ---> x && y || a
@@ -13000,7 +13005,7 @@ Compressor.prototype.compress = function(node) {
1300013005
left: condition,
1300113006
right: fuse(consequent, seq_tail, "left"),
1300213007
}),
13003-
right: alternative,
13008+
right: merge_expression(seq_tail.right, alternative),
1300413009
}).optimize(compressor);
1300513010
}
1300613011
// x ? a : y && a ---> (x || y) && a
@@ -13014,7 +13019,7 @@ Compressor.prototype.compress = function(node) {
1301413019
left: condition,
1301513020
right: fuse(alternative, alt_tail, "left"),
1301613021
}),
13017-
right: consequent,
13022+
right: merge_expression(consequent, alt_tail.right),
1301813023
}).optimize(compressor);
1301913024
}
1302013025
// x ? a : y || a ---> !x && y || a
@@ -13028,7 +13033,7 @@ Compressor.prototype.compress = function(node) {
1302813033
left: negated,
1302913034
right: fuse(alternative, alt_tail, "left"),
1303013035
}),
13031-
right: consequent,
13036+
right: merge_expression(consequent, alt_tail.right),
1303213037
}).optimize(compressor);
1303313038
}
1303413039
var in_bool = compressor.option("booleans") && compressor.in_boolean_context();

Diff for: test/compress/conditionals.js

+42
Original file line numberDiff line numberDiff line change
@@ -2928,3 +2928,45 @@ issue_5666_2: {
29282928
}
29292929
expect_stdout: "NaN"
29302930
}
2931+
2932+
issue_5673_1: {
2933+
options = {
2934+
conditionals: true,
2935+
reduce_vars: true,
2936+
unused: true,
2937+
}
2938+
input: {
2939+
var a = "PASS", b = null;
2940+
console.log(function(c) {
2941+
return c || (b ? c : (c = a) && c);
2942+
}());
2943+
}
2944+
expect: {
2945+
var a = "PASS", b = null;
2946+
console.log(function(c) {
2947+
return c || (b || (c = a)) && c;
2948+
}());
2949+
}
2950+
expect_stdout: "PASS"
2951+
}
2952+
2953+
issue_5673_2: {
2954+
options = {
2955+
conditionals: true,
2956+
reduce_vars: true,
2957+
unused: true,
2958+
}
2959+
input: {
2960+
var a = "PASS";
2961+
console.log(function(b) {
2962+
return (b = a) ? b : (b = a) && b;
2963+
}());
2964+
}
2965+
expect: {
2966+
var a = "PASS";
2967+
console.log(function(b) {
2968+
return ((b = a) || (b = a)) && b;
2969+
}());
2970+
}
2971+
expect_stdout: "PASS"
2972+
}

0 commit comments

Comments
 (0)