Skip to content

Commit 7f63e81

Browse files
test($compile): check no memory leak with coexisting element transcludes
If an element contains two "element" transcludes then the initial clone consists of only comment nodes. The concern was that this meant that the transclude scopes would not be cleaned up. But it turns out that in the case that there are only comments then the scope is never attached to anything so we don't need to worry about cleaning it up. Later if a concrete element is created as part of the transclude then these elements will have destroy handlers.
1 parent cb43711 commit 7f63e81

1 file changed

Lines changed: 60 additions & 0 deletions

File tree

test/ng/compileSpec.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3928,6 +3928,66 @@ describe('$compile', function() {
39283928
});
39293929

39303930

3931+
3932+
it('should not leak if two "element" transclusions are on the same element', function() {
3933+
var calcCacheSize = function() {
3934+
var size = 0;
3935+
forEach(jqLite.cache, function(item, key) { size++; });
3936+
return size;
3937+
};
3938+
3939+
inject(function($compile, $rootScope) {
3940+
expect(calcCacheSize()).toEqual(0);
3941+
3942+
element = $compile('<div><div ng-repeat="x in xs" ng-if="x==1">{{x}}</div></div>')($rootScope);
3943+
expect(calcCacheSize()).toEqual(1);
3944+
3945+
$rootScope.$apply('xs = [0,1]');
3946+
expect(calcCacheSize()).toEqual(2);
3947+
3948+
$rootScope.$apply('xs = [0]');
3949+
expect(calcCacheSize()).toEqual(1);
3950+
3951+
$rootScope.$apply('xs = []');
3952+
expect(calcCacheSize()).toEqual(1);
3953+
3954+
element.remove();
3955+
expect(calcCacheSize()).toEqual(0);
3956+
});
3957+
});
3958+
3959+
3960+
it('should not leak if two "element" transclusions are on the same element', function() {
3961+
var calcCacheSize = function() {
3962+
var size = 0;
3963+
forEach(jqLite.cache, function(item, key) { size++; });
3964+
return size;
3965+
};
3966+
inject(function($compile, $rootScope) {
3967+
expect(calcCacheSize()).toEqual(0);
3968+
element = $compile('<div><div ng-repeat="x in xs" ng-if="val">{{x}}</div></div>')($rootScope);
3969+
3970+
$rootScope.$apply('xs = [0,1]');
3971+
// At this point we have a bunch of comment placeholders but no real transcluded elements
3972+
// So the cache only contains the root element's data
3973+
expect(calcCacheSize()).toEqual(1);
3974+
3975+
$rootScope.$apply('val = true');
3976+
// Now we have two concrete transcluded elements plus some comments so two more cache items
3977+
expect(calcCacheSize()).toEqual(3);
3978+
3979+
$rootScope.$apply('val = false');
3980+
// Once again we only have comments so no transcluded elements and the cache is back to just
3981+
// the root element
3982+
expect(calcCacheSize()).toEqual(1);
3983+
3984+
element.remove();
3985+
// Now we've even removed the root element along with its cache
3986+
expect(calcCacheSize()).toEqual(0);
3987+
});
3988+
});
3989+
3990+
39313991
it('should remove transclusion scope, when the DOM is destroyed', function() {
39323992
module(function() {
39333993
directive('box', valueFn({

0 commit comments

Comments
 (0)