@@ -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+ */
142149export 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 }
0 commit comments