]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
test: add tests
authordaiwei <daiwei521@126.com>
Fri, 21 Feb 2025 01:07:25 +0000 (09:07 +0800)
committerdaiwei <daiwei521@126.com>
Fri, 21 Feb 2025 06:32:51 +0000 (14:32 +0800)
packages/runtime-core/__tests__/components/Suspense.spec.ts
packages/runtime-core/src/componentRenderUtils.ts

index 65e801de277f767d4784ced162b1c3f1cfd6e0ef..0944c40d6b23b91e1970f8b7e1fc36d9a94e561f 100644 (file)
@@ -8,13 +8,16 @@ import {
   KeepAlive,
   Suspense,
   type SuspenseProps,
+  createBlock,
   createCommentVNode,
+  createElementBlock,
   h,
   nextTick,
   nodeOps,
   onErrorCaptured,
   onMounted,
   onUnmounted,
+  openBlock,
   ref,
   render,
   resolveDynamicComponent,
@@ -26,6 +29,7 @@ import {
 import { computed, createApp, defineComponent, inject, provide } from 'vue'
 import type { RawSlots } from 'packages/runtime-core/src/componentSlots'
 import { resetSuspenseId } from '../../src/components/Suspense'
+import { PatchFlags } from '@vue/shared'
 
 describe('Suspense', () => {
   const deps: Promise<any>[] = []
@@ -2161,6 +2165,63 @@ describe('Suspense', () => {
     await Promise.all(deps)
   })
 
+  // #12920
+  test('unmount Suspense after children self-update', async () => {
+    const Comp = defineAsyncComponent({
+      setup() {
+        const show = ref(true)
+        onMounted(() => {
+          // trigger self-update
+          show.value = !show.value
+        })
+        return () =>
+          show.value
+            ? (openBlock(), createElementBlock('div', { key: 0 }, 'show'))
+            : (openBlock(), createElementBlock('div', { key: 1 }, 'hidden'))
+      },
+    })
+
+    const toggle = ref(true)
+    const root = nodeOps.createElement('div')
+    const App = {
+      render() {
+        return (
+          openBlock(),
+          createElementBlock(
+            Fragment,
+            null,
+            [
+              h('h1', null, toggle.value),
+              toggle.value
+                ? (openBlock(),
+                  createBlock(
+                    Suspense,
+                    { key: 0 },
+                    {
+                      default: h(Comp),
+                    },
+                  ))
+                : createCommentVNode('v-if', true),
+            ],
+            PatchFlags.STABLE_FRAGMENT,
+          )
+        )
+      },
+    }
+    render(h(App), root)
+    expect(serializeInner(root)).toBe(`<h1>true</h1><!---->`)
+
+    await Promise.all(deps)
+    await nextTick()
+    expect(serializeInner(root)).toBe(`<h1>true</h1><div>hidden</div>`)
+
+    // unmount suspense
+    toggle.value = false
+    await Promise.all(deps)
+    await nextTick()
+    expect(serializeInner(root)).toBe(`<h1>true</h1><!--v-if-->`)
+  })
+
   describe('warnings', () => {
     // base function to check if a combination of slots warns or not
     function baseCheckWarn(
index 5e5e159aae0893cfc1169eb9f5183ffd0770980b..c9cc5ded7c23ee76e990ff847de5c95f356d5961 100644 (file)
@@ -457,14 +457,17 @@ export function updateHOCHostEl(
   while (parent) {
     const root = parent.subTree
     if (root.suspense && root.suspense.activeBranch === vnode) {
-      root.el = vnode.el
+      root.suspense.vnode.el = root.el = vnode.el
     }
     if (root === vnode) {
       ;(vnode = parent.vnode).el = el
-      if (suspense && suspense.activeBranch === vnode) suspense.vnode.el = el
       parent = parent.parent
     } else {
       break
     }
   }
+  // also update suspense vnode el
+  if (suspense && suspense.activeBranch === vnode) {
+    suspense.vnode.el = el
+  }
 }