Which @angular/* package(s) are the source of the bug?
zone.js
Is this a regression?
Yes
Description
Our application is using [email protected] outside of Angular, as a dependency of OpenTelemetry.
In our application we noticed memory leaks involving large subtrees of detached HTMLElements after updating to [email protected]. Version 0.14.2 does not have an issue.
The issue seems to be related to the fact that zone.js registers an "abort" handler on the AbortSignal object passed in to the addEventListener() call and the callback it is registering captures the task in its scope. This handler is as far as I can tell never removed off the AbortSignal object.
https://github.com/angular/angular/blob/zone.js-0.14.3/packages/zone.js/lib/common/events.ts#L488
The big issue I see with the current implementation is that zone.js has no clue what the lifetime and ownership model is for the AbortSignal object in question or the element that is captured in the task within the callback that is never removed.
In our particular case the detached HTMLElement captured within the task is part of a larger subtree that gets removed/detached. The signal itself is owned by some code associated with an ancestor element that out-lives the subtree that is removed, so as long as that listener callback is alive, so is the task, the element it captures, and any other elements in the detached subtree the element is still referencing via parentNode, next/prevSibling, etc.
Also, we can't assume that this "abort" listener will be removed via a corresponding element's removeEventListener() call because there may never be a removeEventListener() call made ... and in most circumstances when a subtree of elements is detached, this would be ok and things would garbage collect just fine.
The issue can be observed with this simple test case:
addeventlistener-signal-bug.txt
If you load the test case into Chrome:
- Press the remove button in the test case
- Open the Web Inspector Memory Panel
- Hit the Garbage Collect button
- Trigger a Heap Snapshot
In the resulting Heap Snapshot you will notice that there are detached HTMLDiv, HTMLButton, HTMLUL, and HTMLLI elements listed.
If you remove the include of zone.js from the test case, and then repeat the steps above, you will see that the elements mentioned above are no longer listed in the Heap Snapshot, meaning they were garbage collected properly.
Please provide a link to a minimal reproduction of the bug
No response
Please provide the exception or error you saw
No response
Please provide the environment you discovered this bug in (run ng version)
No response
Anything else?
No response
Which @angular/* package(s) are the source of the bug?
zone.js
Is this a regression?
Yes
Description
Our application is using [email protected] outside of Angular, as a dependency of OpenTelemetry.
In our application we noticed memory leaks involving large subtrees of detached HTMLElements after updating to [email protected]. Version 0.14.2 does not have an issue.
The issue seems to be related to the fact that zone.js registers an "abort" handler on the AbortSignal object passed in to the addEventListener() call and the callback it is registering captures the task in its scope. This handler is as far as I can tell never removed off the AbortSignal object.
https://github.com/angular/angular/blob/zone.js-0.14.3/packages/zone.js/lib/common/events.ts#L488
The big issue I see with the current implementation is that zone.js has no clue what the lifetime and ownership model is for the AbortSignal object in question or the element that is captured in the task within the callback that is never removed.
In our particular case the detached HTMLElement captured within the task is part of a larger subtree that gets removed/detached. The signal itself is owned by some code associated with an ancestor element that out-lives the subtree that is removed, so as long as that listener callback is alive, so is the task, the element it captures, and any other elements in the detached subtree the element is still referencing via parentNode, next/prevSibling, etc.
Also, we can't assume that this "abort" listener will be removed via a corresponding element's removeEventListener() call because there may never be a removeEventListener() call made ... and in most circumstances when a subtree of elements is detached, this would be ok and things would garbage collect just fine.
The issue can be observed with this simple test case:
addeventlistener-signal-bug.txt
If you load the test case into Chrome:
In the resulting Heap Snapshot you will notice that there are detached HTMLDiv, HTMLButton, HTMLUL, and HTMLLI elements listed.
If you remove the include of zone.js from the test case, and then repeat the steps above, you will see that the elements mentioned above are no longer listed in the Heap Snapshot, meaning they were garbage collected properly.
Please provide a link to a minimal reproduction of the bug
No response
Please provide the exception or error you saw
No response
Please provide the environment you discovered this bug in (run
ng version)No response
Anything else?
No response