diff --git a/src/ng/interpolate.js b/src/ng/interpolate.js index e03aa961..016fdfac 100644 --- a/src/ng/interpolate.js +++ b/src/ng/interpolate.js @@ -301,7 +301,7 @@ function $InterpolateProvider() { exp: text, //just for compatibility with regular watchers created via $watch separators: separators, expressions: expressions, - $$watchDelegate: function (scope, listener, objectEquality) { + $$watchDelegate: function (scope, listener, objectEquality, deregisterNotifier) { var lastValue; return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) { var currValue = compute(values); @@ -309,7 +309,7 @@ function $InterpolateProvider() { listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope); } lastValue = currValue; - }, objectEquality); + }, objectEquality, deregisterNotifier); } }); } diff --git a/src/ng/parse.js b/src/ng/parse.js index 11cf501d..bee17285 100644 --- a/src/ng/parse.js +++ b/src/ng/parse.js @@ -1035,7 +1035,7 @@ function $ParseProvider() { } }; - function oneTimeWatch(scope, listener, objectEquality, parsedExpression) { + function oneTimeWatch(scope, listener, objectEquality, deregisterNotifier, parsedExpression) { var unwatch, lastValue; return unwatch = scope.$watch(function oneTimeWatch(scope) { return parsedExpression(scope); @@ -1051,7 +1051,7 @@ function $ParseProvider() { } }); } - }, objectEquality); + }, objectEquality, deregisterNotifier); } function oneTimeLiteralWatch(scope, listener, objectEquality, parsedExpression) { @@ -1078,7 +1078,7 @@ function $ParseProvider() { } } - function constantWatch(scope, listener, objectEquality, parsedExpression) { + function constantWatch(scope, listener, objectEquality, deregisterNotifier, parsedExpression) { var unwatch; return unwatch = scope.$watch(function constantWatch(scope) { return parsedExpression(scope); @@ -1087,7 +1087,7 @@ function $ParseProvider() { listener.apply(this, arguments); } unwatch(); - }, objectEquality); + }, objectEquality, deregisterNotifier); } function addInterceptor(parsedExpression, interceptorFn) { diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js index 24b80a36..b92f96b4 100644 --- a/src/ng/rootScope.js +++ b/src/ng/rootScope.js @@ -322,13 +322,15 @@ function $RootScopeProvider(){ * - `scope` refers to the current scope * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of * comparing for reference equality. + * @param {function()=} deregisterNotifier Function to call when the deregistration function + * get called. * @returns {function()} Returns a deregistration function for this listener. */ - $watch: function(watchExp, listener, objectEquality) { + $watch: function(watchExp, listener, objectEquality, deregisterNotifier) { var get = compileToFn(watchExp, 'watch'); if (get.$$watchDelegate) { - return get.$$watchDelegate(this, listener, objectEquality, get); + return get.$$watchDelegate(this, listener, objectEquality, deregisterNotifier, get); } var scope = this, array = scope.$$watchers, @@ -356,6 +358,9 @@ function $RootScopeProvider(){ return function deregisterWatch() { arrayRemove(array, watcher); lastDirtyWatch = null; + if (isFunction(deregisterNotifier)) { + deregisterNotifier(); + } }; }, diff --git a/test/ng/rootScopeSpec.js b/test/ng/rootScopeSpec.js index f2f699a8..a6aa91ea 100644 --- a/test/ng/rootScopeSpec.js +++ b/test/ng/rootScopeSpec.js @@ -526,6 +526,34 @@ describe('Scope', function() { expect(log).toEqual(['watch1', 'watchAction1', 'watch2', 'watchAction2', 'watch3', 'watchAction3', 'watch2', 'watch3']); })); + + describe('deregisterNotifier', function () { + it('should call the deregisterNotifier when the watch is deregistered', inject( + function($rootScope) { + var notifier = jasmine.createSpy('deregisterNotifier'); + var listenerRemove = $rootScope.$watch('noop', noop, false, notifier); + + expect(notifier).not.toHaveBeenCalled(); + + listenerRemove(); + expect(notifier).toHaveBeenCalledOnce(); + })); + + + it('should call the deregisterNotifier when a one-time expression is stable', inject( + function($rootScope) { + var notifier = jasmine.createSpy('deregisterNotifier'); + $rootScope.$watch('::foo', noop, false, notifier); + + expect(notifier).not.toHaveBeenCalledOnce(); + $rootScope.$digest(); + expect(notifier).not.toHaveBeenCalledOnce(); + + $rootScope.foo = 'foo'; + $rootScope.$digest(); + expect(notifier).toHaveBeenCalledOnce(); + })); + }); });