]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor: move resolveSuspense out
authorEvan You <yyx990803@gmail.com>
Wed, 11 Sep 2019 21:38:26 +0000 (17:38 -0400)
committerEvan You <yyx990803@gmail.com>
Wed, 11 Sep 2019 21:38:26 +0000 (17:38 -0400)
packages/runtime-core/__tests__/rendererSuspense.spec.ts
packages/runtime-core/src/createRenderer.ts
packages/runtime-core/src/suspense.ts

index 009618ec4da56bbf1883ba1d29f8897e4a2291be..5e80267b90e48ff005b4818e46f9c76bf710d09b 100644 (file)
@@ -286,7 +286,7 @@ describe('renderer: suspense', () => {
     expect(calls).toEqual([])
   })
 
-  test.todo('unmount suspense after resolve')
+  test('unmount suspense after resolve', () => {})
 
   test.todo('unmount suspense before resolve')
 
index 133672c0f41dc4e099b4998d3a1ff8579e303565..9d665f4816de379076a91c7ed2d47c056fde34bc 100644 (file)
@@ -721,63 +721,16 @@ export function createRenderer<
     isSVG: boolean,
     optimized: boolean
   ) {
+    const hiddenContainer = hostCreateElement('div')
     const suspense = (n2.suspense = createSuspenseBoundary(
       n2,
       parentSuspense,
-      hostCreateElement('div'),
-      resolveSuspense
+      parentComponent,
+      container,
+      hiddenContainer,
+      anchor
     ))
 
-    function resolveSuspense() {
-      if (__DEV__) {
-        if (suspense.isResolved) {
-          throw new Error(
-            `suspense.resolve() is called when it's already resolved`
-          )
-        }
-        if (suspense.isUnmounted) {
-          throw new Error(
-            `suspense.resolve() is called when it's already unmounted`
-          )
-        }
-      }
-      const { subTree, fallbackTree, effects, vnode } = suspense
-      // unmount fallback tree
-      if (fallbackTree.el) {
-        unmount(fallbackTree as HostVNode, parentComponent, suspense, true)
-      }
-      // move content from off-dom container to actual container
-      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
-      while (parent) {
-        if (!parent.isResolved) {
-          // found a pending parent suspense, merge buffered post jobs
-          // into that parent
-          parent.effects.push(...effects)
-          hasUnresolvedAncestor = true
-          break
-        }
-      }
-      // no pending parent suspense, flush all jobs
-      if (!hasUnresolvedAncestor) {
-        queuePostFlushCb(effects)
-      }
-      suspense.isResolved = true
-      // invoke @resolve event
-      const onResolve = vnode.props && vnode.props.onResolve
-      if (isFunction(onResolve)) {
-        onResolve()
-      }
-    }
-
     const { content, fallback } = normalizeSuspenseChildren(n2)
     suspense.subTree = content
     suspense.fallbackTree = fallback
@@ -786,7 +739,7 @@ export function createRenderer<
     patch(
       null,
       content,
-      suspense.container,
+      hiddenContainer,
       null,
       parentComponent,
       suspense,
@@ -809,7 +762,7 @@ export function createRenderer<
       n2.el = fallback.el
     } else {
       // Suspense has no async deps. Just resolve.
-      suspense.resolve()
+      resolveSuspense(suspense)
     }
   }
 
@@ -831,7 +784,7 @@ export function createRenderer<
       patch(
         oldSubTree,
         content,
-        suspense.container,
+        suspense.hiddenContainer,
         null,
         parentComponent,
         suspense,
@@ -873,6 +826,64 @@ export function createRenderer<
     suspense.fallbackTree = fallback
   }
 
+  function resolveSuspense(suspense: HostSuspsenseBoundary) {
+    if (__DEV__) {
+      if (suspense.isResolved) {
+        throw new Error(
+          `suspense.resolve() is called when it's already resolved`
+        )
+      }
+      if (suspense.isUnmounted) {
+        throw new Error(
+          `suspense.resolve() is called when it's already unmounted`
+        )
+      }
+    }
+    const {
+      subTree,
+      fallbackTree,
+      effects,
+      vnode,
+      parentComponent,
+      container,
+      anchor
+    } = suspense
+    // unmount fallback tree
+    if (fallbackTree.el) {
+      unmount(fallbackTree as HostVNode, parentComponent, suspense, true)
+    }
+    // move content from off-dom container to actual container
+    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
+    while (parent) {
+      if (!parent.isResolved) {
+        // found a pending parent suspense, merge buffered post jobs
+        // into that parent
+        parent.effects.push(...effects)
+        hasUnresolvedAncestor = true
+        break
+      }
+    }
+    // no pending parent suspense, flush all jobs
+    if (!hasUnresolvedAncestor) {
+      queuePostFlushCb(effects)
+    }
+    suspense.isResolved = true
+    // invoke @resolve event
+    const onResolve = vnode.props && vnode.props.onResolve
+    if (isFunction(onResolve)) {
+      onResolve()
+    }
+  }
+
   function processComponent(
     n1: HostVNode | null,
     n2: HostVNode,
@@ -992,7 +1003,7 @@ export function createRenderer<
         )
         updateHOCHostEl(instance, initialVNode.el as HostNode)
         if (parentSuspense.deps === 0) {
-          parentSuspense.resolve()
+          resolveSuspense(parentSuspense)
         }
       })
       // give it a placeholder
@@ -1621,7 +1632,7 @@ export function createRenderer<
     ) {
       parentSuspense.deps--
       if (parentSuspense.deps === 0) {
-        parentSuspense.resolve()
+        resolveSuspense(parentSuspense)
       }
     }
   }
index 98068b2a8582299c180d0a26ac27cc3f01cdee07..fb8c36fbeecf9ede2c252d8f1761ba743a83b4e9 100644 (file)
@@ -1,6 +1,7 @@
 import { VNode, normalizeVNode } from './vnode'
 import { ShapeFlags } from '.'
 import { isFunction } from '@vue/shared'
+import { ComponentInternalInstance } from './component'
 
 export const SuspenseSymbol = __DEV__ ? Symbol('Suspense key') : Symbol()
 
@@ -11,33 +12,39 @@ export interface SuspenseBoundary<
 > {
   vnode: HostVNode
   parent: SuspenseBoundary<HostNode, HostElement> | null
+  parentComponent: ComponentInternalInstance | null
   container: HostElement
+  hiddenContainer: HostElement
+  anchor: HostNode | null
   subTree: HostVNode
   fallbackTree: HostVNode
   deps: number
   isResolved: boolean
   isUnmounted: boolean
   effects: Function[]
-  resolve(): void
 }
 
 export function createSuspenseBoundary<HostNode, HostElement>(
   vnode: VNode<HostNode, HostElement>,
   parent: SuspenseBoundary<HostNode, HostElement> | null,
+  parentComponent: ComponentInternalInstance | null,
   container: HostElement,
-  resolve: () => void
+  hiddenContainer: HostElement,
+  anchor: HostNode | null
 ): SuspenseBoundary<HostNode, HostElement> {
   return {
     vnode,
     parent,
+    parentComponent,
     container,
+    hiddenContainer,
+    anchor,
     deps: 0,
     subTree: null as any, // will be set immediately after creation
     fallbackTree: null as any, // will be set immediately after creation
     isResolved: false,
     isUnmounted: false,
-    effects: [],
-    resolve
+    effects: []
   }
 }