@@ -3121,4 +3121,124 @@ describe('e2e: Transition', () => {
3121
3121
} ,
3122
3122
E2E_TIMEOUT ,
3123
3123
)
3124
+
3125
+ // https://github.com/vuejs/core/issues/12181#issuecomment-2414380955
3126
+ describe ( 'not leaking' , async ( ) => {
3127
+ test ( 'switching VNodes' , async ( ) => {
3128
+ const client = await page ( ) . createCDPSession ( )
3129
+ await page ( ) . evaluate ( async ( ) => {
3130
+ const { createApp, ref, nextTick } = ( window as any ) . Vue
3131
+ const empty = ref ( true )
3132
+
3133
+ createApp ( {
3134
+ components : {
3135
+ Child : {
3136
+ setup : ( ) => {
3137
+ // Big arrays kick GC earlier
3138
+ const test = ref ( [ ...Array ( 30_000_000 ) ] . map ( ( _ , i ) => ( { i } ) ) )
3139
+ // TODO: Use a diferent TypeScript env for testing
3140
+ // @ts -expect-error - Custom property and same lib as runtime is used
3141
+ window . __REF__ = new WeakRef ( test )
3142
+
3143
+ return { test }
3144
+ } ,
3145
+ template : `
3146
+ <p>{{ test.length }}</p>
3147
+ ` ,
3148
+ } ,
3149
+ Empty : {
3150
+ template : '<div></div>' ,
3151
+ } ,
3152
+ } ,
3153
+ template : `
3154
+ <transition>
3155
+ <component :is="empty ? 'Empty' : 'Child'" />
3156
+ </transition>
3157
+ ` ,
3158
+ setup ( ) {
3159
+ return { empty }
3160
+ } ,
3161
+ } ) . mount ( '#app' )
3162
+
3163
+ await nextTick ( )
3164
+ empty . value = false
3165
+ await nextTick ( )
3166
+ empty . value = true
3167
+ await nextTick ( )
3168
+ } )
3169
+
3170
+ const isCollected = async ( ) =>
3171
+ // @ts -expect-error - Custom property
3172
+ await page ( ) . evaluate ( ( ) => window . __REF__ . deref ( ) === undefined )
3173
+
3174
+ while ( ( await isCollected ( ) ) === false ) {
3175
+ await client . send ( 'HeapProfiler.collectGarbage' )
3176
+ }
3177
+
3178
+ expect ( await isCollected ( ) ) . toBe ( true )
3179
+ } )
3180
+
3181
+ // https://github.com/vuejs/core/issues/12181#issue-2588232334
3182
+ test ( 'switching deep vnodes edge case' , async ( ) => {
3183
+ const client = await page ( ) . createCDPSession ( )
3184
+ await page ( ) . evaluate ( async ( ) => {
3185
+ const { createApp, ref, nextTick } = ( window as any ) . Vue
3186
+ const shown = ref ( false )
3187
+
3188
+ createApp ( {
3189
+ components : {
3190
+ Child : {
3191
+ setup : ( ) => {
3192
+ // Big arrays kick GC earlier
3193
+ const test = ref ( [ ...Array ( 30_000_000 ) ] . map ( ( _ , i ) => ( { i } ) ) )
3194
+ // TODO: Use a diferent TypeScript env for testing
3195
+ // @ts -expect-error - Custom property and same lib as runtime is used
3196
+ window . __REF__ = new WeakRef ( test )
3197
+
3198
+ return { test }
3199
+ } ,
3200
+ template : `
3201
+ <p>{{ test.length }}</p>
3202
+ ` ,
3203
+ } ,
3204
+ Wrapper : {
3205
+ template : `
3206
+ <transition>
3207
+ <div v-if="true">
3208
+ <slot />
3209
+ </div>
3210
+ </transition>
3211
+ ` ,
3212
+ } ,
3213
+ } ,
3214
+ template : `
3215
+ <button id="toggleBtn" @click="shown = !shown">{{ shown ? 'Hide' : 'Show' }}</button>
3216
+ <Wrapper>
3217
+ <Child v-if="shown" />
3218
+ <div v-else></div>
3219
+ </Wrapper>
3220
+ ` ,
3221
+ setup ( ) {
3222
+ return { shown }
3223
+ } ,
3224
+ } ) . mount ( '#app' )
3225
+
3226
+ await nextTick ( )
3227
+ shown . value = true
3228
+ await nextTick ( )
3229
+ shown . value = false
3230
+ await nextTick ( )
3231
+ } )
3232
+
3233
+ const isCollected = async ( ) =>
3234
+ // @ts -expect-error - Custom property
3235
+ await page ( ) . evaluate ( ( ) => window . __REF__ . deref ( ) === undefined )
3236
+
3237
+ while ( ( await isCollected ( ) ) === false ) {
3238
+ await client . send ( 'HeapProfiler.collectGarbage' )
3239
+ }
3240
+
3241
+ expect ( await isCollected ( ) ) . toBe ( true )
3242
+ } )
3243
+ } )
3124
3244
} )
0 commit comments