fix(Scope): don't let watch deregistration mess up the dirty-checking digest loop

Closes #5525
This commit is contained in:
Igor Minar 2014-01-02 14:39:24 -08:00
parent 010413f90a
commit 884ef0dbcd
2 changed files with 48 additions and 0 deletions

View file

@ -353,6 +353,7 @@ function $RootScopeProvider(){
return function() {
arrayRemove(array, watcher);
lastDirtyWatch = null;
};
},

View file

@ -405,6 +405,53 @@ describe('Scope', function() {
$rootScope.$apply('remove = true');
}).not.toThrow();
}));
it('should not mess up the digest loop if deregistration happens during digest', inject(
function($rootScope, log) {
// we are testing this due to regression #5525 which is related to how the digest loops lastDirtyWatch
// short-circuiting optimization works
// scenario: watch1 deregistering watch1
var scope = $rootScope.$new();
var deregWatch1 = scope.$watch(log.fn('watch1'), function() { deregWatch1(); log('watchAction1'); });
scope.$watch(log.fn('watch2'), log.fn('watchAction2'));
scope.$watch(log.fn('watch3'), log.fn('watchAction3'));
$rootScope.$digest();
expect(log).toEqual(['watch1', 'watchAction1', 'watch2', 'watchAction2', 'watch3', 'watchAction3',
'watch2', 'watch3']);
scope.$destroy();
log.reset();
// scenario: watch1 deregistering watch2
scope = $rootScope.$new();
scope.$watch(log.fn('watch1'), function() { deregWatch2(); log('watchAction1'); });
var deregWatch2 = scope.$watch(log.fn('watch2'), log.fn('watchAction2'));
scope.$watch(log.fn('watch3'), log.fn('watchAction3'));
$rootScope.$digest();
expect(log).toEqual(['watch1', 'watchAction1', 'watch1', 'watch3', 'watchAction3',
'watch1', 'watch3']);
scope.$destroy();
log.reset();
// scenario: watch2 deregistering watch1
scope = $rootScope.$new();
deregWatch1 = scope.$watch(log.fn('watch1'), log.fn('watchAction1'));
scope.$watch(log.fn('watch2'), function() { deregWatch1(); log('watchAction2'); });
scope.$watch(log.fn('watch3'), log.fn('watchAction3'));
$rootScope.$digest();
expect(log).toEqual(['watch1', 'watchAction1', 'watch2', 'watchAction2', 'watch3', 'watchAction3',
'watch2', 'watch3']);
}));
});