From 9d8c15e4cf03ed1da33a963b5bfdf271068f1439 Mon Sep 17 00:00:00 2001 From: Kael Date: Wed, 22 Jun 2022 01:39:04 +1000 Subject: [PATCH] fix(ssr): fix hydration error when disabled teleport is component root fixes #6152 --- .../runtime-core/__tests__/hydration.spec.ts | 36 +++++++++++++++++-- packages/runtime-core/src/hydration.ts | 20 +++++++---- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/packages/runtime-core/__tests__/hydration.spec.ts b/packages/runtime-core/__tests__/hydration.spec.ts index 17ffbb40092..cf24a1ba347 100644 --- a/packages/runtime-core/__tests__/hydration.spec.ts +++ b/packages/runtime-core/__tests__/hydration.spec.ts @@ -418,17 +418,47 @@ describe('SSR hydration', () => { expect(nextVNode.el).toBe(container.firstChild?.lastChild) }) - test('Teleport (nested)', () => { + test('Teleport (as component root, disabled)', () => { const teleportContainer = document.createElement('div') teleportContainer.id = 'teleport5' + document.body.appendChild(teleportContainer) + + const wrapper = { + render() { + return h(Teleport, { to: '#teleport5', disabled: true }, [ + h('div', ['hello']) + ]) + } + } + + const { vnode, container } = mountWithHydration( + '
hello
', + () => h('div', [h(wrapper), h('div')]) + ) + expect(vnode.el).toBe(container.firstChild) + // component el + const wrapperVNode = (vnode as any).children[0] + const tpStart = container.firstChild?.firstChild + const tpEnd = tpStart?.nextSibling?.nextSibling + expect(wrapperVNode.el).toBe(tpStart) + expect(wrapperVNode.component.subTree.el).toBe(tpStart) + expect(wrapperVNode.component.subTree.anchor).toBe(tpEnd) + // next node hydrate properly + const nextVNode = (vnode as any).children[1] + expect(nextVNode.el).toBe(container.firstChild?.lastChild) + }) + + test('Teleport (nested)', () => { + const teleportContainer = document.createElement('div') + teleportContainer.id = 'teleport6' teleportContainer.innerHTML = `
child
` document.body.appendChild(teleportContainer) const { vnode, container } = mountWithHydration( '', () => - h(Teleport, { to: '#teleport5' }, [ - h('div', [h(Teleport, { to: '#teleport5' }, [h('div', 'child')])]) + h(Teleport, { to: '#teleport6' }, [ + h('div', [h(Teleport, { to: '#teleport6' }, [h('div', 'child')])]) ]) ) diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts index 8ada97b166b..50a0fa5ccf4 100644 --- a/packages/runtime-core/src/hydration.ts +++ b/packages/runtime-core/src/hydration.ts @@ -227,13 +227,19 @@ export function createHydrationFunctions( ? locateClosingAsyncAnchor(node) : nextSibling(node) - // #4293 teleport as component root - if ( - nextNode && - isComment(nextNode) && - nextNode.data === 'teleport end' - ) { - nextNode = nextSibling(nextNode) + // #6152 teleport as component root + if (isComment(node) && node.data === 'teleport start') { + while ( + nextNode && !( + isComment(nextNode) && + nextNode.data === 'teleport end' + ) + ) { + nextNode = nextSibling(nextNode) + } + if (nextNode) { + nextNode = nextSibling(nextNode) + } } // #3787