Chromium Code Reviews| 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); |