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:
Toggle
twice (so now you see Nothing
on the screen again)LeakObject
still exists when it shouldn't really exist.This is how it should look like:
Can someone please help/explain?
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 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.
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('!');
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With