@@ -151,20 +151,31 @@ export class DynamicFragment extends VaporFragment {
151151 this . render ( render , transition , parent , instance )
152152
153153 if ( this . fallback ) {
154- // set fallback for nested fragments
155- const hasNestedFragment = isFragment ( this . nodes )
156- if ( hasNestedFragment ) {
157- setFragmentFallback ( this . nodes as VaporFragment , this . fallback )
154+ // Find the deepest invalid fragment
155+ let invalidFragment : VaporFragment | null = null
156+ if ( isFragment ( this . nodes ) ) {
157+ setFragmentFallback (
158+ this . nodes ,
159+ this . fallback ,
160+ ( frag : VaporFragment ) => {
161+ if ( ! isValidBlock ( frag . nodes ) ) {
162+ invalidFragment = frag
163+ }
164+ } ,
165+ )
166+ }
167+
168+ // Check self validity (when no nested fragment or nested is valid)
169+ if ( ! invalidFragment && ! isValidBlock ( this . nodes ) ) {
170+ invalidFragment = this
158171 }
159172
160- const invalidFragment = findInvalidFragment ( this )
161173 if ( invalidFragment ) {
162174 parent && remove ( this . nodes , parent )
163175 const scope = this . scope || ( this . scope = new EffectScope ( ) )
164176 scope . run ( ( ) => {
165- // for nested fragments, render invalid fragment's fallback
166- if ( hasNestedFragment ) {
167- renderFragmentFallback ( invalidFragment )
177+ if ( invalidFragment !== this ) {
178+ renderFragmentFallback ( invalidFragment ! )
168179 } else {
169180 this . nodes = this . fallback ! ( ) || [ ]
170181 }
@@ -294,10 +305,28 @@ export class DynamicFragment extends VaporFragment {
294305 }
295306}
296307
308+ // Track which fallback has been set on each fragment
309+ // to avoid duplicate chaining when nested DynamicFragments call setFragmentFallback
310+ const processedFallbacks = new WeakMap < VaporFragment , BlockFn > ( )
311+
297312export function setFragmentFallback (
298313 fragment : VaporFragment ,
299314 fallback : BlockFn ,
315+ onFragment ?: ( frag : VaporFragment ) => void ,
300316) : void {
317+ if ( processedFallbacks . get ( fragment ) === fallback ) {
318+ // Already processed with this fallback, skip re-setting
319+ // but still recurse since nodes may have changed
320+ if ( onFragment ) onFragment ( fragment )
321+ if ( isFragment ( fragment . nodes ) ) {
322+ setFragmentFallback ( fragment . nodes , fragment . fallback ! , onFragment )
323+ }
324+ return
325+ }
326+
327+ // Mark as processed
328+ processedFallbacks . set ( fragment , fallback )
329+
301330 if ( fragment . fallback ) {
302331 const originalFallback = fragment . fallback
303332 // if the original fallback also renders invalid blocks,
@@ -313,8 +342,10 @@ export function setFragmentFallback(
313342 fragment . fallback = fallback
314343 }
315344
345+ if ( onFragment ) onFragment ( fragment )
346+
316347 if ( isFragment ( fragment . nodes ) ) {
317- setFragmentFallback ( fragment . nodes , fragment . fallback )
348+ setFragmentFallback ( fragment . nodes , fragment . fallback , onFragment )
318349 }
319350}
320351
@@ -328,14 +359,6 @@ function renderFragmentFallback(fragment: VaporFragment): void {
328359 }
329360}
330361
331- function findInvalidFragment ( fragment : VaporFragment ) : VaporFragment | null {
332- if ( isValidBlock ( fragment . nodes ) ) return null
333-
334- return isFragment ( fragment . nodes )
335- ? findInvalidFragment ( fragment . nodes ) || fragment
336- : fragment
337- }
338-
339362export function isFragment ( val : NonNullable < unknown > ) : val is VaporFragment {
340363 return val instanceof VaporFragment
341364}
0 commit comments