Skip to content

Commit

Permalink
Moves Deferred-related code into a separate module. Context handling …
Browse files Browse the repository at this point in the history
…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 2d0bc7c
Show file tree
Hide file tree
Showing 17 changed files with 407 additions and 393 deletions.
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -12,6 +12,7 @@ COMPILER = ${JS_ENGINE} ${BUILD_DIR}/uglify.js --unsafe
POST_COMPILER = ${JS_ENGINE} ${BUILD_DIR}/post-compile.js POST_COMPILER = ${JS_ENGINE} ${BUILD_DIR}/post-compile.js


BASE_FILES = ${SRC_DIR}/core.js\ BASE_FILES = ${SRC_DIR}/core.js\
${SRC_DIR}/deferred.js\
${SRC_DIR}/support.js\ ${SRC_DIR}/support.js\
${SRC_DIR}/data.js\ ${SRC_DIR}/data.js\
${SRC_DIR}/queue.js\ ${SRC_DIR}/queue.js\
Expand Down
174 changes: 2 additions & 172 deletions src/core.js
Expand Up @@ -50,15 +50,9 @@ var jQuery = function( selector, context ) {
// For matching the engine and version of the browser // For matching the engine and version of the browser
browserMatch, browserMatch,


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

// The deferred used on DOM ready // The deferred used on DOM ready
readyList, readyList,


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

// The ready event handler // The ready event handler
DOMContentLoaded, DOMContentLoaded,


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


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


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


// Catch cases where $(document).ready() is called after the // Catch cases where $(document).ready() is called after the
// browser event has already occurred. // browser event has already occurred.
Expand Down Expand Up @@ -792,167 +786,6 @@ jQuery.extend({
return (new Date()).getTime(); 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. // Use of jQuery.browser is frowned upon.
// More details: http://docs.jquery.com/Utilities/jQuery.browser // More details: http://docs.jquery.com/Utilities/jQuery.browser
uaMatch: function( ua ) { uaMatch: function( ua ) {
Expand Down Expand Up @@ -991,9 +824,6 @@ jQuery.extend({
browser: {} browser: {}
}); });


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

// Populate the class2type map // Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase(); class2type[ "[object " + name + "]" ] = name.toLowerCase();
Expand Down
169 changes: 169 additions & 0 deletions src/deferred.js
@@ -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 );
1 change: 1 addition & 0 deletions test/csp.php
Expand Up @@ -6,6 +6,7 @@
<title>CSP Test Page</title> <title>CSP Test Page</title>


<script src="../src/core.js"></script> <script src="../src/core.js"></script>
<script src="../src/deferred.js"></script>
<script src="../src/support.js"></script> <script src="../src/support.js"></script>
<script src="../src/data.js"></script> <script src="../src/data.js"></script>
<script src="../src/queue.js"></script> <script src="../src/queue.js"></script>
Expand Down

0 comments on commit 2d0bc7c

Please sign in to comment.