[bug] Memory leak with this.$router.apps array and secondary apps on page being destroyed #2639
Description
Version
3.0.2 (and earlier)
Reproduction link
https://bootstrap-vue.js.org/play/
See next steps to easily reproduce the issue.
Steps to reproduce
Just go to https://bootstrap-vue.js.org/play/
And enter the following code in the HTML Template area:
<div>
<p>This App UID: {{ _uid }}</p>
<p>$route.apps length: {{ $router.apps.length }}</p>
<pre>{{
$router.apps.map(
a => {
return { uid: a._uid, destroyed: a._isDestroyed }
}
).reverse()
}}</pre>
</div>
and just enter { }
into the JavaScript area (or leave it as is)
Hit space / delete the space every second or so in either the HTML entry area, or the javascript entry area (there is a 0.75 second debouncer on the app creation/destroy on keypress).
Each time, the rendered app will be destroyed and recreated.
The app shows a mapped version of $router.apps
array (in the results section)
You will see the array grow and grow and grow, with all these destroyed
instances sticking around.
It looks like vue-router isn't cleaning out $router.apps
array during the destroy hook of the app. (`hook:destroyed').
What is expected?
That the apps that have been $destroyed
would be removed from the $router.apps
array
What is actually happening?
The destroyed app references remain in the $router.apps
array, causing memory usage to grow/leak.
I've noticed a memory leak with this.$router.apps
array. It might be related (but not sure) to other memory leaks reported.
On a docs site we have, we have a playground that allows you to create and test mini apps in real time.
As the user edits the test app, it destroys (app.$destroy()), and then re compiles and mounts the new version.
Each time the playground app is created, it gets appended to the this.$router.apps
array, while the destroyed app still remains in the array (albeit it has a destroyed instance, but there is still quite a bit of stuff in the reference).
The playground is running under Nuxt.js, and each test in the playground is created as a new app (with a reference to the main $router instance).
We are adding in a temporary fix that will scan the $router.apps
array, and slice out the destroyed app reference.