})
describe('dynamic child anchor', () => {
- test('component with element siblings', () => {
- expect(
- getCompiledString(`
- <div>
- <div/>
- <Comp1/>
- <div/>
- </div>
- `),
- ).toMatchInlineSnapshot(`
- "\`<div><div></div>\`)
- _push("<!--[[-->")
- _push(_ssrRenderComponent(_component_Comp1, null, null, _parent))
- _push("<!--]]-->")
- _push(\`<div></div></div>\`"
- `)
- })
-
test('with consecutive components', () => {
expect(
getCompiledString(`
}
}
- return hasStaticPreviousSibling && hasStaticNextSibling
+ let hasConsecutiveDynamicNodes = false
+ if (index > 0 && index < len - 1) {
+ if (index > 0 && !isStaticElement(children[index - 1])) {
+ hasConsecutiveDynamicNodes = true
+ }
+
+ if (
+ !hasConsecutiveDynamicNodes &&
+ index < len - 1 &&
+ !isStaticElement(children[index + 1])
+ ) {
+ hasConsecutiveDynamicNodes = true
+ }
+ }
+
+ return (
+ hasStaticPreviousSibling &&
+ hasStaticNextSibling &&
+ hasConsecutiveDynamicNodes
+ )
}
})
describe('dynamic child anchor', () => {
- test('component with element siblings', () => {
- const Comp = {
- render() {
- return createTextVNode('foo')
- },
- }
- const { vnode, container } = mountWithHydration(
- `<div><span></span><!--[[-->foo<!--]]--><span></span></div>`,
- () => h('div', null, [h('span'), h(Comp), h('span')]),
- )
- expect(vnode.el).toBe(container.firstChild)
- expect(`Hydration children mismatch`).not.toHaveBeenWarned()
- })
-
test('with consecutive components', () => {
const Comp = {
render() {
test('component with anchor insertion', async () => {
const { container, data } = await testHydration(
- `
- <template>
+ `<template>
<div>
<span/>
<components.Child/>
},
)
expect(container.innerHTML).toMatchInlineSnapshot(
- `"<div><span></span><!--[[-->foo<!--]]--><span></span></div>"`,
+ `"<div><span></span>foo<span></span></div>"`,
)
data.value = 'bar'
await nextTick()
expect(container.innerHTML).toMatchInlineSnapshot(
- `"<div><span></span><!--[[-->bar<!--]]--><span></span></div>"`,
+ `"<div><span></span>bar<span></span></div>"`,
)
})
)
})
+ test('mixed component and element with anchor insertion', async () => {
+ const { container, data } = await testHydration(
+ `<template>
+ <div>
+ <span/>
+ <components.Child/>
+ <span/>
+ <components.Child/>
+ <span/>
+ </div>
+ </template>
+ `,
+ {
+ Child: `<template>{{ data }}</template>`,
+ },
+ )
+ expect(container.innerHTML).toMatchInlineSnapshot(
+ `"<div><span></span>foo<span></span>foo<span></span></div>"`,
+ )
+
+ data.value = 'bar'
+ await nextTick()
+ expect(container.innerHTML).toMatchInlineSnapshot(
+ `"<div><span></span>bar<span></span>bar<span></span></div>"`,
+ )
+ })
+
+ test.todo('mixed component and text with anchor insertion', async () => {
+ const { container, data } = await testHydration(
+ `<template>
+ <div>
+ <span/>
+ <components.Child/>
+ {{ data }}
+ <components.Child/>
+ <span/>
+ </div>
+ </template>
+ `,
+ {
+ Child: `<template>{{ data }}</template>`,
+ },
+ )
+ expect(container.innerHTML).toMatchInlineSnapshot(``)
+
+ data.value = 'bar'
+ await nextTick()
+ expect(container.innerHTML).toMatchInlineSnapshot(``)
+ })
+
test.todo('if')
test.todo('for')
// prepend / firstChild
if (insertionAnchor === 0) {
node = child(insertionParent!)
- } else {
+ } else if (insertionParent && insertionAnchor) {
// dynamic child anchor `<!--[[-->`
if (insertionAnchor && isDynamicStart(insertionAnchor)) {
- const anchor = (insertionParent!.lds = insertionParent!.lds
+ const anchor = (insertionParent!.$lds = insertionParent!.$lds
? // continuous dynamic children, the next dynamic start must exist
- locateNextDynamicStart(insertionParent!.lds)!
+ locateNextDynamicStart(insertionParent!.$lds)!
: insertionAnchor)
node = anchor.nextSibling
} else {
node = insertionAnchor
- ? insertionAnchor.previousSibling
- : insertionParent
- ? insertionParent.lastChild
- : currentHydrationNode
- if (node && isComment(node, ']')) {
- // fragment backward search
- if (node.$fs) {
- // already cached matching fragment start
- node = node.$fs
- } else {
- let cur: Node | null = node
- let curFragEnd = node
- let fragDepth = 0
- node = null
- while (cur) {
- cur = cur.previousSibling
- if (cur) {
- if (isComment(cur, '[')) {
- curFragEnd.$fs = cur
- if (!fragDepth) {
- node = cur
- break
- } else {
- fragDepth--
- }
- } else if (isComment(cur, ']')) {
- curFragEnd = cur
- fragDepth++
+ }
+ } else {
+ node = insertionAnchor
+ ? insertionAnchor.previousSibling
+ : insertionParent
+ ? insertionParent.lastChild
+ : currentHydrationNode
+ if (node && isComment(node, ']')) {
+ // fragment backward search
+ if (node.$fs) {
+ // already cached matching fragment start
+ node = node.$fs
+ } else {
+ let cur: Node | null = node
+ let curFragEnd = node
+ let fragDepth = 0
+ node = null
+ while (cur) {
+ cur = cur.previousSibling
+ if (cur) {
+ if (isComment(cur, '[')) {
+ curFragEnd.$fs = cur
+ if (!fragDepth) {
+ node = cur
+ break
+ } else {
+ fragDepth--
}
+ } else if (isComment(cur, ']')) {
+ curFragEnd = cur
+ fragDepth++
}
}
}
export let insertionParent:
| (ParentNode & {
// cached the last dynamic start anchor
- lds?: Anchor
+ $lds?: Anchor
})
| undefined
export let insertionAnchor: Node | 0 | undefined | null