fix: Expression x === 'y' && '' should not evaluate to undefined. (#8880)

Fixes https://github.com/babel/minify/issues/908.
This commit is contained in:
Cyp 2018-10-16 21:25:49 +02:00 committed by Nicolò Ribaudo
parent 5fa3628506
commit e541d6031a
2 changed files with 26 additions and 11 deletions

View File

@ -257,7 +257,7 @@ function _evaluate(path, state) {
} }
if (path.isLogicalExpression()) { if (path.isLogicalExpression()) {
// If we are confident that one side of an && is false, or the left // If we are confident that the left side of an && is false, or the left
// side of an || is true, we can be confident about the entire expression // side of an || is true, we can be confident about the entire expression
const wasConfident = state.confident; const wasConfident = state.confident;
const left = evaluateCached(path.get("left"), state); const left = evaluateCached(path.get("left"), state);
@ -265,25 +265,17 @@ function _evaluate(path, state) {
state.confident = wasConfident; state.confident = wasConfident;
const right = evaluateCached(path.get("right"), state); const right = evaluateCached(path.get("right"), state);
const rightConfident = state.confident; const rightConfident = state.confident;
state.confident = leftConfident && rightConfident;
switch (node.operator) { switch (node.operator) {
case "||": case "||":
// TODO consider having a "truthy type" that doesn't bail on // TODO consider having a "truthy type" that doesn't bail on
// left uncertainty but can still evaluate to truthy. // left uncertainty but can still evaluate to truthy.
if (left && leftConfident) { state.confident = leftConfident && (!!left || rightConfident);
state.confident = true;
return left;
}
if (!state.confident) return; if (!state.confident) return;
return left || right; return left || right;
case "&&": case "&&":
if ((!left && leftConfident) || (!right && rightConfident)) { state.confident = leftConfident && (!left || rightConfident);
state.confident = true;
}
if (!state.confident) return; if (!state.confident) return;
return left && right; return left && right;

View File

@ -40,6 +40,29 @@ describe("evaluation", function() {
).toBe(false); ).toBe(false);
}); });
it("should short-circuit && and ||", function() {
expect(
getPath("x === 'y' || 42")
.get("body")[0]
.evaluate().confident,
).toBe(false);
expect(
getPath("x === 'y' && 0")
.get("body")[0]
.evaluate().confident,
).toBe(false);
expect(
getPath("42 || x === 'y'")
.get("body")[0]
.evaluate().value,
).toBe(42);
expect(
getPath("0 && x === 'y'")
.get("body")[0]
.evaluate().value,
).toBe(0);
});
it("should work with repeated, indeterminate identifiers", function() { it("should work with repeated, indeterminate identifiers", function() {
expect( expect(
getPath("var num = foo(); (num > 0 && num < 100);") getPath("var num = foo(); (num > 0 && num < 100);")