]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat(runtime-vapor): add withVaporCtx helper to manage currentInstance context in...
authoredison <daiwei521@126.com>
Wed, 22 Oct 2025 02:24:46 +0000 (10:24 +0800)
committerGitHub <noreply@github.com>
Wed, 22 Oct 2025 02:24:46 +0000 (10:24 +0800)
packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap
packages/compiler-vapor/__tests__/transforms/vSlot.spec.ts
packages/compiler-vapor/src/generators/component.ts
packages/runtime-vapor/src/componentSlots.ts
packages/runtime-vapor/src/index.ts

index 0120f5f487827e4f3cbfdbe53d7cb94a24381b37..62465315737daccbfa9705228622f0ebf062eba4 100644 (file)
@@ -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, setInsertionState as _setInsertionState, createComponentWithFallback as _createComponentWithFallback, withVaporDirectives as _withVaporDirectives, createIf as _createIf, withVaporCtx as _withVaporCtx, template as _template } from 'vue';
 const t0 = _template("<div></div>")
 
 export function render(_ctx) {
@@ -35,7 +35,7 @@ export function render(_ctx) {
   const _directive_hello = _resolveDirective("hello")
   const _directive_test = _resolveDirective("test")
   const n4 = _createComponentWithFallback(_component_Comp, null, {
-    "default": () => {
+    "default": _withVaporCtx(() => {
       const n0 = _createIf(() => (true), () => {
         const n3 = t0()
         _setInsertionState(n3, null, true)
@@ -44,7 +44,7 @@ export function render(_ctx) {
         return n3
       })
       return n0
-    }
+    })
   }, true)
   _withVaporDirectives(n4, [[_directive_test]])
   return n4
index e7d34070ea33f081a6dc3f19828a06003312ade5..811ebf638efd244478907f98457355fdb031223a 100644 (file)
@@ -1,7 +1,7 @@
 // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
 exports[`compiler: transform slot > dynamic slots name 1`] = `
-"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
 const t0 = _template("foo")
 
 export function render(_ctx) {
@@ -10,10 +10,10 @@ export function render(_ctx) {
     $: [
       () => ({
         name: _ctx.name,
-        fn: () => {
+        fn: _withVaporCtx(() => {
           const n0 = t0()
           return n0
-        }
+        })
       })
     ]
   }, true)
@@ -22,7 +22,7 @@ export function render(_ctx) {
 `;
 
 exports[`compiler: transform slot > dynamic slots name w/ v-for 1`] = `
-"import { resolveComponent as _resolveComponent, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createForSlots as _createForSlots, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, withVaporCtx as _withVaporCtx, createForSlots as _createForSlots, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
 const t0 = _template(" ")
 
 export function render(_ctx) {
@@ -31,11 +31,11 @@ export function render(_ctx) {
     $: [
       () => (_createForSlots(_ctx.list, (item) => ({
         name: item,
-        fn: (_slotProps0) => {
+        fn: _withVaporCtx((_slotProps0) => {
           const n0 = t0()
           _renderEffect(() => _setText(n0, _toDisplayString(_slotProps0["bar"])))
           return n0
-        }
+        })
       })))
     ]
   }, true)
@@ -44,7 +44,7 @@ export function render(_ctx) {
 `;
 
 exports[`compiler: transform slot > dynamic slots name w/ v-for and provide absent key 1`] = `
-"import { resolveComponent as _resolveComponent, createForSlots as _createForSlots, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, withVaporCtx as _withVaporCtx, createForSlots as _createForSlots, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
 const t0 = _template("foo")
 
 export function render(_ctx) {
@@ -53,10 +53,10 @@ export function render(_ctx) {
     $: [
       () => (_createForSlots(_ctx.list, (_, __, index) => ({
         name: index,
-        fn: () => {
+        fn: _withVaporCtx(() => {
           const n0 = t0()
           return n0
-        }
+        })
       })))
     ]
   }, true)
@@ -65,7 +65,7 @@ export function render(_ctx) {
 `;
 
 exports[`compiler: transform slot > dynamic slots name w/ v-if / v-else[-if] 1`] = `
-"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
 const t0 = _template("condition slot")
 const t1 = _template("another condition")
 const t2 = _template("else condition")
@@ -77,25 +77,25 @@ export function render(_ctx) {
       () => (_ctx.condition
         ? {
           name: "condition",
-          fn: () => {
+          fn: _withVaporCtx(() => {
             const n0 = t0()
             return n0
-          }
+          })
         }
         : _ctx.anotherCondition
           ? {
             name: "condition",
-            fn: (_slotProps0) => {
+            fn: _withVaporCtx((_slotProps0) => {
               const n2 = t1()
               return n2
-            }
+            })
           }
           : {
             name: "condition",
-            fn: () => {
+            fn: _withVaporCtx(() => {
               const n4 = t2()
               return n4
-            }
+            })
           })
     ]
   }, true)
@@ -104,114 +104,114 @@ export function render(_ctx) {
 `;
 
 exports[`compiler: transform slot > forwarded slots > <slot w/ nested component> 1`] = `
-"import { forwardedSlotCreator as _forwardedSlotCreator, resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback } from 'vue';
+"import { forwardedSlotCreator as _forwardedSlotCreator, resolveComponent as _resolveComponent, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback } from 'vue';
 
 export function render(_ctx) {
   const _createForwardedSlot = _forwardedSlotCreator()
   const _component_Comp = _resolveComponent("Comp")
   const n2 = _createComponentWithFallback(_component_Comp, null, {
-    "default": () => {
+    "default": _withVaporCtx(() => {
       const n1 = _createComponentWithFallback(_component_Comp, null, {
-        "default": () => {
+        "default": _withVaporCtx(() => {
           const n0 = _createForwardedSlot("default", null)
           return n0
-        }
+        })
       })
       return n1
-    }
+    })
   }, true)
   return n2
 }"
 `;
 
 exports[`compiler: transform slot > forwarded slots > <slot> tag only 1`] = `
-"import { forwardedSlotCreator as _forwardedSlotCreator, resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback } from 'vue';
+"import { forwardedSlotCreator as _forwardedSlotCreator, resolveComponent as _resolveComponent, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback } from 'vue';
 
 export function render(_ctx) {
   const _createForwardedSlot = _forwardedSlotCreator()
   const _component_Comp = _resolveComponent("Comp")
   const n1 = _createComponentWithFallback(_component_Comp, null, {
-    "default": () => {
+    "default": _withVaporCtx(() => {
       const n0 = _createForwardedSlot("default", null)
       return n0
-    }
+    })
   }, true)
   return n1
 }"
 `;
 
 exports[`compiler: transform slot > forwarded slots > <slot> tag w/ template 1`] = `
-"import { forwardedSlotCreator as _forwardedSlotCreator, resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback } from 'vue';
+"import { forwardedSlotCreator as _forwardedSlotCreator, resolveComponent as _resolveComponent, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback } from 'vue';
 
 export function render(_ctx) {
   const _createForwardedSlot = _forwardedSlotCreator()
   const _component_Comp = _resolveComponent("Comp")
   const n2 = _createComponentWithFallback(_component_Comp, null, {
-    "default": () => {
+    "default": _withVaporCtx(() => {
       const n0 = _createForwardedSlot("default", null)
       return n0
-    }
+    })
   }, true)
   return n2
 }"
 `;
 
 exports[`compiler: transform slot > forwarded slots > <slot> tag w/ v-for 1`] = `
-"import { forwardedSlotCreator as _forwardedSlotCreator, resolveComponent as _resolveComponent, createFor as _createFor, createComponentWithFallback as _createComponentWithFallback } from 'vue';
+"import { forwardedSlotCreator as _forwardedSlotCreator, resolveComponent as _resolveComponent, createFor as _createFor, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback } from 'vue';
 
 export function render(_ctx) {
   const _createForwardedSlot = _forwardedSlotCreator()
   const _component_Comp = _resolveComponent("Comp")
   const n3 = _createComponentWithFallback(_component_Comp, null, {
-    "default": () => {
+    "default": _withVaporCtx(() => {
       const n0 = _createFor(() => (_ctx.b), (_for_item0) => {
         const n2 = _createForwardedSlot("default", null)
         return n2
       })
       return n0
-    }
+    })
   }, true)
   return n3
 }"
 `;
 
 exports[`compiler: transform slot > forwarded slots > <slot> tag w/ v-if 1`] = `
-"import { forwardedSlotCreator as _forwardedSlotCreator, resolveComponent as _resolveComponent, createIf as _createIf, createComponentWithFallback as _createComponentWithFallback } from 'vue';
+"import { forwardedSlotCreator as _forwardedSlotCreator, resolveComponent as _resolveComponent, createIf as _createIf, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback } from 'vue';
 
 export function render(_ctx) {
   const _createForwardedSlot = _forwardedSlotCreator()
   const _component_Comp = _resolveComponent("Comp")
   const n3 = _createComponentWithFallback(_component_Comp, null, {
-    "default": () => {
+    "default": _withVaporCtx(() => {
       const n0 = _createIf(() => (_ctx.ok), () => {
         const n2 = _createForwardedSlot("default", null)
         return n2
       })
       return n0
-    }
+    })
   }, true)
   return n3
 }"
 `;
 
 exports[`compiler: transform slot > implicit default slot 1`] = `
-"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
 const t0 = _template("<div></div>")
 
 export function render(_ctx) {
   const _component_Comp = _resolveComponent("Comp")
   const n1 = _createComponentWithFallback(_component_Comp, null, {
-    "default": () => {
+    "default": _withVaporCtx(() => {
       const n0 = t0()
       return n0
-    }
+    })
   }, true)
   return n1
 }"
 `;
 
 exports[`compiler: transform slot > named slots w/ implicit default slot 1`] = `
-"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
 const t0 = _template("foo")
 const t1 = _template("bar")
 const t2 = _template("<span></span>")
@@ -219,63 +219,63 @@ const t2 = _template("<span></span>")
 export function render(_ctx) {
   const _component_Comp = _resolveComponent("Comp")
   const n4 = _createComponentWithFallback(_component_Comp, null, {
-    "one": () => {
+    "one": _withVaporCtx(() => {
       const n0 = t0()
       return n0
-    },
-    "default": () => {
+    }),
+    "default": _withVaporCtx(() => {
       const n2 = t1()
       const n3 = t2()
       return [n2, n3]
-    }
+    })
   }, true)
   return n4
 }"
 `;
 
 exports[`compiler: transform slot > nested component slot 1`] = `
-"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback } from 'vue';
+"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, withVaporCtx as _withVaporCtx } from 'vue';
 
 export function render(_ctx) {
   const _component_B = _resolveComponent("B")
   const _component_A = _resolveComponent("A")
   const n1 = _createComponentWithFallback(_component_A, null, {
-    "default": () => {
+    "default": _withVaporCtx(() => {
       const n0 = _createComponentWithFallback(_component_B)
       return n0
-    }
+    })
   }, true)
   return n1
 }"
 `;
 
 exports[`compiler: transform slot > nested slots scoping 1`] = `
-"import { resolveComponent as _resolveComponent, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
 const t0 = _template(" ")
 
 export function render(_ctx) {
   const _component_Inner = _resolveComponent("Inner")
   const _component_Comp = _resolveComponent("Comp")
   const n5 = _createComponentWithFallback(_component_Comp, null, {
-    "default": (_slotProps0) => {
+    "default": _withVaporCtx((_slotProps0) => {
       const n1 = _createComponentWithFallback(_component_Inner, null, {
-        "default": (_slotProps1) => {
+        "default": _withVaporCtx((_slotProps1) => {
           const n0 = t0()
           _renderEffect(() => _setText(n0, _toDisplayString(_slotProps0["foo"] + _slotProps1["bar"] + _ctx.baz)))
           return n0
-        }
+        })
       })
       const n3 = t0()
       _renderEffect(() => _setText(n3, " " + _toDisplayString(_slotProps0["foo"] + _ctx.bar + _ctx.baz)))
       return [n1, n3]
-    }
+    })
   }, true)
   return n5
 }"
 `;
 
 exports[`compiler: transform slot > on component dynamically named slot 1`] = `
-"import { resolveComponent as _resolveComponent, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
 const t0 = _template(" ")
 
 export function render(_ctx) {
@@ -284,11 +284,11 @@ export function render(_ctx) {
     $: [
       () => ({
         name: _ctx.named,
-        fn: (_slotProps0) => {
+        fn: _withVaporCtx((_slotProps0) => {
           const n0 = t0()
           _renderEffect(() => _setText(n0, _toDisplayString(_slotProps0["foo"] + _ctx.bar)))
           return n0
-        }
+        })
       })
     ]
   }, true)
@@ -297,48 +297,48 @@ export function render(_ctx) {
 `;
 
 exports[`compiler: transform slot > on component named slot 1`] = `
-"import { resolveComponent as _resolveComponent, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
 const t0 = _template(" ")
 
 export function render(_ctx) {
   const _component_Comp = _resolveComponent("Comp")
   const n1 = _createComponentWithFallback(_component_Comp, null, {
-    "named": (_slotProps0) => {
+    "named": _withVaporCtx((_slotProps0) => {
       const n0 = t0()
       _renderEffect(() => _setText(n0, _toDisplayString(_slotProps0["foo"] + _ctx.bar)))
       return n0
-    }
+    })
   }, true)
   return n1
 }"
 `;
 
 exports[`compiler: transform slot > on-component default slot 1`] = `
-"import { resolveComponent as _resolveComponent, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
 const t0 = _template(" ")
 
 export function render(_ctx) {
   const _component_Comp = _resolveComponent("Comp")
   const n1 = _createComponentWithFallback(_component_Comp, null, {
-    "default": (_slotProps0) => {
+    "default": _withVaporCtx((_slotProps0) => {
       const n0 = t0()
       _renderEffect(() => _setText(n0, _toDisplayString(_slotProps0["foo"] + _ctx.bar)))
       return n0
-    }
+    })
   }, true)
   return n1
 }"
 `;
 
 exports[`compiler: transform slot > quote slot name 1`] = `
-"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback } from 'vue';
+"import { resolveComponent as _resolveComponent, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback } from 'vue';
 
 export function render(_ctx) {
   const _component_Comp = _resolveComponent("Comp")
   const n1 = _createComponentWithFallback(_component_Comp, null, {
-    "nav-bar-title-before": () => {
+    "nav-bar-title-before": _withVaporCtx(() => {
       return null
-    }
+    })
   }, true)
   return n1
 }"
@@ -367,7 +367,7 @@ export function render(_ctx) {
 `;
 
 exports[`compiler: transform slot > with whitespace: 'preserve' > implicit default slot 1`] = `
-"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
 const t0 = _template(" Header ")
 const t1 = _template(" ")
 const t2 = _template("<p></p>")
@@ -375,57 +375,57 @@ const t2 = _template("<p></p>")
 export function render(_ctx) {
   const _component_Comp = _resolveComponent("Comp")
   const n4 = _createComponentWithFallback(_component_Comp, null, {
-    "header": () => {
+    "header": _withVaporCtx(() => {
       const n0 = t0()
       return n0
-    },
-    "default": () => {
+    }),
+    "default": _withVaporCtx(() => {
       const n2 = t1()
       const n3 = t2()
       return [n2, n3]
-    }
+    })
   }, true)
   return n4
 }"
 `;
 
 exports[`compiler: transform slot > with whitespace: 'preserve' > named default slot + implicit whitespace content 1`] = `
-"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
 const t0 = _template(" Header ")
 const t1 = _template(" Default ")
 
 export function render(_ctx) {
   const _component_Comp = _resolveComponent("Comp")
   const n5 = _createComponentWithFallback(_component_Comp, null, {
-    "header": () => {
+    "header": _withVaporCtx(() => {
       const n0 = t0()
       return n0
-    },
-    "default": () => {
+    }),
+    "default": _withVaporCtx(() => {
       const n3 = t1()
       return n3
-    }
+    })
   }, true)
   return n5
 }"
 `;
 
 exports[`compiler: transform slot > with whitespace: 'preserve' > should not generate whitespace only default slot 1`] = `
-"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
+"import { resolveComponent as _resolveComponent, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback, template as _template } from 'vue';
 const t0 = _template(" Header ")
 const t1 = _template(" Footer ")
 
 export function render(_ctx) {
   const _component_Comp = _resolveComponent("Comp")
   const n5 = _createComponentWithFallback(_component_Comp, null, {
-    "header": () => {
+    "header": _withVaporCtx(() => {
       const n0 = t0()
       return n0
-    },
-    "footer": () => {
+    }),
+    "footer": _withVaporCtx(() => {
       const n3 = t1()
       return n3
-    }
+    })
   }, true)
   return n5
 }"
index 63b6b00010b187d96b7f680656c7dcd6031f641b..f2e94814c43a437082eeb541b3ad8cc7266fb834 100644 (file)
@@ -67,7 +67,7 @@ describe('compiler: transform slot', () => {
     )
     expect(code).toMatchSnapshot()
 
-    expect(code).contains(`"default": (_slotProps0) =>`)
+    expect(code).contains(`"default": _withVaporCtx((_slotProps0) =>`)
     expect(code).contains(`_slotProps0["foo"] + _ctx.bar`)
 
     expect(ir.block.dynamic.children[0].operation).toMatchObject({
@@ -101,7 +101,7 @@ describe('compiler: transform slot', () => {
     )
     expect(code).toMatchSnapshot()
 
-    expect(code).contains(`"named": (_slotProps0) =>`)
+    expect(code).contains(`"named": _withVaporCtx((_slotProps0) =>`)
     expect(code).contains(`_slotProps0["foo"] + _ctx.bar`)
 
     expect(ir.block.dynamic.children[0].operation).toMatchObject({
@@ -130,7 +130,7 @@ describe('compiler: transform slot', () => {
     )
     expect(code).toMatchSnapshot()
 
-    expect(code).contains(`fn: (_slotProps0) =>`)
+    expect(code).contains(`fn: _withVaporCtx((_slotProps0) =>`)
     expect(code).contains(`_slotProps0["foo"] + _ctx.bar`)
 
     expect(ir.block.dynamic.children[0].operation).toMatchObject({
@@ -204,8 +204,8 @@ describe('compiler: transform slot', () => {
     )
     expect(code).toMatchSnapshot()
 
-    expect(code).contains(`"default": (_slotProps0) =>`)
-    expect(code).contains(`"default": (_slotProps1) =>`)
+    expect(code).contains(`"default": _withVaporCtx((_slotProps0) =>`)
+    expect(code).contains(`"default": _withVaporCtx((_slotProps1) =>`)
     expect(code).contains(`_slotProps0["foo"] + _slotProps1["bar"] + _ctx.baz`)
     expect(code).contains(`_slotProps0["foo"] + _ctx.bar + _ctx.baz`)
 
@@ -282,7 +282,7 @@ describe('compiler: transform slot', () => {
     )
     expect(code).toMatchSnapshot()
 
-    expect(code).contains(`fn: (_slotProps0) =>`)
+    expect(code).contains(`fn: _withVaporCtx((_slotProps0) =>`)
     expect(code).contains(`_setText(n0, _toDisplayString(_slotProps0["bar"]))`)
 
     expect(ir.block.dynamic.children[0].operation).toMatchObject({
@@ -346,7 +346,7 @@ describe('compiler: transform slot', () => {
     )
     expect(code).toMatchSnapshot()
 
-    expect(code).contains(`fn: (_slotProps0) =>`)
+    expect(code).contains(`fn: _withVaporCtx((_slotProps0) =>`)
 
     expect(ir.block.dynamic.children[0].operation).toMatchObject({
       type: IRNodeTypes.CREATE_COMPONENT_NODE,
index 04df6c5a48a3804766502bb1b4d4f41c27904b6e..ae213af222b839ae6d8280c01acbef3ac6eb3ebc 100644 (file)
@@ -29,6 +29,7 @@ import {
 import { genExpression, genVarName } from './expression'
 import { genPropKey, genPropValue } from './prop'
 import {
+  NodeTypes,
   type SimpleExpressionNode,
   createSimpleExpression,
   isMemberExpression,
@@ -407,7 +408,7 @@ function genSlotBlockWithProps(oper: SlotBlockIRNode, context: CodegenContext) {
   let propsName: string | undefined
   let exitScope: (() => void) | undefined
   let depth: number | undefined
-  const { props, key } = oper
+  const { props, key, node } = oper
   const idsOfProps = new Set<string>()
 
   if (props) {
@@ -458,5 +459,10 @@ function genSlotBlockWithProps(oper: SlotBlockIRNode, context: CodegenContext) {
     ]
   }
 
+  if (node.type === NodeTypes.ELEMENT && !isBuiltInComponent(node.tag)) {
+    // wrap with withVaporCtx to ensure correct currentInstance inside slot
+    blockFn = [`${context.helper('withVaporCtx')}(`, ...blockFn, `)`]
+  }
+
   return blockFn
 }
index aa0651658c057fdce6c02bbdd0fce7c95d8982b5..346c272b6d59c080a6faf702ba2f725270264e2f 100644 (file)
@@ -1,7 +1,7 @@
 import { EMPTY_OBJ, NO, hasOwn, isArray, isFunction } from '@vue/shared'
 import { type Block, type BlockFn, insert } from './block'
 import { rawPropsProxyHandlers } from './componentProps'
-import { currentInstance, isRef } from '@vue/runtime-dom'
+import { currentInstance, isRef, setCurrentInstance } from '@vue/runtime-dom'
 import type { LooseRawProps, VaporComponentInstance } from './component'
 import { renderEffect } from './renderEffect'
 import {
@@ -97,6 +97,18 @@ export function getSlot(
   }
 }
 
+export function withVaporCtx(fn: Function): Function {
+  const instance = currentInstance as VaporComponentInstance
+  return (...args: any[]) => {
+    const prev = setCurrentInstance(instance)
+    try {
+      return fn(...args)
+    } finally {
+      setCurrentInstance(...prev)
+    }
+  }
+}
+
 export function forwardedSlotCreator(): (
   name: string | (() => string),
   rawProps?: LooseRawProps | null,
index 3e76b6955d33d9da78277e905e46131c283c5860..a9d919f8175e2ea004a26c275e4160eda5fc8470 100644 (file)
@@ -16,7 +16,11 @@ export {
   isVaporComponent,
 } from './component'
 export { renderEffect } from './renderEffect'
-export { createSlot, forwardedSlotCreator } from './componentSlots'
+export {
+  createSlot,
+  forwardedSlotCreator,
+  withVaporCtx,
+} from './componentSlots'
 export { template } from './dom/template'
 export { createTextNode, child, nthChild, next, txt } from './dom/node'
 export {