refactor($scope): prevent multiple calls to listener on $destroy

Prevent isolated scopes from having listeners that get called
multiple times when on `$destroy`
This commit is contained in:
Lucas Galfaso
2014-09-14 18:47:37 +02:00
committed by Peter Bacon Darwin
parent 86d33c5f9d
commit cd2cfafcab
3 changed files with 42 additions and 10 deletions

View File

@@ -222,7 +222,15 @@ function $RootScopeProvider(){
} else { } else {
parent.$$childHead = parent.$$childTail = child; parent.$$childHead = parent.$$childTail = child;
} }
// The listener needs to be added after the parent is set
if (isolate || parent != this) child.$on('$destroy', destroyChild);
return child; return child;
function destroyChild() {
child.$$destroyed = true;
}
}, },
/** /**

View File

@@ -4971,17 +4971,17 @@ describe('$compile', function() {
return [$rootScope].concat( return [$rootScope].concat(
getChildScopes($rootScope) getChildScopes($rootScope)
).length; ).length;
}
function getChildScopes(scope) { function getChildScopes(scope) {
var children = []; var children = [];
if (!scope.$$childHead) { return children; } if (!scope.$$childHead) { return children; }
var childScope = scope.$$childHead; var childScope = scope.$$childHead;
do { do {
children.push(childScope); children.push(childScope);
children = children.concat(getChildScopes(childScope)); children = children.concat(getChildScopes(childScope));
} while ((childScope = childScope.$$nextSibling)); } while ((childScope = childScope.$$nextSibling));
return children; return children;
}
} }
beforeEach(module(function() { beforeEach(module(function() {
@@ -5117,6 +5117,23 @@ describe('$compile', function() {
expect(countScopes($rootScope)).toEqual(1); expect(countScopes($rootScope)).toEqual(1);
})); }));
it('should destroy mark as destroyed all sub scopes of the scope being destroyed',
inject(function($compile, $rootScope) {
element = $compile(
'<div toggle>' +
'<div ng:repeat="msg in [\'msg-1\']">{{ msg }}</div>' +
'</div>'
)($rootScope);
$rootScope.$apply('t = true');
var childScopes = getChildScopes($rootScope);
$rootScope.$apply('t = false');
for (var i = 0; i < childScopes.length; ++i) {
expect(childScopes[i].$$destroyed).toBe(true);
}
}));
}); });

View File

@@ -1020,6 +1020,13 @@ describe('Scope', function() {
expect(log).toBe('123'); expect(log).toBe('123');
})); }));
it('should broadcast the $destroy only once', inject(function($rootScope, log) {
var isolateScope = first.$new(true);
isolateScope.$on('$destroy', log.fn('event'));
first.$destroy();
isolateScope.$destroy();
expect(log).toEqual('event');
}));
it('should decrement ancestor $$listenerCount entries', inject(function($rootScope) { it('should decrement ancestor $$listenerCount entries', inject(function($rootScope) {
var EVENT = 'fooEvent', var EVENT = 'fooEvent',