]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-vapor): move `next`, `child` and `nthChild` before setInsertionState...
authorzhiyuanzmj <260480378@qq.com>
Wed, 18 Jun 2025 01:05:43 +0000 (09:05 +0800)
committerGitHub <noreply@github.com>
Wed, 18 Jun 2025 01:05:43 +0000 (09:05 +0800)
packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
packages/compiler-vapor/__tests__/compile.spec.ts
packages/compiler-vapor/__tests__/transforms/transformChildren.spec.ts
packages/compiler-vapor/src/generators/block.ts
packages/compiler-vapor/src/generators/template.ts

index e56676d87068a758a3992eb347b6582b5c549ff3..d4a8b6827bb135edab82eb4ec07f448a305a3d61 100644 (file)
@@ -157,9 +157,9 @@ export function render(_ctx, $props, $emit, $attrs, $slots) {
   const _component_Comp = _resolveComponent("Comp")
   const n0 = t0()
   const n3 = t1()
+  const n2 = _child(n3)
   _setInsertionState(n3, 0)
   const n1 = _createComponentWithFallback(_component_Comp)
-  const n2 = _child(n3)
   _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(" ")
index 33f399caa7705167b5902e4145b62f1b64d23a21..3a2ce41f0cdacdeeeaede0b7cca67e28742f41d9 100644 (file)
@@ -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()
+    })
+  })
 })
index e656312356cc97806810c248df3ed0ba4072572d..2d8ae8c960d2d0bac4222ca2da60f339091bd3bb 100644 (file)
@@ -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()
   })
 })
index 09d05bf3e91c3e968689de6d6ca64b72883b5137..ff240dd6eac05068f63d88df62be4e39d97ff13d 100644 (file)
@@ -66,7 +66,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))
index 356c1ccbe15c4d77b400f435111c175b0c485056..5a066b09e9a622435465988ab2af5cb4736222e6 100644 (file)
@@ -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))
     }
   }