-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
/
index.js
85 lines (69 loc) 路 2.2 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
/* @noflow */
import type { NodePath } from "@babel/traverse";
import wrapFunction from "@babel/helper-wrap-function";
import annotateAsPure from "@babel/helper-annotate-as-pure";
import * as t from "@babel/types";
const awaitVisitor = {
Function(path) {
path.skip();
},
AwaitExpression(path, { wrapAwait }) {
const argument = path.get("argument");
if (path.parentPath.isYieldExpression()) {
path.replaceWith(argument.node);
return;
}
path.replaceWith(
t.yieldExpression(
wrapAwait
? t.callExpression(t.cloneNode(wrapAwait), [argument.node])
: argument.node,
),
);
},
};
export default function (
path: NodePath,
helpers: { wrapAsync: Object, wrapAwait: Object },
) {
path.traverse(awaitVisitor, {
wrapAwait: helpers.wrapAwait,
});
const isIIFE = checkIsIIFE(path);
path.node.async = false;
path.node.generator = true;
wrapFunction(path, t.cloneNode(helpers.wrapAsync));
const isProperty =
path.isObjectMethod() ||
path.isClassMethod() ||
path.parentPath.isObjectProperty() ||
path.parentPath.isClassProperty();
if (!isProperty && !isIIFE && path.isExpression()) {
annotateAsPure(path);
}
function checkIsIIFE(path: NodePath) {
if (path.parentPath.isCallExpression({ callee: path.node })) {
return true;
}
// try to catch calls to Function#bind, as emitted by arrowFunctionToExpression in spec mode
// this may also catch .bind(this) written by users, but does it matter? 馃
const { parentPath } = path;
if (
parentPath.isMemberExpression() &&
t.isIdentifier(parentPath.node.property, { name: "bind" })
) {
const { parentPath: bindCall } = parentPath;
// (function () { ... }).bind(this)()
return (
// first, check if the .bind is actually being called
bindCall.isCallExpression() &&
// and whether its sole argument is 'this'
bindCall.node.arguments.length === 1 &&
t.isThisExpression(bindCall.node.arguments[0]) &&
// and whether the result of the .bind(this) is being called
bindCall.parentPath.isCallExpression({ callee: bindCall.node })
);
}
return false;
}
}