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

Commit 48f384f

Browse files
fix(ngMessages): prevent memory leak from messages that are never attached
Closes #16389 Closes #16404
1 parent b86876c commit 48f384f

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

src/ngMessages/messages.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -417,13 +417,6 @@ angular.module('ngMessages', [], function initAngularHelpers() {
417417

418418
$scope.$watchCollection($attrs.ngMessages || $attrs['for'], ctrl.render);
419419

420-
// If the element is destroyed, proactively destroy all the currently visible messages
421-
$element.on('$destroy', function() {
422-
forEach(messages, function(item) {
423-
item.message.detach();
424-
});
425-
});
426-
427420
this.reRender = function() {
428421
if (!renderLater) {
429422
renderLater = true;
@@ -498,6 +491,9 @@ angular.module('ngMessages', [], function initAngularHelpers() {
498491
function removeMessageNode(parent, comment, key) {
499492
var messageNode = messages[key];
500493

494+
// This message node may have already been removed by a call to deregister()
495+
if (!messageNode) return;
496+
501497
var match = findPreviousMessage(parent, comment);
502498
if (match) {
503499
match.next = messageNode.next;
@@ -719,6 +715,10 @@ function ngMessageDirectiveFactory() {
719715
}
720716
}
721717
});
718+
719+
scope.$on('$destroy', function() {
720+
ngMessagesCtrl.deregister(commentNode);
721+
});
722722
}
723723
};
724724
}];

test/ngMessages/messagesSpec.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,27 @@ describe('ngMessages', function() {
636636
})
637637
);
638638

639+
it('should unregister the ngMessage even if it was never attached',
640+
inject(function($compile, $rootScope) {
641+
var html =
642+
'<div ng-messages="items">' +
643+
'<div ng-if="show"><div ng-message="x">ERROR</div></div>' +
644+
'</div>';
645+
646+
element = $compile(html)($rootScope);
647+
648+
var ctrl = element.controller('ngMessages');
649+
650+
$rootScope.$apply('show = true');
651+
expect(messageChildren(element).length).toBe(0);
652+
expect(Object.keys(ctrl.messages).length).toEqual(1);
653+
654+
$rootScope.$apply('show = false');
655+
expect(messageChildren(element).length).toBe(0);
656+
expect(Object.keys(ctrl.messages).length).toEqual(0);
657+
})
658+
);
659+
639660

640661
describe('when including templates', function() {
641662
they('should work with a dynamic collection model which is managed by ngRepeat',

0 commit comments

Comments
 (0)