Skip to content

Commit 169e051

Browse files
committed
chore: tweak slot parent instance
1 parent 66d3a31 commit 169e051

File tree

7 files changed

+59
-66
lines changed

7 files changed

+59
-66
lines changed

packages/compiler-vapor/__tests__/transforms/__snapshots__/transformSlotOutlet.spec.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ exports[`compiler: transform <slot> outlets > slot outlet with scopeId and slott
115115
"import { createSlot as _createSlot } from 'vue';
116116
117117
export function render(_ctx) {
118-
const n0 = _createSlot("default", null, null, undefined, true)
118+
const n0 = _createSlot("default", null, null, true)
119119
return n0
120120
}"
121121
`;

packages/compiler-vapor/src/generators/slotOutlet.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ export function genSlotOutlet(
3030
nameExpr,
3131
genRawProps(oper.props, context) || 'null',
3232
fallbackArg,
33-
noSlotted && 'undefined', // instance
3433
noSlotted && 'true', // noSlotted
3534
),
3635
)

packages/runtime-core/src/apiCreateApp.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,12 @@ export interface VaporInteropInterface {
212212
transition: TransitionHooks,
213213
): void
214214

215-
vdomMount: (component: ConcreteComponent, props?: any, slots?: any) => any
215+
vdomMount: (
216+
component: ConcreteComponent,
217+
parentComponent: any,
218+
props?: any,
219+
slots?: any,
220+
) => any
216221
vdomUnmount: UnmountComponentFn
217222
vdomSlot: (
218223
slots: any,

packages/runtime-vapor/src/block.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,14 +255,22 @@ export function setScopeId(block: Block, scopeIds: string[]): void {
255255
}
256256

257257
export function setComponentScopeId(instance: VaporComponentInstance): void {
258-
const { parent, slotOwnerScopeId } = instance
259-
if (!parent) return
258+
const { parent, scopeId } = instance
259+
if (!parent || !scopeId) return
260+
260261
// prevent setting scopeId on multi-root fragments
261262
if (isArray(instance.block) && instance.block.length > 1) return
262263

263264
const scopeIds: string[] = []
264-
const scopeId = slotOwnerScopeId || (parent && parent.type.__scopeId)
265-
if (scopeId) scopeIds.push(scopeId)
265+
const parentScopeId = parent && parent.type.__scopeId
266+
// if parent scopeId is different from scopeId, this means scopeId
267+
// is inherited from slot owner, so we need to set it to the component
268+
// scopeIds. the `parentScopeId-s` is handled in createSlot
269+
if (parentScopeId !== scopeId) {
270+
scopeIds.push(scopeId)
271+
} else {
272+
if (parentScopeId) scopeIds.push(parentScopeId)
273+
}
266274

267275
// inherit scopeId from vdom parent
268276
if (

packages/runtime-vapor/src/component.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,10 @@ import {
6969
type RawSlots,
7070
type StaticSlots,
7171
type VaporSlot,
72-
currentSlotOwner,
7372
dynamicSlotsProxyHandlers,
7473
getParentInstance,
7574
getSlot,
76-
setUseSlotConsumer,
75+
setCurrentSlotConsumer,
7776
} from './componentSlots'
7877
import { hmrReload, hmrRerender } from './hmr'
7978
import {
@@ -225,12 +224,14 @@ export function createComponent(
225224

226225
// vdom interop enabled and component is not an explicit vapor component
227226
if (appContext.vapor && !component.__vapor) {
227+
const prevSlotConsumer = setCurrentSlotConsumer(null)
228228
const frag = appContext.vapor.vdomMount(
229229
component as any,
230+
parentInstance as any,
230231
rawProps,
231232
rawSlots,
232233
)
233-
234+
setCurrentSlotConsumer(prevSlotConsumer)
234235
if (!isHydrating) {
235236
if (_insertionParent) insert(frag, _insertionParent, _insertionAnchor)
236237
} else {
@@ -266,6 +267,9 @@ export function createComponent(
266267
parentInstance,
267268
)
268269

270+
// set currentSlotConsumer to null to avoid affecting the child components
271+
const prevSlotConsumer = setCurrentSlotConsumer(null)
272+
269273
// HMR
270274
if (__DEV__ && component.__hmrId) {
271275
registerHMR(instance)
@@ -324,6 +328,8 @@ export function createComponent(
324328
setupComponent(instance, component)
325329
}
326330

331+
// reset currentSlotConsumer to previous value after setupFn call is finished
332+
setCurrentSlotConsumer(prevSlotConsumer)
327333
onScopeDispose(() => unmountComponent(instance), true)
328334

329335
if (_insertionParent || isHydrating) {
@@ -333,6 +339,7 @@ export function createComponent(
333339
if (isHydrating && _insertionAnchor !== undefined) {
334340
advanceHydrationNode(_insertionParent!)
335341
}
342+
336343
return instance
337344
}
338345

@@ -477,7 +484,7 @@ export class VaporComponentInstance implements GenericComponentInstance {
477484

478485
slots: StaticSlots
479486

480-
slotOwnerScopeId?: string | null
487+
scopeId?: string | null
481488

482489
// to hold vnode props / slots in vdom interop mode
483490
rawPropsRef?: ShallowRef<any>
@@ -605,14 +612,12 @@ export class VaporComponentInstance implements GenericComponentInstance {
605612
: rawSlots
606613
: EMPTY_OBJ
607614

608-
this.slotOwnerScopeId = currentSlotOwner && currentSlotOwner.type.__scopeId
615+
this.scopeId = currentInstance && currentInstance.type.__scopeId
609616

610617
// apply custom element special handling
611618
if (comp.ce) {
612619
comp.ce(this)
613620
}
614-
615-
setUseSlotConsumer(false)
616621
}
617622

618623
/**
@@ -681,8 +686,7 @@ export function createPlainElement(
681686
;(el as any).$root = isSingleRoot
682687

683688
if (!isHydrating) {
684-
const scopeOwner = currentSlotOwner || currentInstance
685-
const scopeId = scopeOwner && scopeOwner.type.__scopeId
689+
const scopeId = currentInstance!.type.__scopeId
686690
if (scopeId) setScopeId(el, [scopeId])
687691
}
688692

packages/runtime-vapor/src/componentSlots.ts

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,15 @@ import { setDynamicProps } from './dom/prop'
2727

2828
/**
2929
* Current slot scopeIds for vdom interop
30-
* @internal
3130
*/
3231
export let currentSlotScopeIds: string[] | null = null
3332

34-
/**
35-
* @internal
36-
*/
37-
export function setCurrentSlotScopeIds(
38-
scopeIds: string[] | null,
39-
): string[] | null {
40-
const prev = currentSlotScopeIds
41-
currentSlotScopeIds = scopeIds
42-
return prev
33+
function setCurrentSlotScopeIds(scopeIds: string[] | null): string[] | null {
34+
try {
35+
return currentSlotScopeIds
36+
} finally {
37+
currentSlotScopeIds = scopeIds
38+
}
4339
}
4440

4541
export type RawSlots = Record<string, VaporSlot> & {
@@ -122,34 +118,24 @@ export function getSlot(
122118
}
123119
}
124120

125-
export let currentSlotOwner: GenericComponentInstance | null = null
126121
export let currentSlotConsumer: GenericComponentInstance | null = null
127122

128-
function setCurrentSlotOwner(owner: GenericComponentInstance | null) {
129-
try {
130-
return currentSlotOwner
131-
} finally {
132-
currentSlotOwner = owner
133-
}
134-
}
135-
136-
function setCurrentSlotConsumer(consumer: GenericComponentInstance | null) {
123+
export function setCurrentSlotConsumer(
124+
consumer: GenericComponentInstance | null,
125+
): GenericComponentInstance | null {
137126
try {
138127
return currentSlotConsumer
139128
} finally {
140129
currentSlotConsumer = consumer
141130
}
142131
}
143132

144-
export let useSlotConsumer = false
145-
export function setUseSlotConsumer(value: boolean): void {
146-
useSlotConsumer = value
147-
}
148-
133+
// When rendering components in slot, currentInstance is changed in withVaporCtx
134+
// should use currentSlotConsumer as parent until new instance is created
135+
// it requires to be set to null after new instance is created to avoid affecting
136+
// the child components and reset to previous value after setupFn call is finished
149137
export function getParentInstance(): GenericComponentInstance | null {
150-
// when rendering components in slot, currentInstance is changed in withVaporCtx
151-
// should use currentSlotConsumer as parent until new instance is created
152-
return useSlotConsumer ? currentSlotConsumer : currentInstance
138+
return currentSlotConsumer || currentInstance
153139
}
154140

155141
/**
@@ -160,17 +146,13 @@ export function getParentInstance(): GenericComponentInstance | null {
160146
export function withVaporCtx(fn: Function): BlockFn {
161147
const owner = currentInstance
162148
return (...args: any[]) => {
163-
useSlotConsumer = true
164149
const prev = setCurrentInstance(owner)
165-
const prevOwner = setCurrentSlotOwner(owner)
166150
const prevConsumer = setCurrentSlotConsumer(prev[0])
167151
try {
168152
return fn(...args)
169153
} finally {
170-
setCurrentSlotConsumer(prevConsumer)
171-
setCurrentSlotOwner(prevOwner)
172154
setCurrentInstance(...prev)
173-
useSlotConsumer = false
155+
setCurrentSlotConsumer(prevConsumer)
174156
}
175157
}
176158
}

packages/runtime-vapor/src/vdomInterop.ts

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,7 @@ import {
5959
} from '@vue/shared'
6060
import { type RawProps, rawPropsProxyHandlers } from './componentProps'
6161
import type { RawSlots, VaporSlot } from './componentSlots'
62-
import {
63-
currentSlotOwner,
64-
currentSlotScopeIds,
65-
getParentInstance,
66-
} from './componentSlots'
62+
import { currentSlotScopeIds } from './componentSlots'
6763
import { renderEffect } from './renderEffect'
6864
import { _next, createTextNode } from './dom/node'
6965
import { optimizePropertyLookup } from './dom/prop'
@@ -277,10 +273,10 @@ let vdomHydrateNode: HydrationRenderer['hydrateNode'] | undefined
277273
function createVDOMComponent(
278274
internals: RendererInternals,
279275
component: ConcreteComponent,
276+
parentComponent: VaporComponentInstance | null,
280277
rawProps?: LooseRawProps | null,
281278
rawSlots?: LooseRawSlots | null,
282279
): VaporFragment {
283-
const parentInstance = getParentInstance() as VaporComponentInstance | null
284280
const frag = new VaporFragment([])
285281
const vnode = (frag.vnode = createVNode(
286282
component,
@@ -290,9 +286,9 @@ function createVDOMComponent(
290286
{ props: component.props },
291287
rawProps as RawProps,
292288
rawSlots as RawSlots,
293-
parentInstance ? parentInstance.appContext : undefined,
289+
parentComponent ? parentComponent.appContext : undefined,
294290
undefined,
295-
parentInstance,
291+
parentComponent,
296292
)
297293

298294
// overwrite how the vdom instance handles props
@@ -322,9 +318,9 @@ function createVDOMComponent(
322318
if (vnode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
323319
vdomDeactivate(
324320
vnode,
325-
findParentKeepAlive(parentInstance!)!.getStorageContainer(),
321+
findParentKeepAlive(parentComponent!)!.getStorageContainer(),
326322
internals,
327-
parentInstance as any,
323+
parentComponent as any,
328324
null,
329325
)
330326
return
@@ -333,14 +329,13 @@ function createVDOMComponent(
333329
}
334330

335331
frag.hydrate = () => {
336-
hydrateVNode(vnode, parentInstance as any)
332+
hydrateVNode(vnode, parentComponent as any)
337333
onScopeDispose(unmount, true)
338334
isMounted = true
339335
frag.nodes = vnode.el as any
340336
}
341337

342-
const scopeOwner = currentSlotOwner || parentInstance
343-
vnode.scopeId = (scopeOwner && scopeOwner.type.__scopeId) || null
338+
vnode.scopeId = (currentInstance && currentInstance.type.__scopeId) || null
344339
vnode.slotScopeIds = currentSlotScopeIds
345340

346341
frag.insert = (parentNode, anchor, transition) => {
@@ -351,21 +346,21 @@ function createVDOMComponent(
351346
parentNode,
352347
anchor,
353348
internals,
354-
parentInstance as any,
349+
parentComponent as any,
355350
null,
356351
undefined,
357352
false,
358353
)
359354
} else {
360355
const prev = currentInstance
361-
simpleSetCurrentInstance(parentInstance)
356+
simpleSetCurrentInstance(parentComponent)
362357
if (!isMounted) {
363358
if (transition) setVNodeTransitionHooks(vnode, transition)
364359
internals.mt(
365360
vnode,
366361
parentNode,
367362
anchor,
368-
parentInstance as any,
363+
parentComponent as any,
369364
null,
370365
undefined,
371366
false,
@@ -381,7 +376,7 @@ function createVDOMComponent(
381376
parentNode,
382377
anchor,
383378
MoveType.REORDER,
384-
parentInstance as any,
379+
parentComponent as any,
385380
)
386381
}
387382
simpleSetCurrentInstance(prev)

0 commit comments

Comments
 (0)