wip: process component as a single element during hydration

This commit is contained in:
daiwei 2025-08-05 15:13:07 +08:00
parent a83231043f
commit bd5d341ffe
5 changed files with 132 additions and 131 deletions

View File

@ -409,9 +409,9 @@ describe('ssr: element', () => {
</div> </div>
`), `),
).toMatchInlineSnapshot(` ).toMatchInlineSnapshot(`
"\`<div><div></div>\`) "\`<div><div></div><!--[[-->\`)
_push(_ssrRenderComponent(_component_Comp1, null, null, _parent)) _push(_ssrRenderComponent(_component_Comp1, null, null, _parent))
_push(\`<!--[[-->\`) _push(\`<!--]]--><!--[[-->\`)
_push(_ssrRenderComponent(_component_Comp2, null, null, _parent)) _push(_ssrRenderComponent(_component_Comp2, null, null, _parent))
_push(\`<!--]]--><div></div></div>\`" _push(\`<!--]]--><div></div></div>\`"
`) `)
@ -430,15 +430,15 @@ describe('ssr: element', () => {
</div> </div>
`), `),
).toMatchInlineSnapshot(` ).toMatchInlineSnapshot(`
"\`<div><div></div>\`) "\`<div><div></div><!--[[-->\`)
_push(_ssrRenderComponent(_component_Comp1, null, null, _parent)) _push(_ssrRenderComponent(_component_Comp1, null, null, _parent))
_push(\`<!--[[-->\`) _push(\`<!--]]--><!--[[-->\`)
_push(_ssrRenderComponent(_component_Comp2, null, null, _parent)) _push(_ssrRenderComponent(_component_Comp2, null, null, _parent))
_push(\`<!--]]--><!--[[-->\`) _push(\`<!--]]--><!--[[-->\`)
_push(_ssrRenderComponent(_component_Comp3, null, null, _parent)) _push(_ssrRenderComponent(_component_Comp3, null, null, _parent))
_push(\`<!--]]-->\`) _push(\`<!--]]--><!--[[-->\`)
_push(_ssrRenderComponent(_component_Comp4, null, null, _parent)) _push(_ssrRenderComponent(_component_Comp4, null, null, _parent))
_push(\`<div></div></div>\`" _push(\`<!--]]--><div></div></div>\`"
`) `)
}) })
}) })

View File

@ -197,7 +197,11 @@ export function processChildren(
ssrProcessElement(child, context) ssrProcessElement(child, context)
break break
case ElementTypes.COMPONENT: case ElementTypes.COMPONENT:
if (inElement)
context.pushStringPart(`<!--${DYNAMIC_START_ANCHOR_LABEL}-->`)
ssrProcessComponent(child, context, parent) ssrProcessComponent(child, context, parent)
if (inElement)
context.pushStringPart(`<!--${DYNAMIC_END_ANCHOR_LABEL}-->`)
break break
case ElementTypes.SLOT: case ElementTypes.SLOT:
ssrProcessSlotOutlet(child, context) ssrProcessSlotOutlet(child, context)

View File

@ -713,7 +713,7 @@ describe('SSR hydration', () => {
// server render // server render
container.innerHTML = await renderToString(h(App)) container.innerHTML = await renderToString(h(App))
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
'<div><!--teleport start--><!--teleport end--></div>', '<div><!--[[--><!--teleport start--><!--teleport end--><!--]]--></div>',
) )
expect(teleportContainer1.innerHTML).toBe('') expect(teleportContainer1.innerHTML).toBe('')
expect(teleportContainer2.innerHTML).toBe('') expect(teleportContainer2.innerHTML).toBe('')
@ -721,7 +721,7 @@ describe('SSR hydration', () => {
// hydrate // hydrate
createSSRApp(App).mount(container) createSSRApp(App).mount(container)
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
'<div><!--teleport start--><!--teleport end--></div>', '<div><!--[[--><!--teleport start--><!--teleport end--><!--]]--></div>',
) )
expect(teleportContainer1.innerHTML).toBe('<span>Teleported</span>') expect(teleportContainer1.innerHTML).toBe('<span>Teleported</span>')
expect(teleportContainer2.innerHTML).toBe('') expect(teleportContainer2.innerHTML).toBe('')
@ -1005,7 +1005,7 @@ describe('SSR hydration', () => {
// server render // server render
container.innerHTML = await renderToString(h(App)) container.innerHTML = await renderToString(h(App))
expect(container.innerHTML).toMatchInlineSnapshot( expect(container.innerHTML).toMatchInlineSnapshot(
`"<div><span>1</span><span>2</span></div>"`, `"<div><!--[[--><span>1</span><!--]]--><!--[[--><span>2</span><!--]]--></div>"`,
) )
// reset asyncDeps from ssr // reset asyncDeps from ssr
asyncDeps.length = 0 asyncDeps.length = 0
@ -1923,14 +1923,14 @@ describe('SSR hydration', () => {
const root = document.createElement('div') const root = document.createElement('div')
root.innerHTML = await renderToString(h(App)) root.innerHTML = await renderToString(h(App))
createSSRApp(App).mount(root) createSSRApp(App).mount(root)
expect(root.innerHTML).toBe('<div><div>foo</div></div>') expect(root.innerHTML).toBe('<div><!--[[--><div>foo</div><!--]]--></div>')
reload(id, { reload(id, {
__hmrId: id, __hmrId: id,
template: `<div>bar</div>`, template: `<div>bar</div>`,
}) })
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<div><div>bar</div></div>') expect(root.innerHTML).toBe('<div><!--[[--><div>bar</div><!--]]--></div>')
}) })
test('hmr root reload', async () => { test('hmr root reload', async () => {

View File

@ -276,13 +276,13 @@ describe('Vapor Mode hydration', () => {
{ Child: `<template>{{ data }}</template>` }, { Child: `<template>{{ data }}</template>` },
) )
expect(container.innerHTML).toMatchInlineSnapshot( expect(container.innerHTML).toMatchInlineSnapshot(
`"<div><span></span>foo</div>"`, `"<div><span></span><!--[[-->foo<!--]]--></div>"`,
) )
data.value = 'bar' data.value = 'bar'
await nextTick() await nextTick()
expect(container.innerHTML).toMatchInlineSnapshot( expect(container.innerHTML).toMatchInlineSnapshot(
`"<div><span></span>bar</div>"`, `"<div><span></span><!--[[-->bar<!--]]--></div>"`,
) )
}) })
@ -294,13 +294,13 @@ describe('Vapor Mode hydration', () => {
{ Child: `<template><div>{{ data }}</div>-{{ data }}-</template>` }, { Child: `<template><div>{{ data }}</div>-{{ data }}-</template>` },
) )
expect(container.innerHTML).toMatchInlineSnapshot( expect(container.innerHTML).toMatchInlineSnapshot(
`"<div><span></span><!--[--><div>foo</div>-foo-<!--]--></div>"`, `"<div><span></span><!--[[--><!--[--><div>foo</div>-foo-<!--]--><!--]]--></div>"`,
) )
data.value = 'bar' data.value = 'bar'
await nextTick() await nextTick()
expect(container.innerHTML).toMatchInlineSnapshot( expect(container.innerHTML).toMatchInlineSnapshot(
`"<div><span></span><!--[--><div>bar</div>-bar-<!--]--></div>"`, `"<div><span></span><!--[[--><!--[--><div>bar</div>-bar-<!--]--><!--]]--></div>"`,
) )
}) })
@ -312,13 +312,13 @@ describe('Vapor Mode hydration', () => {
{ Child: `<template><div>{{ data }}</div>-{{ data }}-</template>` }, { Child: `<template><div>{{ data }}</div>-{{ data }}-</template>` },
) )
expect(container.innerHTML).toMatchInlineSnapshot( expect(container.innerHTML).toMatchInlineSnapshot(
`"<div><!--[--><div>foo</div>-foo-<!--]--><span></span></div>"`, `"<div><!--[[--><!--[--><div>foo</div>-foo-<!--]--><!--]]--><span></span></div>"`,
) )
data.value = 'bar' data.value = 'bar'
await nextTick() await nextTick()
expect(container.innerHTML).toMatchInlineSnapshot( expect(container.innerHTML).toMatchInlineSnapshot(
`"<div><!--[--><div>bar</div>-bar-<!--]--><span></span></div>"`, `"<div><!--[[--><!--[--><div>bar</div>-bar-<!--]--><!--]]--><span></span></div>"`,
) )
}) })
@ -334,11 +334,11 @@ describe('Vapor Mode hydration', () => {
) )
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<!--[-->` + `<!--[[--><!--[-->` +
`<div></div>` + `<div></div>` +
`<!--[--><div>foo</div>-foo-<!--]-->` + `<!--[--><div>foo</div>-foo-<!--]-->` +
`<div></div>` + `<div></div>` +
`<!--]-->` + `<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -347,11 +347,11 @@ describe('Vapor Mode hydration', () => {
await nextTick() await nextTick()
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<!--[-->` + `<!--[[--><!--[-->` +
`<div></div>` + `<div></div>` +
`<!--[--><div>bar</div>-bar-<!--]-->` + `<!--[--><div>bar</div>-bar-<!--]-->` +
`<div></div>` + `<div></div>` +
`<!--]-->` + `<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -372,13 +372,13 @@ describe('Vapor Mode hydration', () => {
}, },
) )
expect(container.innerHTML).toMatchInlineSnapshot( expect(container.innerHTML).toMatchInlineSnapshot(
`"<div><span></span>foo<span></span></div>"`, `"<div><span></span><!--[[-->foo<!--]]--><span></span></div>"`,
) )
data.value = 'bar' data.value = 'bar'
await nextTick() await nextTick()
expect(container.innerHTML).toMatchInlineSnapshot( expect(container.innerHTML).toMatchInlineSnapshot(
`"<div><span></span>bar<span></span></div>"`, `"<div><span></span><!--[[-->bar<!--]]--><span></span></div>"`,
) )
}) })
@ -393,13 +393,13 @@ describe('Vapor Mode hydration', () => {
}, },
) )
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div><span></span><div>foo</div><span></span></div>`, `<div><span></span><!--[[--><div>foo</div><!--]]--><span></span></div>`,
) )
data.value = 'bar' data.value = 'bar'
await nextTick() await nextTick()
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div><span></span><div>bar</div><span></span></div>`, `<div><span></span><!--[[--><div>bar</div><!--]]--><span></span></div>`,
) )
}) })
@ -416,11 +416,11 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<div>` + `<!--[[--><div>` +
`<span></span>` + `<span></span>` +
`<div>foo</div>` + `<!--[[--><div>foo</div><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>` + `</div><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -430,11 +430,11 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<div>` + `<!--[[--><div>` +
`<span></span>` + `<span></span>` +
`<div>bar</div>` + `<!--[[--><div>bar</div><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>` + `</div><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -458,7 +458,7 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`foo` + `<!--[[-->foo<!--]]-->` +
`<!--[[-->foo<!--]]-->` + `<!--[[-->foo<!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
@ -469,7 +469,7 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`bar` + `<!--[[-->bar<!--]]-->` +
`<!--[[-->bar<!--]]-->` + `<!--[[-->bar<!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
@ -493,14 +493,14 @@ describe('Vapor Mode hydration', () => {
data, data,
) )
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div><span>foo</span><span>bar</span></div>`, `<div><!--[[--><span>foo</span><!--]]--><!--[[--><span>bar</span><!--]]--></div>`,
) )
data.foo = 'foo1' data.foo = 'foo1'
data.bar = 'bar1' data.bar = 'bar1'
await nextTick() await nextTick()
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div><span>foo1</span><span>bar1</span></div>`, `<div><!--[[--><span>foo1</span><!--]]--><!--[[--><span>bar1</span><!--]]--></div>`,
) )
}) })
@ -517,7 +517,7 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<div>foo</div>` + `<!--[[--><div>foo</div><!--]]-->` +
`<!--[[--><div>foo</div><!--]]-->` + `<!--[[--><div>foo</div><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
@ -528,7 +528,7 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<div>bar</div>` + `<!--[[--><div>bar</div><!--]]-->` +
`<!--[[--><div>bar</div><!--]]-->` + `<!--[[--><div>bar</div><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
@ -548,12 +548,12 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<div>` + `<!--[[--><div>` +
`<span></span>` + `<span></span>` +
`<div>foo</div>` + `<!--[[--><div>foo</div><!--]]-->` +
`<!--[[--><div>foo</div><!--]]-->` + `<!--[[--><div>foo</div><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>` + `</div><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -563,12 +563,12 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<div>` + `<!--[[--><div>` +
`<span></span>` + `<span></span>` +
`<div>bar</div>` + `<!--[[--><div>bar</div><!--]]-->` +
`<!--[[--><div>bar</div><!--]]-->` + `<!--[[--><div>bar</div><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>` + `</div><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -593,9 +593,9 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`foo` + `<!--[[-->foo<!--]]-->` +
`<span></span>` + `<span></span>` +
`foo` + `<!--[[-->foo<!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -605,9 +605,9 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`bar` + `<!--[[-->bar<!--]]-->` +
`<span></span>` + `<span></span>` +
`bar` + `<!--[[-->bar<!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -632,9 +632,9 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`foo` + `<!--[[-->foo<!--]]-->` +
`<!--[[--> foo <!--]]-->` + ` <!--[[--> foo <!--]]--> ` +
`foo` + `<!--[[-->foo<!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -644,9 +644,9 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`bar` + `<!--[[-->bar<!--]]-->` +
`<!--[[--> bar <!--]]-->` + ` <!--[[--> bar <!--]]--> ` +
`bar` + `<!--[[-->bar<!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -669,7 +669,7 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>foo</div>-foo<!--]-->` + `<!--[[--><!--[--><div>foo</div>-foo<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -679,7 +679,7 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>bar</div>-bar<!--]-->` + `<!--[[--><!--[--><div>bar</div>-bar<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -698,7 +698,7 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>foo</div>-foo-<!--]-->` + `<!--[[--><!--[--><div>foo</div>-foo-<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -708,7 +708,7 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>bar</div>-bar-<!--]-->` + `<!--[[--><!--[--><div>bar</div>-bar-<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -727,11 +727,11 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<div>` + `<!--[[--><div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>foo</div>-foo-<!--]-->` + `<!--[[--><!--[--><div>foo</div>-foo-<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>` + `</div><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -741,11 +741,11 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<div>` + `<!--[[--><div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>bar</div>-bar-<!--]-->` + `<!--[[--><!--[--><div>bar</div>-bar-<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>` + `</div><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -769,10 +769,8 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>foo</div>-foo<!--]-->` + `<!--[[--><!--[--><div>foo</div>-foo<!--]--><!--]]-->` +
`<!--[[-->` + `<!--[[--><!--[--><div>foo</div>-foo<!--]--><!--]]-->` +
`<!--[--><div>foo</div>-foo<!--]-->` +
`<!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -782,10 +780,8 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>bar</div>-bar<!--]-->` + `<!--[[--><!--[--><div>bar</div>-bar<!--]--><!--]]-->` +
`<!--[[-->` + `<!--[[--><!--[--><div>bar</div>-bar<!--]--><!--]]-->` +
`<!--[--><div>bar</div>-bar<!--]-->` +
`<!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -804,10 +800,8 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>foo</div>-foo-<!--]-->` + `<!--[[--><!--[--><div>foo</div>-foo-<!--]--><!--]]-->` +
`<!--[[-->` + `<!--[[--><!--[--><div>foo</div>-foo-<!--]--><!--]]-->` +
`<!--[--><div>foo</div>-foo-<!--]-->` +
`<!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -817,10 +811,8 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>bar</div>-bar-<!--]-->` + `<!--[[--><!--[--><div>bar</div>-bar-<!--]--><!--]]-->` +
`<!--[[-->` + `<!--[[--><!--[--><div>bar</div>-bar-<!--]--><!--]]-->` +
`<!--[--><div>bar</div>-bar-<!--]-->` +
`<!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -839,14 +831,12 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<div>` + `<!--[[--><div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>foo</div>-foo-<!--]-->` + `<!--[[--><!--[--><div>foo</div>-foo-<!--]--><!--]]-->` +
`<!--[[-->` + `<!--[[--><!--[--><div>foo</div>-foo-<!--]--><!--]]-->` +
`<!--[--><div>foo</div>-foo-<!--]-->` +
`<!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>` + `</div><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -856,14 +846,12 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<div>` + `<!--[[--><div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>bar</div>-bar-<!--]-->` + `<!--[[--><!--[--><div>bar</div>-bar-<!--]--><!--]]-->` +
`<!--[[-->` + `<!--[[--><!--[--><div>bar</div>-bar-<!--]--><!--]]-->` +
`<!--[--><div>bar</div>-bar-<!--]-->` +
`<!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>` + `</div><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -882,10 +870,10 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<!--[-->` + `<!--[[--><!--[-->` +
`<!--[--><div>foo</div>-foo-<!--]-->` + `<!--[--><div>foo</div>-foo-<!--]-->` +
`<!--[--><div>foo</div>-foo-<!--]-->` + `<!--[--><div>foo</div>-foo-<!--]-->` +
`<!--]-->` + `<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -895,10 +883,10 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<!--[-->` + `<!--[[--><!--[-->` +
`<!--[--><div>bar</div>-bar-<!--]-->` + `<!--[--><div>bar</div>-bar-<!--]-->` +
`<!--[--><div>bar</div>-bar-<!--]-->` + `<!--[--><div>bar</div>-bar-<!--]-->` +
`<!--]-->` + `<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -923,9 +911,9 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>foo</div>-foo<!--]-->` + `<!--[[--><!--[--><div>foo</div>-foo<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`<!--[--><div>foo</div>-foo<!--]-->` + `<!--[[--><!--[--><div>foo</div>-foo<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -935,9 +923,9 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>bar</div>-bar<!--]-->` + `<!--[[--><!--[--><div>bar</div>-bar<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`<!--[--><div>bar</div>-bar<!--]-->` + `<!--[[--><!--[--><div>bar</div>-bar<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -962,9 +950,9 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>foo</div>-foo<!--]-->` + `<!--[[--><!--[--><div>foo</div>-foo<!--]--><!--]]-->` +
` <!--[[--> foo <!--]]--> ` + ` <!--[[--> foo <!--]]--> ` +
`<!--[--><div>foo</div>-foo<!--]-->` + `<!--[[--><!--[--><div>foo</div>-foo<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -974,9 +962,9 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<!--[--><div>bar</div>-bar<!--]-->` + `<!--[[--><!--[--><div>bar</div>-bar<!--]--><!--]]-->` +
` <!--[[--> bar <!--]]--> ` + ` <!--[[--> bar <!--]]--> ` +
`<!--[--><div>bar</div>-bar<!--]-->` + `<!--[[--><!--[--><div>bar</div>-bar<!--]--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -1022,7 +1010,7 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<div>foo</div><!--${anchorLabel}-->` + `<!--[[--><div>foo</div><!--${anchorLabel}--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -1032,7 +1020,7 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<div>bar</div><!--${anchorLabel}-->` + `<!--[[--><div>bar</div><!--${anchorLabel}--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
) )
@ -1057,7 +1045,7 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<div>foo</div><!--${anchorLabel}-->` + `<!--[[--><div>foo</div><!--${anchorLabel}--><!--]]-->` +
`<!--[[--><div>foo</div><!--${anchorLabel}--><!--]]-->` + `<!--[[--><div>foo</div><!--${anchorLabel}--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
@ -1068,7 +1056,7 @@ describe('Vapor Mode hydration', () => {
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span></span>` + `<span></span>` +
`<div>bar</div><!--${anchorLabel}-->` + `<!--[[--><div>bar</div><!--${anchorLabel}--><!--]]-->` +
`<!--[[--><div>bar</div><!--${anchorLabel}--><!--]]-->` + `<!--[[--><div>bar</div><!--${anchorLabel}--><!--]]-->` +
`<span></span>` + `<span></span>` +
`</div>`, `</div>`,
@ -1145,7 +1133,9 @@ describe('Vapor Mode hydration', () => {
{ Child: `<template>foo</template>` }, { Child: `<template>foo</template>` },
data, data,
) )
expect(container.innerHTML).toBe(`<div>foo</div><!--${anchorLabel}-->`) expect(container.innerHTML).toBe(
`<div><!--[[-->foo<!--]]--></div><!--${anchorLabel}-->`,
)
data.value = false data.value = false
await nextTick() await nextTick()
@ -1481,8 +1471,8 @@ describe('Vapor Mode hydration', () => {
) )
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<span>foo</span>` + `<!--[[--><span>foo</span><!--]]-->` +
`<span>bar</span>` + `<!--[[--><span>bar</span><!--]]-->` +
`</div>` + `</div>` +
`<!--${anchorLabel}-->`, `<!--${anchorLabel}-->`,
) )
@ -2335,9 +2325,9 @@ describe('Vapor Mode hydration', () => {
) )
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<div>bar</div>` + `<!--[[--><div>bar</div><!--]]-->` +
`<!--[--><span>foo</span><!--]--><!--${slotAnchorLabel}-->` + `<!--[--><span>foo</span><!--]--><!--${slotAnchorLabel}-->` +
`<div>bar</div>` + `<!--[[--><div>bar</div><!--]]-->` +
`</div>`, `</div>`,
) )
@ -2345,9 +2335,9 @@ describe('Vapor Mode hydration', () => {
await nextTick() await nextTick()
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<div>hello</div>` + `<!--[[--><div>hello</div><!--]]-->` +
`<!--[--><span>foo</span><!--]--><!--${slotAnchorLabel}-->` + `<!--[--><span>foo</span><!--]--><!--${slotAnchorLabel}-->` +
`<div>hello</div>` + `<!--[[--><div>hello</div><!--]]-->` +
`</div>`, `</div>`,
) )
}) })
@ -2381,9 +2371,9 @@ describe('Vapor Mode hydration', () => {
) )
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<!--[--><div>foo</div> bar<!--]-->` + `<!--[[--><!--[--><div>foo</div> bar<!--]--><!--]]-->` +
`<!--[--><span>foo</span><!--]--><!--${slotAnchorLabel}-->` + `<!--[--><span>foo</span><!--]--><!--${slotAnchorLabel}-->` +
`<!--[--><div>foo</div> bar<!--]-->` + `<!--[[--><!--[--><div>foo</div> bar<!--]--><!--]]-->` +
`</div>`, `</div>`,
) )
@ -2392,9 +2382,9 @@ describe('Vapor Mode hydration', () => {
await nextTick() await nextTick()
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<!--[--><div>hello</div> vapor<!--]-->` + `<!--[[--><!--[--><div>hello</div> vapor<!--]--><!--]]-->` +
`<!--[--><span>hello</span><!--]--><!--${slotAnchorLabel}-->` + `<!--[--><span>hello</span><!--]--><!--${slotAnchorLabel}-->` +
`<!--[--><div>hello</div> vapor<!--]-->` + `<!--[[--><!--[--><div>hello</div> vapor<!--]--><!--]]-->` +
`</div>`, `</div>`,
) )
}) })
@ -2667,14 +2657,14 @@ describe('Vapor Mode hydration', () => {
) )
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<div>` + `<!--[[--><div>` +
`<div>` + `<!--[[--><div>` +
`<!--[-->` + `<!--[-->` +
`<!--[--><span>foo</span><!--]--><!--slot-->` + `<!--[--><span>foo</span><!--]--><!--slot-->` +
`<!--]-->` + `<!--]-->` +
`<!--slot-->` + `<!--slot-->` +
`</div>` + `</div><!--]]-->` +
`</div>` + `</div><!--]]-->` +
`<div>bar</div>` + `<div>bar</div>` +
`</div>`, `</div>`,
) )
@ -2684,14 +2674,14 @@ describe('Vapor Mode hydration', () => {
await nextTick() await nextTick()
expect(container.innerHTML).toBe( expect(container.innerHTML).toBe(
`<div>` + `<div>` +
`<div>` + `<!--[[--><div>` +
`<div>` + `<!--[[--><div>` +
`<!--[-->` + `<!--[-->` +
`<!--[--><span>foo1</span><!--]--><!--slot-->` + `<!--[--><span>foo1</span><!--]--><!--slot-->` +
`<!--]-->` + `<!--]-->` +
`<!--slot-->` + `<!--slot-->` +
`</div>` + `</div><!--]]-->` +
`</div>` + `</div><!--]]-->` +
`<div>bar1</div>` + `<div>bar1</div>` +
`</div>`, `</div>`,
) )

View File

@ -12,7 +12,7 @@ import {
disableHydrationNodeLookup, disableHydrationNodeLookup,
enableHydrationNodeLookup, enableHydrationNodeLookup,
} from './node' } from './node'
import { isVaporAnchors } from '@vue/shared' import { DYNAMIC_END_ANCHOR_LABEL, isVaporAnchors } from '@vue/shared'
export let isHydrating = false export let isHydrating = false
export let currentHydrationNode: Node | null = null export let currentHydrationNode: Node | null = null
@ -23,15 +23,22 @@ export function setCurrentHydrationNode(node: Node | null): void {
function findParentSibling(n: Node): Node | null { function findParentSibling(n: Node): Node | null {
if (!n.parentNode) return null if (!n.parentNode) return null
const next = n.parentNode.nextSibling let next = n.parentNode.nextSibling
while (next && isComment(next, DYNAMIC_END_ANCHOR_LABEL)) {
next = next.nextElementSibling
}
return next ? next : findParentSibling(n.parentNode) return next ? next : findParentSibling(n.parentNode)
} }
export function advanceHydrationNode(node: Node & { $ps?: Node | null }): void { export function advanceHydrationNode(node: Node & { $ps?: Node | null }): void {
let next = node.nextSibling
while (next && isComment(next, DYNAMIC_END_ANCHOR_LABEL)) {
next = next.nextSibling
}
// if no next sibling, find the next node in the parent chain // if no next sibling, find the next node in the parent chain
const next = const ret = next || node.$ps || (node.$ps = findParentSibling(node))
node.nextSibling || node.$ps || (node.$ps = findParentSibling(node)) if (ret) setCurrentHydrationNode(ret)
if (next) setCurrentHydrationNode(next)
} }
let isOptimized = false let isOptimized = false