diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js index 71a82dcda547..ba08e5d80eaf 100644 --- a/src/ng/rootScope.js +++ b/src/ng/rootScope.js @@ -866,13 +866,12 @@ function $RootScopeProvider() { * clean up DOM bindings before an element is removed from the DOM. */ $destroy: function() { - // we can't destroy the root scope or a scope that has been already destroyed + // We can't destroy a scope that has been already destroyed. if (this.$$destroyed) return; var parent = this.$parent; this.$broadcast('$destroy'); this.$$destroyed = true; - if (this === $rootScope) return; incrementWatchersCount(this, -this.$$watchersCount); for (var eventName in this.$$listenerCount) { @@ -881,8 +880,8 @@ function $RootScopeProvider() { // sever all the references to parent scopes (after this cleanup, the current scope should // not be retained by any of our references and should be eligible for garbage collection) - if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; - if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; + if (parent && parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; + if (parent && parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; diff --git a/test/ng/rootScopeSpec.js b/test/ng/rootScopeSpec.js index 75fb3232536c..7e145826538b 100644 --- a/test/ng/rootScopeSpec.js +++ b/test/ng/rootScopeSpec.js @@ -1021,16 +1021,33 @@ describe('Scope', function() { it('should broadcast $destroy on rootScope', inject(function($rootScope) { - var spy = spyOn(angular, 'noop'); - $rootScope.$on('$destroy', angular.noop); + var spy = jasmine.createSpy('$destroy handler'); + $rootScope.$on('$destroy', spy); $rootScope.$destroy(); - $rootScope.$digest(); - expect(log).toEqual('123'); expect(spy).toHaveBeenCalled(); expect($rootScope.$$destroyed).toBe(true); })); + it('should remove all listeners after $destroy of rootScope', inject(function($rootScope) { + var spy = jasmine.createSpy('$destroy handler'); + $rootScope.$on('dummy', spy); + $rootScope.$destroy(); + $rootScope.$broadcast('dummy'); + expect(spy).not.toHaveBeenCalled(); + })); + + + it('should remove all watchers after $destroy of rootScope', inject(function($rootScope) { + var spy = jasmine.createSpy('$watch spy'); + var digest = $rootScope.$digest; + $rootScope.$watch(spy); + $rootScope.$destroy(); + digest.call($rootScope); + expect(spy).not.toHaveBeenCalled(); + })); + + it('should remove first', inject(function($rootScope) { first.$destroy(); $rootScope.$digest();