]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): ensure suspense content inherit scopeId (#10652)
authoredison <daiwei521@126.com>
Mon, 19 Aug 2024 08:19:24 +0000 (16:19 +0800)
committerGitHub <noreply@github.com>
Mon, 19 Aug 2024 08:19:24 +0000 (16:19 +0800)
close #5148

packages/runtime-core/__tests__/scopeId.spec.ts
packages/runtime-core/src/renderer.ts

index 08753e023a1a079ccc825195eefbb97e9c483546..d9a7d4dbfa498942561b8cdbd6d54a34fa71f90a 100644 (file)
@@ -1,5 +1,6 @@
 import {
   Fragment,
+  Suspense,
   createBlock,
   createCommentVNode,
   createVNode,
@@ -47,6 +48,49 @@ describe('scopeId runtime support', () => {
     )
   })
 
+  // #5148
+  test('should attach scopeId to suspense content', async () => {
+    const deps: Promise<any>[] = []
+    const Child = {
+      async setup() {
+        const p = new Promise(r => setTimeout(r, 1))
+        deps.push(p.then(() => Promise.resolve()))
+
+        await p
+        return () => h('div', 'async')
+      },
+    }
+
+    const Wrapper = {
+      setup(_: any, { slots }: any) {
+        return () => slots.default({ Component: h(Child) })
+      },
+    }
+
+    const App = {
+      __scopeId: 'parent',
+      setup() {
+        return () =>
+          h(Wrapper, null, {
+            default: withCtx(({ Component }: any) =>
+              h(Suspense, null, {
+                default: h(Component),
+                fallback: h('div', 'fallback'),
+              }),
+            ),
+          })
+      },
+    }
+
+    const root = nodeOps.createElement('div')
+    render(h(App), root)
+    expect(serializeInner(root)).toBe(`<div parent>fallback</div>`)
+
+    await Promise.all(deps)
+    await nextTick()
+    expect(serializeInner(root)).toBe(`<div parent>async</div>`)
+  })
+
   // :slotted basic
   test('should work on slots', () => {
     const Child = {
index ce0639895029aae1ead760935b3361a45a434386..11736e9dff228656c64a6479ee265a60fbecf675 100644 (file)
@@ -62,6 +62,7 @@ import { setRef } from './rendererTemplateRef'
 import {
   type SuspenseBoundary,
   type SuspenseImpl,
+  isSuspense,
   queueEffectWithSuspense,
 } from './components/Suspense'
 import {
@@ -749,7 +750,11 @@ function baseCreateRenderer(
         subTree =
           filterSingleRoot(subTree.children as VNodeArrayChildren) || subTree
       }
-      if (vnode === subTree) {
+      if (
+        vnode === subTree ||
+        (isSuspense(subTree.type) &&
+          (subTree.ssContent === vnode || subTree.ssFallback === vnode))
+      ) {
         const parentVNode = parentComponent.vnode
         setScopeId(
           el,