@@ -2316,6 +2316,19 @@ describe('Scope', function() {
23162316 } ) ) ;
23172317
23182318
2319+ // See issue https://github.com/angular/angular.js/issues/16135
2320+ it ( 'should deallocate the listener array entry' , inject ( function ( $rootScope ) {
2321+ var remove1 = $rootScope . $on ( 'abc' , noop ) ;
2322+ $rootScope . $on ( 'abc' , noop ) ;
2323+
2324+ expect ( $rootScope . $$listeners [ 'abc' ] . length ) . toBe ( 2 ) ;
2325+
2326+ remove1 ( ) ;
2327+
2328+ expect ( $rootScope . $$listeners [ 'abc' ] . length ) . toBe ( 1 ) ;
2329+ } ) ) ;
2330+
2331+
23192332 it ( 'should call next listener after removing the current listener via its own handler' , inject ( function ( $rootScope ) {
23202333 var listener1 = jasmine . createSpy ( 'listener1' ) . and . callFake ( function ( ) { remove1 ( ) ; } ) ;
23212334 var remove1 = $rootScope . $on ( 'abc' , listener1 ) ;
@@ -2448,6 +2461,107 @@ describe('Scope', function() {
24482461 expect ( $rootScope . $$listenerCount ) . toEqual ( { abc : 1 } ) ;
24492462 expect ( child . $$listenerCount ) . toEqual ( { abc : 1 } ) ;
24502463 } ) ) ;
2464+
2465+
2466+ it ( 'should throw on recursive $broadcast' , inject ( function ( $rootScope ) {
2467+ $rootScope . $on ( 'e' , function ( ) { $rootScope . $broadcast ( 'e' ) ; } ) ;
2468+
2469+ expect ( function ( ) { $rootScope . $emit ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (1)' ) ;
2470+ expect ( function ( ) { $rootScope . $broadcast ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (1)' ) ;
2471+ } ) ) ;
2472+
2473+
2474+ it ( 'should throw on nested recursive $broadcast' , inject ( function ( $rootScope ) {
2475+ $rootScope . $on ( 'e2' , function ( ) { $rootScope . $broadcast ( 'e' ) ; } ) ;
2476+ $rootScope . $on ( 'e' , function ( ) { $rootScope . $broadcast ( 'e2' ) ; } ) ;
2477+
2478+ expect ( function ( ) { $rootScope . $emit ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (1)' ) ;
2479+ expect ( function ( ) { $rootScope . $broadcast ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (1)' ) ;
2480+ } ) ) ;
2481+
2482+
2483+ it ( 'should throw on recursive $emit' , inject ( function ( $rootScope ) {
2484+ $rootScope . $on ( 'e' , function ( ) { $rootScope . $emit ( 'e' ) ; } ) ;
2485+
2486+ expect ( function ( ) { $rootScope . $emit ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (1)' ) ;
2487+ expect ( function ( ) { $rootScope . $broadcast ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (1)' ) ;
2488+ } ) ) ;
2489+
2490+
2491+ it ( 'should throw on nested recursive $emit' , inject ( function ( $rootScope ) {
2492+ $rootScope . $on ( 'e2' , function ( ) { $rootScope . $emit ( 'e' ) ; } ) ;
2493+ $rootScope . $on ( 'e' , function ( ) { $rootScope . $emit ( 'e2' ) ; } ) ;
2494+
2495+ expect ( function ( ) { $rootScope . $emit ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (1)' ) ;
2496+ expect ( function ( ) { $rootScope . $broadcast ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (1)' ) ;
2497+ } ) ) ;
2498+
2499+
2500+ it ( 'should throw on recursive $broadcast on child listener' , inject ( function ( $rootScope ) {
2501+ var child = $rootScope . $new ( ) ;
2502+ child . $on ( 'e' , function ( ) { $rootScope . $broadcast ( 'e' ) ; } ) ;
2503+
2504+ expect ( function ( ) { child . $emit ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (2)' ) ;
2505+ expect ( function ( ) { child . $broadcast ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (2)' ) ;
2506+ } ) ) ;
2507+
2508+
2509+ it ( 'should throw on nested recursive $broadcast on child listener' , inject ( function ( $rootScope ) {
2510+ var child = $rootScope . $new ( ) ;
2511+ child . $on ( 'e2' , function ( ) { $rootScope . $broadcast ( 'e' ) ; } ) ;
2512+ child . $on ( 'e' , function ( ) { $rootScope . $broadcast ( 'e2' ) ; } ) ;
2513+
2514+ expect ( function ( ) { child . $emit ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (2)' ) ;
2515+ expect ( function ( ) { child . $broadcast ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (2)' ) ;
2516+ } ) ) ;
2517+
2518+
2519+ it ( 'should throw on recursive $emit parent listener' , inject ( function ( $rootScope ) {
2520+ var child = $rootScope . $new ( ) ;
2521+ $rootScope . $on ( 'e' , function ( ) { child . $emit ( 'e' ) ; } ) ;
2522+
2523+ expect ( function ( ) { child . $emit ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (1)' ) ;
2524+ expect ( function ( ) { $rootScope . $emit ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (1)' ) ;
2525+ expect ( function ( ) { $rootScope . $broadcast ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (1)' ) ;
2526+ } ) ) ;
2527+
2528+
2529+ it ( 'should throw on nested recursive $emit parent listener' , inject ( function ( $rootScope ) {
2530+ var child = $rootScope . $new ( ) ;
2531+ $rootScope . $on ( 'e2' , function ( ) { child . $emit ( 'e' ) ; } ) ;
2532+ $rootScope . $on ( 'e' , function ( ) { child . $emit ( 'e2' ) ; } ) ;
2533+
2534+ expect ( function ( ) { child . $emit ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (1)' ) ;
2535+ expect ( function ( ) { $rootScope . $emit ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (1)' ) ;
2536+ expect ( function ( ) { $rootScope . $broadcast ( 'e' , 5 ) ; } ) . toThrowMinErr ( '$rootScope' , 'inevt' , 'e already $emit/$broadcast-ing on scope (1)' ) ;
2537+ } ) ) ;
2538+
2539+
2540+ it ( 'should clear recursive state of $broadcast if $exceptionHandler rethrows' , function ( ) {
2541+ module ( function ( $exceptionHandlerProvider ) {
2542+ $exceptionHandlerProvider . mode ( 'rethrow' ) ;
2543+ } ) ;
2544+ inject ( function ( $rootScope ) {
2545+ var throwingListener = jasmine . createSpy ( 'thrower' ) . and . callFake ( function ( ) {
2546+ throw new Error ( 'Listener Error!' ) ;
2547+ } ) ;
2548+ var secondListener = jasmine . createSpy ( 'second' ) ;
2549+
2550+ $rootScope . $on ( 'e' , throwingListener ) ;
2551+ $rootScope . $on ( 'e' , secondListener ) ;
2552+
2553+ expect ( function ( ) { $rootScope . $broadcast ( 'e' ) ; } ) . toThrowError ( 'Listener Error!' ) ;
2554+ expect ( throwingListener ) . toHaveBeenCalled ( ) ;
2555+ expect ( secondListener ) . not . toHaveBeenCalled ( ) ;
2556+
2557+ throwingListener . calls . reset ( ) ;
2558+ secondListener . calls . reset ( ) ;
2559+
2560+ expect ( function ( ) { $rootScope . $broadcast ( 'e' ) ; } ) . toThrowError ( 'Listener Error!' ) ;
2561+ expect ( throwingListener ) . toHaveBeenCalled ( ) ;
2562+ expect ( secondListener ) . not . toHaveBeenCalled ( ) ;
2563+ } ) ;
2564+ } ) ;
24512565 } ) ;
24522566 } ) ;
24532567
@@ -2537,7 +2651,7 @@ describe('Scope', function() {
25372651 expect ( spy1 ) . toHaveBeenCalledOnce ( ) ;
25382652 expect ( spy2 ) . toHaveBeenCalledOnce ( ) ;
25392653 expect ( spy3 ) . toHaveBeenCalledOnce ( ) ;
2540- expect ( child . $$listeners [ 'evt' ] . length ) . toBe ( 3 ) ; // cleanup will happen on next $emit
2654+ expect ( child . $$listeners [ 'evt' ] . length ) . toBe ( 2 ) ;
25412655
25422656 spy1 . calls . reset ( ) ;
25432657 spy2 . calls . reset ( ) ;
@@ -2571,7 +2685,7 @@ describe('Scope', function() {
25712685 expect ( spy1 ) . toHaveBeenCalledOnce ( ) ;
25722686 expect ( spy2 ) . toHaveBeenCalledOnce ( ) ;
25732687 expect ( spy3 ) . toHaveBeenCalledOnce ( ) ;
2574- expect ( child . $$listeners [ 'evt' ] . length ) . toBe ( 3 ) ; //cleanup will happen on next $broadcast
2688+ expect ( child . $$listeners [ 'evt' ] . length ) . toBe ( 2 ) ;
25752689
25762690 spy1 . calls . reset ( ) ;
25772691 spy2 . calls . reset ( ) ;
0 commit comments