diff --git a/packages/runtime-core/__tests__/hydration.spec.ts b/packages/runtime-core/__tests__/hydration.spec.ts
index 759804b97f1..abf50c54668 100644
--- a/packages/runtime-core/__tests__/hydration.spec.ts
+++ b/packages/runtime-core/__tests__/hydration.spec.ts
@@ -75,6 +75,16 @@ describe('SSR hydration', () => {
expect(vnode.el.nodeType).toBe(8) // comment
})
+ test('comment (real left square bracket)', () => {
+ const { vnode, container } = mountWithHydration(
+ `
foo
`,
+ () => h('div', [h('span', 'foo'), createCommentVNode('hello')])
+ )
+ expect(vnode.el).toBe(container.firstChild)
+ expect(container.innerHTML).toBe('foo
')
+ expect(`Hydration node mismatch`).not.toHaveBeenWarned()
+ })
+
test('static', () => {
const html = 'hello
'
const { vnode, container } = mountWithHydration(html, () =>
@@ -1177,5 +1187,21 @@ describe('SSR hydration', () => {
expect(teleportContainer.innerHTML).toBe(`value`)
expect(`Hydration children mismatch`).toHaveBeenWarned()
})
+
+ test('comment mismatch (element)', () => {
+ const { container } = mountWithHydration(`
`, () =>
+ h('div', [createCommentVNode('hi')])
+ )
+ expect(container.innerHTML).toBe('')
+ expect(`Hydration node mismatch`).toHaveBeenWarned()
+ })
+
+ test('comment mismatch (text)', () => {
+ const { container } = mountWithHydration(`foobar
`, () =>
+ h('div', [createCommentVNode('hi')])
+ )
+ expect(container.innerHTML).toBe('')
+ expect(`Hydration node mismatch`).toHaveBeenWarned()
+ })
})
})
diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts
index 4e91cb3d1cb..b8940e6679a 100644
--- a/packages/runtime-core/src/hydration.ts
+++ b/packages/runtime-core/src/hydration.ts
@@ -145,18 +145,17 @@ export function createHydrationFunctions(
}
break
case Comment:
- if (domType !== DOMNodeTypes.COMMENT || isFragmentStart) {
- if ((node as Element).tagName.toLowerCase() === 'template') {
- const content = (vnode.el! as HTMLTemplateElement).content
- .firstChild!
-
- // replace node with inner children
- replaceNode(content, node, parentComponent)
- vnode.el = node = content
- nextNode = nextSibling(node)
- } else {
- nextNode = onMismatch()
- }
+ if (isTemplateNode(node)) {
+ nextNode = nextSibling(node)
+ // wrapped
+ // replace node with inner child
+ replaceNode(
+ (vnode.el = node.content.firstChild!),
+ node,
+ parentComponent
+ )
+ } else if (domType !== DOMNodeTypes.COMMENT || isFragmentStart) {
+ nextNode = onMismatch()
} else {
nextNode = nextSibling(node)
}
@@ -209,7 +208,7 @@ export function createHydrationFunctions(
(domType !== DOMNodeTypes.ELEMENT ||
(vnode.type as string).toLowerCase() !==
(node as Element).tagName.toLowerCase()) &&
- !isTemplateNode(node as Element)
+ !isTemplateNode(node)
) {
nextNode = onMismatch()
} else {
@@ -637,17 +636,16 @@ export function createHydrationFunctions(
let parent = parentComponent
while (parent) {
if (parent.vnode.el === oldNode) {
- parent.vnode.el = newNode
- parent.subTree.el = newNode
+ parent.vnode.el = parent.subTree.el = newNode
}
parent = parent.parent
}
}
- const isTemplateNode = (node: Element): boolean => {
+ const isTemplateNode = (node: Node): node is HTMLTemplateElement => {
return (
node.nodeType === DOMNodeTypes.ELEMENT &&
- node.tagName.toLowerCase() === 'template'
+ (node as Element).tagName.toLowerCase() === 'template'
)
}