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 {
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;
function destroyChild() {
child.$$destroyed = true;
}
},
/**

View File

@@ -4971,17 +4971,17 @@ describe('$compile', function() {
return [$rootScope].concat(
getChildScopes($rootScope)
).length;
}
function getChildScopes(scope) {
var children = [];
if (!scope.$$childHead) { return children; }
var childScope = scope.$$childHead;
do {
children.push(childScope);
children = children.concat(getChildScopes(childScope));
} while ((childScope = childScope.$$nextSibling));
return children;
}
function getChildScopes(scope) {
var children = [];
if (!scope.$$childHead) { return children; }
var childScope = scope.$$childHead;
do {
children.push(childScope);
children = children.concat(getChildScopes(childScope));
} while ((childScope = childScope.$$nextSibling));
return children;
}
beforeEach(module(function() {
@@ -5117,6 +5117,23 @@ describe('$compile', function() {
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');
}));
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) {
var EVENT = 'fooEvent',