Просмотр исходного кода

test: add test case for transition memory leaks

from https://github.com/vuejs/core/pull/12190
Evan You 1 год назад
Родитель
Сommit
54812eacaa
1 измененных файлов с 120 добавлено и 0 удалено
  1. 120 0
      packages/vue/__tests__/e2e/Transition.spec.ts

+ 120 - 0
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: `
+                <p>{{ test.length }}</p>
+              `,
+            },
+            Empty: {
+              template: '<div></div>',
+            },
+          },
+          template: `
+            <transition>
+              <component :is="empty ? 'Empty' : 'Child'" />
+            </transition>
+          `,
+          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: `
+                <p>{{ test.length }}</p>
+              `,
+            },
+            Wrapper: {
+              template: `
+                <transition>
+                  <div v-if="true">
+                    <slot />
+                  </div>
+                </transition>
+              `,
+            },
+          },
+          template: `
+            <button id="toggleBtn" @click="shown = !shown">{{ shown ? 'Hide' : 'Show' }}</button>
+            <Wrapper>
+              <Child v-if="shown" />
+              <div v-else></div>
+            </Wrapper>
+          `,
+          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)
+    })
+  })
 })