Skip to content

Commit

Permalink
fix: Expression x === 'y' && '' should not evaluate to undefined. (#8880
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyp authored and nicolo-ribaudo committed Oct 16, 2018
1 parent 5fa3628 commit e541d60
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 11 deletions.
14 changes: 3 additions & 11 deletions packages/babel-traverse/src/path/evaluation.js
Expand Up @@ -257,33 +257,25 @@ function _evaluate(path, state) {
}

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
const wasConfident = state.confident;
const left = evaluateCached(path.get("left"), state);
const leftConfident = state.confident;
state.confident = wasConfident;
const right = evaluateCached(path.get("right"), state);
const rightConfident = state.confident;
state.confident = leftConfident && rightConfident;

switch (node.operator) {
case "||":
// TODO consider having a "truthy type" that doesn't bail on
// left uncertainty but can still evaluate to truthy.
if (left && leftConfident) {
state.confident = true;
return left;
}

state.confident = leftConfident && (!!left || rightConfident);
if (!state.confident) return;

return left || right;
case "&&":
if ((!left && leftConfident) || (!right && rightConfident)) {
state.confident = true;
}
state.confident = leftConfident && (!left || rightConfident);
if (!state.confident) return;
return left && right;
Expand Down
23 changes: 23 additions & 0 deletions packages/babel-traverse/test/evaluation.js
Expand Up @@ -40,6 +40,29 @@ describe("evaluation", function() {
).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() {
expect(
getPath("var num = foo(); (num > 0 && num < 100);")
Expand Down

0 comments on commit e541d60

Please sign in to comment.