Permalink
Browse files

Moves Deferred-related code into a separate module. Context handling …

…has been simplified in _Deferred.resolve and jQuery.when has been refactored for clarity (and minor optimization).
  • Loading branch information...
jaubourg committed Mar 3, 2011
1 parent c127989 commit 2d0bc7ce72ab8d64da0506a88c8cc543ce3ceaba
@@ -12,6 +12,7 @@ COMPILER = ${JS_ENGINE} ${BUILD_DIR}/uglify.js --unsafe
POST_COMPILER = ${JS_ENGINE} ${BUILD_DIR}/post-compile.js

BASE_FILES = ${SRC_DIR}/core.js\
${SRC_DIR}/deferred.js\
${SRC_DIR}/support.js\
${SRC_DIR}/data.js\
${SRC_DIR}/queue.js\
@@ -50,15 +50,9 @@ var jQuery = function( selector, context ) {
// For matching the engine and version of the browser
browserMatch,

// Has the ready events already been bound?
readyBound = false,

// The deferred used on DOM ready
readyList,

// Promise methods
promiseMethods = "then done fail isResolved isRejected promise".split( " " ),

// The ready event handler
DOMContentLoaded,

@@ -408,11 +402,11 @@ jQuery.extend({
},

bindReady: function() {
if ( readyBound ) {
if ( readyList ) {
return;
}

readyBound = true;
readyList = jQuery._Deferred();

// Catch cases where $(document).ready() is called after the
// browser event has already occurred.
@@ -792,167 +786,6 @@ jQuery.extend({
return (new Date()).getTime();
},

// Create a simple deferred (one callbacks list)
_Deferred: function() {
var // callbacks list
callbacks = [],
// stored [ context , args ]
fired,
// to avoid firing when already doing so
firing,
// flag to know if the deferred has been cancelled
cancelled,
// the deferred itself
deferred = {

// done( f1, f2, ...)
done: function() {
if ( !cancelled ) {
var args = arguments,
i,
length,
elem,
type,
_fired;
if ( fired ) {
_fired = fired;
fired = 0;
}
for ( i = 0, length = args.length; i < length; i++ ) {
elem = args[ i ];
type = jQuery.type( elem );
if ( type === "array" ) {
deferred.done.apply( deferred, elem );
} else if ( type === "function" ) {
callbacks.push( elem );
}
}
if ( _fired ) {
deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
}
}
return this;
},

// resolve with given context and args
resolveWith: function( context, args ) {
if ( !cancelled && !fired && !firing ) {
// make sure args are available (#8421)
args = args || [];
firing = 1;
try {
while( callbacks[ 0 ] ) {
callbacks.shift().apply( context, args );
}
}
finally {
fired = [ context, args ];
firing = 0;
}
}
return this;
},

// resolve with this as context and given arguments
resolve: function() {
deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments );
return this;
},

// Has this deferred been resolved?
isResolved: function() {
return !!( firing || fired );
},

// Cancel
cancel: function() {
cancelled = 1;
callbacks = [];
return this;
}
};

return deferred;
},

// Full fledged deferred (two callbacks list)
Deferred: function( func ) {
var deferred = jQuery._Deferred(),
failDeferred = jQuery._Deferred(),
promise;
// Add errorDeferred methods, then and promise
jQuery.extend( deferred, {
then: function( doneCallbacks, failCallbacks ) {
deferred.done( doneCallbacks ).fail( failCallbacks );
return this;
},
fail: failDeferred.done,
rejectWith: failDeferred.resolveWith,
reject: failDeferred.resolve,
isRejected: failDeferred.isResolved,
// Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object
promise: function( obj ) {
if ( obj == null ) {
if ( promise ) {
return promise;
}
promise = obj = {};
}
var i = promiseMethods.length;
while( i-- ) {
obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
}
return obj;
}
} );
// Make sure only one callback list will be used
deferred.done( failDeferred.cancel ).fail( deferred.cancel );
// Unexpose cancel
delete deferred.cancel;
// Call given func if any
if ( func ) {
func.call( deferred, deferred );
}
return deferred;
},

// Deferred helper
when: function( object ) {
var lastIndex = arguments.length,
deferred = lastIndex <= 1 && object && jQuery.isFunction( object.promise ) ?
object :
jQuery.Deferred(),
promise = deferred.promise();

if ( lastIndex > 1 ) {
var array = slice.call( arguments, 0 ),
count = lastIndex,
iCallback = function( index ) {
return function( value ) {
array[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value;
if ( !( --count ) ) {
deferred.resolveWith( promise, array );
}
};
};
while( ( lastIndex-- ) ) {
object = array[ lastIndex ];
if ( object && jQuery.isFunction( object.promise ) ) {
object.promise().then( iCallback(lastIndex), deferred.reject );
} else {
--count;
}
}
if ( !count ) {
deferred.resolveWith( promise, array );
}
} else if ( deferred !== object ) {
deferred.resolve( object );
}
return promise;
},

// Use of jQuery.browser is frowned upon.
// More details: http://docs.jquery.com/Utilities/jQuery.browser
uaMatch: function( ua ) {
@@ -991,9 +824,6 @@ jQuery.extend({
browser: {}
});

// Create readyList deferred
readyList = jQuery._Deferred();

This comment has been minimized.

@eddiemonge

eddiemonge Mar 20, 2011

Contributor

moving this line completely breaks jQuery in Blackberry Playbook emulator.

This comment has been minimized.

@jaubourg

jaubourg Mar 20, 2011

Author Member

Could you be a bit more specific?

This comment has been minimized.

@eddiemonge

eddiemonge Mar 20, 2011

Contributor

After testing all the files and changes, this is the line that causes jQuery to completely fail on the Playbook. Like nothing in jQuery will work because of this. however, something else fixes it in 1.5.2pre but I didn't have time to track down what fixes so I deleted my comment, or thought I did.


// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
@@ -0,0 +1,169 @@
(function( jQuery ) {

var // Promise methods
promiseMethods = "then done fail isResolved isRejected promise".split( " " ),
// Static reference to slice
sliceDeferred = [].slice;

jQuery.extend({
// Create a simple deferred (one callbacks list)
_Deferred: function() {
var // callbacks list
callbacks = [],
// stored [ context , args ]
fired,
// to avoid firing when already doing so
firing,
// flag to know if the deferred has been cancelled
cancelled,
// the deferred itself
deferred = {

// done( f1, f2, ...)
done: function() {
if ( !cancelled ) {
var args = arguments,
i,
length,
elem,
type,
_fired;
if ( fired ) {
_fired = fired;
fired = 0;
}
for ( i = 0, length = args.length; i < length; i++ ) {
elem = args[ i ];
type = jQuery.type( elem );
if ( type === "array" ) {
deferred.done.apply( deferred, elem );
} else if ( type === "function" ) {
callbacks.push( elem );
}
}
if ( _fired ) {
deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
}
}
return this;
},

// resolve with given context and args
resolveWith: function( context, args ) {
if ( !cancelled && !fired && !firing ) {
// make sure args are available (#8421)
args = args || [];
firing = 1;
try {
while( callbacks[ 0 ] ) {
callbacks.shift().apply( context, args );
}
}
finally {
fired = [ context, args ];
firing = 0;
}
}
return this;
},

// resolve with this as context and given arguments
resolve: function() {
deferred.resolveWith( this, arguments );
return this;
},

// Has this deferred been resolved?
isResolved: function() {
return !!( firing || fired );
},

// Cancel
cancel: function() {
cancelled = 1;
callbacks = [];
return this;
}
};

return deferred;
},

// Full fledged deferred (two callbacks list)
Deferred: function( func ) {
var deferred = jQuery._Deferred(),
failDeferred = jQuery._Deferred(),
promise;
// Add errorDeferred methods, then and promise
jQuery.extend( deferred, {
then: function( doneCallbacks, failCallbacks ) {
deferred.done( doneCallbacks ).fail( failCallbacks );
return this;
},
fail: failDeferred.done,
rejectWith: failDeferred.resolveWith,
reject: failDeferred.resolve,
isRejected: failDeferred.isResolved,
// Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object
promise: function( obj ) {
if ( obj == null ) {
if ( promise ) {
return promise;
}
promise = obj = {};
}
var i = promiseMethods.length;
while( i-- ) {
obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
}
return obj;
}
} );
// Make sure only one callback list will be used
deferred.done( failDeferred.cancel ).fail( deferred.cancel );
// Unexpose cancel
delete deferred.cancel;
// Call given func if any
if ( func ) {
func.call( deferred, deferred );
}
return deferred;
},

// Deferred helper
when: function( firstParam ) {
var args = arguments,
i = 0,
length = args.length,
count = length,
deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
firstParam :
jQuery.Deferred();
function resolveFunc( i ) {
return function( value ) {
args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
if ( !( --count ) ) {
deferred.resolveWith( deferred, args );
}
};
}
if ( length > 1 ) {
for( ; i < length; i++ ) {
if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) {
args[ i ].promise().then( resolveFunc(i), deferred.reject );
} else {
--count;
}
}
if ( !count ) {
deferred.resolveWith( deferred, args );
}
} else if ( deferred !== firstParam ) {
deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
}
return deferred.promise();
}
});

})( jQuery );
@@ -6,6 +6,7 @@
<title>CSP Test Page</title>

<script src="../src/core.js"></script>
<script src="../src/deferred.js"></script>
<script src="../src/support.js"></script>
<script src="../src/data.js"></script>
<script src="../src/queue.js"></script>
Oops, something went wrong.

0 comments on commit 2d0bc7c

Please sign in to comment.