From: edison Date: Wed, 22 Oct 2025 02:24:46 +0000 (+0800) Subject: feat(runtime-vapor): add withVaporCtx helper to manage currentInstance context in... X-Git-Tag: v3.6.0-alpha.3~22 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d381c2f804d914394644406bb96ef6c7e3dccc57;p=thirdparty%2Fvuejs%2Fcore.git feat(runtime-vapor): add withVaporCtx helper to manage currentInstance context in slot blocks (#14007) --- diff --git a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap index 0120f5f487..6246531573 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, setInsertionState as _setInsertionState, createComponentWithFallback as _createComponentWithFallback, withVaporDirectives as _withVaporDirectives, createIf as _createIf, withVaporCtx as _withVaporCtx, template as _template } from 'vue'; const t0 = _template("
") 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 diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap index e7d34070ea..811ebf638e 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap @@ -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 > 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 > 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 > 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 > 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 > 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("
") 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("") @@ -219,63 +219,63 @@ const t2 = _template("") 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("

") @@ -375,57 +375,57 @@ const t2 = _template("

") 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 }" diff --git a/packages/compiler-vapor/__tests__/transforms/vSlot.spec.ts b/packages/compiler-vapor/__tests__/transforms/vSlot.spec.ts index 63b6b00010..f2e94814c4 100644 --- a/packages/compiler-vapor/__tests__/transforms/vSlot.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vSlot.spec.ts @@ -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, diff --git a/packages/compiler-vapor/src/generators/component.ts b/packages/compiler-vapor/src/generators/component.ts index 04df6c5a48..ae213af222 100644 --- a/packages/compiler-vapor/src/generators/component.ts +++ b/packages/compiler-vapor/src/generators/component.ts @@ -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() 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 } diff --git a/packages/runtime-vapor/src/componentSlots.ts b/packages/runtime-vapor/src/componentSlots.ts index aa0651658c..346c272b6d 100644 --- a/packages/runtime-vapor/src/componentSlots.ts +++ b/packages/runtime-vapor/src/componentSlots.ts @@ -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, diff --git a/packages/runtime-vapor/src/index.ts b/packages/runtime-vapor/src/index.ts index 3e76b6955d..a9d919f817 100644 --- a/packages/runtime-vapor/src/index.ts +++ b/packages/runtime-vapor/src/index.ts @@ -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 {