@@ -2316,6 +2316,19 @@ describe('Scope', function() {
2316
2316
} ) ) ;
2317
2317
2318
2318
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
+
2319
2332
it ( 'should call next listener after removing the current listener via its own handler' , inject ( function ( $rootScope ) {
2320
2333
var listener1 = jasmine . createSpy ( 'listener1' ) . and . callFake ( function ( ) { remove1 ( ) ; } ) ;
2321
2334
var remove1 = $rootScope . $on ( 'abc' , listener1 ) ;
@@ -2448,6 +2461,107 @@ describe('Scope', function() {
2448
2461
expect ( $rootScope . $$listenerCount ) . toEqual ( { abc : 1 } ) ;
2449
2462
expect ( child . $$listenerCount ) . toEqual ( { abc : 1 } ) ;
2450
2463
} ) ) ;
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
+ } ) ;
2451
2565
} ) ;
2452
2566
} ) ;
2453
2567
@@ -2537,7 +2651,7 @@ describe('Scope', function() {
2537
2651
expect ( spy1 ) . toHaveBeenCalledOnce ( ) ;
2538
2652
expect ( spy2 ) . toHaveBeenCalledOnce ( ) ;
2539
2653
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 ) ;
2541
2655
2542
2656
spy1 . calls . reset ( ) ;
2543
2657
spy2 . calls . reset ( ) ;
@@ -2571,7 +2685,7 @@ describe('Scope', function() {
2571
2685
expect ( spy1 ) . toHaveBeenCalledOnce ( ) ;
2572
2686
expect ( spy2 ) . toHaveBeenCalledOnce ( ) ;
2573
2687
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 ) ;
2575
2689
2576
2690
spy1 . calls . reset ( ) ;
2577
2691
spy2 . calls . reset ( ) ;
0 commit comments