-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
/
Copy pathtopLevelAwait.ts
69 lines (65 loc) · 1.72 KB
/
topLevelAwait.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
import type { AwaitExpression } from '@babel/types'
import type { ScriptCompileContext } from './context'
/**
* Support context-persistence between top-level await expressions:
*
* ```js
* const instance = getCurrentInstance()
* await foo()
* expect(getCurrentInstance()).toBe(instance)
* ```
*
* In the future we can potentially get rid of this when Async Context
* becomes generally available: https://github.com/tc39/proposal-async-context
*
* ```js
* // input
* await foo()
* // output
* ;(
* ([__temp,__restore] = withAsyncContext(() => foo())),
* await __temp,
* __restore()
* )
*
* // input
* const a = await foo()
* // output
* const a = (
* ([__temp, __restore] = withAsyncContext(() => foo())),
* __temp = await __temp,
* __restore(),
* __temp
* )
* ```
*/
export function processAwait(
ctx: ScriptCompileContext,
node: AwaitExpression,
needSemi: boolean,
isStatement: boolean,
): void {
const argumentStart =
node.argument.extra && node.argument.extra.parenthesized
? (node.argument.extra.parenStart as number)
: node.argument.start!
const startOffset = ctx.startOffset!
const argumentStr = ctx.descriptor.source.slice(
argumentStart + startOffset,
node.argument.end! + startOffset,
)
const containsNestedAwait = /\bawait\b/.test(argumentStr)
ctx.s.overwrite(
node.start! + startOffset,
argumentStart + startOffset,
`${needSemi ? `;` : ``}(\n ([__temp,__restore] = ${ctx.helper(
`withAsyncContext`,
)}(${containsNestedAwait ? `async ` : ``}() => `,
)
ctx.s.appendLeft(
node.end! + startOffset,
`)),\n ${isStatement ? `` : `__temp = `}await __temp,\n __restore()${
isStatement ? `` : `,\n __temp`
}\n)`,
)
}