/
index.js
95 lines (85 loc) · 3.03 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
"use strict";
const evaluate = require("babel-helper-evaluate-path");
function evaluateTruthy(path) {
const res = evaluate(path);
if (res.confident) return !!res.value;
}
module.exports = function({ types: t }) {
const flipExpressions = require("babel-helper-flip-expressions")(t);
return {
name: "minify-guarded-expressions",
visitor: {
// Convert guarded expressions
// !a && b() --> a || b();
// This could change the return result of the expression so we only do it
// on things where the result is ignored.
LogicalExpression: {
enter: [
function(path) {
const { node } = path;
const left = path.get("left");
const right = path.get("right");
// issues - 171, 174, 176
// we assume that it is returned/assigned/part of a bigger expression
// or utilized somehow
// we check if we shouldBail only when evaluating
// the rightside of the expression;
// if the left side is evaluated to be deterministic,
// we can safely replace the entire expression
const shouldBail = !path.parentPath.isExpressionStatement();
if (node.operator === "&&") {
const leftTruthy = evaluateTruthy(left);
if (leftTruthy === false) {
// Short-circuit
path.replaceWith(node.left);
} else if (leftTruthy === true && left.isPure()) {
path.replaceWith(node.right);
} else if (
evaluateTruthy(right) === false &&
right.isPure() &&
!shouldBail
) {
path.replaceWith(node.left);
}
} else if (node.operator === "||") {
const leftTruthy = evaluateTruthy(left);
if (leftTruthy === false && left.isPure()) {
path.replaceWith(node.right);
} else if (leftTruthy === true) {
// Short-circuit
path.replaceWith(node.left);
} else if (
evaluateTruthy(right) === false &&
right.isPure() &&
!shouldBail
) {
path.replaceWith(node.left);
}
}
},
function(path) {
const { node } = path;
if (flipExpressions.hasSeen(node)) {
return;
}
if (
!path.parentPath.isExpressionStatement() &&
!(
path.parentPath.isSequenceExpression() &&
path.parentPath.parentPath.isExpressionStatement()
)
) {
return;
}
// Start counting savings from one since we can ignore the last
// expression.
if (flipExpressions.shouldFlip(node, 1)) {
const newNode = flipExpressions.flip(node, true);
path.replaceWith(newNode);
}
}
]
}
}
};
};