Skip to content

Commit f01841a

Browse files
committed
fix(runtime-vapor): unmount leaving KeepAlive cache entries
Summary: - remove cached branches from their actual parent during teardown - preserve logical unmount when a cached branch is already detached - cover KeepAlive unmount during a pending deactivation leave
1 parent eedfd2d commit f01841a

2 files changed

Lines changed: 38 additions & 2 deletions

File tree

packages/runtime-vapor/__tests__/components/KeepAlive.spec.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,41 @@ describe('VaporKeepAlive', () => {
13761376
app.unmount()
13771377
})
13781378

1379+
test('unmounts a cached branch with a pending deactivation leave', async () => {
1380+
const CompA = compile(`<template><div>A</div></template>`, ref())
1381+
const CompB = compile(`<template><div>B</div></template>`, ref())
1382+
const leaves: Array<() => void> = []
1383+
const data = shallowRef({
1384+
current: CompA,
1385+
onLeave: (_el: Element, done: () => void) => leaves.push(done),
1386+
})
1387+
const App = compile(
1388+
`<template>
1389+
<Transition :css="false" @leave="data.onLeave">
1390+
<KeepAlive :max="2">
1391+
<component :is="data.current" />
1392+
</KeepAlive>
1393+
</Transition>
1394+
</template>`,
1395+
data,
1396+
)
1397+
const { host, app } = define(App as any).render()
1398+
const a = host.firstElementChild
1399+
1400+
data.value = { ...data.value, current: CompB }
1401+
await nextTick()
1402+
1403+
expect(leaves).toHaveLength(1)
1404+
expect(a!.parentNode).toBe(host)
1405+
expect(() => app.unmount()).not.toThrow()
1406+
expect(host.innerHTML).toBe('')
1407+
expect(leaves).toHaveLength(1)
1408+
1409+
leaves[0]()
1410+
await nextTick()
1411+
expect(host.innerHTML).toBe('')
1412+
})
1413+
13791414
test('unmounts an incoming branch superseded during mount', async () => {
13801415
const deactivatedB = vi.fn()
13811416
const unmountedB = vi.fn()

packages/runtime-vapor/src/components/KeepAlive.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,6 @@ const VaporKeepAliveImpl = defineVaporComponent({
170170
block: VaporComponentInstance | VaporFragment,
171171
isCurrent: boolean,
172172
) => {
173-
174173
if (cache.has(key)) {
175174
if (isCurrent) {
176175
// Only active branches should refresh their recency. Background
@@ -357,7 +356,9 @@ const VaporKeepAliveImpl = defineVaporComponent({
357356
}
358357

359358
unsetShapeFlag(cached)
360-
remove(cached, storageContainer)
359+
// A cached branch may still be leaving in its live parent.
360+
const parentNode = findBlockBoundary(cached).parentNode
361+
remove(cached, (parentNode as ParentNode | null) || undefined)
361362
})
362363

363364
// Same-tick branch switches can tear down KeepAlive after the next branch

0 commit comments

Comments
 (0)