corrade-http-templates – Blame information for rev 61
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
61 | office | 1 | define( [ |
2 | "./core", |
||
3 | "./var/isFunction", |
||
4 | "./var/slice", |
||
5 | "./callbacks" |
||
6 | ], function( jQuery, isFunction, slice ) { |
||
7 | |||
8 | "use strict"; |
||
9 | |||
10 | function Identity( v ) { |
||
11 | return v; |
||
12 | } |
||
13 | function Thrower( ex ) { |
||
14 | throw ex; |
||
15 | } |
||
16 | |||
17 | function adoptValue( value, resolve, reject, noValue ) { |
||
18 | var method; |
||
19 | |||
20 | try { |
||
21 | |||
22 | // Check for promise aspect first to privilege synchronous behavior |
||
23 | if ( value && isFunction( ( method = value.promise ) ) ) { |
||
24 | method.call( value ).done( resolve ).fail( reject ); |
||
25 | |||
26 | // Other thenables |
||
27 | } else if ( value && isFunction( ( method = value.then ) ) ) { |
||
28 | method.call( value, resolve, reject ); |
||
29 | |||
30 | // Other non-thenables |
||
31 | } else { |
||
32 | |||
33 | // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: |
||
34 | // * false: [ value ].slice( 0 ) => resolve( value ) |
||
35 | // * true: [ value ].slice( 1 ) => resolve() |
||
36 | resolve.apply( undefined, [ value ].slice( noValue ) ); |
||
37 | } |
||
38 | |||
39 | // For Promises/A+, convert exceptions into rejections |
||
40 | // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in |
||
41 | // Deferred#then to conditionally suppress rejection. |
||
42 | } catch ( value ) { |
||
43 | |||
44 | // Support: Android 4.0 only |
||
45 | // Strict mode functions invoked without .call/.apply get global-object context |
||
46 | reject.apply( undefined, [ value ] ); |
||
47 | } |
||
48 | } |
||
49 | |||
50 | jQuery.extend( { |
||
51 | |||
52 | Deferred: function( func ) { |
||
53 | var tuples = [ |
||
54 | |||
55 | // action, add listener, callbacks, |
||
56 | // ... .then handlers, argument index, [final state] |
||
57 | [ "notify", "progress", jQuery.Callbacks( "memory" ), |
||
58 | jQuery.Callbacks( "memory" ), 2 ], |
||
59 | [ "resolve", "done", jQuery.Callbacks( "once memory" ), |
||
60 | jQuery.Callbacks( "once memory" ), 0, "resolved" ], |
||
61 | [ "reject", "fail", jQuery.Callbacks( "once memory" ), |
||
62 | jQuery.Callbacks( "once memory" ), 1, "rejected" ] |
||
63 | ], |
||
64 | state = "pending", |
||
65 | promise = { |
||
66 | state: function() { |
||
67 | return state; |
||
68 | }, |
||
69 | always: function() { |
||
70 | deferred.done( arguments ).fail( arguments ); |
||
71 | return this; |
||
72 | }, |
||
73 | "catch": function( fn ) { |
||
74 | return promise.then( null, fn ); |
||
75 | }, |
||
76 | |||
77 | // Keep pipe for back-compat |
||
78 | pipe: function( /* fnDone, fnFail, fnProgress */ ) { |
||
79 | var fns = arguments; |
||
80 | |||
81 | return jQuery.Deferred( function( newDefer ) { |
||
82 | jQuery.each( tuples, function( i, tuple ) { |
||
83 | |||
84 | // Map tuples (progress, done, fail) to arguments (done, fail, progress) |
||
85 | var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; |
||
86 | |||
87 | // deferred.progress(function() { bind to newDefer or newDefer.notify }) |
||
88 | // deferred.done(function() { bind to newDefer or newDefer.resolve }) |
||
89 | // deferred.fail(function() { bind to newDefer or newDefer.reject }) |
||
90 | deferred[ tuple[ 1 ] ]( function() { |
||
91 | var returned = fn && fn.apply( this, arguments ); |
||
92 | if ( returned && isFunction( returned.promise ) ) { |
||
93 | returned.promise() |
||
94 | .progress( newDefer.notify ) |
||
95 | .done( newDefer.resolve ) |
||
96 | .fail( newDefer.reject ); |
||
97 | } else { |
||
98 | newDefer[ tuple[ 0 ] + "With" ]( |
||
99 | this, |
||
100 | fn ? [ returned ] : arguments |
||
101 | ); |
||
102 | } |
||
103 | } ); |
||
104 | } ); |
||
105 | fns = null; |
||
106 | } ).promise(); |
||
107 | }, |
||
108 | then: function( onFulfilled, onRejected, onProgress ) { |
||
109 | var maxDepth = 0; |
||
110 | function resolve( depth, deferred, handler, special ) { |
||
111 | return function() { |
||
112 | var that = this, |
||
113 | args = arguments, |
||
114 | mightThrow = function() { |
||
115 | var returned, then; |
||
116 | |||
117 | // Support: Promises/A+ section 2.3.3.3.3 |
||
118 | // https://promisesaplus.com/#point-59 |
||
119 | // Ignore double-resolution attempts |
||
120 | if ( depth < maxDepth ) { |
||
121 | return; |
||
122 | } |
||
123 | |||
124 | returned = handler.apply( that, args ); |
||
125 | |||
126 | // Support: Promises/A+ section 2.3.1 |
||
127 | // https://promisesaplus.com/#point-48 |
||
128 | if ( returned === deferred.promise() ) { |
||
129 | throw new TypeError( "Thenable self-resolution" ); |
||
130 | } |
||
131 | |||
132 | // Support: Promises/A+ sections 2.3.3.1, 3.5 |
||
133 | // https://promisesaplus.com/#point-54 |
||
134 | // https://promisesaplus.com/#point-75 |
||
135 | // Retrieve `then` only once |
||
136 | then = returned && |
||
137 | |||
138 | // Support: Promises/A+ section 2.3.4 |
||
139 | // https://promisesaplus.com/#point-64 |
||
140 | // Only check objects and functions for thenability |
||
141 | ( typeof returned === "object" || |
||
142 | typeof returned === "function" ) && |
||
143 | returned.then; |
||
144 | |||
145 | // Handle a returned thenable |
||
146 | if ( isFunction( then ) ) { |
||
147 | |||
148 | // Special processors (notify) just wait for resolution |
||
149 | if ( special ) { |
||
150 | then.call( |
||
151 | returned, |
||
152 | resolve( maxDepth, deferred, Identity, special ), |
||
153 | resolve( maxDepth, deferred, Thrower, special ) |
||
154 | ); |
||
155 | |||
156 | // Normal processors (resolve) also hook into progress |
||
157 | } else { |
||
158 | |||
159 | // ...and disregard older resolution values |
||
160 | maxDepth++; |
||
161 | |||
162 | then.call( |
||
163 | returned, |
||
164 | resolve( maxDepth, deferred, Identity, special ), |
||
165 | resolve( maxDepth, deferred, Thrower, special ), |
||
166 | resolve( maxDepth, deferred, Identity, |
||
167 | deferred.notifyWith ) |
||
168 | ); |
||
169 | } |
||
170 | |||
171 | // Handle all other returned values |
||
172 | } else { |
||
173 | |||
174 | // Only substitute handlers pass on context |
||
175 | // and multiple values (non-spec behavior) |
||
176 | if ( handler !== Identity ) { |
||
177 | that = undefined; |
||
178 | args = [ returned ]; |
||
179 | } |
||
180 | |||
181 | // Process the value(s) |
||
182 | // Default process is resolve |
||
183 | ( special || deferred.resolveWith )( that, args ); |
||
184 | } |
||
185 | }, |
||
186 | |||
187 | // Only normal processors (resolve) catch and reject exceptions |
||
188 | process = special ? |
||
189 | mightThrow : |
||
190 | function() { |
||
191 | try { |
||
192 | mightThrow(); |
||
193 | } catch ( e ) { |
||
194 | |||
195 | if ( jQuery.Deferred.exceptionHook ) { |
||
196 | jQuery.Deferred.exceptionHook( e, |
||
197 | process.stackTrace ); |
||
198 | } |
||
199 | |||
200 | // Support: Promises/A+ section 2.3.3.3.4.1 |
||
201 | // https://promisesaplus.com/#point-61 |
||
202 | // Ignore post-resolution exceptions |
||
203 | if ( depth + 1 >= maxDepth ) { |
||
204 | |||
205 | // Only substitute handlers pass on context |
||
206 | // and multiple values (non-spec behavior) |
||
207 | if ( handler !== Thrower ) { |
||
208 | that = undefined; |
||
209 | args = [ e ]; |
||
210 | } |
||
211 | |||
212 | deferred.rejectWith( that, args ); |
||
213 | } |
||
214 | } |
||
215 | }; |
||
216 | |||
217 | // Support: Promises/A+ section 2.3.3.3.1 |
||
218 | // https://promisesaplus.com/#point-57 |
||
219 | // Re-resolve promises immediately to dodge false rejection from |
||
220 | // subsequent errors |
||
221 | if ( depth ) { |
||
222 | process(); |
||
223 | } else { |
||
224 | |||
225 | // Call an optional hook to record the stack, in case of exception |
||
226 | // since it's otherwise lost when execution goes async |
||
227 | if ( jQuery.Deferred.getStackHook ) { |
||
228 | process.stackTrace = jQuery.Deferred.getStackHook(); |
||
229 | } |
||
230 | window.setTimeout( process ); |
||
231 | } |
||
232 | }; |
||
233 | } |
||
234 | |||
235 | return jQuery.Deferred( function( newDefer ) { |
||
236 | |||
237 | // progress_handlers.add( ... ) |
||
238 | tuples[ 0 ][ 3 ].add( |
||
239 | resolve( |
||
240 | 0, |
||
241 | newDefer, |
||
242 | isFunction( onProgress ) ? |
||
243 | onProgress : |
||
244 | Identity, |
||
245 | newDefer.notifyWith |
||
246 | ) |
||
247 | ); |
||
248 | |||
249 | // fulfilled_handlers.add( ... ) |
||
250 | tuples[ 1 ][ 3 ].add( |
||
251 | resolve( |
||
252 | 0, |
||
253 | newDefer, |
||
254 | isFunction( onFulfilled ) ? |
||
255 | onFulfilled : |
||
256 | Identity |
||
257 | ) |
||
258 | ); |
||
259 | |||
260 | // rejected_handlers.add( ... ) |
||
261 | tuples[ 2 ][ 3 ].add( |
||
262 | resolve( |
||
263 | 0, |
||
264 | newDefer, |
||
265 | isFunction( onRejected ) ? |
||
266 | onRejected : |
||
267 | Thrower |
||
268 | ) |
||
269 | ); |
||
270 | } ).promise(); |
||
271 | }, |
||
272 | |||
273 | // Get a promise for this deferred |
||
274 | // If obj is provided, the promise aspect is added to the object |
||
275 | promise: function( obj ) { |
||
276 | return obj != null ? jQuery.extend( obj, promise ) : promise; |
||
277 | } |
||
278 | }, |
||
279 | deferred = {}; |
||
280 | |||
281 | // Add list-specific methods |
||
282 | jQuery.each( tuples, function( i, tuple ) { |
||
283 | var list = tuple[ 2 ], |
||
284 | stateString = tuple[ 5 ]; |
||
285 | |||
286 | // promise.progress = list.add |
||
287 | // promise.done = list.add |
||
288 | // promise.fail = list.add |
||
289 | promise[ tuple[ 1 ] ] = list.add; |
||
290 | |||
291 | // Handle state |
||
292 | if ( stateString ) { |
||
293 | list.add( |
||
294 | function() { |
||
295 | |||
296 | // state = "resolved" (i.e., fulfilled) |
||
297 | // state = "rejected" |
||
298 | state = stateString; |
||
299 | }, |
||
300 | |||
301 | // rejected_callbacks.disable |
||
302 | // fulfilled_callbacks.disable |
||
303 | tuples[ 3 - i ][ 2 ].disable, |
||
304 | |||
305 | // rejected_handlers.disable |
||
306 | // fulfilled_handlers.disable |
||
307 | tuples[ 3 - i ][ 3 ].disable, |
||
308 | |||
309 | // progress_callbacks.lock |
||
310 | tuples[ 0 ][ 2 ].lock, |
||
311 | |||
312 | // progress_handlers.lock |
||
313 | tuples[ 0 ][ 3 ].lock |
||
314 | ); |
||
315 | } |
||
316 | |||
317 | // progress_handlers.fire |
||
318 | // fulfilled_handlers.fire |
||
319 | // rejected_handlers.fire |
||
320 | list.add( tuple[ 3 ].fire ); |
||
321 | |||
322 | // deferred.notify = function() { deferred.notifyWith(...) } |
||
323 | // deferred.resolve = function() { deferred.resolveWith(...) } |
||
324 | // deferred.reject = function() { deferred.rejectWith(...) } |
||
325 | deferred[ tuple[ 0 ] ] = function() { |
||
326 | deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); |
||
327 | return this; |
||
328 | }; |
||
329 | |||
330 | // deferred.notifyWith = list.fireWith |
||
331 | // deferred.resolveWith = list.fireWith |
||
332 | // deferred.rejectWith = list.fireWith |
||
333 | deferred[ tuple[ 0 ] + "With" ] = list.fireWith; |
||
334 | } ); |
||
335 | |||
336 | // Make the deferred a promise |
||
337 | promise.promise( deferred ); |
||
338 | |||
339 | // Call given func if any |
||
340 | if ( func ) { |
||
341 | func.call( deferred, deferred ); |
||
342 | } |
||
343 | |||
344 | // All done! |
||
345 | return deferred; |
||
346 | }, |
||
347 | |||
348 | // Deferred helper |
||
349 | when: function( singleValue ) { |
||
350 | var |
||
351 | |||
352 | // count of uncompleted subordinates |
||
353 | remaining = arguments.length, |
||
354 | |||
355 | // count of unprocessed arguments |
||
356 | i = remaining, |
||
357 | |||
358 | // subordinate fulfillment data |
||
359 | resolveContexts = Array( i ), |
||
360 | resolveValues = slice.call( arguments ), |
||
361 | |||
362 | // the master Deferred |
||
363 | master = jQuery.Deferred(), |
||
364 | |||
365 | // subordinate callback factory |
||
366 | updateFunc = function( i ) { |
||
367 | return function( value ) { |
||
368 | resolveContexts[ i ] = this; |
||
369 | resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; |
||
370 | if ( !( --remaining ) ) { |
||
371 | master.resolveWith( resolveContexts, resolveValues ); |
||
372 | } |
||
373 | }; |
||
374 | }; |
||
375 | |||
376 | // Single- and empty arguments are adopted like Promise.resolve |
||
377 | if ( remaining <= 1 ) { |
||
378 | adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, |
||
379 | !remaining ); |
||
380 | |||
381 | // Use .then() to unwrap secondary thenables (cf. gh-3000) |
||
382 | if ( master.state() === "pending" || |
||
383 | isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { |
||
384 | |||
385 | return master.then(); |
||
386 | } |
||
387 | } |
||
388 | |||
389 | // Multiple arguments are aggregated like Promise.all array elements |
||
390 | while ( i-- ) { |
||
391 | adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); |
||
392 | } |
||
393 | |||
394 | return master.promise(); |
||
395 | } |
||
396 | } ); |
||
397 | |||
398 | return jQuery; |
||
399 | } ); |