Skip to content

Commit 3aba5c9

Browse files
committed
refactor: wrap the ctx when initializing the slots
1 parent 2e39f3e commit 3aba5c9

File tree

4 files changed

+73
-57
lines changed

4 files changed

+73
-57
lines changed

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

+40-21
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
nextTick,
99
ref,
1010
template,
11-
withCtx,
1211
} from '../src'
1312
import { makeRender } from './_utils'
1413

@@ -35,21 +34,6 @@ function renderWithSlots(slots: any): any {
3534
}
3635

3736
describe('component: slots', () => {
38-
test('initSlots: instance.slots should be set correctly', () => {
39-
const { slots } = renderWithSlots({ _: 1 })
40-
expect(slots).toMatchObject({ _: 1 })
41-
})
42-
43-
// NOTE: slot normalization is not supported
44-
test.todo(
45-
'initSlots: should normalize object slots (when value is null, string, array)',
46-
() => {},
47-
)
48-
test.todo(
49-
'initSlots: should normalize object slots (when value is function)',
50-
() => {},
51-
)
52-
5337
test('initSlots: instance.slots should be set correctly', () => {
5438
let instance: any
5539
const Comp = defineComponent({
@@ -74,6 +58,16 @@ describe('component: slots', () => {
7458
)
7559
})
7660

61+
// NOTE: slot normalization is not supported
62+
test.todo(
63+
'initSlots: should normalize object slots (when value is null, string, array)',
64+
() => {},
65+
)
66+
test.todo(
67+
'initSlots: should normalize object slots (when value is function)',
68+
() => {},
69+
)
70+
7771
// runtime-core's "initSlots: instance.slots should be set correctly (when vnode.shapeFlag is not SLOTS_CHILDREN)"
7872
test('initSlots: instance.slots should be set correctly', () => {
7973
const { slots } = renderWithSlots({
@@ -154,12 +148,16 @@ describe('component: slots', () => {
154148
})
155149

156150
test('the current instance should be kept in the slot', async () => {
157-
let instanceInSlot: any
151+
let instanceInDefaultSlot: any
152+
let instanceInVForSlot: any
153+
let instanceInVIfSlot: any
158154

159155
const Comp = defineComponent({
160156
render() {
161157
const instance = getCurrentInstance()
162158
instance!.slots.default!()
159+
instance!.slots.inVFor!()
160+
instance!.slots.inVIf!()
163161
return template('<div></div>')()
164162
},
165163
})
@@ -170,16 +168,37 @@ describe('component: slots', () => {
170168
Comp,
171169
{},
172170
{
173-
default: withCtx(() => {
174-
instanceInSlot = getCurrentInstance()
171+
default: () => {
172+
instanceInDefaultSlot = getCurrentInstance()
175173
return template('content')()
176-
}),
174+
},
177175
},
176+
() => [
177+
[
178+
{
179+
name: 'inVFor',
180+
fn: () => {
181+
instanceInVForSlot = getCurrentInstance()
182+
return template('content')()
183+
},
184+
},
185+
],
186+
{
187+
name: 'inVIf',
188+
key: '1',
189+
fn: () => {
190+
instanceInVIfSlot = getCurrentInstance()
191+
return template('content')()
192+
},
193+
},
194+
],
178195
)
179196
},
180197
}).render()
181198

182-
expect(instanceInSlot).toBe(instance)
199+
expect(instanceInDefaultSlot).toBe(instance)
200+
expect(instanceInVForSlot).toBe(instance)
201+
expect(instanceInVIfSlot).toBe(instance)
183202
})
184203

185204
test.todo('should respect $stable flag', async () => {

packages/runtime-vapor/src/componentRenderContext.ts

-22
This file was deleted.

packages/runtime-vapor/src/componentSlots.ts

+33-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { type IfAny, extend, isArray } from '@vue/shared'
1+
import { type IfAny, isArray } from '@vue/shared'
22
import { baseWatch } from '@vue/reactivity'
3-
import type { ComponentInternalInstance } from './component'
3+
import { type ComponentInternalInstance, setCurrentInstance } from './component'
44
import type { Block } from './apiRender'
55
import { createVaporPreScheduler } from './scheduler'
66

@@ -29,7 +29,14 @@ export const initSlots = (
2929
rawSlots: InternalSlots | null = null,
3030
dynamicSlots: DynamicSlots | null = null,
3131
) => {
32-
const slots: InternalSlots = extend({}, rawSlots)
32+
const slots: InternalSlots = {}
33+
34+
for (const key in rawSlots) {
35+
const slot = rawSlots[key]
36+
if (slot) {
37+
slots[key] = withCtx(slot)
38+
}
39+
}
3340

3441
if (dynamicSlots) {
3542
const dynamicSlotKeys: Record<string, true> = {}
@@ -41,20 +48,22 @@ export const initSlots = (
4148
// array of dynamic slot generated by <template v-for="..." #[...]>
4249
if (isArray(slot)) {
4350
for (let j = 0; j < slot.length; j++) {
44-
slots[slot[j].name] = slot[j].fn
51+
slots[slot[j].name] = withCtx(slot[j].fn)
4552
dynamicSlotKeys[slot[j].name] = true
4653
}
4754
} else if (slot) {
4855
// conditional single slot generated by <template v-if="..." #foo>
49-
slots[slot.name] = slot.key
50-
? (...args: any[]) => {
51-
const res = slot.fn(...args)
52-
// attach branch key so each conditional branch is considered a
53-
// different fragment
54-
if (res) (res as any).key = slot.key
55-
return res
56-
}
57-
: slot.fn
56+
slots[slot.name] = withCtx(
57+
slot.key
58+
? (...args: any[]) => {
59+
const res = slot.fn(...args)
60+
// attach branch key so each conditional branch is considered a
61+
// different fragment
62+
if (res) (res as any).key = slot.key
63+
return res
64+
}
65+
: slot.fn,
66+
)
5867
dynamicSlotKeys[slot.name] = true
5968
}
6069
}
@@ -77,4 +86,15 @@ export const initSlots = (
7786
}
7887

7988
instance.slots = slots
89+
90+
function withCtx(fn: Slot): Slot {
91+
return (...args: any[]) => {
92+
const reset = setCurrentInstance(instance.parent!)
93+
try {
94+
return fn(...args)
95+
} finally {
96+
reset()
97+
}
98+
}
99+
}
80100
}

packages/runtime-vapor/src/index.ts

-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ export {
5050
type FunctionalComponent,
5151
type SetupFn,
5252
} from './component'
53-
export { withCtx } from './componentRenderContext'
5453
export { renderEffect } from './renderEffect'
5554
export {
5655
watch,

0 commit comments

Comments
 (0)