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

Unified 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: Created 4 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/async/zone.dart
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index 9f015255d5b5547da939c5516f1656d5b3e8a63a..5dd5714b1b09e8ba2eb8814155ff1c835b1d3030 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -7,6 +7,7 @@ part of dart.async;
typedef R ZoneCallback<R>();
typedef R ZoneUnaryCallback<R, T>(T arg);
typedef R ZoneBinaryCallback<R, T1, T2>(T1 arg1, T2 arg2);
+
typedef T TaskCreate<T, S extends TaskSpecification>(
S specification, Zone zone);
typedef void TaskRun<T, A>(T task, A arg);
@@ -261,12 +262,23 @@ class _ZoneSpecification implements ZoneSpecification {
/**
* This class wraps zones for delegation.
Lasse Reichstein Nielsen 2016/06/20 21:19:16 Doesn't make sense. You can wrap a zone, but not (
floitsch 2016/07/01 04:03:40 Done.
*
- * When forwarding to parent zones one can't just invoke the parent zone's
- * exposed functions (like [Zone.run]), but one needs to provide more
- * information (like the zone the `run` was initiated). Zone callbacks thus
- * receive more information including this [ZoneDelegate] class. When delegating
- * to the parent zone one should go through the given instance instead of
- * directly invoking the parent zone.
+ * Custom zones (created through `Zone.fork` or `runZoned`) can provide
+ * implementations of most members of zones. This is similar to overriding
Lasse Reichstein Nielsen 2016/06/20 21:19:15 members of `Zone`? "members" feels weird, since t
floitsch 2016/07/01 04:03:38 Done.
+ * methods on [Zone], except that this mechanism doesn't require subclassing.
+ *
+ * A very common operation of intercepting function is to eventually delegate
Lasse Reichstein Nielsen 2016/06/20 21:19:16 Drop "very". intercepting functions? But "interce
floitsch 2016/07/01 04:03:38 Done.
+ * to its parent zone. Intercepting functions receive a parent delegate (of
+ * type [ZoneDelegate] for this purpose.
+ *
+ * Providing zone delegates to intercepting functions has two advantages:
Lasse Reichstein Nielsen 2016/06/20 21:19:16 I don't think this belongs in user-directed docume
floitsch 2016/07/01 04:03:40 Reworded.
+ * 1. the intercepting function can provide more information to the parent zone.
+ * In particular it has to provide the zone in which the action has been
+ * initiated.
+ * 2. The library can implement the delegates in a more efficient way, since
+ * it can skip zones that would just delegate to their parents.
+ *
+ * As mentioned in advantage 1, delegates receive a additional arguments.
+ * CONTINUE HERE.
*/
abstract class ZoneDelegate {
/*=R*/ handleUncaughtError/*<R>*/(
@@ -296,39 +308,133 @@ abstract class ZoneDelegate {
}
/**
- * A Zone represents the asynchronous version of a dynamic extent. Asynchronous
- * callbacks are executed in the zone they have been queued in. For example,
- * the callback of a `future.then` is executed in the same zone as the one where
- * the `then` was invoked.
+ * A Zone represents an environment that remains stable across asynchronous
Lasse Reichstein Nielsen 2016/06/20 21:19:16 `Zone`
floitsch 2016/07/01 04:03:39 changed to 'zone'.
+ * calls, and which is responsible for handling uncaught asynchronous errors,
Lasse Reichstein Nielsen 2016/06/20 21:19:16 Full stop after "calls", then new paragraph. The
floitsch 2016/07/01 04:03:38 Incorporated (partially) your text.
+ * or operations such as [print] and [scheduleMicrotask].
+ *
+ * Asynchronous callbacks are executed in the zone they have been queued in. For
+ * example, the callback of a `future.then` is executed in the same zone as the
+ * one where the `then` was invoked.
+ *
+ * Code is always executed inside a zone. When a program is started, the
Lasse Reichstein Nielsen 2016/06/20 21:19:16 "inside" feels a little too concrete for me. How a
floitsch 2016/07/01 04:03:39 Done.
+ * default zone ([Zone.ROOT]) is installed. Users can provide
+ * shadowing, nested zones.
+ *
+ * The [Zone] class is not subclassable, but users can provide custom zones by
+ * forking an existing zone (usually [Zone.current]) with a [ZoneSpecification].
+ * Zone specifications contain intercepting functions that are invoked when the
+ * zone members are invoked. As such, they provide the same functionality as
+ * subclassing (but allow for a more efficient implementation).
+ *
+ * Asynchronous callbacks always return in the zone in which they have been
Lasse Reichstein Nielsen 2016/06/20 21:19:16 have been -> are callbacks are functions, when yo
floitsch 2016/07/01 04:03:38 Done.
+ * scheduled. This happens in two steps:
+ * - the callback is registered using one of [registerCallback],
+ * [registerUnaryCallback], or [registerBinaryCallback].
+ * - the asynchronous operation (such as [Future.then] or [Stream.listen])
+ * remember the current zone. Either, they store the zone in a data structure
+ * (as is done for [Future]s), or they wrap the callback to capture the
+ * current zone. A convenience function [bindCallback] (and the corresponding
+ * [bindUnaryCallback] or [bindBindaryCallback]) perform the registration and
+ * wrapping at the same time.
+ *
+ * Note that all asynchronous primitives (like [Timer.run]) have to be
+ * implemented by the embedder, and that users generally don't need to worry
+ * about keeping track of zones. However, new embedders (or native extensions)
+ * need to ensure that new asynchronous primitives (like for example
+ * `requestAnimationFrame` in the HTML library) respect this contract.
*/
abstract class Zone {
// Private constructor so that it is not possible instantiate a Zone class.
Zone._();
- /** The root zone that is implicitly created. */
+ /**
+ * The root zone that is implicitly created.
Lasse Reichstein Nielsen 2016/06/20 21:19:16 The root zone. This is the zone that the isolate
floitsch 2016/07/01 04:03:39 somehow incorporated.
+ *
+ * The root zone implements the default behavior of all zone operations.
+ * Many methods, like [registerCallback] don't do anything, others, like
+ * [scheduleMicrotask] interact with the embedder to implement the desired
+ * behavior.
+ */
static const Zone ROOT = _ROOT_ZONE;
/** The currently running zone. */
static Zone _current = _ROOT_ZONE;
+ /** The zone that is currently active. */
static Zone get current => _current;
+ /**
+ * Handles uncaught asynchronous errors.
+ *
+ * Most asynchronous classes, like [Future] or [Stream] push errors to their
+ * listeners. Errors are propagated this way, until, either a listener handles
Lasse Reichstein Nielsen 2016/06/22 14:32:01 remove both commas.
floitsch 2016/07/01 04:03:39 Done.
+ * the error (for example with [Future.catchError]), or no listener is
+ * available anymore. In the latter case, futures and streams invoke the
+ * zone's [handleUncaughtError].
Lasse Reichstein Nielsen 2016/06/22 14:32:03 Mention that we also handle uncuaght errors from o
floitsch 2016/07/01 04:03:39 Reworded.
+ *
+ * By default, in the root zone, uncaught asynchronous errors are treated
+ * like synchronous uncaught exceptions (although the root zone defers the
+ * reporting by a microtask, to give other microtasks the opportunity to run
+ * one last time).
Lasse Reichstein Nielsen 2016/06/22 14:32:03 Actually not. An uncaught error that hits the unca
floitsch 2016/07/01 04:03:38 Removed the mention of microtask.
+ */
/*=R*/ handleUncaughtError/*<R>*/(error, StackTrace stackTrace);
/**
* Returns the parent zone.
*
* Returns `null` if `this` is the [ROOT] zone.
+ *
+ * Zones are created by [fork] (or [runZoned] which forks the [current] zone)
+ * on an existing zone. The new zone keeps the forking zone as [parent] zone.
Lasse Reichstein Nielsen 2016/06/22 14:32:01 Move parentheses to after "an existing zone". Mayb
floitsch 2016/07/01 04:03:39 I don't know anymore why it was added. Probably be
*/
Zone get parent;
/**
* The error zone is the one that is responsible for dealing with uncaught
* errors.
- * Errors are not allowed to cross between zones with different error-zones.
*
- * This is the closest parent or ancestor zone of this zone that has a custom
+ * This is the closest parent zone of this zone that provides a
* [handleUncaughtError] method.
+ *
+ * Asynchronous errors never cross zone boundaries of zones with different
Lasse Reichstein Nielsen 2016/06/22 14:32:02 ... boundaries between zones ...
floitsch 2016/07/01 04:03:38 Done.
+ * error-zones.
Lasse Reichstein Nielsen 2016/06/22 14:32:03 error-zones -> error handlers.
floitsch 2016/07/01 04:03:39 Done.
+ *
+ * Example:
+ * ```
+ * import 'dart:async';
+ *
+ * main() {
+ * var future;
+ * runZoned(() {
+ * // The asynchronous error is caught by the custom zone which prints
+ * // 'asynchronous error'.
+ * future = new Future.error("asynchronous error");
+ * }, onError: (e) { print(e); }); // Creates a zone with an error handler.
+ * // The following `catchError` is never reached, because the custom zone
Lasse Reichstein Nielsen 2016/06/22 14:32:02 is never reached -> never sees the error (sounds
floitsch 2016/07/01 04:03:38 Done.
+ * // that is created by the call to `runZoned` provides an error handler.
Lasse Reichstein Nielsen 2016/06/22 14:32:03 -> custom zone created by `runZoned` (just becaus
floitsch 2016/07/01 04:03:39 Done.
+ * future.catchError((e) { throw "is never reached"; });
+ * }
+ * ```
+ *
+ * Note that errors are not entering zones with different error handlers
Lasse Reichstein Nielsen 2016/06/22 14:32:03 are not entering -> cannot enter Maybe: *enter* (
floitsch 2016/07/01 04:03:40 Done.
+ * either:
+ * ```
+ * import 'dart:async';
+ *
+ * main() {
+ * runZoned(() {
+ * // The following asynchronous error is *not* caught by the `catchError`
+ * // in the nested zone, since errors are not to cross zone boundaries
+ * // with different error handlers.
+ * // Instead the error is handled by the current error handler,
+ * // printing "Caught by outer zone: asynchronous error".
+ * var future = new Future.error("asynchronous error");
+ * runZoned(() {
+ * future.catchError((e) { throw "is never reached"; });
+ * }, onError: (e) { throw "is never reached"; });
+ * }, onError: (e) { print("Caught by outer zone: $e"); });
+ * }
+ * ```
*/
Zone get errorZone;
Lasse Reichstein Nielsen 2016/06/22 14:32:02 And this shouldn't be public either. :)
floitsch 2016/07/01 04:03:39 That one is definitely used in the async library.
@@ -336,62 +442,87 @@ abstract class Zone {
* Returns true if `this` and [otherZone] are in the same error zone.
*
* Two zones are in the same error zone if they inherit their
Lasse Reichstein Nielsen 2016/06/22 14:32:03 Rewrite: if they have the same [errorZone].
floitsch 2016/07/01 04:03:40 Done.
- * [handleUncaughtError] callback from the same [errorZone].
+ * [errorZone] is the same.
*/
bool inSameErrorZone(Zone otherZone);
/**
* Creates a new zone as a child of `this`.
*
- * The new zone will have behavior like the current zone, except where
- * overridden by functions in [specification].
+ * The new zone uses the closures in the given [specification] to override
+ * the current's zone behavior. All specification entries that are `null`
+ * are automatically delegated to the parent zone (`this`).
Lasse Reichstein Nielsen 2016/06/22 14:32:03 Maybe: are automatically delegated to -> inherits
floitsch 2016/07/01 04:03:38 Done.
*
- * The new zone will have the same stored values (accessed through
+ * The new zone has the same stored values (accessed through
* `operator []`) as this zone, but updated with the keys and values
Lasse Reichstein Nielsen 2016/06/22 14:32:03 drop "but". Maybe: The new zone inherits the store
floitsch 2016/07/01 04:03:40 Done.
* in [zoneValues]. If a key is in both this zone's values and in
- * `zoneValues`, the new zone will use the value from `zoneValues``.
+ * `zoneValues`, the new zone uses the value from `zoneValues`.
+ *
+ * Note that the fork operation is interceptible. A zone can thus replace
Lasse Reichstein Nielsen 2016/06/22 14:32:02 replace -> change (change covers both "modify" and
floitsch 2016/07/01 04:03:39 Done.
+ * the zone specification (or zone value), giving the parent zone full control
Lasse Reichstein Nielsen 2016/06/22 14:32:03 value -> values parent zone -> forking zone ("pare
floitsch 2016/07/01 04:03:40 Done.
+ * over the child zone.
*/
- Zone fork({ ZoneSpecification specification,
- Map zoneValues });
+ Zone fork({ZoneSpecification specification,
+ Map zoneValues});
/**
* Executes the given function [f] in this zone.
Lasse Reichstein Nielsen 2016/06/22 14:32:03 We should rename `f` to `action` or something non-
floitsch 2016/07/01 04:03:40 Done.
+ *
+ * By default (as implemented in the [ROOT] zone, this updates the [current]
Lasse Reichstein Nielsen 2016/06/22 14:32:03 By default, as implemented in the [ROOT] zone, thi
floitsch 2016/07/01 04:03:39 Done.
+ * zone to this zone, and executes [f].
Lasse Reichstein Nielsen 2016/06/22 14:32:02 Add: If [action] throws, the synchronous exception
floitsch 2016/07/01 04:03:40 Done.
+ *
+ * Since the root zone is the only zone that can modify the [current] getter,
Lasse Reichstein Nielsen 2016/06/22 14:32:03 the [current] getter -> the value of [current] (n
floitsch 2016/07/01 04:03:40 Done.
+ * custom zones have to delegate to their parent zone if they wish to run
Lasse Reichstein Nielsen 2016/06/22 14:32:02 custom zone intercepting [run] should always deleg
floitsch 2016/07/01 04:03:38 Done.
+ * in their zone (which is generally the recommended behavior).
*/
/*=R*/ run/*<R>*/(/*=R*/ f());
/**
* Executes the given callback [f] with argument [arg] in this zone.
Lasse Reichstein Nielsen 2016/06/22 14:32:02 arg -> argument consider f -> action. (the "no abb
floitsch 2016/07/01 04:03:39 Done.
+ *
+ * See [run].
Lasse Reichstein Nielsen 2016/06/22 14:32:03 As [run] except that [action] is called with one [
floitsch 2016/07/01 04:03:38 Done.
*/
/*=R*/ runUnary/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg);
/**
* Executes the given callback [f] with argument [arg1] and [arg2] in this
Lasse Reichstein Nielsen 2016/06/22 14:32:03 Executes [action] with two arguments. As [run] ex
floitsch 2016/07/01 04:03:38 Done.
* zone.
+ *
+ * See [run].
*/
/*=R*/ runBinary/*<R, T1, T2>*/(
/*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2);
/**
- * Executes the given function [f] in this zone.
+ * Executes the given function [f] in this zone and catches synchronous
Lasse Reichstein Nielsen 2016/06/22 14:32:02 f->action.
floitsch 2016/07/01 04:03:40 Done.
+ * errors.
+ *
+ * This function is equivalent to:
+ * ```
+ * try {
+ * return run(f);
Lasse Reichstein Nielsen 2016/06/22 14:32:03 consider using "this.run" for emphasiz (and "this.
floitsch 2016/07/01 04:03:39 Done.
+ * } catch (e, s) {
+ * return handleUncaughtError(e, s);
+ * }
+ * ```
*
- * Same as [run] but catches uncaught errors and gives them to
- * [handleUncaughtError].
+ * See [run].
*/
/*=R*/ runGuarded/*<R>*/(/*=R*/ f());
/**
- * Executes the given callback [f] in this zone.
+ * Executes the given callback [f] with argument [arg] in this zone and
+ * catches synchronous errors.
*
- * Same as [runUnary] but catches uncaught errors and gives them to
- * [handleUncaughtError].
+ * See [runGuarded].
*/
/*=R*/ runUnaryGuarded/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg);
/**
- * Executes the given callback [f] in this zone.
+ * Executes the given callback [f] with arguments [arg1] and [arg2] in this
+ * zone.
*
- * Same as [runBinary] but catches uncaught errors and gives them to
- * [handleUncaughtError].
+ * See [runGuarded].
*/
/*=R*/ runBinaryGuarded/*<R, T1, T2>*/(
/*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2);
@@ -407,6 +538,8 @@ abstract class Zone {
*
* Returns a potentially new callback that should be used in place of the
Lasse Reichstein Nielsen 2016/06/22 14:32:02 Returns the, potentially new, callback that will l
floitsch 2016/07/01 04:03:38 Done.
* given [callback].
+ *
+ * Custom zones may intercept this operation.
Lasse Reichstein Nielsen 2016/06/22 14:32:02 Add: The default implementation of [Zone.ROOT] ret
floitsch 2016/07/01 04:03:38 Done.
*/
ZoneCallback/*<R>*/ registerCallback/*<R>*/(/*=R*/ callback());
@@ -460,45 +593,80 @@ abstract class Zone {
/*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), { bool runGuarded: true });
/**
- * Intercepts errors when added programmatically to a `Future` or `Stream`.
+ * Intercepts errors when added programatically to a `Future` or `Stream`.
*
- * When caling [Completer.completeError], [Stream.addError],
+ * When calling [Completer.completeError], [Stream.addError],
* or [Future] constructors that take an error or a callback that may throw,
Lasse Reichstein Nielsen 2016/06/22 14:32:03 that take a callback that may throw synchronously,
floitsch 2016/07/01 04:03:40 Done.
* the current zone is allowed to intercept and replace the error.
*
- * When other libraries use intermediate controllers or completers, such
- * calls may contain errors that have already been processed.
+ * There is no guarantee that an error is only sent through [errorCallback]
+ * once. Libraries that use intermediate controllers or completers might
+ * end up invoking [errorCallback] multiple times.
+ *
+ * Returns `null` if no replacement is desired. Otherwise returns an instance
+ * of [AsyncError] holding the new pair of error and stack trace.
*
- * Return `null` if no replacement is desired.
- * The original error is used unchanged in that case.
- * Otherwise return an instance of [AsyncError] holding
- * the new pair of error and stack trace.
- * If the [AsyncError.error] is `null`, it is replaced by a [NullThrownError].
+ * Although not recommended, the returned instance may have its `error` member
+ * ([AsyncError.error]) be equal to `null` in which case the error should be
+ * replaced by a [NullThrownError].
+ *
+ * Custom zones may intercept this operation.
Lasse Reichstein Nielsen 2016/06/22 14:32:02 Maybe add: Implementations of a new asynchronous p
floitsch 2016/07/01 04:03:38 Done.
*/
AsyncError errorCallback(Object error, StackTrace stackTrace);
/**
* Runs [f] asynchronously in this zone.
Lasse Reichstein Nielsen 2016/06/22 14:32:03 f -> action, task or callback.
floitsch 2016/07/01 04:03:39 Done.
+ *
+ * The global `scheduleMicrotask` delegates to the current zone's
Lasse Reichstein Nielsen 2016/06/22 14:32:01 (Ick. We need a scope override in DartDoc to be ab
floitsch 2016/07/01 04:03:40 Acknowledged.
+ * [scheduleMicrotask]. The root zone's implementation interacts with the
+ * embedder to schedule the given callback as microtask.
Lasse Reichstein Nielsen 2016/06/22 14:32:02 embedder -> underlying system ("embedder" is not
floitsch 2016/07/01 04:03:38 Done.
+ *
+ * Custom zones may intercept this operation (for example to wrap the given
+ * callback [f]).
*/
void scheduleMicrotask(void f());
/**
* Creates a task, given a [create] function and a [specification].
Lasse Reichstein Nielsen 2016/06/22 14:32:03 That's actually vacuous. It's a function named "cr
floitsch 2016/07/01 04:03:39 Partially incorporated. In particular I don't want
*
- * The [create] function is invoked with the [specification] as argument. It
- * returns a task object which is used for all future interactions with the
- * zone.
- *
- * Custom zones may replace the [specification] with a different one, thus
- * modifying the task parameters.
+ * By default, in the root zone, the [create] function is invoked with the
+ * [specification] as argument. It returns a task object which is used for all
+ * future interactions with the zone. Generally, the object is a unique
Lasse Reichstein Nielsen 2016/06/22 14:32:02 with the zone -> between the zone and the task
Lasse Reichstein Nielsen 2016/06/22 14:32:02 -> The object is a unique instance representing th
floitsch 2016/07/01 04:03:39 Done.
floitsch 2016/07/01 04:03:40 Done.
+ * instance that is also returned to whoever initiated the action.
+ * For example, the HTML library uses the returned [StreamSubscription] as
+ * task object, when users register an event listener.
Lasse Reichstein Nielsen 2016/06/22 14:32:01 remove comma
floitsch 2016/07/01 04:03:40 Done.
*
- * Tasks are created when the program is starting an operation that returns
- * through the event loop. For example, a timer or an http request both
+ * Tasks are created when the program starts an operation that returns
+ * through the event loop. For example, a timer or an HTTP request both
Lasse Reichstein Nielsen 2016/06/22 14:32:03 "return through the event loop" is a clever image,
floitsch 2016/07/01 04:03:39 Partially incorporated. Kept the 'return' in the n
* return through the event loop and are therefore tasks.
*
* If the [create] function is not invoked (because a custom zone has
* replaced or intercepted it), then the operation is *not* started. This
- * means that a custom zone can intercept tasks, like http requests.
+ * means that a custom zone can intercept tasks, like HTTP requests.
+ *
+ * A task goes through the following steps:
+ * - a user invokes a library function that should eventually return through
+ * the event loop (and not just as a microtask).
+ * - the library function creates a [TaskSpecification] that contains the
+ * necessary information to start the operation, and invokes
+ * `Zone.current.createTask` with the specification and a [create] closure.
+ * The closure, when invoked, uses the specification to start the operation
+ * (usually by interacting with the embedder, ar as a native extension),
Lasse Reichstein Nielsen 2016/06/22 14:32:02 embedder -> underlying system (everywhere) ar ->
floitsch 2016/07/01 04:03:40 Done.
+ * and returns a task object that identifies the running task.
+ * - custom zones handle the request and (unless completely intercepted and
+ * aborted), end up calling the root zone's [createTask] which runs the
+ * provided `create` closure (which may have been replaced at this point).
Lasse Reichstein Nielsen 2016/06/22 14:32:02 parens into comma. (too mmany parenthesized clause
floitsch 2016/07/01 04:03:40 Done.
+ * - later, the asynchronous operation returns through the event loop.
+ * It invokes [Zone.runTask] on the zone the task should run on (which had
Lasse Reichstein Nielsen 2016/06/22 14:32:02 on the zone in which the task should run (and whic
floitsch 2016/07/01 04:03:39 Done.
+ * been given to the create function). The [runTask] function receives the
+ * task object, a `run` function and an argument. As before, custom zones
+ * may intercept this call. Eventually (unless aborted), the `run` function
+ * is invoked, running Dart code that has been registered to run when the
Lasse Reichstein Nielsen 2016/06/22 14:32:03 too much "run". Maybe: Eventually the `run` funct
floitsch 2016/07/01 04:03:39 Shortened it. I don't want to use 'callback' since
+ * task returns. This last step may happen multiple times for tasks that are
+ * not oneshot tasks (see [ZoneSpecification.isOneShot].
Lasse Reichstein Nielsen 2016/06/22 14:32:03 missing end paren.
floitsch 2016/07/01 04:03:40 Done.
+ *
+ * Custom zones may replace the [specification] with a different one, thus
+ * modifying the task parameters.
Lasse Reichstein Nielsen 2016/06/22 14:32:02 Add: An operation that wishes to be an interceptab
floitsch 2016/07/01 04:03:38 Done.
*/
Object/*=T*/ createTask/*<T, S>*/(
TaskCreate/*<T, S>*/ create, TaskSpecification/*=S*/ specification);
Lasse Reichstein Nielsen 2016/06/22 14:32:03 I would expand function types when used for parame
floitsch 2016/07/01 04:03:40 Done.
@@ -517,6 +685,8 @@ abstract class Zone {
* It is good practice, if task operations provide a meaningful [arg], so
* that custom zones can deal with it. They might want to log it, or
* replace it.
+ *
+ * See [createTask].
*/
void runTask/*<T, A>*/(
TaskRun/*<T, A>*/ run, Object/*=T*/ task, Object/*=A*/ arg);
Lasse Reichstein Nielsen 2016/06/22 14:32:01 arg->argument.
floitsch 2016/07/01 04:03:40 Done.
@@ -535,6 +705,24 @@ abstract class Zone {
/**
* Prints the given [line].
+ *
+ * The global `print` function delegates to the current zone's [print]
+ * function which makes it possible to intercept the print function.
Lasse Reichstein Nielsen 2016/06/22 14:32:03 intercept the print function -> intercept printing
floitsch 2016/07/01 04:03:39 Done.
+ *
+ * Example:
+ * ```
+ * import 'dart:async';
+ *
+ * main() {
+ * runZoned(() {
+ * // Ends up printing: "Intercepted: in zone".
+ * print("in zone");
+ * }, zoneSpecification: new ZoneSpecification(
+ * print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
+ * parent.print(zone, "Intercepted: $line");
+ * }));
+ * }
+ * ```
*/
void print(String line);
« 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