There seems to be a memory leak in Angular version 1.3 through to 1.5.10 when using a directive to focus() an input element.
Plunker link: https://plnkr.co/edit/slltOvsFsddoaO7LJJ1z
Steps to reproduce:
1) Download the code as a zip file (running inside of Plunker seems to obscure the issue)
2) Open up the index.html file and in Chrome dev tools and go to Timeline
3) Start Timeline recording and then press "Hello" on the webpage. Wait for the page to cycle 200 iterations (about 20 seconds) of reloading the controller (and leak the nodes)
4) Press the Garbage Collection icon at the top of the Timeline, and stop recording. When viewing the node count graph you will see that we started with roughly 100 nodes, and end up with around 1600.
Counter example where the issue doesn't happen:
1) Modify the if statement in helloworld.js inside the 'persistentFocus' directive, so that the directive code doesn't run. Run the above 4 steps and see that we start with roughly 100 nodes, and finish with roughly 100 nodes.
I am able to reproduce this on
Linux Chrome Version 55.0.2883.87 (64-bit)
and
OS X Chrome Version 55.0.2883.95 (64-bit)
There seems to be a memory leak in Angular version 1.3 through to 1.5.10
Does this mean that the issue is gone in later versions (e.g. 1.6.1)?
@gkalpak - i haven't tested on 1.6.x yet
Is the leak related to ui.router? If not, can you create a reproduction that is not including unnecessary dependencies, so it is easier to pinpoint the problem?
I can reproduce the problem by stripping out ui.router and replacing with ngRoute. Here is a fork:
https://plnkr.co/edit/WKjwKoaR9QzSRtByTGKT?p=info
I am simply using these routers so I can simulate switching between controllers rapidly and exacerbating the leak. If you know of a better way to reloading the controller + template let me know.
FWIW, I'm wondering if this is a bug in Chrome's Devtools or a quirk of the Timeline view. I don't see actual memory usage drastically increasing here, and both the Heap Allocation view and the classic 3 Heap Snapshot method in the Profile tab do not show any leaks or detached/orphaned nodes.
@dcherman It's possible it's a Chrome issue - but I believe that it's not a minor quirk since I can see the tab memory usage steadily increasing in the Chrome Task Manager (try doing more than 200 iterations).
We originally had this problem in a very large application, and there I was able to increase the memory usage by over 500MB by continuously reloading the controller - here the problem is less pronounced due to how small the example page is, but I can still increase the tab memory usage from 25MB -> 50MB by doing 100,000 iterations of reloading the controller.
Can you see the memory increase in the system task manager, too? Or for other browsers?
Cannot reproduce in Firefox. I am using a rather crude method of viewing the tab's memory footprint since Firefox doesn't appear to have a memory profiler.
Firefox does have a memory profiler: https://developer.mozilla.org/en-US/docs/Tools/Memory.
I've taken snapshots before and after the controller switch, and I can't find an increase in nodes. I can see a small increase in memory, but it doesn't look like it's related to nodes. It might be fluctuation caused by something else. I've also included a version that uses ngIf to switch and it looks about the same: https://plnkr.co/edit/WidOeMR8Cf44Q8MH8j2m?p=preview
There's also no difference between focused / unfocused.
For the time being, I'm gonna close this as we cannot reproduce an explicit leak. Feel free to reopen if you can provide a new demo.
@Narretz I encountered this issue too, with button element, using AngularJS v1.5.6. I tested it in my app, and got DOM nodes leaking on focus on and
@sharonvardi, can you please open a new issue about this?
Sorry. It's not a bug in Angular. I reproduced it also when using native JavaScript only. Looks like a bug in Chrome?
FYI: started a task in the Chrome DevTools tracker https://bugs.chromium.org/p/chromium/issues/detail?id=866872
Most helpful comment
Sorry. It's not a bug in Angular. I reproduced it also when using native JavaScript only. Looks like a bug in Chrome?