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