Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(146)

Side by Side Diff: pkg/dev_compiler/tool/input_sdk/lib/async/future.dart

Issue 2456803004: fixes #27586, prefer context type in generic inference (Closed)
Patch Set: fix Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart.async; 5 part of dart.async;
6 6
7 /// A type representing values that are either `Future<T>` or `T`.
8 ///
9 /// This class declaration is a public stand-in for an internal
10 /// future-or-value generic type. References to this class are resolved to the
11 /// internal type.
12 ///
13 /// It is a compile-time error for any class to extend, mix in or implement
14 /// `FutureOr`.
15 ///
16 /// Note: the `FutureOr<T>` type is interpreted as `dynamic` in non strong-mode.
17 ///
18 /// # Examples
19 /// ``` dart
20 /// // The `Future<T>.then` function takes a callback [f] that returns either
21 /// // an `S` or a `Future<S>`.
22 /// Future<S> then<S>(FutureOr<S> f(T x), ...);
23 ///
24 /// // `Completer<T>.complete` takes either a `T` or `Future<T>`.
25 /// void complete(FutureOr<T> value);
26 /// ```
27 ///
28 /// # Advanced
29 /// The `FutureOr<int>` type is actually the "type union" of the types `int` and
30 /// `Future<int>`. This type union is defined in such a way that
31 /// `FutureOr<Object>` is both a super- and sub-type of `Object` (sub-type
32 /// because `Object` is one of the types of the union, super-type because
33 /// `Object` is a super-type of both of the types of the union). Together it
34 /// means that `FutureOr<Object>` is equivalent to `Object`.
35 ///
36 /// As a corollary, `FutureOr<Object>` is equivalent to
37 /// `FutureOr<FutureOr<Object>>`, `FutureOr<Future<Object>> is equivalent to
38 /// `Future<Object>`.
39 abstract class FutureOr<T> {
40 // Private constructor, so that it is not subclassable, mixable, or
41 // instantiable.
42 FutureOr._() {
43 throw new UnsupportedError("FutureOr can't be instantiated");
44 }
45 }
46
47 /** 7 /**
48 * An object representing a delayed computation. 8 * An object representing a delayed computation.
49 * 9 *
50 * A [Future] is used to represent a potential value, or error, 10 * A [Future] is used to represent a potential value, or error,
51 * that will be available at some time in the future. 11 * that will be available at some time in the future.
52 * Receivers of a [Future] can register callbacks 12 * Receivers of a [Future] can register callbacks
53 * that handle the value or error once it is available. 13 * that handle the value or error once it is available.
54 * For example: 14 * For example:
55 * 15 *
56 * Future<int> future = getFuture(); 16 * Future<int> future = getFuture();
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 * If calling [computation] throws, the created future will complete with the 218 * If calling [computation] throws, the created future will complete with the
259 * error. 219 * error.
260 * 220 *
261 * See also [Completer] for a way to create and complete a future at a 221 * See also [Completer] for a way to create and complete a future at a
262 * later time that isn't necessarily after a known fixed duration. 222 * later time that isn't necessarily after a known fixed duration.
263 */ 223 */
264 factory Future.delayed(Duration duration, [computation()]) { 224 factory Future.delayed(Duration duration, [computation()]) {
265 _Future<T> result = new _Future<T>(); 225 _Future<T> result = new _Future<T>();
266 new Timer(duration, () { 226 new Timer(duration, () {
267 try { 227 try {
268 result._complete(computation?.call()); 228 result._complete(computation == null ? null : computation());
269 } catch (e, s) { 229 } catch (e, s) {
270 _completeWithErrorCallback(result, e, s); 230 _completeWithErrorCallback(result, e, s);
271 } 231 }
272 }); 232 });
273 return result; 233 return result;
274 } 234 }
275 235
276 /** 236 /**
277 * Wait for all the given futures to complete and collect their values. 237 * Wait for all the given futures to complete and collect their values.
278 * 238 *
279 * Returns a future which will complete once all the futures in a list are 239 * Returns a future which will complete once all the futures in a list are
280 * complete. If any of the futures in the list completes with an error, 240 * complete. If any of the futures in the list completes with an error,
281 * the resulting future also completes with an error. Otherwise the value 241 * the resulting future also completes with an error. Otherwise the value
282 * of the returned future will be a list of all the values that were 242 * of the returned future will be a list of all the values that were
283 * produced. 243 * produced.
284 * 244 *
285 * If `eagerError` is true, the future completes with an error immediately on 245 * If `eagerError` is true, the future completes with an error immediately on
286 * the first error from one of the futures. Otherwise all futures must 246 * the first error from one of the futures. Otherwise all futures must
287 * complete before the returned future is completed (still with the first 247 * complete before the returned future is completed (still with the first
288 * error to occur, the remaining errors are silently dropped). 248 * error to occur, the remaining errors are silently dropped).
289 * 249 *
290 * If [cleanUp] is provided, in the case of an error, any non-null result of 250 * If [cleanUp] is provided, in the case of an error, any non-null result of
291 * a successful future is passed to `cleanUp`, which can then release any 251 * a successful future is passed to `cleanUp`, which can then release any
292 * resources that the successful operation allocated. 252 * resources that the successful operation allocated.
293 * 253 *
294 * The call to `cleanUp` should not throw. If it does, the error will be an 254 * The call to `cleanUp` should not throw. If it does, the error will be an
295 * uncaught asynchronous error. 255 * uncaught asynchronous error.
296 */ 256 */
297 static Future<List<T>> wait<T>(Iterable<Future<T>> futures, 257 static Future<List/*<T>*/> wait/*<T>*/(Iterable<Future/*<T>*/> futures,
298 {bool eagerError: false, 258 {bool eagerError: false,
299 void cleanUp(T successValue)}) { 259 void cleanUp(/*=T*/ successValue)}) {
300 final _Future<List<T>> result = new _Future<List<T>>(); 260 final _Future<List/*<T>*/> result = new _Future<List/*<T>*/>();
301 List<T> values; // Collects the values. Set to null on error. 261 List/*<T>*/ values; // Collects the values. Set to null on error.
302 int remaining = 0; // How many futures are we waiting for. 262 int remaining = 0; // How many futures are we waiting for.
303 var error; // The first error from a future. 263 var error; // The first error from a future.
304 StackTrace stackTrace; // The stackTrace that came with the error. 264 StackTrace stackTrace; // The stackTrace that came with the error.
305 265
306 // Handle an error from any of the futures. 266 // Handle an error from any of the futures.
307 void handleError(theError, theStackTrace) { 267 void handleError(theError, theStackTrace) {
308 remaining--; 268 remaining--;
309 if (values != null) { 269 if (values != null) {
310 if (cleanUp != null) { 270 if (cleanUp != null) {
311 for (var value in values) { 271 for (var value in values) {
312 if (value != null) { 272 if (value != null) {
313 // Ensure errors from cleanUp are uncaught. 273 // Ensure errors from cleanUp are uncaught.
314 new Future.sync(() { cleanUp(value); }); 274 new Future.sync(() { cleanUp(value); });
315 } 275 }
316 } 276 }
317 } 277 }
318 values = null; 278 values = null;
319 if (remaining == 0 || eagerError) { 279 if (remaining == 0 || eagerError) {
320 result._completeError(theError, theStackTrace); 280 result._completeError(theError, theStackTrace);
321 } else { 281 } else {
322 error = theError; 282 error = theError;
323 stackTrace = theStackTrace; 283 stackTrace = theStackTrace;
324 } 284 }
325 } else if (remaining == 0 && !eagerError) { 285 } else if (remaining == 0 && !eagerError) {
326 result._completeError(error, stackTrace); 286 result._completeError(error, stackTrace);
327 } 287 }
328 } 288 }
329 289
330 try { 290 // As each future completes, put its value into the corresponding
331 // As each future completes, put its value into the corresponding 291 // position in the list of values.
332 // position in the list of values. 292 for (Future future in futures) {
333 for (Future future in futures) { 293 int pos = remaining++;
334 int pos = remaining; 294 future.then((Object/*=T*/ value) {
335 future.then((T value) { 295 remaining--;
336 remaining--; 296 if (values != null) {
337 if (values != null) { 297 values[pos] = value;
338 values[pos] = value; 298 if (remaining == 0) {
339 if (remaining == 0) { 299 result._completeWithValue(values);
340 result._completeWithValue(values);
341 }
342 } else {
343 if (cleanUp != null && value != null) {
344 // Ensure errors from cleanUp are uncaught.
345 new Future.sync(() { cleanUp(value); });
346 }
347 if (remaining == 0 && !eagerError) {
348 result._completeError(error, stackTrace);
349 }
350 } 300 }
351 }, onError: handleError); 301 } else {
352 // Increment the 'remaining' after the call to 'then'. 302 if (cleanUp != null && value != null) {
353 // If that call throws, we don't expect any future callback from 303 // Ensure errors from cleanUp are uncaught.
354 // the future, and we also don't increment remaining. 304 new Future.sync(() { cleanUp(value); });
355 remaining++; 305 }
356 } 306 if (remaining == 0 && !eagerError) {
357 if (remaining == 0) { 307 result._completeError(error, stackTrace);
358 return new Future.value(const []); 308 }
359 } 309 }
360 values = new List<T>(remaining); 310 }, onError: handleError);
361 } catch (e, st) {
362 // The error must have been thrown while iterating over the futures
363 // list, or while installing a callback handler on the future.
364 if (remaining == 0 || eagerError) {
365 // Throw a new Future.error.
366 // Don't just call `result._completeError` since that would propagate
367 // the error too eagerly, not giving the callers time to install
368 // error handlers.
369 // Also, don't use `_asyncCompleteError` since that one doesn't give
370 // zones the chance to intercept the error.
371 return new Future.error(e, st);
372 } else {
373 // Don't allocate a list for values, thus indicating that there was an
374 // error.
375 // Set error to the caught exception.
376 error = e;
377 stackTrace = st;
378 }
379 } 311 }
312 if (remaining == 0) {
313 return new Future.value(const []);
314 }
315 values = new List/*<T>*/(remaining);
380 return result; 316 return result;
381 } 317 }
382 318
383 /** 319 /**
384 * Returns the result of the first future in [futures] to complete. 320 * Returns the result of the first future in [futures] to complete.
385 * 321 *
386 * The returned future is completed with the result of the first 322 * The returned future is completed with the result of the first
387 * future in [futures] to report that it is complete. 323 * future in [futures] to report that it is complete.
388 * The results of all the other futures are discarded. 324 * The results of all the other futures are discarded.
389 * 325 *
390 * If [futures] is empty, or if none of its futures complete, 326 * If [futures] is empty, or if none of its futures complete,
391 * the returned future never completes. 327 * the returned future never completes.
392 */ 328 */
393 static Future<T> any<T>(Iterable<Future<T>> futures) { 329 static Future/*<T>*/ any/*<T>*/(Iterable<Future/*<T>*/> futures) {
394 var completer = new Completer<T>.sync(); 330 var completer = new Completer/*<T>*/.sync();
395 var onValue = (T value) { 331 var onValue = (/*=T*/ value) {
396 if (!completer.isCompleted) completer.complete(value); 332 if (!completer.isCompleted) completer.complete(value);
397 }; 333 };
398 var onError = (error, stack) { 334 var onError = (error, stack) {
399 if (!completer.isCompleted) completer.completeError(error, stack); 335 if (!completer.isCompleted) completer.completeError(error, stack);
400 }; 336 };
401 for (var future in futures) { 337 for (var future in futures) {
402 future.then(onValue, onError: onError); 338 future.then(onValue, onError: onError);
403 } 339 }
404 return completer.future; 340 return completer.future;
405 } 341 }
(...skipping 14 matching lines...) Expand all
420 */ 356 */
421 static Future forEach(Iterable input, f(element)) { 357 static Future forEach(Iterable input, f(element)) {
422 Iterator iterator = input.iterator; 358 Iterator iterator = input.iterator;
423 return doWhile(() { 359 return doWhile(() {
424 if (!iterator.moveNext()) return false; 360 if (!iterator.moveNext()) return false;
425 return new Future.sync(() => f(iterator.current)).then((_) => true); 361 return new Future.sync(() => f(iterator.current)).then((_) => true);
426 }); 362 });
427 } 363 }
428 364
429 /** 365 /**
430 * Performs an async operation repeatedly until it returns `false`. 366 * Perform an async operation repeatedly until it returns `false`.
431 * 367 *
432 * The function [f] is called repeatedly while it returns either the [bool] 368 * Runs [f] repeatedly, starting the next iteration only when the [Future]
433 * value `true` or a [Future] which completes with the value `true`. 369 * returned by [f] completes to `true`. Returns a [Future] that completes once
370 * [f] returns `false`.
434 * 371 *
435 * If a call to [f] returns `false` or a [Future] that completes to `false`, 372 * The return values of all [Future]s are discarded. Any errors will cause the
436 * iteration ends and the future returned by [doWhile] is completed. 373 * iteration to stop and will be piped through the returned [Future].
437 * 374 *
438 * If a future returned by [f] completes with an error, iteration ends and 375 * The function [f] may return either a [bool] or a [Future] that completes to
439 * the future returned by [doWhile] completes with the same error. 376 * a [bool]. If it returns a non-[Future], iteration continues immediately.
440 * 377 * Otherwise it waits for the returned [Future] to complete.
441 * The [f] function must return either a `bool` value or a [Future] completing
442 * with a `bool` value.
443 */ 378 */
444 static Future doWhile(f()) { 379 static Future doWhile(f()) {
445 _Future doneSignal = new _Future(); 380 _Future doneSignal = new _Future();
446 var nextIteration; 381 var nextIteration;
447 // Bind this callback explicitly so that each iteration isn't bound in the 382 // Bind this callback explicitly so that each iteration isn't bound in the
448 // context of all the previous iterations' callbacks. 383 // context of all the previous iterations' callbacks.
449 nextIteration = Zone.current.bindUnaryCallback((bool keepGoing) { 384 nextIteration = Zone.current.bindUnaryCallback((bool keepGoing) {
450 if (keepGoing) { 385 if (keepGoing) {
451 new Future.sync(f).then(nextIteration, 386 new Future.sync(f).then(nextIteration,
452 onError: doneSignal._completeError); 387 onError: doneSignal._completeError);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 * the future returned by `then` will be completed with 425 * the future returned by `then` will be completed with
491 * the same result as the future returned by the callback. 426 * the same result as the future returned by the callback.
492 * 427 *
493 * If [onError] is not given, and this future completes with an error, 428 * If [onError] is not given, and this future completes with an error,
494 * the error is forwarded directly to the returned future. 429 * the error is forwarded directly to the returned future.
495 * 430 *
496 * In most cases, it is more readable to use [catchError] separately, possibly 431 * In most cases, it is more readable to use [catchError] separately, possibly
497 * with a `test` parameter, instead of handling both value and error in a 432 * with a `test` parameter, instead of handling both value and error in a
498 * single [then] call. 433 * single [then] call.
499 */ 434 */
500 Future<S> then<S>(FutureOr<S> onValue(T value), { Function onError }); 435 Future/*<S>*/ then/*<S>*/(onValue(T value), { Function onError });
501 436
502 /** 437 /**
503 * Handles errors emitted by this [Future]. 438 * Handles errors emitted by this [Future].
504 * 439 *
505 * This is the asynchronous equivalent of a "catch" block. 440 * This is the asynchronous equivalent of a "catch" block.
506 * 441 *
507 * Returns a new [Future] that will be completed with either the result of 442 * Returns a new [Future] that will be completed with either the result of
508 * this future or the result of calling the `onError` callback. 443 * this future or the result of calling the `onError` callback.
509 * 444 *
510 * If this future completes with a value, 445 * If this future completes with a value,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 */ 488 */
554 // The `Function` below can stand for several types: 489 // The `Function` below can stand for several types:
555 // - (dynamic) -> T 490 // - (dynamic) -> T
556 // - (dynamic, StackTrace) -> T 491 // - (dynamic, StackTrace) -> T
557 // - (dynamic) -> Future<T> 492 // - (dynamic) -> Future<T>
558 // - (dynamic, StackTrace) -> Future<T> 493 // - (dynamic, StackTrace) -> Future<T>
559 // Given that there is a `test` function that is usually used to do an 494 // Given that there is a `test` function that is usually used to do an
560 // `isCheck` we should also expect functions that take a specific argument. 495 // `isCheck` we should also expect functions that take a specific argument.
561 // Note: making `catchError` return a `Future<T>` in non-strong mode could be 496 // Note: making `catchError` return a `Future<T>` in non-strong mode could be
562 // a breaking change. 497 // a breaking change.
563 Future<T> catchError(Function onError, 498 Future/*<T>*/ catchError(Function onError,
564 {bool test(Object error)}); 499 {bool test(Object error)});
565 500
566 /** 501 /**
567 * Register a function to be called when this future completes. 502 * Register a function to be called when this future completes.
568 * 503 *
569 * The [action] function is called when this future completes, whether it 504 * The [action] function is called when this future completes, whether it
570 * does so with a value or with an error. 505 * does so with a value or with an error.
571 * 506 *
572 * This is the asynchronous equivalent of a "finally" block. 507 * This is the asynchronous equivalent of a "finally" block.
573 * 508 *
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 if (replacement != null) { 755 if (replacement != null) {
821 error = _nonNullError(replacement.error); 756 error = _nonNullError(replacement.error);
822 stackTrace = replacement.stackTrace; 757 stackTrace = replacement.stackTrace;
823 } 758 }
824 result._completeError(error, stackTrace); 759 result._completeError(error, stackTrace);
825 } 760 }
826 761
827 /** Helper function that converts `null` to a [NullThrownError]. */ 762 /** Helper function that converts `null` to a [NullThrownError]. */
828 Object _nonNullError(Object error) => 763 Object _nonNullError(Object error) =>
829 (error != null) ? error : new NullThrownError(); 764 (error != null) ? error : new NullThrownError();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698