diff --git a/packages/runtime-dom/src/components/TransitionGroup.ts b/packages/runtime-dom/src/components/TransitionGroup.ts index 928e5d955f1..7bb5ce0c6b1 100644 --- a/packages/runtime-dom/src/components/TransitionGroup.ts +++ b/packages/runtime-dom/src/components/TransitionGroup.ts @@ -81,6 +81,7 @@ const TransitionGroupImpl: ComponentOptions = /*@__PURE__*/ decorate({ moveClass, ) ) { + prevChildren = [] return } @@ -110,6 +111,7 @@ const TransitionGroupImpl: ComponentOptions = /*@__PURE__*/ decorate({ }) el.addEventListener('transitionend', cb) }) + prevChildren = [] }) return () => { diff --git a/packages/vue/__tests__/e2e/TransitionGroup.spec.ts b/packages/vue/__tests__/e2e/TransitionGroup.spec.ts index 22f22540902..62d89db4e31 100644 --- a/packages/vue/__tests__/e2e/TransitionGroup.spec.ts +++ b/packages/vue/__tests__/e2e/TransitionGroup.spec.ts @@ -645,4 +645,55 @@ describe('e2e: TransitionGroup', () => { }, E2E_TIMEOUT, ) + + test( + 'not leaking after children unmounted', + async () => { + const client = await page().createCDPSession() + await page().evaluate(async () => { + const { createApp, ref, nextTick } = (window as any).Vue + const show = ref(true) + + createApp({ + components: { + Child: { + setup: () => { + // Big arrays kick GC earlier + const test = ref([...Array(3000)].map((_, i) => ({ i }))) + // @ts-expect-error - Custom property and same lib as runtime is used + window.__REF__ = new WeakRef(test) + + return { test } + }, + template: ` +
{{ test.length }}
+ `, + }, + }, + template: ` +