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

Side by Side Diff: sdk/lib/async/zone.dart

Issue 2082553003: More documentation for zones. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: A few small improvements. Created 4 years, 5 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 typedef R ZoneCallback<R>(); 7 typedef R ZoneCallback<R>();
8 typedef R ZoneUnaryCallback<R, T>(T arg); 8 typedef R ZoneUnaryCallback<R, T>(T arg);
9 typedef R ZoneBinaryCallback<R, T1, T2>(T1 arg1, T2 arg2); 9 typedef R ZoneBinaryCallback<R, T1, T2>(T1 arg1, T2 arg2);
10 10
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 typedef void RunTaskHandler/*<T, A>*/(Zone self, ZoneDelegate parent, Zone zone, 50 typedef void RunTaskHandler/*<T, A>*/(Zone self, ZoneDelegate parent, Zone zone,
51 TaskRun/*<T, A>*/ run, Object/*=T*/ task, Object/*=A*/ arg); 51 TaskRun/*<T, A>*/ run, Object/*=T*/ task, Object/*=A*/ arg);
52 typedef void ScheduleMicrotaskHandler( 52 typedef void ScheduleMicrotaskHandler(
53 Zone self, ZoneDelegate parent, Zone zone, void f()); 53 Zone self, ZoneDelegate parent, Zone zone, void f());
54 typedef void PrintHandler( 54 typedef void PrintHandler(
55 Zone self, ZoneDelegate parent, Zone zone, String line); 55 Zone self, ZoneDelegate parent, Zone zone, String line);
56 typedef Zone ForkHandler(Zone self, ZoneDelegate parent, Zone zone, 56 typedef Zone ForkHandler(Zone self, ZoneDelegate parent, Zone zone,
57 ZoneSpecification specification, 57 ZoneSpecification specification,
58 Map zoneValues); 58 Map zoneValues);
59 59
60 // Typedefs for methods, that will be deprecated once tasks are 60 // Typedefs for methods, that will be deprecated once tasks are
Lasse Reichstein Nielsen 2016/07/01 11:25:01 remove comma. This is not a dart-doc, so it doesn
floitsch 2016/07/02 03:11:20 Done.
61 // non-experimental. 61 // non-experimental.
62 typedef Timer CreateTimerHandler( 62 typedef Timer CreateTimerHandler(
63 Zone self, ZoneDelegate parent, Zone zone, Duration duration, void f()); 63 Zone self, ZoneDelegate parent, Zone zone, Duration duration, void f());
64 typedef Timer CreatePeriodicTimerHandler( 64 typedef Timer CreatePeriodicTimerHandler(
65 Zone self, ZoneDelegate parent, Zone zone, 65 Zone self, ZoneDelegate parent, Zone zone,
66 Duration period, void f(Timer timer)); 66 Duration period, void f(Timer timer));
67 67
68 /** Pair of error and stack trace. Returned by [Zone.errorCallback]. */ 68 /** Pair of error and stack trace. Returned by [Zone.errorCallback]. */
69 class AsyncError implements Error { 69 class AsyncError implements Error {
70 final Object error; 70 final Object error;
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 final PrintHandler print; 270 final PrintHandler print;
271 final ForkHandler fork; 271 final ForkHandler fork;
272 272
273 // TODO(floitsch): deprecate once tasks are non-experimental. 273 // TODO(floitsch): deprecate once tasks are non-experimental.
274 final CreateTimerHandler createTimer; 274 final CreateTimerHandler createTimer;
275 // TODO(floitsch): deprecate once tasks are non-experimental. 275 // TODO(floitsch): deprecate once tasks are non-experimental.
276 final CreatePeriodicTimerHandler createPeriodicTimer; 276 final CreatePeriodicTimerHandler createPeriodicTimer;
277 } 277 }
278 278
279 /** 279 /**
280 * This class wraps zones for delegation. 280 * An adapted view of the parent zone.
281 * 281 *
282 * When forwarding to parent zones one can't just invoke the parent zone's 282 * This class allows the implementation of a zone method to invoke methods on
283 * exposed functions (like [Zone.run]), but one needs to provide more 283 * the parent zone while retaining knowledge of the originating zone.
284 * information (like the zone the `run` was initiated). Zone callbacks thus 284 *
285 * receive more information including this [ZoneDelegate] class. When delegating 285 * Custom zones (created through [Zone.fork] or [runZoned]) can provide
286 * to the parent zone one should go through the given instance instead of 286 * implementations of most methods of zones. This is similar to overriding
287 * directly invoking the parent zone. 287 * methods on [Zone], except that this mechanism doesn't require subclassing.
288 *
289 * A custom zone function (provided through a [ZoneSpecification]) typically
290 * records or wraps its parameters and then delegates the operation to its
291 * parent zone using the provided [ZoneDelegate].
292 *
293 * While zones have access to their parent zone (through [Zone.parent]) it is
294 * recommended to call the methods on the provided parent delegate for two
295 * reasons:
296 * 1. the delegate methods take an additional `zone` argument which is the
297 * zone the action has been initiated in.
298 * 2. delegate calls are more efficient, since the implementation knows how
299 * to skip zones that would just delegate to their parents.
288 */ 300 */
289 abstract class ZoneDelegate { 301 abstract class ZoneDelegate {
290 /*=R*/ handleUncaughtError/*<R>*/( 302 /*=R*/ handleUncaughtError/*<R>*/(
291 Zone zone, error, StackTrace stackTrace); 303 Zone zone, error, StackTrace stackTrace);
292 /*=R*/ run/*<R>*/(Zone zone, /*=R*/ f()); 304 /*=R*/ run/*<R>*/(Zone zone, /*=R*/ f());
293 /*=R*/ runUnary/*<R, T>*/(Zone zone, /*=R*/ f(/*=T*/ arg), /*=T*/ arg); 305 /*=R*/ runUnary/*<R, T>*/(Zone zone, /*=R*/ f(/*=T*/ arg), /*=T*/ arg);
294 /*=R*/ runBinary/*<R, T1, T2>*/(Zone zone, 306 /*=R*/ runBinary/*<R, T1, T2>*/(Zone zone,
295 /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2); 307 /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2);
296 ZoneCallback/*<R>*/ registerCallback/*<R>*/(Zone zone, /*=R*/ f()); 308 ZoneCallback/*<R>*/ registerCallback/*<R>*/(Zone zone, /*=R*/ f());
297 ZoneUnaryCallback/*<R, T>*/ registerUnaryCallback/*<R, T>*/( 309 ZoneUnaryCallback/*<R, T>*/ registerUnaryCallback/*<R, T>*/(
(...skipping 13 matching lines...) Expand all
311 void print(Zone zone, String line); 323 void print(Zone zone, String line);
312 Zone fork(Zone zone, ZoneSpecification specification, Map zoneValues); 324 Zone fork(Zone zone, ZoneSpecification specification, Map zoneValues);
313 325
314 // TODO(floitsch): deprecate once tasks are non-experimental. 326 // TODO(floitsch): deprecate once tasks are non-experimental.
315 Timer createTimer(Zone zone, Duration duration, void f()); 327 Timer createTimer(Zone zone, Duration duration, void f());
316 // TODO(floitsch): deprecate once tasks are non-experimental. 328 // TODO(floitsch): deprecate once tasks are non-experimental.
317 Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer)); 329 Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer));
318 } 330 }
319 331
320 /** 332 /**
321 * A Zone represents the asynchronous version of a dynamic extent. Asynchronous 333 * A zone represents an environment that remains stable across asynchronous
322 * callbacks are executed in the zone they have been queued in. For example, 334 * calls.
323 * the callback of a `future.then` is executed in the same zone as the one where 335 *
324 * the `then` was invoked. 336 * Asynchronous callbacks are executed in the zone they have been queued in. For
337 * example, the callback of a `future.then` is executed in the same zone as the
338 * one where the `then` was invoked.
Lasse Reichstein Nielsen 2016/07/01 11:25:01 Consider moving this paragraph somewhere after "Co
floitsch 2016/07/02 03:11:20 Done. Removed.
339 *
340 * Code is always executed in the context of a zone, available as
341 * [Zone.current]. The initial `main` function runs in the context of the
342 * default zone ([Zone.ROOT]). Code can be run in a different zone using either
343 * [runZoned], to create a new zone, or [Zone.run] to run code in the context of
344 * an existing zone likely created using [Zone.fork].
345 *
346 * Developers can create a new zone that overrides some of the functionality of
347 * an existing zone. For example, custom zones can replace of modify the
348 * behavior of `print`, timers, microtasks or how uncaught errors are handled.
349 *
350 * The [Zone] class is not subclassable, but users can provide custom zones by
351 * forking an existing zone (usually [Zone.current]) with a [ZoneSpecification].
352 * This is similar to creating a new class that extends the base `Zone` class
353 * and that overrides some methods, except without actually creating a new
354 * class. Instead the overriding methods are provided as functions that
355 * explicitly take the equivalent of their own class, the "super" class and the
356 * `this` object as parameters.
357 *
358 * Asynchronous callbacks always run in the context of the zone where they were
359 * scheduled. This is implemented using two steps:
Lasse Reichstein Nielsen 2016/07/01 11:25:01 Is this repeating paragraph 2 above? (if so, maybe
floitsch 2016/07/02 03:11:19 Done.
360 * 1. the callback is first registered using one of [registerCallback],
361 * [registerUnaryCallback], or [registerBinaryCallback]. This allows the zone
362 * to record that a callback exists and potentially modify it (by returning a
363 * different callback). The code doing the registration (e.g., `Future.then`)
364 * also remembers the current zone so that it can later run the callback in
365 * that zone.
366 * 2. At a later point the registered callback is run in the remembered zone.
367 *
368 * This is all handled internally by the platform code and most users don't need
369 * to worry about it. However, developers of new asynchronous operations,
370 * provided by the underlying system or through native extensions, must follow
371 * the protocol to be zone compatible.
372 *
373 * For convenience, zones provide [bindCallback] (and the corresponding
374 * [bindUnaryCallback] or [bindBinaryCallback]) to make it easier to respect the
375 * zone contract: these functions first invoke the corresponding `register`
376 * functions and then wrap the returned function so that it runs in the current
377 * zone when it is later asynchronously invoked.
325 */ 378 */
326 abstract class Zone { 379 abstract class Zone {
327 // Private constructor so that it is not possible instantiate a Zone class. 380 // Private constructor so that it is not possible instantiate a Zone class.
328 Zone._(); 381 Zone._();
329 382
330 /** The root zone that is implicitly created. */ 383 /**
384 * The root zone.
385 *
386 * All isolate entry functions (`main` or spawned functions) start running in
387 * the root zone. Without any custom zone the whole program always runs in the
Lasse Reichstein Nielsen 2016/07/01 11:25:01 Without any custom zone .. -> If no custom zone i
floitsch 2016/07/02 03:11:20 Done.
388 * root zone and [Zone.current] is always identical to [Zone.ROOT].
389 *
390 * The root zone implements the default behavior of all zone operations.
391 * Many methods, like [registerCallback] do the bare minimum, others, like
Lasse Reichstein Nielsen 2016/07/01 11:25:01 ... do the bare minimum, and are only provided as
floitsch 2016/07/02 03:11:20 Done.
392 * [scheduleMicrotask] interact with the underlying system to implement the
Lasse Reichstein Nielsen 2016/07/01 11:25:01 comma before interact.
floitsch 2016/07/02 03:11:19 Done.
393 * desired behavior.
394 */
331 static const Zone ROOT = _ROOT_ZONE; 395 static const Zone ROOT = _ROOT_ZONE;
332 396
333 /** The currently running zone. */ 397 /** The currently running zone. */
334 static Zone _current = _ROOT_ZONE; 398 static Zone _current = _ROOT_ZONE;
335 399
400 /** The zone that is currently active. */
336 static Zone get current => _current; 401 static Zone get current => _current;
337 402
403 /**
404 * Handles uncaught asynchronous errors.
405 *
406 * There are two kind of asynchronous errors that are handled by this
407 * function:
408 * 1. uncaught errors that were thrown in asynchronous callbacks. For example,
Lasse Reichstein Nielsen 2016/07/01 11:25:01 Start with capital letter. I'd prefer a comma inst
floitsch 2016/07/02 03:11:19 Done.
409 * a `throw` in [Timer.run].
Lasse Reichstein Nielsen 2016/07/01 11:25:02 ... a throw in the function passed to [Timer.run].
floitsch 2016/07/02 03:11:19 Done.
410 * 2. asynchronous errors that are pushed down [Future] and [Stream] chains
Lasse Reichstein Nielsen 2016/07/01 11:25:01 Start with capital letter again. maybe: down -> th
floitsch 2016/07/02 03:11:20 Done.
411 * but for which no child registered an error handled.
Lasse Reichstein Nielsen 2016/07/01 11:25:01 Comma before but (it's optional, but I would prefe
floitsch 2016/07/02 03:11:19 Done.
412 * Most asynchronous classes, like [Future] or [Stream] push errors to their
413 * listeners. Errors are propagated this way until either a listener handles
414 * the error (for example with [Future.catchError]), or no listener is
415 * available anymore. In the latter case, futures and streams invoke the
416 * zone's [handleUncaughtError].
417 *
418 * By default, when handled by the root zone, uncaught asynchronous errors are
419 * treated like synchronous uncaught exceptions.
Lasse Reichstein Nielsen 2016/07/01 11:25:01 I'd say "uncaught synchronous exceptions". I just
floitsch 2016/07/02 03:11:19 Done.
420 */
338 /*=R*/ handleUncaughtError/*<R>*/(error, StackTrace stackTrace); 421 /*=R*/ handleUncaughtError/*<R>*/(error, StackTrace stackTrace);
339 422
340 /** 423 /**
341 * Returns the parent zone. 424 * Returns the parent zone.
Lasse Reichstein Nielsen 2016/07/01 11:25:01 Describe a getter like a property, not a method. I
floitsch 2016/07/02 03:11:20 Done.
342 * 425 *
343 * Returns `null` if `this` is the [ROOT] zone. 426 * Returns `null` if `this` is the [ROOT] zone.
Lasse Reichstein Nielsen 2016/07/01 11:25:01 -> Is `null` if ...
floitsch 2016/07/02 03:11:20 Done.
427 *
428 * Zones are created by [fork] on an existing zone, or by [runZoned] which
429 * forks the [current] zone. The new zone's parent zone is the zone it was
430 * forked from.
344 */ 431 */
345 Zone get parent; 432 Zone get parent;
346 433
347 /** 434 /**
348 * The error zone is the one that is responsible for dealing with uncaught 435 * The error zone is the one that is responsible for dealing with uncaught
349 * errors. 436 * errors.
350 * Errors are not allowed to cross between zones with different error-zones. 437 *
351 * 438 * This is the closest parent zone of this zone that provides a
352 * This is the closest parent or ancestor zone of this zone that has a custom
353 * [handleUncaughtError] method. 439 * [handleUncaughtError] method.
440 *
441 * Asynchronous errors never cross zone boundaries between zones with
442 * different error handlers.
443 *
444 * Example:
445 * ```
446 * import 'dart:async';
447 *
448 * main() {
449 * var future;
450 * runZoned(() {
451 * // The asynchronous error is caught by the custom zone which prints
452 * // 'asynchronous error'.
453 * future = new Future.error("asynchronous error");
454 * }, onError: (e) { print(e); }); // Creates a zone with an error handler.
455 * // The following `catchError` handler is never invoked, because the
456 * // custom zone created by the call to `runZoned` provides an
457 * // error handler.
458 * future.catchError((e) { throw "is never reached"; });
459 * }
460 * ```
461 *
462 * Note that errors can not enter a child zone with a different error handler
Lasse Reichstein Nielsen 2016/07/01 11:25:01 can not -> cannot (or can't).
floitsch 2016/07/02 03:11:20 Done.
463 * either:
464 * ```
465 * import 'dart:async';
466 *
467 * main() {
468 * runZoned(() {
469 * // The following asynchronous error is *not* caught by the `catchError`
470 * // in the nested zone, since errors are not to cross zone boundaries
471 * // with different error handlers.
472 * // Instead the error is handled by the current error handler,
473 * // printing "Caught by outer zone: asynchronous error".
474 * var future = new Future.error("asynchronous error");
475 * runZoned(() {
476 * future.catchError((e) { throw "is never reached"; });
477 * }, onError: (e) { throw "is never reached"; });
478 * }, onError: (e) { print("Caught by outer zone: $e"); });
479 * }
480 * ```
354 */ 481 */
355 Zone get errorZone; 482 Zone get errorZone;
356 483
357 /** 484 /**
358 * Returns true if `this` and [otherZone] are in the same error zone. 485 * Returns true if `this` and [otherZone] are in the same error zone.
359 * 486 *
360 * Two zones are in the same error zone if they inherit their 487 * Two zones are in the same error zone if they have the same [errorZone].
361 * [handleUncaughtError] callback from the same [errorZone].
362 */ 488 */
363 bool inSameErrorZone(Zone otherZone); 489 bool inSameErrorZone(Zone otherZone);
364 490
365 /** 491 /**
366 * Creates a new zone as a child of `this`. 492 * Creates a new zone as a child of `this`.
367 * 493 *
368 * The new zone will have behavior like the current zone, except where 494 * The new zone uses the closures in the given [specification] to override
369 * overridden by functions in [specification]. 495 * the current's zone behavior. All specification entries that are `null`
370 * 496 * inherit the behavior from the parent zone (`this`).
371 * The new zone will have the same stored values (accessed through 497 *
372 * `operator []`) as this zone, but updated with the keys and values 498 * The new zone inherits the stored values (accessed through `operator []`)
Lasse Reichstein Nielsen 2016/07/04 14:14:19 [operator []] (if you can write that in DartDoc
floitsch 2016/07/05 15:39:57 Dartdoc doesn't link it, but at least doesn't "bre
373 * in [zoneValues]. If a key is in both this zone's values and in 499 * of this zone and updates them with values from [zoneValues], which either
374 * `zoneValues`, the new zone will use the value from `zoneValues``. 500 * adds new values or overrides existing ones.
375 */ 501 *
376 Zone fork({ ZoneSpecification specification, 502 * Note that the fork operation is interceptible. A zone can thus change
377 Map zoneValues }); 503 * the zone specification (or zone values), giving the forking zone full
378 504 * control over the child zone.
379 /** 505 */
380 * Executes the given function [f] in this zone. 506 Zone fork({ZoneSpecification specification,
381 */ 507 Map zoneValues});
382 /*=R*/ run/*<R>*/(/*=R*/ f()); 508
383 509 /**
384 /** 510 * Executes [action] in this zone.
385 * Executes the given callback [f] with argument [arg] in this zone. 511 *
386 */ 512 * By default (as implemented in the [ROOT] zone), runs [action]
387 /*=R*/ runUnary/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg); 513 * with [current] set to this zone.
388 514 *
389 /** 515 * If [action] throws, the synchronous exception is not caught by the zone's
390 * Executes the given callback [f] with argument [arg1] and [arg2] in this 516 * error handler. Use [runGuarded] to achieve that.
517 *
518 * Since the root zone is the only zone that can modify the value of
519 * [current], custom zones intercepting run should always delegate to their
520 * parent zone. They may take actions before and after the call.
521 */
522 /*=R*/ run/*<R>*/(/*=R*/ action());
523
524 /**
525 * Executes the given [action] with [argument] in this zone.
526 *
527 * As [run] except that [action] is called with one [argument] instead of
528 * none.
529 */
530 /*=R*/ runUnary/*<R, T>*/(/*=R*/ action(/*=T*/ argument), /*=T*/ argument);
531
532 /**
533 * Executes the given [action] with [argument1] and [argument2] in this
391 * zone. 534 * zone.
535 *
536 * As [run] except that [action] is called with two arguments instead of none.
392 */ 537 */
393 /*=R*/ runBinary/*<R, T1, T2>*/( 538 /*=R*/ runBinary/*<R, T1, T2>*/(
394 /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2); 539 /*=R*/ action(/*=T1*/ argument1, /*=T2*/ argument2), /*=T1*/ argument1,
395 540 /*=T2*/ argument2);
396 /** 541
397 * Executes the given function [f] in this zone. 542 /**
398 * 543 * Executes the given [action] in this zone and catches synchronous
399 * Same as [run] but catches uncaught errors and gives them to 544 * errors.
400 * [handleUncaughtError]. 545 *
401 */ 546 * This function is equivalent to:
402 /*=R*/ runGuarded/*<R>*/(/*=R*/ f()); 547 * ```
403 548 * try {
404 /** 549 * return this.run(action);
405 * Executes the given callback [f] in this zone. 550 * } catch (e, s) {
406 * 551 * return this.handleUncaughtError(e, s);
407 * Same as [runUnary] but catches uncaught errors and gives them to 552 * }
408 * [handleUncaughtError]. 553 * ```
409 */ 554 *
410 /*=R*/ runUnaryGuarded/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg); 555 * See [run].
411 556 */
412 /** 557 /*=R*/ runGuarded/*<R>*/(/*=R*/ action());
413 * Executes the given callback [f] in this zone. 558
414 * 559 /**
415 * Same as [runBinary] but catches uncaught errors and gives them to 560 * Executes the given [action] with [argument] in this zone and
416 * [handleUncaughtError]. 561 * catches synchronous errors.
562 *
563 * See [runGuarded].
564 */
565 /*=R*/ runUnaryGuarded/*<R, T>*/(/*=R*/ action(/*=T*/ argument),
566 /*=T*/ argument);
567
568 /**
569 * Executes the given [action] with [argument1] and [argument2] in this
570 * zone and catches synchronous errors.
571 *
572 * See [runGuarded].
417 */ 573 */
418 /*=R*/ runBinaryGuarded/*<R, T1, T2>*/( 574 /*=R*/ runBinaryGuarded/*<R, T1, T2>*/(
419 /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2); 575 /*=R*/ action(/*=T1*/ argument1, /*=T2*/ argument2), /*=T1*/ argument1,
576 /*=T2*/ argument2);
420 577
421 /** 578 /**
422 * Registers the given callback in this zone. 579 * Registers the given callback in this zone.
423 * 580 *
424 * It is good practice to register asynchronous or delayed callbacks before 581 * When implementing an asynchronous primitive that uses callbacks, the
425 * invoking [run]. This gives the zone a chance to wrap the callback and 582 * callback must be registered using [registerCallback] at the point where the
426 * to store information with the callback. For example, a zone may decide 583 * user provides the callback. This allows zones to record other information
584 * that they need at the same time, perhaps even wrapping the callback, so
585 * that the callback is prepared when it is later run in the same zones
586 * (using [run]). For example, a zone may decide
427 * to store the stack trace (at the time of the registration) with the 587 * to store the stack trace (at the time of the registration) with the
428 * callback. 588 * callback.
429 * 589 *
430 * Returns a potentially new callback that should be used in place of the 590 * Returns the callback that should be used in place of the provided
431 * given [callback]. 591 * [callback]. Frequently zones simply return the original callback.
592 *
593 * Custom zones may intercept this operation. The default implementation in
594 * [Zone.ROOT] returns the original callback unchanged.
432 */ 595 */
433 ZoneCallback/*<R>*/ registerCallback/*<R>*/(/*=R*/ callback()); 596 ZoneCallback/*<R>*/ registerCallback/*<R>*/(/*=R*/ callback());
434 597
435 /** 598 /**
436 * Registers the given callback in this zone. 599 * Registers the given callback in this zone.
437 * 600 *
438 * Similar to [registerCallback] but with a unary callback. 601 * Similar to [registerCallback] but with a unary callback.
439 */ 602 */
440 ZoneUnaryCallback/*<R, T>*/ registerUnaryCallback/*<R, T>*/( 603 ZoneUnaryCallback/*<R, T>*/ registerUnaryCallback/*<R, T>*/(
441 /*=R*/ callback(/*=T*/ arg)); 604 /*=R*/ callback(/*=T*/ arg));
442 605
443 /** 606 /**
444 * Registers the given callback in this zone. 607 * Registers the given callback in this zone.
445 * 608 *
446 * Similar to [registerCallback] but with a unary callback. 609 * Similar to [registerCallback] but with a unary callback.
447 */ 610 */
448 ZoneBinaryCallback/*<R, T1, T2>*/ registerBinaryCallback/*<R, T1, T2>*/( 611 ZoneBinaryCallback/*<R, T1, T2>*/ registerBinaryCallback/*<R, T1, T2>*/(
449 /*=R*/ callback(/*=T1*/ arg1, /*=T2*/ arg2)); 612 /*=R*/ callback(/*=T1*/ arg1, /*=T2*/ arg2));
450 613
451 /** 614 /**
452 * Equivalent to: 615 * Equivalent to:
453 * 616 *
454 * ZoneCallback registered = registerCallback(f); 617 * ZoneCallback registered = this.registerCallback(action);
455 * if (runGuarded) return () => this.runGuarded(registered); 618 * if (runGuarded) return () => this.runGuarded(registered);
456 * return () => this.run(registered); 619 * return () => this.run(registered);
457 * 620 *
458 */ 621 */
459 ZoneCallback/*<R>*/ bindCallback/*<R>*/( 622 ZoneCallback/*<R>*/ bindCallback/*<R>*/(
460 /*=R*/ f(), { bool runGuarded: true }); 623 /*=R*/ action(), { bool runGuarded: true });
461 624
462 /** 625 /**
463 * Equivalent to: 626 * Equivalent to:
464 * 627 *
465 * ZoneCallback registered = registerUnaryCallback(f); 628 * ZoneCallback registered = this.registerUnaryCallback(action);
466 * if (runGuarded) return (arg) => this.runUnaryGuarded(registered, arg); 629 * if (runGuarded) return (arg) => this.runUnaryGuarded(registered, arg);
467 * return (arg) => thin.runUnary(registered, arg); 630 * return (arg) => thin.runUnary(registered, arg);
468 */ 631 */
469 ZoneUnaryCallback/*<R, T>*/ bindUnaryCallback/*<R, T>*/( 632 ZoneUnaryCallback/*<R, T>*/ bindUnaryCallback/*<R, T>*/(
470 /*=R*/ f(/*=T*/ arg), { bool runGuarded: true }); 633 /*=R*/ action(/*=T*/ argument), { bool runGuarded: true });
471 634
472 /** 635 /**
473 * Equivalent to: 636 * Equivalent to:
474 * 637 *
475 * ZoneCallback registered = registerBinaryCallback(f); 638 * ZoneCallback registered = registerBinaryCallback(action);
476 * if (runGuarded) { 639 * if (runGuarded) {
477 * return (arg1, arg2) => this.runBinaryGuarded(registered, arg); 640 * return (arg1, arg2) => this.runBinaryGuarded(registered, arg);
478 * } 641 * }
479 * return (arg1, arg2) => thin.runBinary(registered, arg1, arg2); 642 * return (arg1, arg2) => thin.runBinary(registered, arg1, arg2);
480 */ 643 */
481 ZoneBinaryCallback/*<R, T1, T2>*/ bindBinaryCallback/*<R, T1, T2>*/( 644 ZoneBinaryCallback/*<R, T1, T2>*/ bindBinaryCallback/*<R, T1, T2>*/(
482 /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), { bool runGuarded: true }); 645 /*=R*/ action(/*=T1*/ argument1, /*=T2*/ argument2),
646 { bool runGuarded: true });
483 647
484 /** 648 /**
485 * Intercepts errors when added programmatically to a `Future` or `Stream`. 649 * Intercepts errors when added programatically to a `Future` or `Stream`.
486 * 650 *
487 * When caling [Completer.completeError], [Stream.addError], 651 * When calling [Completer.completeError], [Stream.addError],
488 * or [Future] constructors that take an error or a callback that may throw, 652 * or for some [Future] constructors the current zone is allowed to intercept
Lasse Reichstein Nielsen 2016/07/01 11:25:01 remove "for". Consider a comma before "the current
floitsch 2016/07/02 03:11:19 Done.
489 * the current zone is allowed to intercept and replace the error. 653 * and replace the error.
490 * 654 *
491 * When other libraries use intermediate controllers or completers, such 655 * Future constructors invoke this function when the error is received
492 * calls may contain errors that have already been processed. 656 * directly, for example with [Future.error], or when the error is caught
657 * synchronously, for example with [Future.sync].
493 * 658 *
494 * Return `null` if no replacement is desired. 659 * There is no guarantee that an error is only sent through [errorCallback]
495 * The original error is used unchanged in that case. 660 * once. Libraries that use intermediate controllers or completers might
496 * Otherwise return an instance of [AsyncError] holding 661 * end up invoking [errorCallback] multiple times.
497 * the new pair of error and stack trace. 662 *
498 * If the [AsyncError.error] is `null`, it is replaced by a [NullThrownError]. 663 * Returns `null` if no replacement is desired. Otherwise returns an instance
664 * of [AsyncError] holding the new pair of error and stack trace.
665 *
666 * Although not recommended, the returned instance may have its `error` member
667 * ([AsyncError.error]) be equal to `null` in which case the error should be
668 * replaced by a [NullThrownError].
669 *
670 * Custom zones may intercept this operation.
671 *
672 * Implementations of a new asynchronous primitive that converts synchronous
673 * errors to asynchronous errors rarely need to invoke [errorCallback], since
674 * errors are usually reported through future completers or stream
675 * controllers.
499 */ 676 */
500 AsyncError errorCallback(Object error, StackTrace stackTrace); 677 AsyncError errorCallback(Object error, StackTrace stackTrace);
501 678
502 /** 679 /**
503 * Runs [f] asynchronously in this zone. 680 * Runs [action] asynchronously in this zone.
681 *
682 * The global `scheduleMicrotask` delegates to the current zone's
683 * [scheduleMicrotask]. The root zone's implementation interacts with the
684 * underlying system to schedule the given callback as a microtask.
685 *
686 * Custom zones may intercept this operation (for example to wrap the given
687 * callback [action]).
504 */ 688 */
505 void scheduleMicrotask(void f()); 689 void scheduleMicrotask(void action());
506 690
507 /** 691 /**
508 * Creates a task, given a [create] function and a [specification]. 692 * Creates a task in the current zone.
509 * 693 *
510 * The [create] function is invoked with the [specification] as argument. It 694 * A task represents an asynchronous operation or process that reports back
511 * returns a task object which is used for all future interactions with the 695 * through the event loop.
512 * zone.
513 * 696 *
514 * Custom zones may replace the [specification] with a different one, thus 697 * This function allows the zone to intercept the initialization of the
515 * modifying the task parameters. 698 * task while the [runTask] function is invoked when the task reports back.
516 * 699 *
517 * Tasks are created when the program is starting an operation that returns 700 * By default, in the root zone, the [create] function is invoked with the
518 * through the event loop. For example, a timer or an http request both 701 * [specification] as argument. It returns a task object which is used for all
702 * future interactions between the zone and the task. The object is
703 * a unique instance representing the task. It is generally returned to
704 * whoever initiated the task.
705 * For example, the HTML library uses the returned [StreamSubscription] as
706 * task object when users register an event listener.
707 *
708 * Tasks are created when the program starts an operation that reports back
709 * through the event loop. For example, a timer or an HTTP request both
519 * return through the event loop and are therefore tasks. 710 * return through the event loop and are therefore tasks.
520 * 711 *
521 * If the [create] function is not invoked (because a custom zone has 712 * If the [create] function is not invoked (because a custom zone has
522 * replaced or intercepted it), then the operation is *not* started. This 713 * replaced or intercepted it), then the operation is *not* started. This
523 * means that a custom zone can intercept tasks, like http requests. 714 * means that a custom zone can intercept tasks, like HTTP requests.
715 *
716 * A task goes through the following steps:
717 * - a user invokes a library function that should eventually return through
718 * the event loop.
719 * - the library function creates a [TaskSpecification] that contains the
720 * necessary information to start the operation, and invokes
721 * `Zone.current.createTask` with the specification and a [create] closure.
722 * The closure, when invoked, uses the specification to start the operation
723 * (usually by interacting with the underlying system, or as a native
724 * extension), and returns a task object that identifies the running task.
725 * - custom zones handle the request and (unless completely intercepted and
726 * aborted), end up calling the root zone's [createTask] which runs the
727 * provided `create` closure, which may have been replaced at this point.
728 * - later, the asynchronous operation returns through the event loop.
729 * It invokes [Zone.runTask] on the zone in which the task should run
730 * (and which was originally passed to the `create` function by
731 * `createTask`). The [runTask] function receives the
732 * task object, a `run` function and an argument. As before, custom zones
733 * may intercept this call. Eventually (unless aborted), the `run` function
734 * is invoked. This last step may happen multiple times for tasks that are
735 * not oneshot tasks (see [ZoneSpecification.isOneShot]).
736 *
737 * Custom zones may replace the [specification] with a different one, thus
738 * modifying the task parameters. An operation that wishes to be an
739 * interceptable task must publicly specify the types that intercepting code
740 * sees:
741 * - The specification type (extending [TaskSpecification]) which holds the
742 * information available when intercepting the `createTask` call.
743 * - The task object type, returned by `createTask` and [create]. This object
744 * may simply be typed as [Object].
745 * - The argument type, if [runTask] takes a meaningful argument.
524 * 746 *
525 * *Experimental*. Might disappear without notice. 747 * *Experimental*. Might disappear without notice.
526 */ 748 */
527 Object/*=T*/ createTask/*<T, S>*/( 749 Object/*=T*/ createTask/*<T, S extends TaskSpecification>*/(
528 TaskCreate/*<T, S>*/ create, TaskSpecification/*=S*/ specification); 750 /*=T*/ create(S specification, Zone zone),
751 TaskSpecification/*=S*/ specification);
529 752
530 /** 753 /**
531 * Runs a task callback. 754 * Runs a task callback.
532 * 755 *
533 * This function is invoked, when an operation, started through [createTask], 756 * This function is invoked when an operation, started through [createTask],
534 * returns to Dart code. 757 * returns to Dart code.
535 * 758 *
536 * Generally, tasks schedule Dart code in the global event loop. As such, 759 * Generally, tasks schedule Dart code in the global event loop. As such,
537 * there is no return value, and [runTask] is a void function. 760 * there is no return value, and [runTask] is a void function.
538 * 761 *
539 * The [task] object must be the same as the one created with [createTask]. 762 * The [task] object must be the same as the one created with [createTask].
540 * 763 *
541 * It is good practice, if task operations provide a meaningful [arg], so 764 * It is good practice, if task operations provide a meaningful [argument], so
542 * that custom zones can deal with it. They might want to log it, or 765 * that custom zones can deal with it. They might want to log it, or
543 * replace it. 766 * replace it.
544 * 767 *
768 * See [createTask].
769 *
545 * *Experimental*. Might disappear without notice. 770 * *Experimental*. Might disappear without notice.
546 */ 771 */
547 void runTask/*<T, A>*/( 772 void runTask/*<T, A>*/(
548 TaskRun/*<T, A>*/ run, Object/*=T*/ task, Object/*=A*/ arg); 773 /*=T*/ run(/*=T*/ task, /*=A*/ argument), Object/*=T*/ task,
774 Object/*=A*/ argument);
549 775
550 /** 776 /**
551 * Creates a Timer where the callback is executed in this zone. 777 * Creates a Timer where the callback is executed in this zone.
552 */ 778 */
553 // TODO(floitsch): deprecate once tasks are non-experimental. 779 // TODO(floitsch): deprecate once tasks are non-experimental.
554 Timer createTimer(Duration duration, void callback()); 780 Timer createTimer(Duration duration, void callback());
555 781
556 /** 782 /**
557 * Creates a periodic Timer where the callback is executed in this zone. 783 * Creates a periodic Timer where the callback is executed in this zone.
558 */ 784 */
559 // TODO(floitsch): deprecate once tasks are non-experimental. 785 // TODO(floitsch): deprecate once tasks are non-experimental.
560 Timer createPeriodicTimer(Duration period, void callback(Timer timer)); 786 Timer createPeriodicTimer(Duration period, void callback(Timer timer));
561 787
562 /** 788 /**
563 * Prints the given [line]. 789 * Prints the given [line].
790 *
791 * The global `print` function delegates to the current zone's [print]
792 * function which makes it possible to intercept printing.
793 *
794 * Example:
795 * ```
796 * import 'dart:async';
797 *
798 * main() {
799 * runZoned(() {
800 * // Ends up printing: "Intercepted: in zone".
801 * print("in zone");
802 * }, zoneSpecification: new ZoneSpecification(
803 * print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
804 * parent.print(zone, "Intercepted: $line");
805 * }));
806 * }
807 * ```
564 */ 808 */
565 void print(String line); 809 void print(String line);
566 810
567 /** 811 /**
568 * Call to enter the Zone. 812 * Call to enter the Zone.
569 * 813 *
570 * The previous current zone is returned. 814 * The previous current zone is returned.
571 */ 815 */
572 static Zone _enter(Zone zone) { 816 static Zone _enter(Zone zone) {
573 assert(zone != null); 817 assert(zone != null);
(...skipping 955 matching lines...) Expand 10 before | Expand all | Expand 10 after
1529 handleUncaughtError: errorHandler); 1773 handleUncaughtError: errorHandler);
1530 } 1774 }
1531 Zone zone = Zone.current.fork(specification: zoneSpecification, 1775 Zone zone = Zone.current.fork(specification: zoneSpecification,
1532 zoneValues: zoneValues); 1776 zoneValues: zoneValues);
1533 if (onError != null) { 1777 if (onError != null) {
1534 return zone.runGuarded(body); 1778 return zone.runGuarded(body);
1535 } else { 1779 } else {
1536 return zone.run(body); 1780 return zone.run(body);
1537 } 1781 }
1538 } 1782 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698