suspense.ts 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. import { VNode } from './vnode'
  2. import { queuePostFlushCb } from './scheduler'
  3. export const SuspenseSymbol = __DEV__ ? Symbol('Suspense key') : Symbol()
  4. export interface SuspenseBoundary<HostNode, HostElement> {
  5. parent: SuspenseBoundary<HostNode, HostElement> | null
  6. contentTree: VNode<HostNode, HostElement> | null
  7. fallbackTree: VNode<HostNode, HostElement> | null
  8. deps: number
  9. isResolved: boolean
  10. bufferedJobs: Function[]
  11. container: HostElement
  12. resolve(): void
  13. }
  14. export function createSuspenseBoundary<HostNode, HostElement>(
  15. parent: SuspenseBoundary<HostNode, HostElement> | null,
  16. container: HostElement
  17. ): SuspenseBoundary<HostNode, HostElement> {
  18. const suspense: SuspenseBoundary<HostNode, HostElement> = {
  19. parent,
  20. container,
  21. deps: 0,
  22. contentTree: null,
  23. fallbackTree: null,
  24. isResolved: false,
  25. bufferedJobs: [],
  26. resolve() {
  27. suspense.isResolved = true
  28. let parent = suspense.parent
  29. let hasUnresolvedAncestor = false
  30. while (parent) {
  31. if (!parent.isResolved) {
  32. parent.bufferedJobs.push(...suspense.bufferedJobs)
  33. hasUnresolvedAncestor = true
  34. break
  35. }
  36. }
  37. if (!hasUnresolvedAncestor) {
  38. queuePostFlushCb(suspense.bufferedJobs)
  39. }
  40. suspense.isResolved = true
  41. }
  42. }
  43. return suspense
  44. }