mirror of https://github.com/vuejs/core.git
fix(hydration): fix tagName access eeror on comment/text node hydration mismatch
fix #9531
This commit is contained in:
parent
405f34587a
commit
dd8a0cf5dc
|
@ -75,6 +75,16 @@ describe('SSR hydration', () => {
|
|||
expect(vnode.el.nodeType).toBe(8) // comment
|
||||
})
|
||||
|
||||
test('comment (real left square bracket)', () => {
|
||||
const { vnode, container } = mountWithHydration(
|
||||
`<div><span>foo</span><!--hello--></div>`,
|
||||
() => h('div', [h('span', 'foo'), createCommentVNode('hello')])
|
||||
)
|
||||
expect(vnode.el).toBe(container.firstChild)
|
||||
expect(container.innerHTML).toBe('<div><span>foo</span><!--hello--></div>')
|
||||
expect(`Hydration node mismatch`).not.toHaveBeenWarned()
|
||||
})
|
||||
|
||||
test('static', () => {
|
||||
const html = '<div><span>hello</span></div>'
|
||||
const { vnode, container } = mountWithHydration(html, () =>
|
||||
|
@ -1177,5 +1187,21 @@ describe('SSR hydration', () => {
|
|||
expect(teleportContainer.innerHTML).toBe(`<span>value</span>`)
|
||||
expect(`Hydration children mismatch`).toHaveBeenWarned()
|
||||
})
|
||||
|
||||
test('comment mismatch (element)', () => {
|
||||
const { container } = mountWithHydration(`<div><span></span></div>`, () =>
|
||||
h('div', [createCommentVNode('hi')])
|
||||
)
|
||||
expect(container.innerHTML).toBe('<div><!--hi--></div>')
|
||||
expect(`Hydration node mismatch`).toHaveBeenWarned()
|
||||
})
|
||||
|
||||
test('comment mismatch (text)', () => {
|
||||
const { container } = mountWithHydration(`<div>foobar</div>`, () =>
|
||||
h('div', [createCommentVNode('hi')])
|
||||
)
|
||||
expect(container.innerHTML).toBe('<div><!--hi--></div>')
|
||||
expect(`Hydration node mismatch`).toHaveBeenWarned()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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 <template> 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 <transition appear>
|
||||
// replace <template> 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'
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue