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)
+ })
+ })
})