Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular directive memory leaks?

I'm using this simple html file to reproduce a memory leak I found:

<!doctype html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular.min.js"></script>
        <script>
            var app = angular.module('testApp', []);

            app.directive('directive1', function() {
                return {
                    template: '<div directive2></div>',
                    scope: true
                };
            });

            app.directive('directive2', function () {
                function LeakObject() {}

                function Foo() {
                    this.bar = function($scope) {
                            $scope.nottheredude;
                    };
                }

                return {
                    scope: true,
                    link: function($scope) {
                            $scope.memoryThatLeaks = new LeakObject();

                            new Foo().bar({});
                            new Foo().bar($scope);
                    }
                };
            });
        </script>
    </head>
    <body ng-app="testApp">
        <button ng-click="show = !show">Toggle</button>
        <div ng-if="show">The directive <div directive1></div></div>
        <div ng-if="!show">Nothing</div>
    </body>
</html>

I have a directive that only creates a new scope and has another directive in its template.

The other directive does something a bit strange (I tried to narrow down the problem to what's causing the leak and that's the shortest code I found that reproduces the issue).

In my main html, I just toggle between nothing and directive1 with a simple ng-if.

Notice that directive2 also creates a new object on the $scope called LeakObject. I expect this object to be garbage collected when I'm toggling back to the nothing div, since the scope of the directive should die and all the data on it with it, but according to Chrome's heap snapshot tool in incognito mode, it's not getting unallocated.

I'm trying to understand why that happens, and why, if I comment out the statement in the bar method, it doesn't happen.

Steps to reproduce:

  1. Open this file in incognito
  2. Open dev tools and go to Profiles
  3. Refresh the page
  4. Click Toggle twice (so now you see Nothing on the screen again)
  5. Take a heap snapshot
  6. Write 'leak' in the filter so you can see the LeakObject still exists when it shouldn't really exist.

This is how it should look like:

The problem

Can someone please help/explain?

like image 986
Barnash Avatar asked Dec 14 '14 07:12

Barnash


People also ask

How do you find memory leaks in angular 8?

The first thing to do is to open the Chrome Dev Tools, open the panel on the right and click on More Tools > Performance Monitor. The memory of our application is displayed in the blue graph.

What is a memory leak JavaScript?

What are memory leaks? In simple words, a memory leak is an allocated piece of memory that the JavaScript engine is unable to reclaim. The JavaScript engine allocates memory when you create objects and variables in your application, and it is smart enough to clear out the memory when you no longer need the objects.


1 Answers

Everything works as expected, after following your steps i don't see any leak objects in the snapshot.

you can add the following code to the link function to see that the directive is actually getting destroy

Controller and directives emit an event right before they are destroyed. This is where you are given the opportunity to tear down your plugins and listeners and pretty much perform garbage collection. Subscribe to the $scope.$on('$destroy', ...) event

$scope.$on('$destroy',function(){
  //$scope.memoryThatLeaks = null;
  alert('!');
 });
like image 121
Moran Helman Avatar answered Oct 15 '22 06:10

Moran Helman