]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(hydration): avoid observing non-Element node (#11954)
authorlinzhe <40790268+linzhe141@users.noreply.github.com>
Fri, 20 Sep 2024 08:41:58 +0000 (16:41 +0800)
committerGitHub <noreply@github.com>
Fri, 20 Sep 2024 08:41:58 +0000 (16:41 +0800)
close #11952

packages/runtime-core/src/hydrationStrategies.ts
packages/vue/__tests__/e2e/hydration-strat-visible.html
packages/vue/__tests__/e2e/hydrationStrategies.spec.ts

index 791ca9e5254355b5748d64d283abb6a090252ab5..bb98ea93c208822af19977aa035a3f0147b477ca 100644 (file)
@@ -48,6 +48,7 @@ export const hydrateOnVisible: HydrationStrategyFactory<
     }
   }, opts)
   forEach(el => {
+    if (!(el instanceof Element)) return
     if (elementIsVisibleInViewport(el)) {
       hydrate()
       ob.disconnect()
index 7b3b5ddf35dca1b563eb9088e68203f8bc4cd179..489222f86062b3200e8bad4bdb92b2f0fe5eff02 100644 (file)
 <script>
   const rootMargin = location.search.match(/rootMargin=(\d+)/)?.[1] ?? 0
   const isFragment = location.search.includes('?fragment')
+  const isVIf = location.search.includes('?v-if')
   if (isFragment) {
     document.getElementById('app').innerHTML =
       `<!--[--><!--[--><span>one</span><!--]--><button>0</button><span>two</span><!--]-->`
+  } else if (isVIf) {
+    document.getElementById('app').innerHTML = `<!---->`
   }
 
   window.isHydrated = false
@@ -24,6 +27,7 @@
     ref,
     onMounted,
     hydrateOnVisible,
+    createCommentVNode,
   } = Vue
 
   const Comp = {
@@ -39,7 +43,9 @@
           { onClick: () => count.value++ },
           count.value,
         )
-        if (isFragment) {
+        if (isVIf) {
+          return createCommentVNode('v-if', true)
+        } else if (isFragment) {
           return [[h('span', 'one')], button, h('span', 'two')]
         } else {
           return button
index 58e3784ba7fcbd261f9de16697dbe19aa426c2a0..69934d9591e8b10f71cd00aafe059c193175e93a 100644 (file)
@@ -65,6 +65,17 @@ describe('async component hydration strategies', () => {
     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 () => {
     await goToCase('media')
     await page().waitForFunction(() => window.isRootMounted)