@@ -632,11 +632,15 @@ export abstract class VueElementBase<
632632 protected _renderSlots ( ) : void {
633633 const outlets = this . _getSlots ( )
634634 const scopeId = this . _instance ! . type . __scopeId
635+ const slotReplacements : Map < Node , Node [ ] > = new Map ( )
636+
635637 for ( let i = 0 ; i < outlets . length ; i ++ ) {
636638 const o = outlets [ i ] as HTMLSlotElement
637639 const slotName = o . getAttribute ( 'name' ) || 'default'
638640 const content = this . _slots ! [ slotName ]
639641 const parent = o . parentNode !
642+ const replacementNodes : Node [ ] = [ ]
643+
640644 if ( content ) {
641645 for ( const n of content ) {
642646 // for :slotted css
@@ -650,11 +654,66 @@ export abstract class VueElementBase<
650654 }
651655 }
652656 parent . insertBefore ( n , o )
657+ replacementNodes . push ( n )
658+ }
659+ } else {
660+ while ( o . firstChild ) {
661+ const child = o . firstChild
662+ parent . insertBefore ( child , o )
663+ replacementNodes . push ( child )
664+ }
665+ }
666+
667+ slotReplacements . set ( o , replacementNodes )
668+ }
669+
670+ // For Vapor: update fragment nodes before removing slots from DOM
671+ if ( slotReplacements . size > 0 && this . _instance && this . _instance . vapor ) {
672+ // @ts -expect-error TODO refactor
673+ this . _replaceNodesInFragments ( this . _instance . block , slotReplacements )
674+ }
675+
676+ // Now safe to remove slots from DOM
677+ slotReplacements . forEach ( ( _ , o ) => o . parentNode ! . removeChild ( o ) )
678+ }
679+
680+ /**
681+ * Replace slot nodes with their content in fragment nodes arrays
682+ * @internal
683+ */
684+ private _replaceNodesInFragments (
685+ block : any ,
686+ replacements : Map < Node , Node [ ] > ,
687+ ) : void {
688+ if ( ! block ) return
689+
690+ if ( Array . isArray ( block ) ) {
691+ for ( let i = 0 ; i < block . length ; i ++ ) {
692+ this . _replaceNodesInFragments ( block [ i ] , replacements )
693+ }
694+ } else if ( block . nodes !== undefined ) {
695+ // This is a fragment with nodes property
696+ if ( Array . isArray ( block . nodes ) ) {
697+ // Replace slot nodes with their content
698+ const newNodes : any [ ] = [ ]
699+ for ( const node of block . nodes ) {
700+ if ( node instanceof Node && replacements . has ( node ) ) {
701+ // Replace with the content nodes
702+ newNodes . push ( ...replacements . get ( node ) ! )
703+ } else {
704+ newNodes . push ( node )
705+ // Recursively process nested fragments
706+ this . _replaceNodesInFragments ( node , replacements )
707+ }
653708 }
709+ block . nodes = newNodes
710+ } else if ( block . nodes instanceof Node && replacements . has ( block . nodes ) ) {
711+ // Replace single node with its content
712+ const replacement = replacements . get ( block . nodes ) !
713+ block . nodes = replacement . length === 1 ? replacement [ 0 ] : replacement
654714 } else {
655- while ( o . firstChild ) parent . insertBefore ( o . firstChild , o )
715+ this . _replaceNodesInFragments ( block . nodes , replacements )
656716 }
657- parent . removeChild ( o )
658717 }
659718 }
660719
0 commit comments