]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: save
authordaiwei <daiwei521@126.com>
Tue, 22 Apr 2025 09:40:31 +0000 (17:40 +0800)
committerdaiwei <daiwei521@126.com>
Tue, 22 Apr 2025 09:46:05 +0000 (17:46 +0800)
packages/compiler-ssr/__tests__/ssrElement.spec.ts
packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
packages/runtime-core/__tests__/hydration.spec.ts
packages/runtime-vapor/__tests__/hydration.spec.ts
packages/runtime-vapor/src/dom/hydration.ts
packages/runtime-vapor/src/insertionState.ts

index 97601ae9abcab71239fa0adfc312f3b3194414fe..59f6b0ffbc9d13ad7906866a8feaa2b95aeb6947 100644 (file)
@@ -398,24 +398,6 @@ describe('ssr: element', () => {
   })
 
   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(`
index a130dc427ff61a12e7dc44f593de60d24d7f76ab..48df3213377403b3044490c13b9f8518d4906b13 100644 (file)
@@ -428,5 +428,24 @@ function shouldAddDynamicAnchor(
     }
   }
 
-  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
+  )
 }
index 07a6504b504f2c4747463ea6b879ab4ecf17e18c..a6a8960fb1f19342dce14498e726b1045f38db34 100644 (file)
@@ -1844,20 +1844,6 @@ describe('SSR hydration', () => {
   })
 
   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() {
index def3c9d9248d85319566295bf52313f42bb7cdde..27ef427a116a8c6b42fd2d0c026ef0db57e699f0 100644 (file)
@@ -241,8 +241,7 @@ describe('Vapor Mode hydration', () => {
 
   test('component with anchor insertion', async () => {
     const { container, data } = await testHydration(
-      `
-      <template>
+      `<template>
         <div>
           <span/>
           <components.Child/>
@@ -255,13 +254,13 @@ describe('Vapor Mode hydration', () => {
       },
     )
     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>"`,
     )
   })
 
@@ -291,6 +290,56 @@ describe('Vapor Mode hydration', () => {
     )
   })
 
+  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')
index 5c1cdde070b7ea7d9997c8ae773d42646061a0d3..a3b0eecb4ba4fc78876404201e32f32f48a8b4bc 100644 (file)
@@ -75,45 +75,47 @@ function locateHydrationNodeImpl() {
   // 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++
             }
           }
         }
index 5004c4d97267747289a275d26f42c84baf2e81b1..8280b65c281ee82b3af447fe6a66c40509d83248 100644 (file)
@@ -1,7 +1,7 @@
 export let insertionParent:
   | (ParentNode & {
       // cached the last dynamic start anchor
-      lds?: Anchor
+      $lds?: Anchor
     })
   | undefined
 export let insertionAnchor: Node | 0 | undefined | null