/
for-await.ts
81 lines (73 loc) 路 2.41 KB
/
for-await.ts
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
import { types as t, template } from "@babel/core";
const buildForAwait = template(`
async function wrapper() {
var ITERATOR_ABRUPT_COMPLETION = false;
var ITERATOR_HAD_ERROR_KEY = false;
var ITERATOR_ERROR_KEY;
try {
for (
var ITERATOR_KEY = GET_ITERATOR(OBJECT), STEP_KEY;
ITERATOR_ABRUPT_COMPLETION = !(STEP_KEY = await ITERATOR_KEY.next()).done;
ITERATOR_ABRUPT_COMPLETION = false
) {
}
} catch (err) {
ITERATOR_HAD_ERROR_KEY = true;
ITERATOR_ERROR_KEY = err;
} finally {
try {
if (ITERATOR_ABRUPT_COMPLETION && ITERATOR_KEY.return != null) {
await ITERATOR_KEY.return();
}
} finally {
if (ITERATOR_HAD_ERROR_KEY) {
throw ITERATOR_ERROR_KEY;
}
}
}
}
`);
export default function (path, { getAsyncIterator }) {
const { node, scope, parent } = path;
const stepKey = scope.generateUidIdentifier("step");
const stepValue = t.memberExpression(stepKey, t.identifier("value"));
const left = node.left;
let declar;
if (t.isIdentifier(left) || t.isPattern(left) || t.isMemberExpression(left)) {
// for await (i of test), for await ({ i } of test)
declar = t.expressionStatement(
t.assignmentExpression("=", left, stepValue),
);
} else if (t.isVariableDeclaration(left)) {
// for await (let i of test)
declar = t.variableDeclaration(left.kind, [
t.variableDeclarator(left.declarations[0].id, stepValue),
]);
}
let template = buildForAwait({
ITERATOR_HAD_ERROR_KEY: scope.generateUidIdentifier("didIteratorError"),
ITERATOR_ABRUPT_COMPLETION: scope.generateUidIdentifier(
"iteratorAbruptCompletion",
),
ITERATOR_ERROR_KEY: scope.generateUidIdentifier("iteratorError"),
ITERATOR_KEY: scope.generateUidIdentifier("iterator"),
GET_ITERATOR: getAsyncIterator,
OBJECT: node.right,
STEP_KEY: t.cloneNode(stepKey),
});
// remove async function wrapper
// @ts-expect-error todo(flow->ts) improve type annotation for buildForAwait
template = template.body.body as t.Statement[];
const isLabeledParent = t.isLabeledStatement(parent);
const tryBody = (template[3] as t.TryStatement).block.body;
const loop = tryBody[0] as t.ForStatement;
if (isLabeledParent) {
tryBody[0] = t.labeledStatement(parent.label, loop);
}
return {
replaceParent: isLabeledParent,
node: template,
declar,
loop,
};
}