Skip to content

Commit 03c4fe9

Browse files
committed
Fixes for bugs found thanks to unit tests.
1 parent 142ae3e commit 03c4fe9

File tree

1 file changed

+39
-23
lines changed

1 file changed

+39
-23
lines changed

src/callbacks.js

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,13 @@ jQuery.Callbacks = function( flags, filter ) {
5656
var // Actual callback list
5757
list = [],
5858
// Stack of fire calls for repeatable lists
59-
stack = !flags.once && [],
59+
stack = [],
6060
// Last fire value (for non-forgettable lists)
6161
memory,
6262
// Flag to know if list is currently firing
6363
firing,
64+
// Index of cells to remove in the list after firing
65+
deleteAfterFire,
6466
// Add a list of callbacks to the list
6567
add = function( args ) {
6668
var i,
@@ -79,15 +81,13 @@ jQuery.Callbacks = function( flags, filter ) {
7981
// if it already exists
8082
if ( flags.relocate ) {
8183
object.remove( elem );
84+
} else if ( flags.unique && object.has( elem ) ) {
85+
continue;
8286
}
83-
// Unless we have a list with unicity and the
84-
// function is already there, add it
85-
if ( !( flags.unique && object.has( elem ) ) ) {
86-
// Get the filtered function if needs be
87-
actual = filter ? filter(elem) : elem;
88-
if ( actual ) {
89-
list.push( [ elem, actual ] );
90-
}
87+
// Get the filtered function if needs be
88+
actual = filter ? filter( elem ) : elem;
89+
if ( actual ) {
90+
list.push( [ elem, actual ] );
9191
}
9292
}
9393
}
@@ -96,13 +96,15 @@ jQuery.Callbacks = function( flags, filter ) {
9696
// Add a callback or a collection of callbacks to the list
9797
add: function() {
9898
if ( list ) {
99+
var length = list.length;
99100
add( arguments );
100-
// If we're not firing and we should call right away
101+
// With memory, if we're not firing then
102+
// we should call right away
101103
if ( !firing && flags.memory && memory ) {
102104
// Trick the list into thinking it needs to be fired
103105
var tmp = memory;
104106
memory = undefined;
105-
object.fireWith( tmp[ 0 ], tmp[ 1 ] );
107+
object.fireWith( tmp[ 0 ], tmp[ 1 ], length );
106108
}
107109
}
108110
return this;
@@ -113,9 +115,14 @@ jQuery.Callbacks = function( flags, filter ) {
113115
var i = 0,
114116
length = list.length;
115117
for ( ; i < length; i++ ) {
116-
if ( fn === list[ i ][ 0 ] ) {
117-
list.splice( i, 1 );
118-
i--;
118+
if ( list[ i ] && fn === list[ i ][ 0 ] ) {
119+
if ( firing ) {
120+
list[ i ] = undefined;
121+
deleteAfterFire.push( i );
122+
} else {
123+
list.splice( i, 1 );
124+
i--;
125+
}
119126
// If we have some unicity property then
120127
// we only need to do this once
121128
if ( flags.unique || flags.relocate ) {
@@ -132,7 +139,7 @@ jQuery.Callbacks = function( flags, filter ) {
132139
var i = 0,
133140
length = list.length;
134141
for ( ; i < length; i++ ) {
135-
if ( fn === list[ i ][ 0 ] ) {
142+
if ( list[ i ] && fn === list[ i ][ 0 ] ) {
136143
return true;
137144
}
138145
}
@@ -158,30 +165,39 @@ jQuery.Callbacks = function( flags, filter ) {
158165
return this;
159166
},
160167
// Call all callbacks with the given context and arguments
161-
fireWith: function( context, args ) {
162-
var i;
163-
if ( list && ( flags.once ? !memory && !firing : stack ) ) {
168+
fireWith: function( context, args, start /* internal */ ) {
169+
var i,
170+
done,
171+
stoppedOnFalse;
172+
if ( list && stack && ( !flags.once || !memory && !firing ) ) {
164173
if ( firing ) {
165174
stack.push( [ context, args ] );
166175
} else {
167176
args = args || [];
168177
memory = !flags.memory || [ context, args ];
169178
firing = true;
179+
deleteAfterFire = [];
170180
try {
171-
for ( i = 0; list && i < list.length; i++ ) {
172-
if ( list[ i ][ 1 ].apply( context, args ) === false && flags.stopOnFalse ) {
181+
for ( i = start || 0; list && i < list.length; i++ ) {
182+
if (( stoppedOnFalse = list[ i ] &&
183+
list[ i ][ 1 ].apply( context, args ) === false &&
184+
flags.stopOnFalse )) {
173185
break;
174186
}
175187
}
176188
} finally {
177189
firing = false;
178190
if ( list ) {
191+
done = ( stoppedOnFalse || i >= list.length );
192+
for ( i = 0; i < deleteAfterFire.length; i++ ) {
193+
list.splice( deleteAfterFire[ i ], 1 );
194+
}
179195
if ( !flags.once ) {
180-
if ( i >= list.length && stack.length ) {
181-
object.fire.apply( this, stack.shift() );
196+
if ( done && stack && stack.length ) {
197+
object.fireWith.apply( this, stack.shift() );
182198
}
183199
} else if ( !flags.memory ) {
184-
object.destroy();
200+
object.disable();
185201
} else {
186202
list = [];
187203
}

0 commit comments

Comments
 (0)