diff --git a/packages/vue/__tests__/e2e/Transition.spec.ts b/packages/vue/__tests__/e2e/Transition.spec.ts index c0863a75991..60274ad134c 100644 --- a/packages/vue/__tests__/e2e/Transition.spec.ts +++ b/packages/vue/__tests__/e2e/Transition.spec.ts @@ -3121,4 +3121,124 @@ describe('e2e: Transition', () => { }, E2E_TIMEOUT, ) + + // https://github.com/vuejs/core/issues/12181#issuecomment-2414380955 + describe('not leaking', async () => { + test('switching VNodes', async () => { + const client = await page().createCDPSession() + await page().evaluate(async () => { + const { createApp, ref, nextTick } = (window as any).Vue + const empty = ref(true) + + createApp({ + components: { + Child: { + setup: () => { + // Big arrays kick GC earlier + const test = ref([...Array(30_000_000)].map((_, i) => ({ i }))) + // TODO: Use a diferent TypeScript env for testing + // @ts-expect-error - Custom property and same lib as runtime is used + window.__REF__ = new WeakRef(test) + + return { test } + }, + template: ` +

{{ test.length }}

+ `, + }, + Empty: { + template: '
', + }, + }, + template: ` + + + + `, + setup() { + return { empty } + }, + }).mount('#app') + + await nextTick() + empty.value = false + await nextTick() + empty.value = true + await nextTick() + }) + + const isCollected = async () => + // @ts-expect-error - Custom property + await page().evaluate(() => window.__REF__.deref() === undefined) + + while ((await isCollected()) === false) { + await client.send('HeapProfiler.collectGarbage') + } + + expect(await isCollected()).toBe(true) + }) + + // https://github.com/vuejs/core/issues/12181#issue-2588232334 + test('switching deep vnodes edge case', async () => { + const client = await page().createCDPSession() + await page().evaluate(async () => { + const { createApp, ref, nextTick } = (window as any).Vue + const shown = ref(false) + + createApp({ + components: { + Child: { + setup: () => { + // Big arrays kick GC earlier + const test = ref([...Array(30_000_000)].map((_, i) => ({ i }))) + // TODO: Use a diferent TypeScript env for testing + // @ts-expect-error - Custom property and same lib as runtime is used + window.__REF__ = new WeakRef(test) + + return { test } + }, + template: ` +

{{ test.length }}

+ `, + }, + Wrapper: { + template: ` + +
+ +
+
+ `, + }, + }, + template: ` + + + +
+
+ `, + setup() { + return { shown } + }, + }).mount('#app') + + await nextTick() + shown.value = true + await nextTick() + shown.value = false + await nextTick() + }) + + const isCollected = async () => + // @ts-expect-error - Custom property + await page().evaluate(() => window.__REF__.deref() === undefined) + + while ((await isCollected()) === false) { + await client.send('HeapProfiler.collectGarbage') + } + + expect(await isCollected()).toBe(true) + }) + }) })