Skip to content

Commit 2f0676f

Browse files
authored
fix(runtime-vapor): enable injection from VDOM parent to slotted Vapor child (#14167)
1 parent 767cd23 commit 2f0676f

File tree

4 files changed

+67
-4
lines changed

4 files changed

+67
-4
lines changed

packages/runtime-core/src/apiCreateApp.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,13 @@ export interface VaporInteropInterface {
192192
update(n1: VNode, n2: VNode, shouldUpdate: boolean): void
193193
unmount(vnode: VNode, doRemove?: boolean): void
194194
move(vnode: VNode, container: any, anchor: any): void
195-
slot(n1: VNode | null, n2: VNode, container: any, anchor: any): void
195+
slot(
196+
n1: VNode | null,
197+
n2: VNode,
198+
container: any,
199+
anchor: any,
200+
parentComponent: ComponentInternalInstance | null,
201+
): void
196202
hydrate(
197203
vnode: VNode,
198204
node: any,

packages/runtime-core/src/renderer.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,13 @@ function baseCreateRenderer(
454454
)
455455
break
456456
case VaporSlot:
457-
getVaporInterface(parentComponent, n2).slot(n1, n2, container, anchor)
457+
getVaporInterface(parentComponent, n2).slot(
458+
n1,
459+
n2,
460+
container,
461+
anchor,
462+
parentComponent,
463+
)
458464
break
459465
default:
460466
if (shapeFlag & ShapeFlags.ELEMENT) {

packages/runtime-vapor/__tests__/apiInject.spec.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
reactive,
1010
readonly,
1111
ref,
12+
renderSlot,
1213
toDisplayString,
1314
} from '@vue/runtime-dom'
1415
import {
@@ -18,11 +19,12 @@ import {
1819
createVaporApp,
1920
defineVaporComponent,
2021
renderEffect,
22+
template,
2123
vaporInteropPlugin,
2224
withVaporCtx,
2325
} from '../src'
2426
import { makeRender } from './_utils'
25-
import { setElementText } from '../src/dom/prop'
27+
import { setElementText, setText } from '../src/dom/prop'
2628

2729
const define = makeRender<any>()
2830

@@ -426,6 +428,10 @@ describe('api: provide/inject', () => {
426428
})
427429

428430
describe('vdom interop', () => {
431+
beforeEach(() => {
432+
document.body.innerHTML = ''
433+
})
434+
429435
test('should inject value from vapor parent', async () => {
430436
const VdomChild = {
431437
setup() {
@@ -453,5 +459,47 @@ describe('vdom interop', () => {
453459
value.value = 'bar'
454460
await nextTick()
455461
expect(root.innerHTML).toBe('<div>bar</div>')
462+
463+
app.unmount()
464+
})
465+
466+
test('slotted vapor child should inject value from vdom parent', async () => {
467+
const value = ref('foo')
468+
const VdomParent = {
469+
setup(_: any, { slots }: any) {
470+
provide('foo', value)
471+
return () => renderSlot(slots, 'default')
472+
},
473+
}
474+
475+
const VaporChild = defineVaporComponent({
476+
setup() {
477+
const foo = inject('foo')
478+
const n0 = template(' ')() as any
479+
renderEffect(() => setText(n0, toDisplayString(foo)))
480+
return n0
481+
},
482+
})
483+
484+
const App = defineVaporComponent({
485+
setup() {
486+
return createComponent(VdomParent, null, {
487+
default: () => createComponent(VaporChild),
488+
})
489+
},
490+
})
491+
492+
const root = document.createElement('div')
493+
document.body.appendChild(root)
494+
const app = createVaporApp(App)
495+
app.use(vaporInteropPlugin)
496+
app.mount(root)
497+
498+
expect(root.innerHTML).toBe('foo')
499+
500+
value.value = 'bar'
501+
await nextTick()
502+
expect(root.innerHTML).toBe('bar')
503+
app.unmount()
456504
})
457505
})

packages/runtime-vapor/src/vdomInterop.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,10 @@ const vaporInteropImpl: Omit<
185185
/**
186186
* vapor slot in vdom
187187
*/
188-
slot(n1: VNode, n2: VNode, container, anchor) {
188+
slot(n1: VNode, n2: VNode, container, anchor, parentComponent) {
189189
if (!n1) {
190+
const prev = currentInstance
191+
simpleSetCurrentInstance(parentComponent)
190192
// mount
191193
let selfAnchor: Node | undefined
192194
const { slot, fallback } = n2.vs!
@@ -198,6 +200,7 @@ const vaporInteropImpl: Omit<
198200
// use fragment's anchor when possible
199201
selfAnchor = slotBlock.anchor
200202
}
203+
simpleSetCurrentInstance(prev)
201204
if (!selfAnchor) selfAnchor = createTextNode()
202205
insert((n2.el = n2.anchor = selfAnchor), container, anchor)
203206
insert((n2.vb = slotBlock), container, selfAnchor)

0 commit comments

Comments
 (0)