diff --git a/packages/runtime-core/__tests__/scopeId.spec.ts b/packages/runtime-core/__tests__/scopeId.spec.ts index 08753e023a1..d9a7d4dbfa4 100644 --- a/packages/runtime-core/__tests__/scopeId.spec.ts +++ b/packages/runtime-core/__tests__/scopeId.spec.ts @@ -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[] = [] + 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(`
fallback
`) + + await Promise.all(deps) + await nextTick() + expect(serializeInner(root)).toBe(`
async
`) + }) + // :slotted basic test('should work on slots', () => { const Child = { diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index ce063989502..11736e9dff2 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -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,