All files / compiler-ssr/src/transforms ssrTransformSuspense.ts

96.49% Statements 55/57
83.33% Branches 5/6
100% Functions 2/2
96.49% Lines 55/57

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 842x                 2x       2x 2x   2x                     2x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 4x 4x 4x 4x     2x 4x 4x 4x   4x 4x     4x 4x 6x 6x 6x   4x 4x 4x 4x 4x 4x 4x  
import {
  type ComponentNode,
  type FunctionExpression,
  type SlotsExpression,
  type TemplateChildNode,
  type TransformContext,
  buildSlots,
  createCallExpression,
  createFunctionExpression,
} from '@vue/compiler-dom'
import {
  type SSRTransformContext,
  processChildrenAsStatement,
} from '../ssrCodegenTransform'
import { SSR_RENDER_SUSPENSE } from '../runtimeHelpers'
 
const wipMap = new WeakMap<ComponentNode, WIPEntry>()
 
interface WIPEntry {
  slotsExp: SlotsExpression
  wipSlots: Array<{
    fn: FunctionExpression
    children: TemplateChildNode[]
  }>
}
 
// phase 1
export function ssrTransformSuspense(
  node: ComponentNode,
  context: TransformContext,
) {
  return (): void => {
    if (node.children.length) {
      const wipEntry: WIPEntry = {
        slotsExp: null!, // to be immediately set
        wipSlots: [],
      }
      wipMap.set(node, wipEntry)
      wipEntry.slotsExp = buildSlots(
        node,
        context,
        (_props, _vForExp, children, loc) => {
          const fn = createFunctionExpression(
            [],
            undefined, // no return, assign body later
            true, // newline
            false, // suspense slots are not treated as normal slots
            loc,
          )
          wipEntry.wipSlots.push({
            fn,
            children,
          })
          return fn
        },
      ).slots
    }
  }
}
 
// phase 2
export function ssrProcessSuspense(
  node: ComponentNode,
  context: SSRTransformContext,
): void {
  // complete wip slots with ssr code
  const wipEntry = wipMap.get(node)
  if (!wipEntry) {
    return
  }
  const { slotsExp, wipSlots } = wipEntry
  for (let i = 0; i < wipSlots.length; i++) {
    const slot = wipSlots[i]
    slot.fn.body = processChildrenAsStatement(slot, context)
  }
  // _push(ssrRenderSuspense(slots))
  context.pushStatement(
    createCallExpression(context.helper(SSR_RENDER_SUSPENSE), [
      `_push`,
      slotsExp,
    ]),
  )
}