2019-09-09 17:59:53 +00:00
|
|
|
import { VNode } from './vnode'
|
|
|
|
import { queuePostFlushCb } from './scheduler'
|
2019-09-07 15:28:40 +00:00
|
|
|
|
|
|
|
export const SuspenseSymbol = __DEV__ ? Symbol('Suspense key') : Symbol()
|
|
|
|
|
2019-09-09 17:59:53 +00:00
|
|
|
export interface SuspenseBoundary<HostNode, HostElement> {
|
|
|
|
parent: SuspenseBoundary<HostNode, HostElement> | null
|
|
|
|
contentTree: VNode<HostNode, HostElement> | null
|
|
|
|
fallbackTree: VNode<HostNode, HostElement> | null
|
2019-09-07 15:28:40 +00:00
|
|
|
deps: number
|
|
|
|
isResolved: boolean
|
2019-09-09 17:59:53 +00:00
|
|
|
bufferedJobs: Function[]
|
|
|
|
container: HostElement
|
2019-09-07 15:28:40 +00:00
|
|
|
resolve(): void
|
|
|
|
}
|
|
|
|
|
2019-09-09 17:59:53 +00:00
|
|
|
export function createSuspenseBoundary<HostNode, HostElement>(
|
|
|
|
parent: SuspenseBoundary<HostNode, HostElement> | null,
|
|
|
|
container: HostElement
|
|
|
|
): SuspenseBoundary<HostNode, HostElement> {
|
|
|
|
const suspense: SuspenseBoundary<HostNode, HostElement> = {
|
|
|
|
parent,
|
|
|
|
container,
|
2019-09-07 15:28:40 +00:00
|
|
|
deps: 0,
|
2019-09-09 17:59:53 +00:00
|
|
|
contentTree: null,
|
|
|
|
fallbackTree: null,
|
2019-09-07 15:28:40 +00:00
|
|
|
isResolved: false,
|
2019-09-09 17:59:53 +00:00
|
|
|
bufferedJobs: [],
|
2019-09-07 15:28:40 +00:00
|
|
|
resolve() {
|
2019-09-09 17:59:53 +00:00
|
|
|
suspense.isResolved = true
|
|
|
|
let parent = suspense.parent
|
|
|
|
let hasUnresolvedAncestor = false
|
|
|
|
while (parent) {
|
|
|
|
if (!parent.isResolved) {
|
|
|
|
parent.bufferedJobs.push(...suspense.bufferedJobs)
|
|
|
|
hasUnresolvedAncestor = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!hasUnresolvedAncestor) {
|
|
|
|
queuePostFlushCb(suspense.bufferedJobs)
|
2019-09-07 15:28:40 +00:00
|
|
|
}
|
2019-09-09 17:59:53 +00:00
|
|
|
suspense.isResolved = true
|
2019-09-07 15:28:40 +00:00
|
|
|
}
|
|
|
|
}
|
2019-09-09 17:59:53 +00:00
|
|
|
|
|
|
|
return suspense
|
2019-09-07 15:28:40 +00:00
|
|
|
}
|