fix(scope): watches can be safely unregistered inside watch handlers

Closes #2915
This commit is contained in:
Paulo Scardine 2013-06-09 23:16:26 -03:00 committed by Pete Bacon Darwin
parent 93d7e60d43
commit a4ec297925
2 changed files with 25 additions and 1 deletions

View file

@ -393,7 +393,7 @@ function $RootScopeProvider(){
watch = watchers[length];
// Most common watches are on primitives, in which case we can short
// circuit it with === operator, only when === fails do we use .equals
if ((value = watch.get(current)) !== (last = watch.last) &&
if (watch && (value = watch.get(current)) !== (last = watch.last) &&
!(watch.eq
? equals(value, last)
: (typeof value == 'number' && typeof last == 'number'

View file

@ -318,6 +318,30 @@ describe('Scope', function() {
expect(listener).not.toHaveBeenCalled();
}));
it('should allow a watch to be unregistered while in a digest', inject(function($rootScope) {
var remove1, remove2;
$rootScope.$watch('remove', function() {
remove1();
remove2();
});
remove1 = $rootScope.$watch('thing', function() {});
remove2 = $rootScope.$watch('thing', function() {});
expect(function() {
$rootScope.$apply('remove = true');
}).not.toThrow();
}));
it('should allow a watch to be added while in a digest', inject(function($rootScope) {
var watch1 = jasmine.createSpy('watch1'),
watch2 = jasmine.createSpy('watch2');
$rootScope.$watch('foo', function() {
$rootScope.$watch('foo', watch1);
$rootScope.$watch('foo', watch2);
});
$rootScope.$apply('foo = true');
expect(watch1).toHaveBeenCalled();
expect(watch2).toHaveBeenCalled();
}));
it('should not infinitely digest when current value is NaN', inject(function($rootScope) {
$rootScope.$watch(function() { return NaN;});