fix(runtime-vapor): improve fallback handling for nested fragments
ci / test (push) Has been cancelled Details
ci / continuous-release (push) Has been cancelled Details

This commit is contained in:
daiwei 2025-07-25 21:51:07 +08:00
parent b8ceb89a46
commit 3a52e46b86
1 changed files with 21 additions and 19 deletions

View File

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