Просмотр исходного кода

wip(vapor): fix children gen for dynamic with anchor insertion

Evan You 1 год назад
Родитель
Сommit
2a76b52d7f

+ 17 - 0
packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap

@@ -1,5 +1,22 @@
 // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
+exports[`compiler: children transform > anchor insertion in middle 1`] = `
+"import { child as _child, next as _next, setInsertionState as _setInsertionState, createIf as _createIf, template as _template } from 'vue';
+const t0 = _template("<div></div>")
+const t1 = _template("<div><div></div><!><div></div></div>", true)
+
+export function render(_ctx) {
+  const n4 = t1()
+  const n3 = _next(_child(n4))
+  _setInsertionState(n4, n3)
+  const n0 = _createIf(() => (1), () => {
+    const n2 = t0()
+    return n2
+  }, null, true)
+  return n4
+}"
+`;
+
 exports[`compiler: children transform > children & sibling references 1`] = `
 "import { child as _child, next as _next, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue';
 const t0 = _template("<div><p> </p> <p> </p></div>", true)

+ 14 - 0
packages/compiler-vapor/__tests__/transforms/transformChildren.spec.ts

@@ -59,4 +59,18 @@ describe('compiler: children transform', () => {
     expect(code).contains(`const n0 = _nthChild(n1, 2)`)
     expect(code).toMatchSnapshot()
   })
+
+  test('anchor insertion in middle', () => {
+    const { code } = compileWithElementTransform(
+      `<div>
+        <div></div>
+        <div v-if="1"></div>
+        <div></div>
+      </div>`,
+    )
+    // ensure the insertion anchor is generated before the insertion statement
+    expect(code).toMatch(`const n3 = _next(_child(n4))
+  _setInsertionState(n4, n3)`)
+    expect(code).toMatchSnapshot()
+  })
 })

+ 10 - 2
packages/compiler-vapor/src/generators/template.ts

@@ -94,15 +94,23 @@ export function genChildren(
         push(...init)
       }
     }
+
+    if (id === child.anchor) {
+      push(...genSelf(child, context))
+    }
+
     if (id !== undefined) {
       push(...genDirectivesForElement(id, context))
     }
+
     prev = [variable, elementIndex]
     childrenToGen.push([child, variable])
   }
 
-  for (const [child, from] of childrenToGen) {
-    push(...genChildren(child, context, from))
+  if (childrenToGen.length) {
+    for (const [child, from] of childrenToGen) {
+      push(...genChildren(child, context, from))
+    }
   }
 
   return frag

+ 21 - 0
packages/runtime-vapor/__tests__/hydration.spec.ts

@@ -239,6 +239,27 @@ describe('Vapor Mode hydration', () => {
     )
   })
 
+  // problem is the <!> placeholder does not exist in SSR output
+  test.todo('component with anchor insertion', async () => {
+    const { container, data } = await testHydration(
+      `
+      <template><div><span/><components.Child/><span/></div></template>
+      `,
+      {
+        Child: `<template>{{ data }}</template>`,
+      },
+    )
+    expect(container.innerHTML).toMatchInlineSnapshot(
+      `"<div><span></span>foo<span></span></div>"`,
+    )
+
+    data.value = 'bar'
+    await nextTick()
+    expect(container.innerHTML).toMatchInlineSnapshot(
+      `"<div><span></span>foo<span></span></div>"`,
+    )
+  })
+
   test.todo('if')
 
   test.todo('for')