From 0fff3a6ef50f1b85f72061b3572e226651d0f1cf Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 10 Sep 2019 11:43:17 -0400 Subject: [PATCH] wip: handle suspense as component root el update --- packages/runtime-core/src/createRenderer.ts | 54 ++++++++++++++------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/packages/runtime-core/src/createRenderer.ts b/packages/runtime-core/src/createRenderer.ts index ff73dcdf..7596e027 100644 --- a/packages/runtime-core/src/createRenderer.ts +++ b/packages/runtime-core/src/createRenderer.ts @@ -613,12 +613,25 @@ export function createRenderer< parentSuspense: SuspenseBoundary | null = null ) { if (n1 == null) { - function resolve() { + const suspense = (n2.suspense = createSuspenseBoundary( + n2, + parentSuspense, + hostCreateElement('div'), + resolveSuspense + )) + + function resolveSuspense() { + const { subTree, fallbackTree, bufferedJobs, vnode } = suspense // unmount fallback tree - unmount(suspense.fallbackTree as HostVNode, parentComponent, true) + unmount(fallbackTree as HostVNode, parentComponent, true) // move content from off-dom container to actual container - move(suspense.subTree as HostVNode, container, anchor) - suspense.vnode.el = (suspense.subTree as HostVNode).el + move(subTree as HostVNode, container, anchor) + const el = (vnode.el = (subTree as HostVNode).el as HostNode) + // suspense as the root node of a component... + if (parentComponent && parentComponent.subTree === vnode) { + parentComponent.vnode.el = el + updateHOCHostEl(parentComponent, el) + } // check if there is a pending parent suspense let parent = suspense.parent let hasUnresolvedAncestor = false @@ -626,25 +639,23 @@ export function createRenderer< if (!parent.isResolved) { // found a pending parent suspense, merge buffered post jobs // into that parent - parent.bufferedJobs.push(...suspense.bufferedJobs) + parent.bufferedJobs.push(...bufferedJobs) hasUnresolvedAncestor = true break } } // no pending parent suspense, flush all jobs if (!hasUnresolvedAncestor) { - queuePostFlushCb(suspense.bufferedJobs) + queuePostFlushCb(bufferedJobs) } suspense.isResolved = true + // invoke @resolve event + const onResolve = vnode.props && vnode.props.onResolve + if (isFunction(onResolve)) { + onResolve() + } } - const suspense = (n2.suspense = createSuspenseBoundary( - n2, - parentSuspense, - hostCreateElement('div'), - resolve - )) - // TODO pass it down as an arg instead if (parentComponent) { setCurrentInstance(parentComponent) @@ -821,6 +832,7 @@ export function createRenderer< instance.asyncResolved = true handleSetupResult(instance, asyncSetupResult) setupRenderEffect(instance, initialVNode, container, anchor, isSVG) + updateHOCHostEl(instance, initialVNode.el as HostNode) if (suspense.deps === 0) { suspense.resolve() } @@ -907,11 +919,7 @@ export function createRenderer< // self-triggered update. In case of HOC, update parent component // vnode el. HOC is indicated by parent instance's subTree pointing // to child component's vnode - let parent = instance.parent - while (parent && parent.subTree === current) { - ;(current = parent.vnode).el = nextTree.el - parent = parent.parent - } + updateHOCHostEl(instance, nextTree.el) } // upated hook if (instance.u !== null) { @@ -925,6 +933,16 @@ export function createRenderer< }, __DEV__ ? createDevEffectOptions(instance) : prodEffectOptions) } + function updateHOCHostEl( + { vnode, parent }: ComponentInternalInstance, + el: HostNode + ) { + while (parent && parent.subTree === vnode) { + ;(vnode = parent.vnode).el = el + parent = parent.parent + } + } + function patchChildren( n1: HostVNode | null, n2: HostVNode,