The following is wrong:
`a == (b ? a : c)` => `b`
Because:
- `b` may not be boolean
- `a` might have side effects
- `a == a` is not always `true` (think `NaN`)
- `a == c` is not always `false`
This commit is contained in:
@@ -3057,32 +3057,6 @@ merge(Compressor.prototype, {
|
||||
reverse();
|
||||
}
|
||||
}
|
||||
if (/^[!=]==?$/.test(self.operator)) {
|
||||
if (self.left instanceof AST_SymbolRef && self.right instanceof AST_Conditional) {
|
||||
if (self.right.consequent instanceof AST_SymbolRef
|
||||
&& self.right.consequent.definition() === self.left.definition()) {
|
||||
if (/^==/.test(self.operator)) return self.right.condition;
|
||||
if (/^!=/.test(self.operator)) return self.right.condition.negate(compressor);
|
||||
}
|
||||
if (self.right.alternative instanceof AST_SymbolRef
|
||||
&& self.right.alternative.definition() === self.left.definition()) {
|
||||
if (/^==/.test(self.operator)) return self.right.condition.negate(compressor);
|
||||
if (/^!=/.test(self.operator)) return self.right.condition;
|
||||
}
|
||||
}
|
||||
if (self.right instanceof AST_SymbolRef && self.left instanceof AST_Conditional) {
|
||||
if (self.left.consequent instanceof AST_SymbolRef
|
||||
&& self.left.consequent.definition() === self.right.definition()) {
|
||||
if (/^==/.test(self.operator)) return self.left.condition;
|
||||
if (/^!=/.test(self.operator)) return self.left.condition.negate(compressor);
|
||||
}
|
||||
if (self.left.alternative instanceof AST_SymbolRef
|
||||
&& self.left.alternative.definition() === self.right.definition()) {
|
||||
if (/^==/.test(self.operator)) return self.left.condition.negate(compressor);
|
||||
if (/^!=/.test(self.operator)) return self.left.condition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self = self.lift_sequences(compressor);
|
||||
if (compressor.option("comparisons")) switch (self.operator) {
|
||||
|
||||
@@ -797,3 +797,99 @@ no_evaluate: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
equality_conditionals_false: {
|
||||
options = {
|
||||
conditionals: false,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b, c) {
|
||||
console.log(
|
||||
a == (b ? a : a),
|
||||
a == (b ? a : c),
|
||||
a != (b ? a : a),
|
||||
a != (b ? a : c),
|
||||
a === (b ? a : a),
|
||||
a === (b ? a : c),
|
||||
a !== (b ? a : a),
|
||||
a !== (b ? a : c)
|
||||
);
|
||||
}
|
||||
f(0, 0, 0);
|
||||
f(0, true, 0);
|
||||
f(1, 2, 3);
|
||||
f(1, null, 3);
|
||||
f(NaN);
|
||||
f(NaN, "foo");
|
||||
}
|
||||
expect: {
|
||||
function f(a, b, c) {
|
||||
console.log(
|
||||
a == (b ? a : a),
|
||||
a == (b ? a : c),
|
||||
a != (b ? a : a),
|
||||
a != (b ? a : c),
|
||||
a === (b ? a : a),
|
||||
a === (b ? a : c),
|
||||
a !== (b ? a : a),
|
||||
a !== (b ? a : c)
|
||||
);
|
||||
}
|
||||
f(0, 0, 0),
|
||||
f(0, true, 0),
|
||||
f(1, 2, 3),
|
||||
f(1, null, 3),
|
||||
f(NaN),
|
||||
f(NaN, "foo");
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
equality_conditionals_true: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b, c) {
|
||||
console.log(
|
||||
a == (b ? a : a),
|
||||
a == (b ? a : c),
|
||||
a != (b ? a : a),
|
||||
a != (b ? a : c),
|
||||
a === (b ? a : a),
|
||||
a === (b ? a : c),
|
||||
a !== (b ? a : a),
|
||||
a !== (b ? a : c)
|
||||
);
|
||||
}
|
||||
f(0, 0, 0);
|
||||
f(0, true, 0);
|
||||
f(1, 2, 3);
|
||||
f(1, null, 3);
|
||||
f(NaN);
|
||||
f(NaN, "foo");
|
||||
}
|
||||
expect: {
|
||||
function f(a, b, c) {
|
||||
console.log(
|
||||
(b, a == a),
|
||||
a == (b ? a : c),
|
||||
(b, a != a),
|
||||
a != (b ? a : c),
|
||||
(b, a === a),
|
||||
a === (b ? a : c),
|
||||
(b, a !== a),
|
||||
a !== (b ? a : c)
|
||||
);
|
||||
}
|
||||
f(0, 0, 0),
|
||||
f(0, true, 0),
|
||||
f(1, 2, 3),
|
||||
f(1, null, 3),
|
||||
f(NaN),
|
||||
f(NaN, "foo");
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user