--- /dev/null
+import {
+ h,
+ ref,
+ Suspense,
+ ComponentOptions,
+ render,
+ nodeOps,
+ serializeInner,
+ nextTick
+} from '@vue/runtime-test'
+
+describe('renderer: suspense', () => {
+ it('should work', async () => {
+ const msg = ref('hello')
+ const deps: Promise<any>[] = []
+
+ const createAsyncComponent = (loader: () => Promise<ComponentOptions>) => ({
+ async setup(props: any, { slots }: any) {
+ const p = loader()
+ deps.push(p)
+ const Inner = await p
+ return () => h(Inner, props, slots)
+ }
+ })
+
+ const AsyncChild = createAsyncComponent(
+ () =>
+ new Promise(resolve => {
+ setTimeout(() => {
+ resolve({
+ setup(props: { msg: string }) {
+ return () => h('div', props.msg)
+ }
+ })
+ }, 0)
+ })
+ )
+
+ const Mid = {
+ setup() {
+ return () =>
+ h(AsyncChild, {
+ msg: msg.value
+ })
+ }
+ }
+
+ const Comp = {
+ name: 'root',
+ setup() {
+ // TODO test fallback
+ return () => h(Suspense, [msg.value, h(Mid)])
+ }
+ }
+
+ const root = nodeOps.createElement('div')
+ render(h(Comp), root)
+ expect(serializeInner(root)).toBe(`<!---->`)
+
+ await Promise.all(deps)
+ await nextTick()
+ expect(serializeInner(root)).toBe(`<!---->hello<div>hello</div><!---->`)
+ })
+})
})
suspense.onResolve(() => {
+ // unmount fallback tree
+ unmount(suspense.fallbackTree as HostVNode, parentComponent, true)
// move content from off-dom container to actual container
- ;(suspense.subTree as any).children.forEach((vnode: HostVNode) => {
- move(vnode, container, anchor)
- })
+ move(suspense.subTree as HostVNode, container, anchor)
suspense.vnode.el = (suspense.subTree as HostVNode).el
// check if there is a pending parent suspense
let parent = suspense.parent
// now check if we have encountered any async deps
if (suspense.deps > 0) {
// TODO mount the fallback tree.
- console.log('fallback')
+ processEmptyNode(
+ null,
+ (suspense.fallbackTree = createVNode(Empty)),
+ container,
+ anchor
+ )
} else {
suspense.resolve()
}
suspense.deps--
suspense.retry()
})
+ // give it a placeholder
+ const placeholder = (instance.subTree = createVNode(Empty))
+ processEmptyNode(null, placeholder, container, anchor)
+ initialVNode.el = placeholder.el
return
}