diff --git a/packages/runtime-core/src/apiCreateApp.ts b/packages/runtime-core/src/apiCreateApp.ts index 9bd13d600bc..514b7878bfd 100644 --- a/packages/runtime-core/src/apiCreateApp.ts +++ b/packages/runtime-core/src/apiCreateApp.ts @@ -192,7 +192,13 @@ export interface VaporInteropInterface { update(n1: VNode, n2: VNode, shouldUpdate: boolean): void unmount(vnode: VNode, doRemove?: boolean): void move(vnode: VNode, container: any, anchor: any): void - slot(n1: VNode | null, n2: VNode, container: any, anchor: any): void + slot( + n1: VNode | null, + n2: VNode, + container: any, + anchor: any, + parentComponent: ComponentInternalInstance | null, + ): void hydrate( vnode: VNode, node: any, diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index c3cb60fd40e..0747ef5e88e 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -454,7 +454,13 @@ function baseCreateRenderer( ) break case VaporSlot: - getVaporInterface(parentComponent, n2).slot(n1, n2, container, anchor) + getVaporInterface(parentComponent, n2).slot( + n1, + n2, + container, + anchor, + parentComponent, + ) break default: if (shapeFlag & ShapeFlags.ELEMENT) { diff --git a/packages/runtime-vapor/__tests__/apiInject.spec.ts b/packages/runtime-vapor/__tests__/apiInject.spec.ts index 50507715063..157873c53df 100644 --- a/packages/runtime-vapor/__tests__/apiInject.spec.ts +++ b/packages/runtime-vapor/__tests__/apiInject.spec.ts @@ -9,6 +9,7 @@ import { reactive, readonly, ref, + renderSlot, toDisplayString, } from '@vue/runtime-dom' import { @@ -18,11 +19,12 @@ import { createVaporApp, defineVaporComponent, renderEffect, + template, vaporInteropPlugin, withVaporCtx, } from '../src' import { makeRender } from './_utils' -import { setElementText } from '../src/dom/prop' +import { setElementText, setText } from '../src/dom/prop' const define = makeRender() @@ -426,6 +428,10 @@ describe('api: provide/inject', () => { }) describe('vdom interop', () => { + beforeEach(() => { + document.body.innerHTML = '' + }) + test('should inject value from vapor parent', async () => { const VdomChild = { setup() { @@ -453,5 +459,47 @@ describe('vdom interop', () => { value.value = 'bar' await nextTick() expect(root.innerHTML).toBe('
bar
') + + app.unmount() + }) + + test('slotted vapor child should inject value from vdom parent', async () => { + const value = ref('foo') + const VdomParent = { + setup(_: any, { slots }: any) { + provide('foo', value) + return () => renderSlot(slots, 'default') + }, + } + + const VaporChild = defineVaporComponent({ + setup() { + const foo = inject('foo') + const n0 = template(' ')() as any + renderEffect(() => setText(n0, toDisplayString(foo))) + return n0 + }, + }) + + const App = defineVaporComponent({ + setup() { + return createComponent(VdomParent, null, { + default: () => createComponent(VaporChild), + }) + }, + }) + + const root = document.createElement('div') + document.body.appendChild(root) + const app = createVaporApp(App) + app.use(vaporInteropPlugin) + app.mount(root) + + expect(root.innerHTML).toBe('foo') + + value.value = 'bar' + await nextTick() + expect(root.innerHTML).toBe('bar') + app.unmount() }) }) diff --git a/packages/runtime-vapor/src/vdomInterop.ts b/packages/runtime-vapor/src/vdomInterop.ts index c6a0d98bbcc..ef872f87588 100644 --- a/packages/runtime-vapor/src/vdomInterop.ts +++ b/packages/runtime-vapor/src/vdomInterop.ts @@ -185,8 +185,10 @@ const vaporInteropImpl: Omit< /** * vapor slot in vdom */ - slot(n1: VNode, n2: VNode, container, anchor) { + slot(n1: VNode, n2: VNode, container, anchor, parentComponent) { if (!n1) { + const prev = currentInstance + simpleSetCurrentInstance(parentComponent) // mount let selfAnchor: Node | undefined const { slot, fallback } = n2.vs! @@ -198,6 +200,7 @@ const vaporInteropImpl: Omit< // use fragment's anchor when possible selfAnchor = slotBlock.anchor } + simpleSetCurrentInstance(prev) if (!selfAnchor) selfAnchor = createTextNode() insert((n2.el = n2.anchor = selfAnchor), container, anchor) insert((n2.vb = slotBlock), container, selfAnchor)