Using a simple html file to replicate a memory leak:
<!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>
Directive creating a new scope with another directive in its template.
Another directive performing a strange action, identified as the cause of the leak.
Main HTML toggling between nothing and directive1
.
The created object on $scope
, LeakObject
, should be garbage collected when toggling back to nothing but remains allocated according to Chrome's heap snapshot tool.
Attempting to understand why this occurs, especially when commenting out the statement in the bar
method prevents it.
Steps to reproduce:
- Open this file in incognito
- Open dev tools and navigate to Profiles
- Refresh the page
- Click
Toggle
twice to displayNothing
- Take a heap snapshot
- Filter for 'leak' to observe the persisting
LeakObject
This is how it should look like:
If anyone can assist or provide an explanation, it would be greatly appreciated.