Skip to content

Commit 939209c

Browse files
committed
fix(ssr): fix hydration for slot with empty text node
fix #5728
1 parent e1bc268 commit 939209c

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

packages/runtime-core/__tests__/hydration.spec.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import {
1313
createTextVNode,
1414
createVNode,
1515
withDirectives,
16-
vModelCheckbox
16+
vModelCheckbox,
17+
renderSlot
1718
} from '@vue/runtime-dom'
1819
import { renderToString, SSRContext } from '@vue/server-renderer'
1920
import { PatchFlags } from '../../shared/src'
@@ -912,6 +913,24 @@ describe('SSR hydration', () => {
912913
expect((container.firstChild!.firstChild as any)._value).toBe(true)
913914
})
914915

916+
// #5728
917+
test('empty text node in slot', () => {
918+
const Comp = {
919+
render(this: any) {
920+
return renderSlot(this.$slots, 'default', {}, () => [
921+
createTextVNode('')
922+
])
923+
}
924+
}
925+
const { container, vnode } = mountWithHydration('<!--[--><!--]-->', () => h(Comp))
926+
expect(container.childNodes.length).toBe(3)
927+
const text = container.childNodes[1]
928+
expect(text.nodeType).toBe(3)
929+
expect(vnode.el).toBe(container.childNodes[0])
930+
// component => slot fragment => text node
931+
expect((vnode as any).component?.subTree.children[0].el).toBe(text)
932+
})
933+
915934
describe('mismatch handling', () => {
916935
test('text node', () => {
917936
const { container } = mountWithHydration(`foo`, () => 'bar')

packages/runtime-core/src/hydration.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,18 @@ export function createHydrationFunctions(
110110
switch (type) {
111111
case Text:
112112
if (domType !== DOMNodeTypes.TEXT) {
113-
nextNode = onMismatch()
113+
// #5728 empty text node inside a slot can cause hydration failure
114+
// because the server rendered HTML won't contain a text node
115+
if (vnode.children === '') {
116+
insert(
117+
(vnode.el = document.createTextNode('')),
118+
node.parentElement!,
119+
node
120+
)
121+
nextNode = node
122+
} else {
123+
nextNode = onMismatch()
124+
}
114125
} else {
115126
if ((node as Text).data !== vnode.children) {
116127
hasMismatch = true

0 commit comments

Comments
 (0)