From c50fb0e951f6d3e0c979f6722c3f7834c7a4ef31 Mon Sep 17 00:00:00 2001
From: zhiyuanzmj <260480378@qq.com>
Date: Tue, 18 Mar 2025 00:04:29 +0800
Subject: [PATCH 1/2] fix(compiler-vapor): move setInsertionState to the end to
 prevent nthChild mismatch

---
 .../__tests__/__snapshots__/compile.spec.ts.snap          | 8 ++++----
 .../__snapshots__/transformChildren.spec.ts.snap          | 4 ++--
 .../__tests__/transforms/__snapshots__/vFor.spec.ts.snap  | 4 ++--
 .../__tests__/transforms/__snapshots__/vOnce.spec.ts.snap | 4 ++--
 .../__tests__/transforms/transformChildren.spec.ts        | 4 ++--
 packages/compiler-vapor/src/generators/operation.ts       | 2 +-
 6 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
index e56676d8706..7614fc3c4bc 100644
--- a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
@@ -26,7 +26,7 @@ export function render(_ctx) {
 `;
 
 exports[`compile > custom directive > component 1`] = `
-"import { resolveComponent as _resolveComponent, resolveDirective as _resolveDirective, setInsertionState as _setInsertionState, createComponentWithFallback as _createComponentWithFallback, withVaporDirectives as _withVaporDirectives, createIf as _createIf, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, resolveDirective as _resolveDirective, createComponentWithFallback as _createComponentWithFallback, withVaporDirectives as _withVaporDirectives, setInsertionState as _setInsertionState, createIf as _createIf, template as _template } from 'vue';
 const t0 = _template("<div></div>")
 
 export function render(_ctx) {
@@ -38,9 +38,9 @@ export function render(_ctx) {
     "default": () => {
       const n0 = _createIf(() => (true), () => {
         const n3 = t0()
-        _setInsertionState(n3)
         const n2 = _createComponentWithFallback(_component_Bar)
         _withVaporDirectives(n2, [[_directive_hello, void 0, void 0, { world: true }]])
+        _setInsertionState(n3)
         return n3
       })
       return n0
@@ -149,7 +149,7 @@ export function render(_ctx, $props, $emit, $attrs, $slots) {
 `;
 
 exports[`compile > directives > v-pre > should not affect siblings after it 1`] = `
-"import { resolveComponent as _resolveComponent, setInsertionState as _setInsertionState, createComponentWithFallback as _createComponentWithFallback, child as _child, toDisplayString as _toDisplayString, setText as _setText, setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, setInsertionState as _setInsertionState, child as _child, toDisplayString as _toDisplayString, setText as _setText, setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
 const t0 = _template("<div :id=\\"foo\\"><Comp></Comp>{{ bar }}</div>")
 const t1 = _template("<div> </div>")
 
@@ -157,8 +157,8 @@ export function render(_ctx, $props, $emit, $attrs, $slots) {
   const _component_Comp = _resolveComponent("Comp")
   const n0 = t0()
   const n3 = t1()
-  _setInsertionState(n3, 0)
   const n1 = _createComponentWithFallback(_component_Comp)
+  _setInsertionState(n3, 0)
   const n2 = _child(n3)
   _renderEffect(() => {
     _setText(n2, _toDisplayString(_ctx.bar))
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap
index 5ae8a94f5b1..884fb633ae9 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap
@@ -1,18 +1,18 @@
 // 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';
+"import { child as _child, next as _next, createIf as _createIf, setInsertionState as _setInsertionState, 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)
+  _setInsertionState(n4, n3)
   return n4
 }"
 `;
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
index cb14f56afdb..dbb0ddb3f26 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
@@ -65,20 +65,20 @@ export function render(_ctx) {
 `;
 
 exports[`compiler: v-for > nested v-for 1`] = `
-"import { setInsertionState as _setInsertionState, child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue';
+"import { child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, setInsertionState as _setInsertionState, template as _template } from 'vue';
 const t0 = _template("<span> </span>")
 const t1 = _template("<div></div>", true)
 
 export function render(_ctx) {
   const n0 = _createFor(() => (_ctx.list), (_for_item0) => {
     const n5 = t1()
-    _setInsertionState(n5)
     const n2 = _createFor(() => (_for_item0.value), (_for_item1) => {
       const n4 = t0()
       const x4 = _child(n4)
       _renderEffect(() => _setText(x4, _toDisplayString(_for_item1.value+_for_item0.value)))
       return n4
     }, null, 1)
+    _setInsertionState(n5)
     return n5
   })
   return n0
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap
index ab3ade45b60..bb35b44e3f1 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap
@@ -36,14 +36,14 @@ export function render(_ctx) {
 `;
 
 exports[`compiler: v-once > on component 1`] = `
-"import { resolveComponent as _resolveComponent, setInsertionState as _setInsertionState, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, setInsertionState as _setInsertionState, template as _template } from 'vue';
 const t0 = _template("<div></div>", true)
 
 export function render(_ctx) {
   const _component_Comp = _resolveComponent("Comp")
   const n1 = t0()
-  _setInsertionState(n1)
   const n0 = _createComponentWithFallback(_component_Comp, { id: () => (_ctx.foo) }, null, null, true)
+  _setInsertionState(n1)
   return n1
 }"
 `;
diff --git a/packages/compiler-vapor/__tests__/transforms/transformChildren.spec.ts b/packages/compiler-vapor/__tests__/transforms/transformChildren.spec.ts
index e656312356c..2d8ae8c960d 100644
--- a/packages/compiler-vapor/__tests__/transforms/transformChildren.spec.ts
+++ b/packages/compiler-vapor/__tests__/transforms/transformChildren.spec.ts
@@ -69,8 +69,8 @@ describe('compiler: children transform', () => {
       </div>`,
     )
     // ensure the insertion anchor is generated before the insertion statement
-    expect(code).toMatch(`const n3 = _next(_child(n4))
-  _setInsertionState(n4, n3)`)
+    expect(code).toMatch(`const n3 = _next(_child(n4))`)
+    expect(code).toMatch(`_setInsertionState(n4, n3)`)
     expect(code).toMatchSnapshot()
   })
 })
diff --git a/packages/compiler-vapor/src/generators/operation.ts b/packages/compiler-vapor/src/generators/operation.ts
index 4247bc6feca..8b0bc90c369 100644
--- a/packages/compiler-vapor/src/generators/operation.ts
+++ b/packages/compiler-vapor/src/generators/operation.ts
@@ -43,10 +43,10 @@ export function genOperationWithInsertionState(
   context: CodegenContext,
 ): CodeFragment[] {
   const [frag, push] = buildCodeFragment()
+  push(...genOperation(oper, context))
   if (isBlockOperation(oper) && oper.parent) {
     push(...genInsertionstate(oper, context))
   }
-  push(...genOperation(oper, context))
   return frag
 }
 

From 015e1eed26a7b815ac402ab1ca10a52d771b6743 Mon Sep 17 00:00:00 2001
From: zhiyuanzmj <260480378@qq.com>
Date: Tue, 18 Mar 2025 12:32:24 +0800
Subject: [PATCH 2/2] fix(compiler-vapor): move `next`, `child` and `nthChild`
 before the setInsertionState

---
 .../__snapshots__/compile.spec.ts.snap        | 34 ++++++++++++++++---
 .../compiler-vapor/__tests__/compile.spec.ts  | 17 ++++++++++
 .../transformChildren.spec.ts.snap            |  4 +--
 .../__snapshots__/vFor.spec.ts.snap           |  4 +--
 .../__snapshots__/vOnce.spec.ts.snap          |  4 +--
 .../compiler-vapor/src/generators/block.ts    |  2 +-
 .../src/generators/operation.ts               |  2 +-
 .../compiler-vapor/src/generators/template.ts | 13 +++----
 8 files changed, 61 insertions(+), 19 deletions(-)

diff --git a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
index 7614fc3c4bc..d4a8b6827bb 100644
--- a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
@@ -26,7 +26,7 @@ export function render(_ctx) {
 `;
 
 exports[`compile > custom directive > component 1`] = `
-"import { resolveComponent as _resolveComponent, resolveDirective as _resolveDirective, createComponentWithFallback as _createComponentWithFallback, withVaporDirectives as _withVaporDirectives, setInsertionState as _setInsertionState, createIf as _createIf, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, resolveDirective as _resolveDirective, setInsertionState as _setInsertionState, createComponentWithFallback as _createComponentWithFallback, withVaporDirectives as _withVaporDirectives, createIf as _createIf, template as _template } from 'vue';
 const t0 = _template("<div></div>")
 
 export function render(_ctx) {
@@ -38,9 +38,9 @@ export function render(_ctx) {
     "default": () => {
       const n0 = _createIf(() => (true), () => {
         const n3 = t0()
+        _setInsertionState(n3)
         const n2 = _createComponentWithFallback(_component_Bar)
         _withVaporDirectives(n2, [[_directive_hello, void 0, void 0, { world: true }]])
-        _setInsertionState(n3)
         return n3
       })
       return n0
@@ -149,7 +149,7 @@ export function render(_ctx, $props, $emit, $attrs, $slots) {
 `;
 
 exports[`compile > directives > v-pre > should not affect siblings after it 1`] = `
-"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, setInsertionState as _setInsertionState, child as _child, toDisplayString as _toDisplayString, setText as _setText, setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, setInsertionState as _setInsertionState, createComponentWithFallback as _createComponentWithFallback, child as _child, toDisplayString as _toDisplayString, setText as _setText, setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
 const t0 = _template("<div :id=\\"foo\\"><Comp></Comp>{{ bar }}</div>")
 const t1 = _template("<div> </div>")
 
@@ -157,9 +157,9 @@ export function render(_ctx, $props, $emit, $attrs, $slots) {
   const _component_Comp = _resolveComponent("Comp")
   const n0 = t0()
   const n3 = t1()
-  const n1 = _createComponentWithFallback(_component_Comp)
-  _setInsertionState(n3, 0)
   const n2 = _child(n3)
+  _setInsertionState(n3, 0)
+  const n1 = _createComponentWithFallback(_component_Comp)
   _renderEffect(() => {
     _setText(n2, _toDisplayString(_ctx.bar))
     _setProp(n3, "id", _ctx.foo)
@@ -230,6 +230,30 @@ export function render(_ctx) {
 }"
 `;
 
+exports[`compile > setInsertionState > next, child and nthChild should be above the setInsertionState 1`] = `
+"import { resolveComponent as _resolveComponent, child as _child, next as _next, setInsertionState as _setInsertionState, createComponentWithFallback as _createComponentWithFallback, nthChild as _nthChild, createIf as _createIf, setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div></div>")
+const t1 = _template("<div><div></div><!><div></div><!><div><button></button></div></div>", true)
+
+export function render(_ctx) {
+  const _component_Comp = _resolveComponent("Comp")
+  const n6 = t1()
+  const n5 = _next(_child(n6))
+  const n7 = _nthChild(n6, 3)
+  const p0 = _next(n7)
+  const n4 = _child(p0)
+  _setInsertionState(n6, n5)
+  const n0 = _createComponentWithFallback(_component_Comp)
+  _setInsertionState(n6, n7)
+  const n1 = _createIf(() => (true), () => {
+    const n3 = t0()
+    return n3
+  })
+  _renderEffect(() => _setProp(n4, "disabled", _ctx.foo))
+  return n6
+}"
+`;
+
 exports[`compile > static + dynamic root 1`] = `
 "import { toDisplayString as _toDisplayString, setText as _setText, template as _template } from 'vue';
 const t0 = _template(" ")
diff --git a/packages/compiler-vapor/__tests__/compile.spec.ts b/packages/compiler-vapor/__tests__/compile.spec.ts
index 33f399caa77..3a2ce41f0cd 100644
--- a/packages/compiler-vapor/__tests__/compile.spec.ts
+++ b/packages/compiler-vapor/__tests__/compile.spec.ts
@@ -220,4 +220,21 @@ describe('compile', () => {
       expect(code).matchSnapshot()
     })
   })
+
+  describe('setInsertionState', () => {
+    test('next, child and nthChild should be above the setInsertionState', () => {
+      const code = compile(`
+      <div>
+        <div />
+        <Comp />
+        <div />
+        <div v-if="true" />
+        <div>
+          <button :disabled="foo" />
+        </div>
+      </div>
+      `)
+      expect(code).toMatchSnapshot()
+    })
+  })
 })
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap
index 884fb633ae9..5ae8a94f5b1 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap
@@ -1,18 +1,18 @@
 // 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, createIf as _createIf, setInsertionState as _setInsertionState, template as _template } from 'vue';
+"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)
-  _setInsertionState(n4, n3)
   return n4
 }"
 `;
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
index dbb0ddb3f26..cb14f56afdb 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
@@ -65,20 +65,20 @@ export function render(_ctx) {
 `;
 
 exports[`compiler: v-for > nested v-for 1`] = `
-"import { child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, setInsertionState as _setInsertionState, template as _template } from 'vue';
+"import { setInsertionState as _setInsertionState, child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue';
 const t0 = _template("<span> </span>")
 const t1 = _template("<div></div>", true)
 
 export function render(_ctx) {
   const n0 = _createFor(() => (_ctx.list), (_for_item0) => {
     const n5 = t1()
+    _setInsertionState(n5)
     const n2 = _createFor(() => (_for_item0.value), (_for_item1) => {
       const n4 = t0()
       const x4 = _child(n4)
       _renderEffect(() => _setText(x4, _toDisplayString(_for_item1.value+_for_item0.value)))
       return n4
     }, null, 1)
-    _setInsertionState(n5)
     return n5
   })
   return n0
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap
index bb35b44e3f1..ab3ade45b60 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap
@@ -36,14 +36,14 @@ export function render(_ctx) {
 `;
 
 exports[`compiler: v-once > on component 1`] = `
-"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, setInsertionState as _setInsertionState, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, setInsertionState as _setInsertionState, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
 const t0 = _template("<div></div>", true)
 
 export function render(_ctx) {
   const _component_Comp = _resolveComponent("Comp")
   const n1 = t0()
-  const n0 = _createComponentWithFallback(_component_Comp, { id: () => (_ctx.foo) }, null, null, true)
   _setInsertionState(n1)
+  const n0 = _createComponentWithFallback(_component_Comp, { id: () => (_ctx.foo) }, null, null, true)
   return n1
 }"
 `;
diff --git a/packages/compiler-vapor/src/generators/block.ts b/packages/compiler-vapor/src/generators/block.ts
index b161b8f45d1..48e4b5cb890 100644
--- a/packages/compiler-vapor/src/generators/block.ts
+++ b/packages/compiler-vapor/src/generators/block.ts
@@ -52,7 +52,7 @@ export function genBlockContent(
     push(...genSelf(child, context))
   }
   for (const child of dynamic.children) {
-    push(...genChildren(child, context, `n${child.id!}`))
+    push(...genChildren(child, context, push, `n${child.id!}`))
   }
 
   push(...genOperations(operation, context))
diff --git a/packages/compiler-vapor/src/generators/operation.ts b/packages/compiler-vapor/src/generators/operation.ts
index 8b0bc90c369..4247bc6feca 100644
--- a/packages/compiler-vapor/src/generators/operation.ts
+++ b/packages/compiler-vapor/src/generators/operation.ts
@@ -43,10 +43,10 @@ export function genOperationWithInsertionState(
   context: CodegenContext,
 ): CodeFragment[] {
   const [frag, push] = buildCodeFragment()
-  push(...genOperation(oper, context))
   if (isBlockOperation(oper) && oper.parent) {
     push(...genInsertionstate(oper, context))
   }
+  push(...genOperation(oper, context))
   return frag
 }
 
diff --git a/packages/compiler-vapor/src/generators/template.ts b/packages/compiler-vapor/src/generators/template.ts
index 356c1ccbe15..5a066b09e9a 100644
--- a/packages/compiler-vapor/src/generators/template.ts
+++ b/packages/compiler-vapor/src/generators/template.ts
@@ -41,6 +41,7 @@ export function genSelf(
 export function genChildren(
   dynamic: IRDynamicInfo,
   context: CodegenContext,
+  pushBlock: (...items: CodeFragment[]) => number,
   from: string = `n${dynamic.id}`,
 ): CodeFragment[] {
   const { helper } = context
@@ -72,17 +73,17 @@ export function genChildren(
     // p for "placeholder" variables that are meant for possible reuse by
     // other access paths
     const variable = id === undefined ? `p${context.block.tempId++}` : `n${id}`
-    push(NEWLINE, `const ${variable} = `)
+    pushBlock(NEWLINE, `const ${variable} = `)
 
     if (prev) {
       if (elementIndex - prev[1] === 1) {
-        push(...genCall(helper('next'), prev[0]))
+        pushBlock(...genCall(helper('next'), prev[0]))
       } else {
-        push(...genCall(helper('nthChild'), from, String(elementIndex)))
+        pushBlock(...genCall(helper('nthChild'), from, String(elementIndex)))
       }
     } else {
       if (elementIndex === 0) {
-        push(...genCall(helper('child'), from))
+        pushBlock(...genCall(helper('child'), from))
       } else {
         // check if there's a node that we can reuse from
         let init = genCall(helper('child'), from)
@@ -91,7 +92,7 @@ export function genChildren(
         } else if (elementIndex > 1) {
           init = genCall(helper('nthChild'), from, String(elementIndex))
         }
-        push(...init)
+        pushBlock(...init)
       }
     }
 
@@ -109,7 +110,7 @@ export function genChildren(
 
   if (childrenToGen.length) {
     for (const [child, from] of childrenToGen) {
-      push(...genChildren(child, context, from))
+      push(...genChildren(child, context, pushBlock, from))
     }
   }