You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Wait for 2s until only one 'my-test' heading remains
Make heap snapshot
What is expected?
There should be 1 instances of IAmStillThere
What is actually happening?
There are 2 instances of IAmStillThere rather than 1
The removed item's instance and full scope (IAmStillThere) is still in memory, because it is retained by the instance.
Open the memory profiler and create a snapshot. Search for IAmStillThere. Observe that there are 2 rather than 1. Observe that the top one (which belongs to key "2") should not be there as it was removed.
The top IAmStillThere is retained because the handler was attached to the vnode as a prop. This vnode is retained because it was the anchor which was passed over to setupRenderEffect for the initial patch only of the component with key "1".
Later on, as "2" is removed, the anchor will remain in the scope of instance.update of "1". So the HTMLElement will leak, and become detached (search for 'Detached HTMLHeadingElement' in the snapshot).
The background of the problem is that setupRenderEffect servers two separate purposes: Mounting and updating. A big if-else statement distinguishes between the two. During mounting, anchor is used to invoke the patch. Anchor is never used while updating (and better so, as it is only valid within the current patch tree state). Even though it will never be used again, it will still stay in the scope of instance.update, which causes it to cling on to things that it shouldn't cling on to.
In my own use case, an advanced scroller, when scrolling up this bug caused all previously visible rows to stay in memory, building up to a major leak.
The solution for this specific case is actually quite simple: dereference immediately after mounting by setting to null.
Let's also do this for initialVNode and container. I don't have an example of how this can go wrong, but I suspect that it can go wrong in edge cases (teleports?). In any way, it's never a bad idea to clean up after yourself ASAP ;-)
The text was updated successfully, but these errors were encountered:
Version
3.0.2
Reproduction link
https://codepen.io/basvanmeurs/full/dyXpPJY
Steps to reproduce
What is expected?
There should be 1 instances of
IAmStillThere
What is actually happening?
There are 2 instances of
IAmStillThere
rather than 1The removed item's instance and full scope (
IAmStillThere
) is still in memory, because it is retained by the instance.Open the memory profiler and create a snapshot. Search for
IAmStillThere
. Observe that there are 2 rather than 1. Observe that the top one (which belongs to key "2") should not be there as it was removed.The top
IAmStillThere
is retained because the handler was attached to the vnode as a prop. This vnode is retained because it was theanchor
which was passed over tosetupRenderEffect
for the initial patch only of the component with key "1".Later on, as "2" is removed, the anchor will remain in the scope of instance.update of "1". So the HTMLElement will leak, and become detached (search for 'Detached HTMLHeadingElement' in the snapshot).
The background of the problem is that setupRenderEffect servers two separate purposes: Mounting and updating. A big if-else statement distinguishes between the two. During mounting, anchor is used to invoke the patch. Anchor is never used while updating (and better so, as it is only valid within the current patch tree state). Even though it will never be used again, it will still stay in the scope of instance.update, which causes it to cling on to things that it shouldn't cling on to.
In my own use case, an advanced scroller, when scrolling up this bug caused all previously visible rows to stay in memory, building up to a major leak.
The solution for this specific case is actually quite simple: dereference immediately after mounting by setting to null.
Let's also do this for
initialVNode
andcontainer
. I don't have an example of how this can go wrong, but I suspect that it can go wrong in edge cases (teleports?). In any way, it's never a bad idea to clean up after yourself ASAP ;-)The text was updated successfully, but these errors were encountered: