From f0f6f7cea6e16650181e71dcfccbee405a1db503 Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 15 Dec 2023 11:39:50 +0800 Subject: [PATCH] fix(Suspense): fix edge case of Suspense being patched during async HOC child remount --- .../__tests__/components/Suspense.spec.ts | 40 +++++++++++++++++++ .../runtime-core/src/componentRenderUtils.ts | 1 + 2 files changed, 41 insertions(+) diff --git a/packages/runtime-core/__tests__/components/Suspense.spec.ts b/packages/runtime-core/__tests__/components/Suspense.spec.ts index 92638cc6ba3..c986ffdd796 100644 --- a/packages/runtime-core/__tests__/components/Suspense.spec.ts +++ b/packages/runtime-core/__tests__/components/Suspense.spec.ts @@ -1690,6 +1690,46 @@ describe('Suspense', () => { expect(serializeInner(root)).toBe(`
sync
`) }) + // #6416 follow up + test('Suspense patched during HOC async component re-mount', async () => { + const key = ref('k') + const data = ref('data') + + const Async = defineAsyncComponent({ + render() { + return h('div', 'async') + } + }) + + const Comp = { + render() { + return h(Async, { key: key.value }) + } + } + + const root = nodeOps.createElement('div') + const App = { + render() { + return h(Suspense, null, { + default: h(Comp, { data: data.value }) + }) + } + } + render(h(App), root) + expect(serializeInner(root)).toBe(``) + + await Promise.all(deps) + + // async mounted, but key change causing a new async comp to be loaded + key.value = 'k1' + await nextTick() + + // patch the Suspense + // should not throw error due to Suspense vnode.el being null + data.value = 'data2' + await Promise.all(deps) + }) + describe('warnings', () => { // base function to check if a combination of slots warns or not function baseCheckWarn( diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index 38a9e8d19d8..2be51a22743 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -428,6 +428,7 @@ export function updateHOCHostEl( { vnode, parent }: ComponentInternalInstance, el: typeof vnode.el // HostNode ) { + if (!el) return while (parent) { const root = parent.subTree if (root.suspense && root.suspense.activeBranch === vnode) {