@@ -1167,7 +1167,7 @@ function $RootScopeProvider() {
1167
1167
$on : function ( name , listener ) {
1168
1168
var namedListeners = this . $$listeners [ name ] ;
1169
1169
if ( ! namedListeners ) {
1170
- this . $$listeners [ name ] = namedListeners = [ ] ;
1170
+ this . $$listeners [ name ] = namedListeners = extend ( [ ] , { $$index : - 1 } ) ;
1171
1171
}
1172
1172
namedListeners . push ( listener ) ;
1173
1173
@@ -1181,10 +1181,12 @@ function $RootScopeProvider() {
1181
1181
1182
1182
var self = this ;
1183
1183
return function ( ) {
1184
- var indexOfListener = namedListeners . indexOf ( listener ) ;
1185
- if ( indexOfListener !== - 1 ) {
1186
- namedListeners [ indexOfListener ] = null ;
1184
+ var index = arrayRemove ( namedListeners , listener ) ;
1185
+ if ( index >= 0 ) {
1187
1186
decrementListenerCount ( self , 1 , name ) ;
1187
+ if ( index <= namedListeners . $$index ) {
1188
+ namedListeners . $$index -- ;
1189
+ }
1188
1190
}
1189
1191
} ;
1190
1192
} ,
@@ -1213,9 +1215,7 @@ function $RootScopeProvider() {
1213
1215
* @return {Object } Event object (see {@link ng.$rootScope.Scope#$on}).
1214
1216
*/
1215
1217
$emit : function ( name , args ) {
1216
- var empty = [ ] ,
1217
- namedListeners ,
1218
- scope = this ,
1218
+ var scope = this ,
1219
1219
stopPropagation = false ,
1220
1220
event = {
1221
1221
name : name ,
@@ -1226,36 +1226,14 @@ function $RootScopeProvider() {
1226
1226
} ,
1227
1227
defaultPrevented : false
1228
1228
} ,
1229
- listenerArgs = concat ( [ event ] , arguments , 1 ) ,
1230
- i , length ;
1229
+ listenerArgs = concat ( [ event ] , arguments , 1 ) ;
1231
1230
1232
1231
do {
1233
- namedListeners = scope . $$listeners [ name ] || empty ;
1234
- event . currentScope = scope ;
1235
- for ( i = 0 , length = namedListeners . length ; i < length ; i ++ ) {
1236
-
1237
- // if listeners were deregistered, defragment the array
1238
- if ( ! namedListeners [ i ] ) {
1239
- namedListeners . splice ( i , 1 ) ;
1240
- i -- ;
1241
- length -- ;
1242
- continue ;
1243
- }
1244
- try {
1245
- //allow all listeners attached to the current scope to run
1246
- namedListeners [ i ] . apply ( null , listenerArgs ) ;
1247
- } catch ( e ) {
1248
- $exceptionHandler ( e ) ;
1249
- }
1250
- }
1251
- //if any listener on the current scope stops propagation, prevent bubbling
1252
- if ( stopPropagation ) {
1253
- event . currentScope = null ;
1254
- return event ;
1255
- }
1232
+ invokeListeners ( scope , event , listenerArgs , name ) ;
1233
+
1256
1234
//traverse upwards
1257
- scope = scope . $parent ;
1258
- } while ( scope ) ;
1235
+ //if any listener on the current scope stops propagation, prevent bubbling
1236
+ } while ( ! stopPropagation && ( scope = scope . $parent ) ) ;
1259
1237
1260
1238
event . currentScope = null ;
1261
1239
@@ -1299,28 +1277,11 @@ function $RootScopeProvider() {
1299
1277
1300
1278
if ( ! target . $$listenerCount [ name ] ) return event ;
1301
1279
1302
- var listenerArgs = concat ( [ event ] , arguments , 1 ) ,
1303
- listeners , i , length ;
1280
+ var listenerArgs = concat ( [ event ] , arguments , 1 ) ;
1304
1281
1305
1282
//down while you can, then up and next sibling or up and next sibling until back at root
1306
1283
while ( ( current = next ) ) {
1307
- event . currentScope = current ;
1308
- listeners = current . $$listeners [ name ] || [ ] ;
1309
- for ( i = 0 , length = listeners . length ; i < length ; i ++ ) {
1310
- // if listeners were deregistered, defragment the array
1311
- if ( ! listeners [ i ] ) {
1312
- listeners . splice ( i , 1 ) ;
1313
- i -- ;
1314
- length -- ;
1315
- continue ;
1316
- }
1317
-
1318
- try {
1319
- listeners [ i ] . apply ( null , listenerArgs ) ;
1320
- } catch ( e ) {
1321
- $exceptionHandler ( e ) ;
1322
- }
1323
- }
1284
+ invokeListeners ( current , event , listenerArgs , name ) ;
1324
1285
1325
1286
// Insanity Warning: scope depth-first traversal
1326
1287
// yes, this code is a bit crazy, but it works and we have tests to prove it!
@@ -1350,6 +1311,24 @@ function $RootScopeProvider() {
1350
1311
1351
1312
return $rootScope ;
1352
1313
1314
+ function invokeListeners ( scope , event , listenerArgs , name ) {
1315
+ var listeners = scope . $$listeners [ name ] ;
1316
+ if ( listeners ) {
1317
+ if ( listeners . $$index !== - 1 ) {
1318
+ throw $rootScopeMinErr ( 'inevt' , '{0} already $emit/$broadcast-ing' , name ) ;
1319
+ }
1320
+ event . currentScope = scope ;
1321
+ for ( listeners . $$index = 0 ; listeners . $$index < listeners . length ; listeners . $$index ++ ) {
1322
+ try {
1323
+ //allow all listeners attached to the current scope to run
1324
+ listeners [ listeners . $$index ] . apply ( null , listenerArgs ) ;
1325
+ } catch ( e ) {
1326
+ $exceptionHandler ( e ) ;
1327
+ }
1328
+ }
1329
+ listeners . $$index = - 1 ;
1330
+ }
1331
+ }
1353
1332
1354
1333
function beginPhase ( phase ) {
1355
1334
if ( $rootScope . $$phase ) {
0 commit comments