]> source.dussan.org Git - jquery.git/commitdiff
Preserves context objects when multiple Deferreds are passed to $.when(). Context...
authorjaubourg <j@ubourg.net>
Sat, 12 May 2012 19:41:39 +0000 (21:41 +0200)
committerjaubourg <j@ubourg.net>
Sat, 12 May 2012 19:41:39 +0000 (21:41 +0200)
src/deferred.js
test/unit/deferred.js

index a06fe21938dd8b9a27a3e1cde9bf8b7a52989dfc..6c42583a586e0c4913e7ff1dace2b5e618325788 100644 (file)
@@ -97,35 +97,39 @@ jQuery.extend({
                var i = 0,
                        resolveValues = sliceDeferred.call( arguments ),
                        length = resolveValues.length,
-                       progressValues = new Array( length ),
 
                        // the count of uncompleted subordinates
                        remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
 
                        // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
                        deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
-                       promise = deferred.promise(),
 
                        // Update function for both resolve and progress values
-                       updateFunc = function( i, arr ) {
+                       updateFunc = function( i, contexts, values ) {
                                return function( value ) {
-                                       arr[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments ) : value;
-                                       if( arr === progressValues ) {
-                                               deferred.notifyWith( promise, arr );
+                                       contexts[ i ] = this;
+                                       values[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments ) : value;
+                                       if( values === progressValues ) {
+                                               deferred.notifyWith( contexts, values );
                                        } else if ( !( --remaining ) ) {
-                                               deferred.resolveWith( promise, arr );
+                                               deferred.resolveWith( contexts, values );
                                        }
                                };
-                       };
+                       },
+                       
+                       progressValues, progressContexts, resolveContexts;
 
                // add listeners to Deferred subordinates; treat others as resolved
                if ( length > 1 ) {
+                       progressValues = new Array( length );
+                       progressContexts = new Array( length );
+                       resolveContexts = new Array( length );
                        for ( ; i < length; i++ ) {
                                if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
                                        resolveValues[ i ].promise()
-                                               .done( updateFunc( i, resolveValues ) )
+                                               .done( updateFunc( i, resolveContexts, resolveValues ) )
                                                .fail( deferred.reject )
-                                               .progress( updateFunc( i, progressValues ) );
+                                               .progress( updateFunc( i, progressContexts, progressValues ) );
                                } else {
                                        --remaining;
                                }
@@ -134,10 +138,10 @@ jQuery.extend({
 
                // if we're not waiting on anything, resolve the master
                if ( !remaining ) {
-                       deferred.resolveWith( deferred, resolveValues );
+                       deferred.resolveWith( resolveContexts, resolveValues );
                }
 
-               return promise;
+               return deferred.promise();
        }
 });
 
index 710d221f08c4f9574931841047e25ac15e891427..97356072466da3ab0e680a111ff26f960d1dfa49 100644 (file)
@@ -289,7 +289,7 @@ test( "jQuery.Deferred.then - context", function() {
 
 test( "jQuery.when" , function() {
 
-       expect( 23 );
+       expect( 34 );
 
        // Some other objects
        jQuery.each( {
@@ -307,15 +307,23 @@ test( "jQuery.when" , function() {
        } , function( message , value ) {
 
                ok( jQuery.isFunction( jQuery.when( value ).done(function( resolveValue ) {
+                       strictEqual( this, window, "Context is the global object with " + message );
                        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().done(function( resolveValue ) {
-               strictEqual( resolveValue , undefined , "Test the promise was resolved with no parameter" );
+               strictEqual( this, window, "Test the promise was resolved with window as its context" );
+               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 context = {};
+
+       jQuery.when( jQuery.Deferred().resolveWith( context ) ).done(function() {
+               strictEqual( this, context, "when( promise ) propagates context" );
+       });
+
        var cache, i;
 
        for( i = 1 ; i < 4 ; i++ ) {
@@ -330,7 +338,7 @@ test( "jQuery.when" , function() {
 
 test("jQuery.when - joined", function() {
 
-       expect(53);
+       expect( 119 );
 
        var deferreds = {
                        value: 1,
@@ -362,11 +370,15 @@ test("jQuery.when - joined", function() {
                                shouldNotify = willNotify[ id1 ] || willNotify[ id2 ],
                                expected = shouldResolve ? [ 1, 1 ] : [ 0, undefined ],
                            expectedNotify = shouldNotify && [ willNotify[ id1 ], willNotify[ id2 ] ],
-                           code = id1 + "/" + id2;
+                           code = id1 + "/" + id2,
+                           context1 = defer1 && jQuery.isFunction( defer1.promise ) ? defer1 : undefined,
+                           context2 = defer2 && jQuery.isFunction( defer2.promise ) ? defer2 : undefined;
 
-                       var promise = jQuery.when( defer1, defer2 ).done(function( a, b ) {
+                       jQuery.when( defer1, defer2 ).done(function( a, b ) {
                                if ( shouldResolve ) {
                                        deepEqual( [ a, b ], expected, code + " => resolve" );
+                                       strictEqual( this[ 0 ], context1, code + " => first context OK" );
+                                       strictEqual( this[ 1 ], context2, code + " => second context OK" );
                                } else {
                                        ok( false ,  code + " => resolve" );
                                }
@@ -376,8 +388,10 @@ test("jQuery.when - joined", function() {
                                } else {
                                        ok( false ,  code + " => reject" );
                                }
-                       }).progress(function progress( a, b ) {
+                       }).progress(function( a, b ) {
                                deepEqual( [ a, b ], expectedNotify, code + " => progress" );
+                               strictEqual( this[ 0 ], expectedNotify[ 0 ] ? context1 : undefined, code + " => first context OK" );
+                               strictEqual( this[ 1 ], expectedNotify[ 1 ] ? context2 : undefined, code + " => second context OK" );
                        });
                } );
        } );