topLevelAwait.ts 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import type { AwaitExpression } from '@babel/types'
  2. import type { ScriptCompileContext } from './context'
  3. /**
  4. * Support context-persistence between top-level await expressions:
  5. *
  6. * ```js
  7. * const instance = getCurrentInstance()
  8. * await foo()
  9. * expect(getCurrentInstance()).toBe(instance)
  10. * ```
  11. *
  12. * In the future we can potentially get rid of this when Async Context
  13. * becomes generally available: https://github.com/tc39/proposal-async-context
  14. *
  15. * ```js
  16. * // input
  17. * await foo()
  18. * // output
  19. * ;(
  20. * ([__temp,__restore] = withAsyncContext(() => foo())),
  21. * await __temp,
  22. * __restore()
  23. * )
  24. *
  25. * // input
  26. * const a = await foo()
  27. * // output
  28. * const a = (
  29. * ([__temp, __restore] = withAsyncContext(() => foo())),
  30. * __temp = await __temp,
  31. * __restore(),
  32. * __temp
  33. * )
  34. * ```
  35. */
  36. export function processAwait(
  37. ctx: ScriptCompileContext,
  38. node: AwaitExpression,
  39. needSemi: boolean,
  40. isStatement: boolean,
  41. ) {
  42. const argumentStart =
  43. node.argument.extra && node.argument.extra.parenthesized
  44. ? (node.argument.extra.parenStart as number)
  45. : node.argument.start!
  46. const startOffset = ctx.startOffset!
  47. const argumentStr = ctx.descriptor.source.slice(
  48. argumentStart + startOffset,
  49. node.argument.end! + startOffset,
  50. )
  51. const containsNestedAwait = /\bawait\b/.test(argumentStr)
  52. ctx.s.overwrite(
  53. node.start! + startOffset,
  54. argumentStart + startOffset,
  55. `${needSemi ? `;` : ``}(\n ([__temp,__restore] = ${ctx.helper(
  56. `withAsyncContext`,
  57. )}(${containsNestedAwait ? `async ` : ``}() => `,
  58. )
  59. ctx.s.appendLeft(
  60. node.end! + startOffset,
  61. `)),\n ${isStatement ? `` : `__temp = `}await __temp,\n __restore()${
  62. isStatement ? `` : `,\n __temp`
  63. }\n)`,
  64. )
  65. }