Repository: jquery/jquery
File: src/deferred.js (JavaScript)

Code before:

			// the master Deferred.
			master = jQuery.Deferred(),

			// Update function for both resolve and progress values
			updateFunc = function( i, contexts, values ) {
				return function( value ) {
					contexts[ i ] = this;
					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
					if ( values === progressValues ) {
						master.notifyWith( contexts, values );
					} else if ( !( --remaining ) ) {
						master.resolveWith(
							contexts.length === 1 ? contexts[ 0 ] : contexts,
							values
						);
					}
				};
			},
			progressValues, progressContexts, resolveContexts;

		// Add listeners to Deferred subordinates; treat others as resolved
		if ( length > 0 ) {
			progressValues = new Array( length );
			progressContexts = new Array( length );
			resolveContexts = new Array( length );
			for ( ; i < length; i++ ) {
				if ( resolveValues[ i ] &&
					jQuery.isFunction( ( method = resolveValues[ i ].promise ) ) ) {

					method.call( resolveValues[ i ] )
						.progress( updateFunc( i, progressContexts, progressValues ) )
						.done( updateFunc( i, resolveContexts, resolveValues ) )
						.fail( master.reject );
				} else if ( resolveValues[ i ] &&
					jQuery.isFunction( ( method = resolveValues[ i ].then ) ) ) {

					method.call(
						resolveValues[ i ],
						updateFunc( i, resolveContexts, resolveValues ),
						master.reject,
						updateFunc( i, progressContexts, progressValues )
					);
				} else {
					updateFunc( i, resolveContexts, resolveValues )( resolveValues[ i ] );
				}
			}
		} else {
			master.resolveWith( resolveContexts );
		}


Review comment (bug):
Welllll, maybe I spoke too soon. Giving the `then` branch precedence changes more than I expected. Lots of failures having to do with unexpected contexts and resolve values when passing multiple Deferreds. Let's make that a separate issue if we still want to do it.


Code after:

			// the master Deferred.
			master = jQuery.Deferred(),

			// Update function for both resolve and progress values
			updateFunc = function( i, contexts, values ) {
				return function( value ) {
					contexts[ i ] = this;
					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
					if ( values === progressValues ) {
						master.notifyWith( contexts, values );
					} else if ( !( --remaining ) ) {
						master.resolveWith(
							contexts.length === 1 ? contexts[ 0 ] : contexts,
							values
						);
					}
				};
			},
			progressValues, progressContexts, resolveContexts;

		// Add listeners to Deferred subordinates; treat others as resolved
		if ( length > 0 ) {
			progressValues = new Array( length );
			progressContexts = new Array( length );
			resolveContexts = new Array( length );
			for ( ; i < length; i++ ) {
				if ( resolveValues[ i ] &&
					jQuery.isFunction( ( method = resolveValues[ i ].promise ) ) ) {

					method.call( resolveValues[ i ] )
						.progress( updateFunc( i, progressContexts, progressValues ) )
						.done( updateFunc( i, resolveContexts, resolveValues ) )
						.fail( master.reject );
				} else if ( resolveValues[ i ] &&
					jQuery.isFunction( ( method = resolveValues[ i ].then ) ) ) {

					method.call(
						resolveValues[ i ],
						updateFunc( i, resolveContexts, resolveValues ),
						master.reject,
						updateFunc( i, progressContexts, progressValues )
					);
				} else {
					updateFunc( i, resolveContexts, resolveValues )( resolveValues[ i ] );
				}
			}

		// If we're not waiting on anything, resolve the master
		} else {
			master.resolveWith();