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); |