diff options
| author | Karl Seamon | 2013-12-10 17:50:30 -0500 |
|---|---|---|
| committer | Igor Minar | 2013-12-27 23:31:00 -0800 |
| commit | 80e7a4558490f7ffd33d142844b9153a5ed00e86 (patch) | |
| tree | a697bc0c7a440a86084dc1024f917ced98986066 /test/ng | |
| parent | 498365f219f65d6c29bdf2f03610a4d3646009bb (diff) | |
| download | angular.js-80e7a4558490f7ffd33d142844b9153a5ed00e86.tar.bz2 | |
perf(Scope): limit propagation of $broadcast to scopes that have listeners for the event
Update $on and $destroy to maintain a count of event keys registered for each scope and its children.
$broadcast will not descend past a node that has a count of 0/undefined for the $broadcasted event key.
Closes #5341
Closes #5371
Diffstat (limited to 'test/ng')
| -rw-r--r-- | test/ng/rootScopeSpec.js | 126 |
1 files changed, 107 insertions, 19 deletions
diff --git a/test/ng/rootScopeSpec.js b/test/ng/rootScopeSpec.js index cc6727c2..3677ccc8 100644 --- a/test/ng/rootScopeSpec.js +++ b/test/ng/rootScopeSpec.js @@ -730,6 +730,28 @@ describe('Scope', function() { first.$apply(); expect(log).toBe('1232323'); })); + + + it('should decrement anscestor $$listenerCount entries', inject(function($rootScope) { + var EVENT = 'fooEvent', + spy = jasmine.createSpy('listener'), + firstSecond = first.$new(); + + firstSecond.$on(EVENT, spy); + firstSecond.$on(EVENT, spy); + middle.$on(EVENT, spy); + + expect($rootScope.$$listenerCount[EVENT]).toBe(3); + expect(first.$$listenerCount[EVENT]).toBe(2); + + firstSecond.$destroy(); + + expect($rootScope.$$listenerCount[EVENT]).toBe(1); + expect(first.$$listenerCount[EVENT]).toBeUndefined(); + + $rootScope.$broadcast(EVENT); + expect(spy.callCount).toBe(1); + })); }); @@ -1091,29 +1113,78 @@ describe('Scope', function() { })); - it('should return a function that deregisters the listener', inject(function($rootScope) { - var log = '', - child = $rootScope.$new(), - listenerRemove; - - function eventFn() { - log += 'X'; - } + it('should increment ancestor $$listenerCount entries', inject(function($rootScope) { + var child1 = $rootScope.$new(), + child2 = child1.$new(), + spy = jasmine.createSpy(); - listenerRemove = child.$on('abc', eventFn); - expect(log).toEqual(''); - expect(listenerRemove).toBeDefined(); + $rootScope.$on('event1', spy); + expect($rootScope.$$listenerCount).toEqual({event1: 1}); - child.$emit('abc'); - child.$broadcast('abc'); - expect(log).toEqual('XX'); + child1.$on('event1', spy); + expect($rootScope.$$listenerCount).toEqual({event1: 2}); + expect(child1.$$listenerCount).toEqual({event1: 1}); - log = ''; - listenerRemove(); - child.$emit('abc'); - child.$broadcast('abc'); - expect(log).toEqual(''); + child2.$on('event2', spy); + expect($rootScope.$$listenerCount).toEqual({event1: 2, event2: 1}); + expect(child1.$$listenerCount).toEqual({event1: 1, event2: 1}); + expect(child2.$$listenerCount).toEqual({event2: 1}); })); + + + describe('deregistration', function() { + + it('should return a function that deregisters the listener', inject(function($rootScope) { + var log = '', + child = $rootScope.$new(), + listenerRemove; + + function eventFn() { + log += 'X'; + } + + listenerRemove = child.$on('abc', eventFn); + expect(log).toEqual(''); + expect(listenerRemove).toBeDefined(); + + child.$emit('abc'); + child.$broadcast('abc'); + expect(log).toEqual('XX'); + expect($rootScope.$$listenerCount['abc']).toBe(1); + + log = ''; + listenerRemove(); + child.$emit('abc'); + child.$broadcast('abc'); + expect(log).toEqual(''); + expect($rootScope.$$listenerCount['abc']).toBeUndefined(); + })); + + + it('should decrement ancestor $$listenerCount entries', inject(function($rootScope) { + var child1 = $rootScope.$new(), + child2 = child1.$new(), + spy = jasmine.createSpy(); + + $rootScope.$on('event1', spy); + expect($rootScope.$$listenerCount).toEqual({event1: 1}); + + child1.$on('event1', spy); + expect($rootScope.$$listenerCount).toEqual({event1: 2}); + expect(child1.$$listenerCount).toEqual({event1: 1}); + + var deregisterEvent2Listener = child2.$on('event2', spy); + expect($rootScope.$$listenerCount).toEqual({event1: 2, event2: 1}); + expect(child1.$$listenerCount).toEqual({event1: 1, event2: 1}); + expect(child2.$$listenerCount).toEqual({event2: 1}); + + deregisterEvent2Listener(); + + expect($rootScope.$$listenerCount).toEqual({event1: 2}); + expect(child1.$$listenerCount).toEqual({event1: 1}); + expect(child2.$$listenerCount).toEqual({}); + })) + }); }); @@ -1360,6 +1431,23 @@ describe('Scope', function() { })); + it('should not descend past scopes with a $$listerCount of 0 or undefined', + inject(function($rootScope) { + var EVENT = 'fooEvent', + spy = jasmine.createSpy('listener'); + + // Precondition: There should be no listeners for fooEvent. + expect($rootScope.$$listenerCount[EVENT]).toBeUndefined(); + + // Add a spy listener to a child scope. + $rootScope.$$childHead.$$listeners[EVENT] = [spy]; + + // $rootScope's count for 'fooEvent' is undefined, so spy should not be called. + $rootScope.$broadcast(EVENT); + expect(spy).not.toHaveBeenCalled(); + })); + + it('should return event object', function() { var result = child1.$broadcast('some'); |
