Skip to content

Commit b4d4e49

Browse files
committed
chore: update
1 parent 2791887 commit b4d4e49

File tree

4 files changed

+59
-49
lines changed

4 files changed

+59
-49
lines changed

packages/runtime-vapor/src/block.ts

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

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

263263
const scopeIds: string[] = []
264264

265-
const scopeOwner = slotOwner || parent
266-
const scopeId = scopeOwner && scopeOwner.type.__scopeId
265+
const scopeId = slotOwnerScopeId || (parent && parent.type.__scopeId)
267266
if (scopeId) scopeIds.push(scopeId)
268267

269268
// inherit scopeId from vdom parent

packages/runtime-vapor/src/component.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ import {
6969
type RawSlots,
7070
type StaticSlots,
7171
type VaporSlot,
72+
currentSlotConsumer,
73+
currentSlotOwner,
7274
dynamicSlotsProxyHandlers,
7375
getSlot,
74-
getSlotConsumer,
75-
getSlotOwner,
7676
} from './componentSlots'
7777
import { hmrReload, hmrRerender } from './hmr'
7878
import {
@@ -193,8 +193,9 @@ export function createComponent(
193193
resetInsertionState()
194194
}
195195

196-
const parentInstance =
197-
getSlotConsumer() || (currentInstance as VaporComponentInstance | null)
196+
// when rendering components in slot, currentInstance is changed in withVaporCtx
197+
// should use currentSlotConsumer as parent
198+
const parentInstance = currentSlotConsumer || currentInstance
198199

199200
if (
200201
isSingleRoot &&
@@ -477,8 +478,7 @@ export class VaporComponentInstance implements GenericComponentInstance {
477478

478479
slots: StaticSlots
479480

480-
// slot owner for scopeId inheritance
481-
slotOwner?: VaporComponentInstance | null
481+
slotOwnerScopeId?: string | null
482482

483483
// to hold vnode props / slots in vdom interop mode
484484
rawPropsRef?: ShallowRef<any>
@@ -606,7 +606,7 @@ export class VaporComponentInstance implements GenericComponentInstance {
606606
: rawSlots
607607
: EMPTY_OBJ
608608

609-
this.slotOwner = getSlotOwner()
609+
this.slotOwnerScopeId = currentSlotOwner && currentSlotOwner.type.__scopeId
610610

611611
// apply custom element special handling
612612
if (comp.ce) {
@@ -680,7 +680,7 @@ export function createPlainElement(
680680
;(el as any).$root = isSingleRoot
681681

682682
if (!isHydrating) {
683-
const scopeOwner = getSlotOwner() || currentInstance
683+
const scopeOwner = currentSlotOwner || currentInstance
684684
const scopeId = scopeOwner && scopeOwner.type.__scopeId
685685
if (scopeId) setScopeId(el, [scopeId])
686686
}

packages/runtime-vapor/src/componentSlots.ts

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -122,34 +122,41 @@ export function getSlot(
122122
}
123123
}
124124

125-
// Tracks slot execution context: the owner that defined the slot, and the
126-
// consumer that is currently rendering it.
127-
const slotOwnerStack: (VaporComponentInstance | null)[] = []
128-
const slotConsumerStack: (VaporComponentInstance | null)[] = []
125+
export let currentSlotOwner: GenericComponentInstance | null = null
126+
export let currentSlotConsumer: GenericComponentInstance | null = null
129127

130-
export function getSlotOwner(): VaporComponentInstance | null {
131-
return slotOwnerStack.length > 0
132-
? slotOwnerStack[slotOwnerStack.length - 1]
133-
: null
128+
function setCurrentSlotOwner(owner: GenericComponentInstance | null) {
129+
try {
130+
return currentSlotOwner
131+
} finally {
132+
currentSlotOwner = owner
133+
}
134134
}
135135

136-
export function getSlotConsumer(): VaporComponentInstance | null {
137-
return slotConsumerStack.length > 0
138-
? slotConsumerStack[slotConsumerStack.length - 1]
139-
: null
136+
function setCurrentSlotConsumer(consumer: GenericComponentInstance | null) {
137+
try {
138+
return currentSlotConsumer
139+
} finally {
140+
currentSlotConsumer = consumer
141+
}
140142
}
141143

144+
/**
145+
* Wrap a slot function to memoize currentInstance
146+
* 1. ensure correct currentInstance in forwarded slots
147+
* 2. elements created in the slot inherit the slot owner's scopeId
148+
*/
142149
export function withVaporCtx(fn: Function): BlockFn {
143-
const ownerInstance = currentInstance as VaporComponentInstance | null
150+
const owner = currentInstance
144151
return (...args: any[]) => {
145-
const prev = setCurrentInstance(ownerInstance)
146-
slotOwnerStack.push(ownerInstance)
147-
slotConsumerStack.push(prev[0] as VaporComponentInstance | null)
152+
const prev = setCurrentInstance(owner)
153+
const prevOwner = setCurrentSlotOwner(owner)
154+
const prevConsumer = setCurrentSlotConsumer(prev[0])
148155
try {
149156
return fn(...args)
150157
} finally {
151-
slotConsumerStack.pop()
152-
slotOwnerStack.pop()
158+
setCurrentSlotConsumer(prevConsumer)
159+
setCurrentSlotOwner(prevOwner)
153160
setCurrentInstance(...prev)
154161
}
155162
}
@@ -166,21 +173,20 @@ export function createSlot(
166173
const _isLastInsertion = isLastInsertion
167174
if (!isHydrating) resetInsertionState()
168175

169-
const consumer = currentInstance as VaporComponentInstance
170-
const owner = getSlotOwner() || consumer
171-
const rawSlots = consumer!.rawSlots
176+
const instance = currentInstance as VaporComponentInstance
177+
const rawSlots = instance.rawSlots
172178
const slotProps = rawProps
173179
? new Proxy(rawProps, rawPropsProxyHandlers)
174180
: EMPTY_OBJ
175181

176182
let fragment: DynamicFragment
177183
if (isRef(rawSlots._)) {
178184
if (isHydrating) locateHydrationNode()
179-
fragment = owner.appContext.vapor!.vdomSlot(
185+
fragment = instance.appContext.vapor!.vdomSlot(
180186
rawSlots._,
181187
name,
182188
slotProps,
183-
owner,
189+
instance,
184190
fallback,
185191
)
186192
} else {
@@ -190,9 +196,10 @@ export function createSlot(
190196
: new DynamicFragment()
191197
const isDynamicName = isFunction(name)
192198

199+
// Calculate slotScopeIds once (for vdom interop)
193200
const slotScopeIds: string[] = []
194201
if (!noSlotted) {
195-
const scopeId = owner.type.__scopeId
202+
const scopeId = instance.type.__scopeId
196203
if (scopeId) {
197204
slotScopeIds.push(`${scopeId}-s`)
198205
}
@@ -201,11 +208,14 @@ export function createSlot(
201208
const renderSlot = () => {
202209
const slotName = isFunction(name) ? name() : name
203210

211+
// in custom element mode, render <slot/> as actual slot outlets
212+
// because in shadowRoot: false mode the slot element gets
213+
// replaced by injected content
204214
if (
205-
(consumer as GenericComponentInstance).ce ||
206-
(consumer.parent &&
207-
isAsyncWrapper(consumer.parent) &&
208-
consumer.parent.ce)
215+
(instance as GenericComponentInstance).ce ||
216+
(instance.parent &&
217+
isAsyncWrapper(instance.parent) &&
218+
instance.parent.ce)
209219
) {
210220
const el = createElement('slot')
211221
renderEffect(() => {
@@ -224,7 +234,6 @@ export function createSlot(
224234
fragment.fallback = fallback
225235
// Create and cache bound version of the slot to make it stable
226236
// so that we avoid unnecessary updates if it resolves to the same slot
227-
228237
fragment.update(
229238
slot._bound ||
230239
(slot._bound = () => {
@@ -253,7 +262,7 @@ export function createSlot(
253262

254263
if (!isHydrating) {
255264
if (!noSlotted) {
256-
const scopeId = owner.type.__scopeId
265+
const scopeId = instance.type.__scopeId
257266
if (scopeId) {
258267
setScopeId(fragment, [`${scopeId}-s`])
259268
}

packages/runtime-vapor/src/vdomInterop.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ import {
5959
} from '@vue/shared'
6060
import { type RawProps, rawPropsProxyHandlers } from './componentProps'
6161
import type { RawSlots, VaporSlot } from './componentSlots'
62-
import { currentSlotScopeIds, getSlotOwner } from './componentSlots'
62+
import {
63+
currentSlotConsumer,
64+
currentSlotOwner,
65+
currentSlotScopeIds,
66+
} from './componentSlots'
6367
import { renderEffect } from './renderEffect'
6468
import { _next, createTextNode } from './dom/node'
6569
import { optimizePropertyLookup } from './dom/prop'
@@ -276,7 +280,8 @@ function createVDOMComponent(
276280
rawProps?: LooseRawProps | null,
277281
rawSlots?: LooseRawSlots | null,
278282
): VaporFragment {
279-
const parentInstance = currentInstance as VaporComponentInstance
283+
const parentInstance = (currentSlotConsumer ||
284+
currentInstance) as VaporComponentInstance
280285
const frag = new VaporFragment([])
281286
const vnode = (frag.vnode = createVNode(
282287
component,
@@ -335,11 +340,8 @@ function createVDOMComponent(
335340
frag.nodes = vnode.el as any
336341
}
337342

338-
const scopeOwner =
339-
getSlotOwner() ||
340-
(parentInstance && parentInstance.slotOwner) ||
341-
parentInstance
342-
vnode.scopeId = scopeOwner && scopeOwner.type.__scopeId!
343+
const scopeOwner = currentSlotOwner || parentInstance
344+
vnode.scopeId = (scopeOwner && scopeOwner.type.__scopeId) || null
343345
vnode.slotScopeIds = currentSlotScopeIds
344346

345347
frag.insert = (parentNode, anchor, transition) => {

0 commit comments

Comments
 (0)