@@ -13,6 +13,38 @@ function Thrower( ex ) {
13
13
throw ex ;
14
14
}
15
15
16
+ function adoptValue ( value , resolve , reject ) {
17
+ var method ;
18
+
19
+ try {
20
+
21
+ // Check for promise aspect first to privilege synchronous behavior
22
+ if ( value && jQuery . isFunction ( ( method = value . promise ) ) ) {
23
+ method . call ( value ) . done ( resolve ) . fail ( reject ) ;
24
+
25
+ // Other thenables
26
+ } else if ( value && jQuery . isFunction ( ( method = value . then ) ) ) {
27
+ method . call ( value , resolve , reject ) ;
28
+
29
+ // Other non-thenables
30
+ } else {
31
+
32
+ // Support: Android 4.0 only
33
+ // Strict mode functions invoked without .call/.apply get global-object context
34
+ resolve . call ( undefined , value ) ;
35
+ }
36
+
37
+ // For Promises/A+, convert exceptions into rejections
38
+ // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
39
+ // Deferred#then to conditionally suppress rejection.
40
+ } catch ( /*jshint -W002 */ value ) {
41
+
42
+ // Support: Android 4.0 only
43
+ // Strict mode functions invoked without .call/.apply get global-object context
44
+ reject . call ( undefined , value ) ;
45
+ }
46
+ }
47
+
16
48
jQuery . extend ( {
17
49
18
50
Deferred : function ( func ) {
@@ -305,67 +337,45 @@ jQuery.extend( {
305
337
} ,
306
338
307
339
// Deferred helper
308
- when : function ( ) {
309
- var method , resolveContexts ,
310
- i = 0 ,
311
- resolveValues = slice . call ( arguments ) ,
312
- length = resolveValues . length ,
340
+ when : function ( singleValue ) {
341
+ var
342
+
343
+ // count of uncompleted subordinates
344
+ remaining = arguments . length ,
313
345
314
- // the count of uncompleted subordinates
315
- remaining = length ,
346
+ // count of unprocessed arguments
347
+ i = remaining ,
348
+
349
+ // subordinate fulfillment data
350
+ resolveContexts = Array ( i ) ,
351
+ resolveValues = slice . call ( arguments ) ,
316
352
317
- // the master Deferred.
353
+ // the master Deferred
318
354
master = jQuery . Deferred ( ) ,
319
355
320
- // Update function for both resolving subordinates
356
+ // subordinate callback factory
321
357
updateFunc = function ( i ) {
322
358
return function ( value ) {
323
359
resolveContexts [ i ] = this ;
324
360
resolveValues [ i ] = arguments . length > 1 ? slice . call ( arguments ) : value ;
325
361
if ( ! ( -- remaining ) ) {
326
- master . resolveWith (
327
- resolveContexts . length === 1 ? resolveContexts [ 0 ] : resolveContexts ,
328
- resolveValues
329
- ) ;
362
+ master . resolveWith ( resolveContexts , resolveValues ) ;
330
363
}
331
364
} ;
332
365
} ;
333
366
334
- // Add listeners to promise-like subordinates; treat others as resolved
335
- if ( length > 0 ) {
336
- resolveContexts = new Array ( length ) ;
337
- for ( ; i < length ; i ++ ) {
338
-
339
- // jQuery.Deferred - treated specially to get resolve-sync behavior
340
- if ( resolveValues [ i ] &&
341
- jQuery . isFunction ( ( method = resolveValues [ i ] . promise ) ) ) {
342
-
343
- method . call ( resolveValues [ i ] )
344
- . done ( updateFunc ( i ) )
345
- . fail ( master . reject ) ;
346
-
347
- // Other thenables
348
- } else if ( resolveValues [ i ] &&
349
- jQuery . isFunction ( ( method = resolveValues [ i ] . then ) ) ) {
350
-
351
- method . call (
352
- resolveValues [ i ] ,
353
- updateFunc ( i ) ,
354
- master . reject
355
- ) ;
356
- } else {
357
-
358
- // Support: Android 4.0 only
359
- // Strict mode functions invoked without .call/.apply get global-object context
360
- updateFunc ( i ) . call ( undefined , resolveValues [ i ] ) ;
361
- }
362
- }
367
+ // Single- and empty arguments are adopted like Promise.resolve
368
+ if ( remaining <= 1 ) {
369
+ adoptValue ( singleValue , master . resolve , master . reject ) ;
363
370
364
- // If we're not waiting on anything, resolve the master
365
- } else {
366
- master . resolveWith ( ) ;
371
+ // Use .then() to unwrap secondary thenables (cf. gh-3000)
372
+ return master . then ( ) ;
367
373
}
368
374
375
+ // Multiple arguments are aggregated like Promise.all array elements
376
+ while ( i -- ) {
377
+ adoptValue ( resolveValues [ i ] , updateFunc ( i ) , master . reject ) ;
378
+ }
369
379
return master . promise ( ) ;
370
380
}
371
381
} ) ;
0 commit comments