Skip to content

Commit 8b848cb

Browse files
authored
fix(TransitionGroup): reset prevChildren to prevent memory leak (#13183)
close #13181
1 parent 016c472 commit 8b848cb

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

packages/runtime-dom/src/components/TransitionGroup.ts

+2
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ const TransitionGroupImpl: ComponentOptions = /*@__PURE__*/ decorate({
8181
moveClass,
8282
)
8383
) {
84+
prevChildren = []
8485
return
8586
}
8687

@@ -110,6 +111,7 @@ const TransitionGroupImpl: ComponentOptions = /*@__PURE__*/ decorate({
110111
})
111112
el.addEventListener('transitionend', cb)
112113
})
114+
prevChildren = []
113115
})
114116

115117
return () => {

packages/vue/__tests__/e2e/TransitionGroup.spec.ts

+51
Original file line numberDiff line numberDiff line change
@@ -645,4 +645,55 @@ describe('e2e: TransitionGroup', () => {
645645
},
646646
E2E_TIMEOUT,
647647
)
648+
649+
test(
650+
'not leaking after children unmounted',
651+
async () => {
652+
const client = await page().createCDPSession()
653+
await page().evaluate(async () => {
654+
const { createApp, ref, nextTick } = (window as any).Vue
655+
const show = ref(true)
656+
657+
createApp({
658+
components: {
659+
Child: {
660+
setup: () => {
661+
// Big arrays kick GC earlier
662+
const test = ref([...Array(3000)].map((_, i) => ({ i })))
663+
// @ts-expect-error - Custom property and same lib as runtime is used
664+
window.__REF__ = new WeakRef(test)
665+
666+
return { test }
667+
},
668+
template: `
669+
<p>{{ test.length }}</p>
670+
`,
671+
},
672+
},
673+
template: `
674+
<transition-group>
675+
<Child v-if="show" />
676+
</transition-group>
677+
`,
678+
setup() {
679+
return { show }
680+
},
681+
}).mount('#app')
682+
683+
show.value = false
684+
await nextTick()
685+
})
686+
687+
const isCollected = async () =>
688+
// @ts-expect-error - Custom property
689+
await page().evaluate(() => window.__REF__.deref() === undefined)
690+
691+
while ((await isCollected()) === false) {
692+
await client.send('HeapProfiler.collectGarbage')
693+
}
694+
695+
expect(await isCollected()).toBe(true)
696+
},
697+
E2E_TIMEOUT,
698+
)
648699
})

0 commit comments

Comments
 (0)