From 169774cb32822541f5b2a0813184444df2f787f7 Mon Sep 17 00:00:00 2001 From: RicardoErii <‘1974364190@qq.com’> Date: Wed, 17 Apr 2024 01:09:13 +0800 Subject: [PATCH 1/5] fix(runtime-core): getKeepAliveChild support slot --- packages/runtime-core/src/components/BaseTransition.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts index e99fe0e496c..a290895656a 100644 --- a/packages/runtime-core/src/components/BaseTransition.ts +++ b/packages/runtime-core/src/components/BaseTransition.ts @@ -19,6 +19,7 @@ import { ErrorCodes, callWithAsyncErrorHandling } from '../errorHandling' import { PatchFlags, ShapeFlags, isArray } from '@vue/shared' import { onBeforeUnmount, onMounted } from '../apiLifecycle' import type { RendererElement } from '../renderer' +import type { RawSlots, Slot } from '../componentSlots' type Hook void> = T | T[] @@ -465,7 +466,8 @@ function getKeepAliveChild(vnode: VNode): VNode | undefined { __DEV__ && vnode.component ? vnode.component.subTree : vnode.children - ? ((vnode.children as VNodeArrayChildren)[0] as VNode) + ? ((vnode.children as VNodeArrayChildren)[0] as VNode) || + ((vnode.children as RawSlots).default as Slot)() : undefined : vnode } From b23aa4819193ab888fbc15edc4387aa1359656c2 Mon Sep 17 00:00:00 2001 From: RicardoErii <‘1974364190@qq.com’> Date: Wed, 17 Apr 2024 22:40:41 +0800 Subject: [PATCH 2/5] fix: fix --- packages/runtime-core/src/components/BaseTransition.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts index a290895656a..d1803b3b974 100644 --- a/packages/runtime-core/src/components/BaseTransition.ts +++ b/packages/runtime-core/src/components/BaseTransition.ts @@ -467,7 +467,7 @@ function getKeepAliveChild(vnode: VNode): VNode | undefined { ? vnode.component.subTree : vnode.children ? ((vnode.children as VNodeArrayChildren)[0] as VNode) || - ((vnode.children as RawSlots).default as Slot)() + ((vnode.children as RawSlots).default as Slot)?.() : undefined : vnode } From f704eaf4331413d0879766edc9c01a34275b48ff Mon Sep 17 00:00:00 2001 From: RicardoErii <‘1974364190@qq.com’> Date: Thu, 18 Apr 2024 00:28:43 +0800 Subject: [PATCH 3/5] fix: fix --- .../src/components/BaseTransition.ts | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts index d1803b3b974..eb60cd46318 100644 --- a/packages/runtime-core/src/components/BaseTransition.ts +++ b/packages/runtime-core/src/components/BaseTransition.ts @@ -19,7 +19,6 @@ import { ErrorCodes, callWithAsyncErrorHandling } from '../errorHandling' import { PatchFlags, ShapeFlags, isArray } from '@vue/shared' import { onBeforeUnmount, onMounted } from '../apiLifecycle' import type { RendererElement } from '../renderer' -import type { RawSlots, Slot } from '../componentSlots' type Hook void> = T | T[] @@ -460,16 +459,24 @@ function emptyPlaceholder(vnode: VNode): VNode | undefined { } function getKeepAliveChild(vnode: VNode): VNode | undefined { - return isKeepAlive(vnode) - ? // #7121 ensure get the child component subtree in case - // it's been replaced during HMR - __DEV__ && vnode.component - ? vnode.component.subTree - : vnode.children - ? ((vnode.children as VNodeArrayChildren)[0] as VNode) || - ((vnode.children as RawSlots).default as Slot)?.() - : undefined - : vnode + if (!isKeepAlive(vnode)) { + return vnode + } + // #7121 ensure get the child component subtree in case + // it's been replaced during HMR + if (__DEV__ && vnode.component) { + return vnode.component.subTree + } + + if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) { + return (vnode.children as VNodeArrayChildren)?.[0] as VNode + } + + if (vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) { + return (vnode.children as any)?.default?.() + } + + return undefined } export function setTransitionHooks(vnode: VNode, hooks: TransitionHooks) { From 50112059001764b463f239c86158a5397abeb295 Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 18 Apr 2024 11:30:42 +0800 Subject: [PATCH 4/5] refactor: tweaks --- .../src/components/BaseTransition.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts index eb60cd46318..5d41751285b 100644 --- a/packages/runtime-core/src/components/BaseTransition.ts +++ b/packages/runtime-core/src/components/BaseTransition.ts @@ -16,7 +16,7 @@ import { warn } from '../warning' import { isKeepAlive } from './KeepAlive' import { toRaw } from '@vue/reactivity' import { ErrorCodes, callWithAsyncErrorHandling } from '../errorHandling' -import { PatchFlags, ShapeFlags, isArray } from '@vue/shared' +import { PatchFlags, ShapeFlags, isArray, isFunction } from '@vue/shared' import { onBeforeUnmount, onMounted } from '../apiLifecycle' import type { RendererElement } from '../renderer' @@ -468,15 +468,18 @@ function getKeepAliveChild(vnode: VNode): VNode | undefined { return vnode.component.subTree } - if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) { - return (vnode.children as VNodeArrayChildren)?.[0] as VNode - } + const { shapeFlag, children } = vnode - if (vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) { - return (vnode.children as any)?.default?.() + if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) { + return (children as VNodeArrayChildren)[0] as VNode } - return undefined + if ( + shapeFlag & ShapeFlags.SLOTS_CHILDREN && + isFunction((children as any).default) + ) { + return (children as any).default() + } } export function setTransitionHooks(vnode: VNode, hooks: TransitionHooks) { From d743a14ebf0f36379c130f6d79517273487144d2 Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 18 Apr 2024 11:39:25 +0800 Subject: [PATCH 5/5] test: add test case --- .../runtime-core/__tests__/components/BaseTransition.spec.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/runtime-core/__tests__/components/BaseTransition.spec.ts b/packages/runtime-core/__tests__/components/BaseTransition.spec.ts index 3184c9c9c6a..1923d161897 100644 --- a/packages/runtime-core/__tests__/components/BaseTransition.spec.ts +++ b/packages/runtime-core/__tests__/components/BaseTransition.spec.ts @@ -1230,4 +1230,9 @@ describe('BaseTransition', () => { await runTestWithKeepAlive(testInOutBeforeFinish) }) }) + + // #10719 + test('should not error on KeepAlive w/ function children', () => { + expect(() => mount({}, () => () => h('div'), true)).not.toThrow() + }) })