Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit b99e74d

Browse files
neko1235ThomasBurleson
authored andcommitted
fix(virtualRepeat): Memory leak
Delete all created elements when the scope is destroyed. Move cleanup code to cleanupBlocks(). Do not clean up used blocks. Add unit tests. Closes #8055. Closes #8056.
1 parent e638c51 commit b99e74d

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

src/components/virtualRepeat/virtual-repeater.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,8 @@ function VirtualRepeatController($scope, $element, $attrs, $browser, $document,
501501
this.blocks = {};
502502
/** @type {Array<!VirtualRepeatController.Block>} A pool of presently unused blocks. */
503503
this.pooledBlocks = [];
504+
505+
$scope.$on('$destroy', angular.bind(this, this.cleanupBlocks_));
504506
}
505507

506508

@@ -536,6 +538,14 @@ VirtualRepeatController.prototype.link_ =
536538
};
537539

538540

541+
/** @private Cleans up unused blocks. */
542+
VirtualRepeatController.prototype.cleanupBlocks_ = function() {
543+
angular.forEach(this.pooledBlocks, function cleanupBlock(block) {
544+
block.element.remove();
545+
});
546+
};
547+
548+
539549
/** @private Attempts to set itemSize by measuring a repeated element in the dom */
540550
VirtualRepeatController.prototype.readItemSize_ = function() {
541551
if (this.itemSize) {

src/components/virtualRepeat/virtual-repeater.spec.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,27 @@ describe('<md-virtual-repeat>', function() {
658658
}));
659659
});
660660

661+
describe('when container scope is destroyed', function() {
662+
663+
it('should clean up unused blocks', function() {
664+
createRepeater();
665+
var containerCtrl = component.controller('mdVirtualRepeatContainer');
666+
scope.items = createItems(NUM_ITEMS);
667+
scope.$apply();
668+
669+
scope.items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
670+
scope.$apply();
671+
672+
scope.$destroy();
673+
674+
var dataCount = 0;
675+
angular.forEach(containerCtrl.repeater.pooledBlocks, function(block) {
676+
dataCount += Object.keys(block.element.data()).length;
677+
});
678+
expect(dataCount).toBe(0);
679+
});
680+
});
681+
661682
/**
662683
* Facade to access transform properly even when jQuery is used;
663684
* since jQuery's css function is obtaining the computed style (not wanted)

0 commit comments

Comments
 (0)