Fixes for bugs found thanks to unit tests.

This commit is contained in:
jaubourg 2011-05-07 03:39:41 +02:00
parent 142ae3e08a
commit 03c4fe9da9

View file

@ -56,11 +56,13 @@ jQuery.Callbacks = function( flags, filter ) {
var // Actual callback list var // Actual callback list
list = [], list = [],
// Stack of fire calls for repeatable lists // Stack of fire calls for repeatable lists
stack = !flags.once && [], stack = [],
// Last fire value (for non-forgettable lists) // Last fire value (for non-forgettable lists)
memory, memory,
// Flag to know if list is currently firing // Flag to know if list is currently firing
firing, firing,
// Index of cells to remove in the list after firing
deleteAfterFire,
// Add a list of callbacks to the list // Add a list of callbacks to the list
add = function( args ) { add = function( args ) {
var i, var i,
@ -79,30 +81,30 @@ jQuery.Callbacks = function( flags, filter ) {
// if it already exists // if it already exists
if ( flags.relocate ) { if ( flags.relocate ) {
object.remove( elem ); object.remove( elem );
} else if ( flags.unique && object.has( elem ) ) {
continue;
} }
// Unless we have a list with unicity and the
// function is already there, add it
if ( !( flags.unique && object.has( elem ) ) ) {
// Get the filtered function if needs be // Get the filtered function if needs be
actual = filter ? filter(elem) : elem; actual = filter ? filter( elem ) : elem;
if ( actual ) { if ( actual ) {
list.push( [ elem, actual ] ); list.push( [ elem, actual ] );
} }
} }
} }
}
}, },
object = { object = {
// Add a callback or a collection of callbacks to the list // Add a callback or a collection of callbacks to the list
add: function() { add: function() {
if ( list ) { if ( list ) {
var length = list.length;
add( arguments ); add( arguments );
// If we're not firing and we should call right away // With memory, if we're not firing then
// we should call right away
if ( !firing && flags.memory && memory ) { if ( !firing && flags.memory && memory ) {
// Trick the list into thinking it needs to be fired // Trick the list into thinking it needs to be fired
var tmp = memory; var tmp = memory;
memory = undefined; memory = undefined;
object.fireWith( tmp[ 0 ], tmp[ 1 ] ); object.fireWith( tmp[ 0 ], tmp[ 1 ], length );
} }
} }
return this; return this;
@ -113,9 +115,14 @@ jQuery.Callbacks = function( flags, filter ) {
var i = 0, var i = 0,
length = list.length; length = list.length;
for ( ; i < length; i++ ) { for ( ; i < length; i++ ) {
if ( fn === list[ i ][ 0 ] ) { if ( list[ i ] && fn === list[ i ][ 0 ] ) {
if ( firing ) {
list[ i ] = undefined;
deleteAfterFire.push( i );
} else {
list.splice( i, 1 ); list.splice( i, 1 );
i--; i--;
}
// If we have some unicity property then // If we have some unicity property then
// we only need to do this once // we only need to do this once
if ( flags.unique || flags.relocate ) { if ( flags.unique || flags.relocate ) {
@ -132,7 +139,7 @@ jQuery.Callbacks = function( flags, filter ) {
var i = 0, var i = 0,
length = list.length; length = list.length;
for ( ; i < length; i++ ) { for ( ; i < length; i++ ) {
if ( fn === list[ i ][ 0 ] ) { if ( list[ i ] && fn === list[ i ][ 0 ] ) {
return true; return true;
} }
} }
@ -158,30 +165,39 @@ jQuery.Callbacks = function( flags, filter ) {
return this; return this;
}, },
// Call all callbacks with the given context and arguments // Call all callbacks with the given context and arguments
fireWith: function( context, args ) { fireWith: function( context, args, start /* internal */ ) {
var i; var i,
if ( list && ( flags.once ? !memory && !firing : stack ) ) { done,
stoppedOnFalse;
if ( list && stack && ( !flags.once || !memory && !firing ) ) {
if ( firing ) { if ( firing ) {
stack.push( [ context, args ] ); stack.push( [ context, args ] );
} else { } else {
args = args || []; args = args || [];
memory = !flags.memory || [ context, args ]; memory = !flags.memory || [ context, args ];
firing = true; firing = true;
deleteAfterFire = [];
try { try {
for ( i = 0; list && i < list.length; i++ ) { for ( i = start || 0; list && i < list.length; i++ ) {
if ( list[ i ][ 1 ].apply( context, args ) === false && flags.stopOnFalse ) { if (( stoppedOnFalse = list[ i ] &&
list[ i ][ 1 ].apply( context, args ) === false &&
flags.stopOnFalse )) {
break; break;
} }
} }
} finally { } finally {
firing = false; firing = false;
if ( list ) { if ( list ) {
done = ( stoppedOnFalse || i >= list.length );
for ( i = 0; i < deleteAfterFire.length; i++ ) {
list.splice( deleteAfterFire[ i ], 1 );
}
if ( !flags.once ) { if ( !flags.once ) {
if ( i >= list.length && stack.length ) { if ( done && stack && stack.length ) {
object.fire.apply( this, stack.shift() ); object.fireWith.apply( this, stack.shift() );
} }
} else if ( !flags.memory ) { } else if ( !flags.memory ) {
object.destroy(); object.disable();
} else { } else {
list = []; list = [];
} }