aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjaubourg <j@ubourg.net>2011-03-03 19:38:06 +0100
committerjaubourg <j@ubourg.net>2011-03-03 19:38:06 +0100
commit2d0bc7ce72ab8d64da0506a88c8cc543ce3ceaba (patch)
tree2079117d0da1dbe2500e3aa78c5f0ff60a453ba3
parentc1279895f3f33cacc08e508c2409b587c0e6a5a2 (diff)
downloadjquery-2d0bc7ce72ab8d64da0506a88c8cc543ce3ceaba.tar.gz
jquery-2d0bc7ce72ab8d64da0506a88c8cc543ce3ceaba.zip
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).
-rw-r--r--Makefile1
-rw-r--r--src/core.js174
-rw-r--r--src/deferred.js169
-rw-r--r--test/csp.php1
-rw-r--r--test/data/offset/absolute.html1
-rw-r--r--test/data/offset/body.html1
-rw-r--r--test/data/offset/fixed.html1
-rw-r--r--test/data/offset/relative.html1
-rw-r--r--test/data/offset/scroll.html1
-rw-r--r--test/data/offset/static.html1
-rw-r--r--test/data/offset/table.html1
-rw-r--r--test/index.html2
-rw-r--r--test/localfile.html1
-rw-r--r--test/networkerror.html1
-rw-r--r--test/readywait.html1
-rw-r--r--test/unit/core.js221
-rw-r--r--test/unit/deferred.js222
17 files changed, 407 insertions, 393 deletions
diff --git a/Makefile b/Makefile
index bf41bccc6..a6aae4253 100644
--- a/Makefile
+++ b/Makefile
@@ -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\
diff --git a/src/core.js b/src/core.js
index 1e7250f60..9312ee288 100644
--- a/src/core.js
+++ b/src/core.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();
-
// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
diff --git a/src/deferred.js b/src/deferred.js
new file mode 100644
index 000000000..f0d7c08c5
--- /dev/null
+++ b/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 );
diff --git a/test/csp.php b/test/csp.php
index acf8f32c9..13c324ea6 100644
--- a/test/csp.php
+++ b/test/csp.php
@@ -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>
diff --git a/test/data/offset/absolute.html b/test/data/offset/absolute.html
index b4db30a6c..9d7990a37 100644
--- a/test/data/offset/absolute.html
+++ b/test/data/offset/absolute.html
@@ -16,6 +16,7 @@
#positionTest { position: absolute; }
</style>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/deferred.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/sizzle/sizzle.js"></script>
<script src="../../../src/sizzle-jquery.js"></script>
diff --git a/test/data/offset/body.html b/test/data/offset/body.html
index e3eb4f809..8dbf282df 100644
--- a/test/data/offset/body.html
+++ b/test/data/offset/body.html
@@ -9,6 +9,7 @@
#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }
</style>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/deferred.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/sizzle/sizzle.js"></script>
<script src="../../../src/sizzle-jquery.js"></script>
diff --git a/test/data/offset/fixed.html b/test/data/offset/fixed.html
index f93c20ffd..3181718da 100644
--- a/test/data/offset/fixed.html
+++ b/test/data/offset/fixed.html
@@ -13,6 +13,7 @@
#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }
</style>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/deferred.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/sizzle/sizzle.js"></script>
<script src="../../../src/sizzle-jquery.js"></script>
diff --git a/test/data/offset/relative.html b/test/data/offset/relative.html
index 35864760e..280a2fc0e 100644
--- a/test/data/offset/relative.html
+++ b/test/data/offset/relative.html
@@ -11,6 +11,7 @@
#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }
</style>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/deferred.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/sizzle/sizzle.js"></script>
<script src="../../../src/sizzle-jquery.js"></script>
diff --git a/test/data/offset/scroll.html b/test/data/offset/scroll.html
index 50de95e01..a0d1f4d18 100644
--- a/test/data/offset/scroll.html
+++ b/test/data/offset/scroll.html
@@ -14,6 +14,7 @@
#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }
</style>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/deferred.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/sizzle/sizzle.js"></script>
<script src="../../../src/sizzle-jquery.js"></script>
diff --git a/test/data/offset/static.html b/test/data/offset/static.html
index b1fb9f158..a61b6d10e 100644
--- a/test/data/offset/static.html
+++ b/test/data/offset/static.html
@@ -11,6 +11,7 @@
#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }
</style>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/deferred.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/sizzle/sizzle.js"></script>
<script src="../../../src/sizzle-jquery.js"></script>
diff --git a/test/data/offset/table.html b/test/data/offset/table.html
index 528e5303d..11fb0e795 100644
--- a/test/data/offset/table.html
+++ b/test/data/offset/table.html
@@ -11,6 +11,7 @@
#marker { position: absolute; border: 2px solid #000; width: 50px; height: 50px; background: #ccc; }
</style>
<script src="../../../src/core.js"></script>
+ <script src="../../../src/deferred.js"></script>
<script src="../../../src/support.js"></script>
<script src="../../../src/sizzle/sizzle.js"></script>
<script src="../../../src/sizzle-jquery.js"></script>
diff --git a/test/index.html b/test/index.html
index d62131530..c7c2ae55d 100644
--- a/test/index.html
+++ b/test/index.html
@@ -9,6 +9,7 @@
<script src="data/testinit.js"></script>
<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>
@@ -31,6 +32,7 @@
<script src="data/testrunner.js"></script>
<script src="unit/core.js"></script>
+ <script src="unit/deferred.js"></script>
<script src="unit/data.js"></script>
<script src="unit/queue.js"></script>
<script src="unit/attributes.js"></script>
diff --git a/test/localfile.html b/test/localfile.html
index 96e0f982c..c552f2145 100644
--- a/test/localfile.html
+++ b/test/localfile.html
@@ -5,6 +5,7 @@
<title>jQuery Local File Test</title>
<!-- Includes -->
<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>
diff --git a/test/networkerror.html b/test/networkerror.html
index b06a6ba46..f98bf4699 100644
--- a/test/networkerror.html
+++ b/test/networkerror.html
@@ -16,6 +16,7 @@
div { margin-top: 10px; }
</style>
<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>
diff --git a/test/readywait.html b/test/readywait.html
index 8e0d3d534..4f124767a 100644
--- a/test/readywait.html
+++ b/test/readywait.html
@@ -15,6 +15,7 @@
#expectedOutput { background-color: green }
</style>
<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>
diff --git a/test/unit/core.js b/test/unit/core.js
index 208b21c67..6ee8724de 100644
--- a/test/unit/core.js
+++ b/test/unit/core.js
@@ -914,227 +914,6 @@ test("jQuery.parseJSON", function(){
}
});
-test("jQuery._Deferred()", function() {
-
- expect( 11 );
-
- var deferred,
- object,
- test;
-
- deferred = jQuery._Deferred();
-
- test = false;
-
- deferred.done( function( value ) {
- equals( value , "value" , "Test pre-resolve callback" );
- test = true;
- } );
-
- deferred.resolve( "value" );
-
- ok( test , "Test pre-resolve callbacks called right away" );
-
- test = false;
-
- deferred.done( function( value ) {
- equals( value , "value" , "Test post-resolve callback" );
- test = true;
- } );
-
- ok( test , "Test post-resolve callbacks called right away" );
-
- deferred.cancel();
-
- test = true;
-
- deferred.done( function() {
- ok( false , "Cancel was ignored" );
- test = false;
- } );
-
- ok( test , "Test cancel" );
-
- deferred = jQuery._Deferred().resolve();
-
- try {
- deferred.done( function() {
- throw "Error";
- } , function() {
- ok( true , "Test deferred do not cancel on exception" );
- } );
- } catch( e ) {
- strictEqual( e , "Error" , "Test deferred propagates exceptions");
- deferred.done();
- }
-
- test = "";
- deferred = jQuery._Deferred().done( function() {
-
- test += "A";
-
- }, function() {
-
- test += "B";
-
- } ).resolve();
-
- strictEqual( test , "AB" , "Test multiple done parameters" );
-
- test = "";
-
- deferred.done( function() {
-
- deferred.done( function() {
-
- test += "C";
-
- } );
-
- test += "A";
-
- }, function() {
-
- test += "B";
- } );
-
- strictEqual( test , "ABC" , "Test done callbacks order" );
-
- deferred = jQuery._Deferred();
-
- deferred.resolveWith( jQuery , [ document ] ).done( function( doc ) {
- ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" );
- });
-
- // #8421
- deferred = jQuery._Deferred();
- deferred.resolveWith().done(function() {
- ok( true, "Test resolveWith can be called with no argument" );
- });
-});
-
-test("jQuery.Deferred()", function() {
-
- expect( 10 );
-
- jQuery.Deferred( function( defer ) {
- strictEqual( this , defer , "Defer passed as this & first argument" );
- this.resolve( "done" );
- }).then( function( value ) {
- strictEqual( value , "done" , "Passed function executed" );
- });
-
- jQuery.Deferred().resolve().then( function() {
- ok( true , "Success on resolve" );
- }, function() {
- ok( false , "Error on resolve" );
- });
-
- jQuery.Deferred().reject().then( function() {
- ok( false , "Success on reject" );
- }, function() {
- ok( true , "Error on reject" );
- });
-
- ( new jQuery.Deferred( function( defer ) {
- strictEqual( this , defer , "Defer passed as this & first argument (new)" );
- this.resolve( "done" );
- }) ).then( function( value ) {
- strictEqual( value , "done" , "Passed function executed (new)" );
- });
-
- ( new jQuery.Deferred() ).resolve().then( function() {
- ok( true , "Success on resolve (new)" );
- }, function() {
- ok( false , "Error on resolve (new)" );
- });
-
- ( new jQuery.Deferred() ).reject().then( function() {
- ok( false , "Success on reject (new)" );
- }, function() {
- ok( true , "Error on reject (new)" );
- });
-
- var tmp = jQuery.Deferred();
-
- strictEqual( tmp.promise() , tmp.promise() , "Test deferred always return same promise" );
- strictEqual( tmp.promise() , tmp.promise().promise() , "Test deferred's promise always return same promise as deferred" );
-});
-
-test("jQuery.when()", function() {
-
- expect( 23 );
-
- // Some other objects
- jQuery.each( {
-
- "an empty string": "",
- "a non-empty string": "some string",
- "zero": 0,
- "a number other than zero": 1,
- "true": true,
- "false": false,
- "null": null,
- "undefined": undefined,
- "a plain object": {}
-
- } , function( message , value ) {
-
- ok( jQuery.isFunction( jQuery.when( value ).then( function( resolveValue ) {
- strictEqual( resolveValue , value , "Test the promise was resolved with " + message );
- } ).promise ) , "Test " + message + " triggers the creation of a new Promise" );
-
- } );
-
- ok( jQuery.isFunction( jQuery.when().then( function( resolveValue ) {
- strictEqual( resolveValue , undefined , "Test the promise was resolved with no parameter" );
- } ).promise ) , "Test calling when with no parameter triggers the creation of a new Promise" );
-
- var cache, i;
-
- for( i = 1 ; i < 4 ; i++ ) {
- jQuery.when( cache || jQuery.Deferred( function() {
- this.resolve( i );
- }) ).then( function( value ) {
- strictEqual( value , 1 , "Function executed" + ( i > 1 ? " only once" : "" ) );
- cache = value;
- }, function() {
- ok( false , "Fail called" );
- });
- }
-});
-
-test("jQuery.when() - joined", function() {
-
- expect(8);
-
- jQuery.when( 1, 2, 3 ).done( function( a, b, c ) {
- strictEqual( a , 1 , "Test first param is first resolved value - non-observables" );
- strictEqual( b , 2 , "Test second param is second resolved value - non-observables" );
- strictEqual( c , 3 , "Test third param is third resolved value - non-observables" );
- }).fail( function() {
- ok( false , "Test the created deferred was resolved - non-observables");
- });
-
- var successDeferred = jQuery.Deferred().resolve( 1 , 2 , 3 ),
- errorDeferred = jQuery.Deferred().reject( "error" , "errorParam" );
-
- jQuery.when( 1 , successDeferred , 3 ).done( function( a, b, c ) {
- strictEqual( a , 1 , "Test first param is first resolved value - resolved observable" );
- same( b , [ 1 , 2 , 3 ] , "Test second param is second resolved value - resolved observable" );
- strictEqual( c , 3 , "Test third param is third resolved value - resolved observable" );
- }).fail( function() {
- ok( false , "Test the created deferred was resolved - resolved observable");
- });
-
- jQuery.when( 1 , errorDeferred , 3 ).done( function() {
- ok( false , "Test the created deferred was rejected - rejected observable");
- }).fail( function( error , errorParam ) {
- strictEqual( error , "error" , "Test first param is first rejected value - rejected observable" );
- strictEqual( errorParam , "errorParam" , "Test second param is second rejected value - rejected observable" );
- });
-});
-
test("jQuery.sub() - Static Methods", function(){
expect(18);
var Subclass = jQuery.sub();
diff --git a/test/unit/deferred.js b/test/unit/deferred.js
new file mode 100644
index 000000000..6ba4767a6
--- /dev/null
+++ b/test/unit/deferred.js
@@ -0,0 +1,222 @@
+module("deferred", { teardown: moduleTeardown });
+
+test("jQuery._Deferred()", function() {
+
+ expect( 11 );
+
+ var deferred,
+ object,
+ test;
+
+ deferred = jQuery._Deferred();
+
+ test = false;
+
+ deferred.done( function( value ) {
+ equals( value , "value" , "Test pre-resolve callback" );
+ test = true;
+ } );
+
+ deferred.resolve( "value" );
+
+ ok( test , "Test pre-resolve callbacks called right away" );
+
+ test = false;
+
+ deferred.done( function( value ) {
+ equals( value , "value" , "Test post-resolve callback" );
+ test = true;
+ } );
+
+ ok( test , "Test post-resolve callbacks called right away" );
+
+ deferred.cancel();
+
+ test = true;
+
+ deferred.done( function() {
+ ok( false , "Cancel was ignored" );
+ test = false;
+ } );
+
+ ok( test , "Test cancel" );
+
+ deferred = jQuery._Deferred().resolve();
+
+ try {
+ deferred.done( function() {
+ throw "Error";
+ } , function() {
+ ok( true , "Test deferred do not cancel on exception" );
+ } );
+ } catch( e ) {
+ strictEqual( e , "Error" , "Test deferred propagates exceptions");
+ deferred.done();
+ }
+
+ test = "";
+ deferred = jQuery._Deferred().done( function() {
+
+ test += "A";
+
+ }, function() {
+
+ test += "B";
+
+ } ).resolve();
+
+ strictEqual( test , "AB" , "Test multiple done parameters" );
+
+ test = "";
+
+ deferred.done( function() {
+
+ deferred.done( function() {
+
+ test += "C";
+
+ } );
+
+ test += "A";
+
+ }, function() {
+
+ test += "B";
+ } );
+
+ strictEqual( test , "ABC" , "Test done callbacks order" );
+
+ deferred = jQuery._Deferred();
+
+ deferred.resolveWith( jQuery , [ document ] ).done( function( doc ) {
+ ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" );
+ });
+
+ // #8421
+ deferred = jQuery._Deferred();
+ deferred.resolveWith().done(function() {
+ ok( true, "Test resolveWith can be called with no argument" );
+ });
+});
+
+test("jQuery.Deferred()", function() {
+
+ expect( 10 );
+
+ jQuery.Deferred( function( defer ) {
+ strictEqual( this , defer , "Defer passed as this & first argument" );
+ this.resolve( "done" );
+ }).then( function( value ) {
+ strictEqual( value , "done" , "Passed function executed" );
+ });
+
+ jQuery.Deferred().resolve().then( function() {
+ ok( true , "Success on resolve" );
+ }, function() {
+ ok( false , "Error on resolve" );
+ });
+
+ jQuery.Deferred().reject().then( function() {
+ ok( false , "Success on reject" );
+ }, function() {
+ ok( true , "Error on reject" );
+ });
+
+ ( new jQuery.Deferred( function( defer ) {
+ strictEqual( this , defer , "Defer passed as this & first argument (new)" );
+ this.resolve( "done" );
+ }) ).then( function( value ) {
+ strictEqual( value , "done" , "Passed function executed (new)" );
+ });
+
+ ( new jQuery.Deferred() ).resolve().then( function() {
+ ok( true , "Success on resolve (new)" );
+ }, function() {
+ ok( false , "Error on resolve (new)" );
+ });
+
+ ( new jQuery.Deferred() ).reject().then( function() {
+ ok( false , "Success on reject (new)" );
+ }, function() {
+ ok( true , "Error on reject (new)" );
+ });
+
+ var tmp = jQuery.Deferred();
+
+ strictEqual( tmp.promise() , tmp.promise() , "Test deferred always return same promise" );
+ strictEqual( tmp.promise() , tmp.promise().promise() , "Test deferred's promise always return same promise as deferred" );
+});
+
+test("jQuery.when()", function() {
+
+ expect( 23 );
+
+ // Some other objects
+ jQuery.each( {
+
+ "an empty string": "",
+ "a non-empty string": "some string",
+ "zero": 0,
+ "a number other than zero": 1,
+ "true": true,
+ "false": false,
+ "null": null,
+ "undefined": undefined,
+ "a plain object": {}
+
+ } , function( message , value ) {
+
+ ok( jQuery.isFunction( jQuery.when( value ).then( function( resolveValue ) {
+ strictEqual( resolveValue , value , "Test the promise was resolved with " + message );
+ } ).promise ) , "Test " + message + " triggers the creation of a new Promise" );
+
+ } );
+
+ ok( jQuery.isFunction( jQuery.when().then( function( resolveValue ) {
+ strictEqual( resolveValue , undefined , "Test the promise was resolved with no parameter" );
+ } ).promise ) , "Test calling when with no parameter triggers the creation of a new Promise" );
+
+ var cache, i;
+
+ for( i = 1 ; i < 4 ; i++ ) {
+ jQuery.when( cache || jQuery.Deferred( function() {
+ this.resolve( i );
+ }) ).then( function( value ) {
+ strictEqual( value , 1 , "Function executed" + ( i > 1 ? " only once" : "" ) );
+ cache = value;
+ }, function() {
+ ok( false , "Fail called" );
+ });
+ }
+});
+
+test("jQuery.when() - joined", function() {
+
+ expect(8);
+
+ jQuery.when( 1, 2, 3 ).done( function( a, b, c ) {
+ strictEqual( a , 1 , "Test first param is first resolved value - non-observables" );
+ strictEqual( b , 2 , "Test second param is second resolved value - non-observables" );
+ strictEqual( c , 3 , "Test third param is third resolved value - non-observables" );
+ }).fail( function() {
+ ok( false , "Test the created deferred was resolved - non-observables");
+ });
+
+ var successDeferred = jQuery.Deferred().resolve( 1 , 2 , 3 ),
+ errorDeferred = jQuery.Deferred().reject( "error" , "errorParam" );
+
+ jQuery.when( 1 , successDeferred , 3 ).done( function( a, b, c ) {
+ strictEqual( a , 1 , "Test first param is first resolved value - resolved observable" );
+ same( b , [ 1 , 2 , 3 ] , "Test second param is second resolved value - resolved observable" );
+ strictEqual( c , 3 , "Test third param is third resolved value - resolved observable" );
+ }).fail( function() {
+ ok( false , "Test the created deferred was resolved - resolved observable");
+ });
+
+ jQuery.when( 1 , errorDeferred , 3 ).done( function() {
+ ok( false , "Test the created deferred was rejected - rejected observable");
+ }).fail( function( error , errorParam ) {
+ strictEqual( error , "error" , "Test first param is first rejected value - rejected observable" );
+ strictEqual( errorParam , "errorParam" , "Test second param is second rejected value - rejected observable" );
+ });
+});