]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-vapor): improve fallback handling for nested fragments edison/fix/vaporSlotFallback 13669/head
authordaiwei <daiwei521@126.com>
Fri, 25 Jul 2025 13:51:07 +0000 (21:51 +0800)
committerdaiwei <daiwei521@126.com>
Fri, 25 Jul 2025 14:17:31 +0000 (22:17 +0800)
packages/runtime-vapor/src/block.ts

index 7c178e894b0ea7604fa814ee02ac49459e06c200..d0fa32855cc5189f5b72f155751c128ca648b679 100644 (file)
@@ -74,18 +74,19 @@ export class DynamicFragment extends VaporFragment {
 
     if (this.fallback) {
       // set fallback for nested fragments
-      const isFrag = isFragment(this.nodes)
-      if (isFrag) {
+      const hasNestedFragment = isFragment(this.nodes)
+      if (hasNestedFragment) {
         setFragmentFallback(this.nodes as VaporFragment, this.fallback)
       }
 
-      if (!isValidBlock(this.nodes)) {
+      const invalidFragment = findInvalidFragment(this)
+      if (invalidFragment) {
         parent && remove(this.nodes, parent)
         const scope = this.scope || (this.scope = new EffectScope())
         scope.run(() => {
-          if (isFrag) {
-            // render fragment's fallback
-            renderFragmentFallback(this.nodes as VaporFragment)
+          // for nested fragments, render invalid fragment's fallback
+          if (hasNestedFragment) {
+            renderFragmentFallback(invalidFragment)
           } else {
             this.nodes = this.fallback!() || []
           }
@@ -98,13 +99,11 @@ export class DynamicFragment extends VaporFragment {
   }
 }
 
-function setFragmentFallback(
-  fragment: VaporFragment,
-  fallback: BlockFn | undefined,
-): void {
-  if (!fragment.fallback) {
-    fragment.fallback = fallback
-  }
+function setFragmentFallback(fragment: VaporFragment, fallback: BlockFn): void {
+  // stop recursion if fragment has its own fallback
+  if (fragment.fallback) return
+
+  fragment.fallback = fallback
   if (isFragment(fragment.nodes)) {
     setFragmentFallback(fragment.nodes, fallback)
   }
@@ -114,17 +113,20 @@ function renderFragmentFallback(fragment: VaporFragment): void {
   if (fragment instanceof ForFragment) {
     fragment.nodes[0] = [fragment.fallback!() || []] as Block[]
   } else if (fragment instanceof DynamicFragment) {
-    const nodes = fragment.nodes
-    if (isFragment(nodes)) {
-      renderFragmentFallback(nodes)
-    } else {
-      fragment.update(fragment.fallback)
-    }
+    fragment.update(fragment.fallback)
   } else {
     // vdom slots
   }
 }
 
+function findInvalidFragment(fragment: VaporFragment): VaporFragment | null {
+  if (isValidBlock(fragment.nodes)) return null
+
+  return isFragment(fragment.nodes)
+    ? findInvalidFragment(fragment.nodes) || fragment
+    : fragment
+}
+
 export function isFragment(val: NonNullable<unknown>): val is VaporFragment {
   return val instanceof VaporFragment
 }