fix(hydration): avoid observing non-Element node (#11954)

close #11952
This commit is contained in:
linzhe 2024-09-20 16:41:58 +08:00 committed by GitHub
parent e075dfad5c
commit 7257e6a342
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 19 additions and 1 deletions

View File

@ -48,6 +48,7 @@ export const hydrateOnVisible: HydrationStrategyFactory<
} }
}, opts) }, opts)
forEach(el => { forEach(el => {
if (!(el instanceof Element)) return
if (elementIsVisibleInViewport(el)) { if (elementIsVisibleInViewport(el)) {
hydrate() hydrate()
ob.disconnect() ob.disconnect()

View File

@ -11,9 +11,12 @@
<script> <script>
const rootMargin = location.search.match(/rootMargin=(\d+)/)?.[1] ?? 0 const rootMargin = location.search.match(/rootMargin=(\d+)/)?.[1] ?? 0
const isFragment = location.search.includes('?fragment') const isFragment = location.search.includes('?fragment')
const isVIf = location.search.includes('?v-if')
if (isFragment) { if (isFragment) {
document.getElementById('app').innerHTML = document.getElementById('app').innerHTML =
`<!--[--><!--[--><span>one</span><!--]--><button>0</button><span>two</span><!--]-->` `<!--[--><!--[--><span>one</span><!--]--><button>0</button><span>two</span><!--]-->`
} else if (isVIf) {
document.getElementById('app').innerHTML = `<!---->`
} }
window.isHydrated = false window.isHydrated = false
@ -24,6 +27,7 @@
ref, ref,
onMounted, onMounted,
hydrateOnVisible, hydrateOnVisible,
createCommentVNode,
} = Vue } = Vue
const Comp = { const Comp = {
@ -39,7 +43,9 @@
{ onClick: () => count.value++ }, { onClick: () => count.value++ },
count.value, count.value,
) )
if (isFragment) { if (isVIf) {
return createCommentVNode('v-if', true)
} else if (isFragment) {
return [[h('span', 'one')], button, h('span', 'two')] return [[h('span', 'one')], button, h('span', 'two')]
} else { } else {
return button return button

View File

@ -65,6 +65,17 @@ describe('async component hydration strategies', () => {
await assertHydrationSuccess() await assertHydrationSuccess()
}) })
test('visible (root v-if) should not throw error', async () => {
const spy = vi.fn()
const currentPage = page()
currentPage.on('pageerror', spy)
await goToCase('visible', '?v-if')
await page().waitForFunction(() => window.isRootMounted)
expect(await page().evaluate(() => window.isHydrated)).toBe(false)
expect(spy).toBeCalledTimes(0)
currentPage.off('pageerror', spy)
})
test('media query', async () => { test('media query', async () => {
await goToCase('media') await goToCase('media')
await page().waitForFunction(() => window.isRootMounted) await page().waitForFunction(() => window.isRootMounted)