From: daiwei Date: Thu, 12 Jun 2025 08:18:19 +0000 (+0800) Subject: chore: Merge branch 'edison/feat/fowardedSlots' into edison/testVapor X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6180b8a200ef28edcc50bf3a4612ba839ca7bf58;p=thirdparty%2Fvuejs%2Fcore.git chore: Merge branch 'edison/feat/fowardedSlots' into edison/testVapor --- 6180b8a200ef28edcc50bf3a4612ba839ca7bf58 diff --cc packages/runtime-vapor/src/block.ts index 31b71848dc,b2d0ca04b6..f0dbe7ab6c --- a/packages/runtime-vapor/src/block.ts +++ b/packages/runtime-vapor/src/block.ts @@@ -38,10 -31,9 +39,9 @@@ export class VaporFragment } export class DynamicFragment extends VaporFragment { - anchor: Node + anchor!: Node scope: EffectScope | undefined current?: BlockFn - fallback?: BlockFn constructor(anchorLabel?: string) { super([]) diff --cc packages/runtime-vapor/src/componentSlots.ts index 1ec6969bc9,b8af4c9162..b250ecef49 --- a/packages/runtime-vapor/src/componentSlots.ts +++ b/packages/runtime-vapor/src/componentSlots.ts @@@ -131,7 -123,8 +132,7 @@@ export function createSlot : EMPTY_OBJ let fragment: DynamicFragment - if (isRef(rawSlots._) && rawSlots._.value) { - + if (isRef(rawSlots._)) { fragment = instance.appContext.vapor!.vdomSlot( rawSlots._, name, diff --cc packages/runtime-vapor/src/vdomInterop.ts index ee8799039b,a6b115f747..cf67e3e518 --- a/packages/runtime-vapor/src/vdomInterop.ts +++ b/packages/runtime-vapor/src/vdomInterop.ts @@@ -2,21 -2,22 +2,25 @@@ import type App, type ComponentInternalInstance, type ConcreteComponent, + type HydrationRenderer, MoveType, type Plugin, + type RendererElement, type RendererInternals, + type RendererNode, type ShallowRef, type Slots, type VNode, type VaporInteropInterface, createVNode, currentInstance, + ensureHydrationRenderer, ensureRenderer, + ensureVaporSlotFallback, + isVNode, onScopeDispose, renderSlot, + shallowReactive, shallowRef, simpleSetCurrentInstance, } from '@vue/runtime-dom' @@@ -273,77 -252,54 +293,71 @@@ function renderVDOMSlot frag.insert = (parentNode, anchor) => { if (!isMounted) { renderEffect(() => { - const vnode = renderSlot( - slotsRef.value, - isFunction(name) ? name() : name, - props, - ) - if (isHydrating) { - locateHydrationNode(true) - ;( - vdomHydrateNode || - (vdomHydrateNode = ensureHydrationRenderer().hydrateNode!) - )( - currentHydrationNode!, - vnode, + let vnode: VNode | undefined + let isValidSlot = false + // only render slot if rawSlots is defined and slot nodes are not empty + // otherwise, render fallback + if (slotsRef.value) { + vnode = renderSlot( + slotsRef.value, + isFunction(name) ? name() : name, + props, + ) + + let children = vnode.children as any[] + // handle forwarded vapor slot without its own fallback + // use the fallback provided by the slot outlet + ensureVaporSlotFallback(children, fallback as any) + isValidSlot = children.length > 0 + } + + if (isValidSlot) { - if (fallbackNodes) { ++ if (isHydrating) { ++ locateHydrationNode(true) ++ ;( ++ vdomHydrateNode || ++ (vdomHydrateNode = ensureHydrationRenderer().hydrateNode!) ++ )( ++ currentHydrationNode!, ++ vnode!, ++ parentComponent as any, ++ null, ++ null, ++ false, ++ ) ++ } else if (fallbackNodes) { + remove(fallbackNodes, parentNode) + fallbackNodes = undefined + } + internals.p( + oldVNode, + vnode!, + parentNode, + anchor, parentComponent as any, + null, ++ undefined, + null, + false, ) + oldVNode = vnode! } else { - let isValidSlotContent - let children = vnode.children as any[] - /* - * Handle forwarded vapor slot inside VDOM slot - * Example: In a vapor component template: - * - * - * - */ - let vaporSlot - if (children.length === 1 && (vaporSlot = children[0].vs)) { - const block = vaporSlot.slot(props) - isValidSlotContent = - isValidBlock(block) || - /* - * If block is a vapor fragment with insert, it indicates a forwarded VDOM slot - * Example: In a VDOM component template: - * - * - * - */ - (isFragment(block) && block.insert) - } else { - isValidSlotContent = children.length > 0 - } - if (isValidSlotContent) { - if (fallbackNodes) { - remove(fallbackNodes, parentNode) - fallbackNodes = undefined + // for forwarded slot without its own fallback, use the fallback + // provided by the slot outlet. + // re-fetch `frag.fallback` as it may have been updated at `createSlot` + fallback = frag.fallback + if (fallback && !fallbackNodes) { + // mount fallback + if (oldVNode) { + internals.um(oldVNode, parentComponent as any, null, true) } - internals.p( - oldVNode, - vnode, + insert( + (fallbackNodes = fallback(internals, parentComponent)), parentNode, anchor, - parentComponent as any, ) - oldVNode = vnode - } else { - if (fallback && !fallbackNodes) { - // mount fallback - if (oldVNode) { - internals.um(oldVNode, parentComponent as any, null, true) - } - insert((fallbackNodes = fallback(props)), parentNode, anchor) - } - oldVNode = null } + oldVNode = null } }) isMounted = true