| Index: sdk/lib/async/zone.dart | 
| diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart | 
| index 24f83f8bd8ba69a5ce7468aa031005d93a9d2266..b81a7fef8114f329909871fb71eb346286003140 100644 | 
| --- a/sdk/lib/async/zone.dart | 
| +++ b/sdk/lib/async/zone.dart | 
| @@ -194,14 +194,26 @@ class _ZoneSpecification implements ZoneSpecification { | 
| } | 
|  | 
| /** | 
| - * This class wraps zones for delegation. | 
| + * An adapted view of the parent zone. | 
| * | 
| - * 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. | 
| + * This class allows the implementation of a zone method to invoke methods on | 
| + * the parent zone while retaining knowledge of the originating zone. | 
| + * | 
| + * Custom zones (created through [Zone.fork] or [runZoned]) can provide | 
| + * implementations of most methods of zones. This is similar to overriding | 
| + * methods on [Zone], except that this mechanism doesn't require subclassing. | 
| + * | 
| + * A custom zone function (provided through a [ZoneSpecification]) typically | 
| + * records or wraps its parameters and then delegates the operation to its | 
| + * parent zone using the provided [ZoneDelegate]. | 
| + * | 
| + * While zones have access to their parent zone (through [Zone.parent]) it is | 
| + * recommended to call the methods on the provided parent delegate for two | 
| + * reasons: | 
| + * 1. the delegate methods take an additional `zone` argument which is the | 
| + *   zone the action has been initiated in. | 
| + * 2. delegate calls are more efficient, since the implementation knows how | 
| + *   to skip zones that would just delegate to their parents. | 
| */ | 
| abstract class ZoneDelegate { | 
| /*=R*/ handleUncaughtError/*<R>*/( | 
| @@ -224,117 +236,266 @@ 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 | 
| + * calls. | 
| + * | 
| + * Code is always executed in the context of a zone, available as | 
| + * [Zone.current]. The initial `main` function runs in the context of the | 
| + * default zone ([Zone.ROOT]). Code can be run in a different zone using either | 
| + * [runZoned], to create a new zone, or [Zone.run] to run code in the context of | 
| + * an existing zone likely created using [Zone.fork]. | 
| + * | 
| + * Developers can create a new zone that overrides some of the functionality of | 
| + * an existing zone. For example, custom zones can replace of modify the | 
| + * behavior of `print`, timers, microtasks or how uncaught errors are handled. | 
| + * | 
| + * The [Zone] class is not subclassable, but users can provide custom zones by | 
| + * forking an existing zone (usually [Zone.current]) with a [ZoneSpecification]. | 
| + * This is similar to creating a new class that extends the base `Zone` class | 
| + * and that overrides some methods, except without actually creating a new | 
| + * class. Instead the overriding methods are provided as functions that | 
| + * explicitly take the equivalent of their own class, the "super" class and the | 
| + * `this` object as parameters. | 
| + * | 
| + * Asynchronous callbacks always run in the context of the zone where they were | 
| + * scheduled. This is implemented using two steps: | 
| + * 1. the callback is first registered using one of [registerCallback], | 
| + *   [registerUnaryCallback], or [registerBinaryCallback]. This allows the zone | 
| + *   to record that a callback exists and potentially modify it (by returning a | 
| + *   different callback). The code doing the registration (e.g., `Future.then`) | 
| + *   also remembers the current zone so that it can later run the callback in | 
| + *   that zone. | 
| + * 2. At a later point the registered callback is run in the remembered zone. | 
| + * | 
| + * This is all handled internally by the platform code and most users don't need | 
| + * to worry about it. However, developers of new asynchronous operations, | 
| + * provided by the underlying system or through native extensions, must follow | 
| + * the protocol to be zone compatible. | 
| + * | 
| + * For convenience, zones provide [bindCallback] (and the corresponding | 
| + * [bindUnaryCallback] or [bindBinaryCallback]) to make it easier to respect the | 
| + * zone contract: these functions first invoke the corresponding `register` | 
| + * functions and then wrap the returned function so that it runs in the current | 
| + * zone when it is later asynchronously invoked. | 
| */ | 
| 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. | 
| +   * | 
| +   * All isolate entry functions (`main` or spawned functions) start running in | 
| +   * the root zone (that is, [Zone.current] is identical to [Zone.ROOT] when the | 
| +   * entry function is called). If no custom zone is created, the rest of the | 
| +   * program always runs in the root zone. | 
| +   * | 
| +   * The root zone implements the default behavior of all zone operations. | 
| +   * Many methods, like [registerCallback] do the bare minimum required of the | 
| +   * function, and are only provided as a hook for custom zones. Others, like | 
| +   * [scheduleMicrotask], interact with the underlying system 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. | 
| +   * | 
| +   * There are two kind of asynchronous errors that are handled by this | 
| +   * function: | 
| +   * 1. Uncaught errors that were thrown in asynchronous callbacks, for example, | 
| +   *   a `throw` in the function passed to [Timer.run]. | 
| +   * 2. Asynchronous errors that are pushed through [Future] and [Stream] | 
| +   *   chains, but for which no child registered an error handler. | 
| +   *   Most asynchronous classes, like [Future] or [Stream] push errors to their | 
| +   *   listeners. Errors are propagated this way until either a listener handles | 
| +   *   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]. | 
| +   * | 
| +   * By default, when handled by the root zone, uncaught asynchronous errors are | 
| +   * treated like uncaught synchronous exceptions. | 
| +   */ | 
| /*=R*/ handleUncaughtError/*<R>*/(error, StackTrace stackTrace); | 
|  | 
| /** | 
| -   * Returns the parent zone. | 
| +   * The parent zone of the this zone. | 
| * | 
| -   * Returns `null` if `this` is the [ROOT] zone. | 
| +   * Is `null` if `this` is the [ROOT] zone. | 
| +   * | 
| +   * Zones are created by [fork] on an existing zone, or by [runZoned] which | 
| +   * forks the [current] zone. The new zone's parent zone is the zone it was | 
| +   * forked from. | 
| */ | 
| 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 between zones with | 
| +   * different error handlers. | 
| +   * | 
| +   * 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` handler is never invoked, because the | 
| +   *   // custom zone created by the call to `runZoned` provides an | 
| +   *   // error handler. | 
| +   *   future.catchError((e) { throw "is never reached"; }); | 
| +   * } | 
| +   * ``` | 
| +   * | 
| +   * Note that errors cannot enter a child zone with a different error handler | 
| +   * 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; | 
|  | 
| /** | 
| * Returns true if `this` and [otherZone] are in the same error zone. | 
| * | 
| -   * Two zones are in the same error zone if they inherit their | 
| -   * [handleUncaughtError] callback from the same [errorZone]. | 
| +   * Two zones are in the same error zone if they have the same [errorZone]. | 
| */ | 
| 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` | 
| +   * inherit the behavior from the parent zone (`this`). | 
| +   * | 
| +   * The new zone inherits the stored values (accessed through [operator []]) | 
| +   * of this zone and updates them with values from [zoneValues], which either | 
| +   * adds new values or overrides existing ones. | 
| * | 
| -   * The new zone will have the same stored values (accessed through | 
| -   * `operator []`) as this zone, but updated with the keys and values | 
| -   * in [zoneValues]. If a key is in both this zone's values and in | 
| -   * `zoneValues`, the new zone will use the value from `zoneValues``. | 
| +   * Note that the fork operation is interceptible. A zone can thus change | 
| +   * the zone specification (or zone values), giving the forking zone full | 
| +   * control over the child zone. | 
| */ | 
| -  Zone fork({ ZoneSpecification specification, | 
| -              Map zoneValues }); | 
| +  Zone fork({ZoneSpecification specification, | 
| +             Map zoneValues}); | 
|  | 
| /** | 
| -   * Executes the given function [f] in this zone. | 
| +   * Executes [action] in this zone. | 
| +   * | 
| +   * By default (as implemented in the [ROOT] zone), runs [action] | 
| +   * with [current] set to this zone. | 
| +   * | 
| +   * If [action] throws, the synchronous exception is not caught by the zone's | 
| +   * error handler. Use [runGuarded] to achieve that. | 
| +   * | 
| +   * Since the root zone is the only zone that can modify the value of | 
| +   * [current], custom zones intercepting run should always delegate to their | 
| +   * parent zone. They may take actions before and after the call. | 
| */ | 
| -  /*=R*/ run/*<R>*/(/*=R*/ f()); | 
| +  /*=R*/ run/*<R>*/(/*=R*/ action()); | 
|  | 
| /** | 
| -   * Executes the given callback [f] with argument [arg] in this zone. | 
| +   * Executes the given [action] with [argument] in this zone. | 
| +   * | 
| +   * As [run] except that [action] is called with one [argument] instead of | 
| +   * none. | 
| */ | 
| -  /*=R*/ runUnary/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg); | 
| +  /*=R*/ runUnary/*<R, T>*/(/*=R*/ action(/*=T*/ argument), /*=T*/ argument); | 
|  | 
| /** | 
| -   * Executes the given callback [f] with argument [arg1] and [arg2] in this | 
| +   * Executes the given [action] with [argument1] and [argument2] in this | 
| * zone. | 
| +   * | 
| +   * As [run] except that [action] is called with two arguments instead of none. | 
| */ | 
| /*=R*/ runBinary/*<R, T1, T2>*/( | 
| -      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2); | 
| +      /*=R*/ action(/*=T1*/ argument1, /*=T2*/ argument2), /*=T1*/ argument1, | 
| +      /*=T2*/ argument2); | 
|  | 
| /** | 
| -   * Executes the given function [f] in this zone. | 
| +   * Executes the given [action] in this zone and catches synchronous | 
| +   * errors. | 
| * | 
| -   * Same as [run] but catches uncaught errors and gives them to | 
| -   * [handleUncaughtError]. | 
| +   * This function is equivalent to: | 
| +   * ``` | 
| +   * try { | 
| +   *   return this.run(action); | 
| +   * } catch (e, s) { | 
| +   *   return this.handleUncaughtError(e, s); | 
| +   * } | 
| +   * ``` | 
| +   * | 
| +   * See [run]. | 
| */ | 
| -  /*=R*/ runGuarded/*<R>*/(/*=R*/ f()); | 
| +  /*=R*/ runGuarded/*<R>*/(/*=R*/ action()); | 
|  | 
| /** | 
| -   * Executes the given callback [f] in this zone. | 
| +   * Executes the given [action] with [argument] 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); | 
| +  /*=R*/ runUnaryGuarded/*<R, T>*/(/*=R*/ action(/*=T*/ argument), | 
| +      /*=T*/ argument); | 
|  | 
| /** | 
| -   * Executes the given callback [f] in this zone. | 
| +   * Executes the given [action] with [argument1] and [argument2] in this | 
| +   * zone and catches synchronous errors. | 
| * | 
| -   * 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); | 
| +      /*=R*/ action(/*=T1*/ argument1, /*=T2*/ argument2), /*=T1*/ argument1, | 
| +      /*=T2*/ argument2); | 
|  | 
| /** | 
| * Registers the given callback in this zone. | 
| * | 
| -   * It is good practice to register asynchronous or delayed callbacks before | 
| -   * invoking [run]. This gives the zone a chance to wrap the callback and | 
| -   * to store information with the callback. For example, a zone may decide | 
| +   * When implementing an asynchronous primitive that uses callbacks, the | 
| +   * callback must be registered using [registerCallback] at the point where the | 
| +   * user provides the callback. This allows zones to record other information | 
| +   * that they need at the same time, perhaps even wrapping the callback, so | 
| +   * that the callback is prepared when it is later run in the same zones | 
| +   * (using [run]). For example, a zone may decide | 
| * to store the stack trace (at the time of the registration) with the | 
| * callback. | 
| * | 
| -   * Returns a potentially new callback that should be used in place of the | 
| -   * given [callback]. | 
| +   * Returns the callback that should be used in place of the provided | 
| +   * [callback]. Frequently zones simply return the original callback. | 
| +   * | 
| +   * Custom zones may intercept this operation. The default implementation in | 
| +   * [Zone.ROOT] returns the original callback unchanged. | 
| */ | 
| ZoneCallback/*<R>*/ registerCallback/*<R>*/(/*=R*/ callback()); | 
|  | 
| @@ -357,58 +518,79 @@ abstract class Zone { | 
| /** | 
| *  Equivalent to: | 
| * | 
| -   *      ZoneCallback registered = registerCallback(f); | 
| +   *      ZoneCallback registered = this.registerCallback(action); | 
| *      if (runGuarded) return () => this.runGuarded(registered); | 
| *      return () => this.run(registered); | 
| * | 
| */ | 
| ZoneCallback/*<R>*/ bindCallback/*<R>*/( | 
| -      /*=R*/ f(), { bool runGuarded: true }); | 
| +      /*=R*/ action(), { bool runGuarded: true }); | 
|  | 
| /** | 
| *  Equivalent to: | 
| * | 
| -   *      ZoneCallback registered = registerUnaryCallback(f); | 
| +   *      ZoneCallback registered = this.registerUnaryCallback(action); | 
| *      if (runGuarded) return (arg) => this.runUnaryGuarded(registered, arg); | 
| *      return (arg) => thin.runUnary(registered, arg); | 
| */ | 
| ZoneUnaryCallback/*<R, T>*/ bindUnaryCallback/*<R, T>*/( | 
| -      /*=R*/ f(/*=T*/ arg), { bool runGuarded: true }); | 
| +      /*=R*/ action(/*=T*/ argument), { bool runGuarded: true }); | 
|  | 
| /** | 
| *  Equivalent to: | 
| * | 
| -   *      ZoneCallback registered = registerBinaryCallback(f); | 
| +   *      ZoneCallback registered = registerBinaryCallback(action); | 
| *      if (runGuarded) { | 
| *        return (arg1, arg2) => this.runBinaryGuarded(registered, arg); | 
| *      } | 
| *      return (arg1, arg2) => thin.runBinary(registered, arg1, arg2); | 
| */ | 
| ZoneBinaryCallback/*<R, T1, T2>*/ bindBinaryCallback/*<R, T1, T2>*/( | 
| -      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), { bool runGuarded: true }); | 
| +      /*=R*/ action(/*=T1*/ argument1, /*=T2*/ argument2), | 
| +      { bool runGuarded: true }); | 
|  | 
| /** | 
| -   * Intercepts errors when added programmatically to a `Future` or `Stream`. | 
| +   * Intercepts errors when added programatically to a `Future` or `Stream`. | 
| +   * | 
| +   * When calling [Completer.completeError], [Stream.addError], | 
| +   * or some [Future] constructors, the current zone is allowed to intercept | 
| +   * and replace the error. | 
| +   * | 
| +   * Future constructors invoke this function when the error is received | 
| +   * directly, for example with [Future.error], or when the error is caught | 
| +   * synchronously, for example with [Future.sync]. | 
| +   * | 
| +   * 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. | 
| * | 
| -   * When caling [Completer.completeError], [Stream.addError], | 
| -   * or [Future] constructors that take an error or a callback that may throw, | 
| -   * the current zone is allowed to intercept and replace the error. | 
| +   * 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]. | 
| * | 
| -   * When other libraries use intermediate controllers or completers, such | 
| -   * calls may contain errors that have already been processed. | 
| +   * Custom zones may intercept this operation. | 
| * | 
| -   * 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]. | 
| +   * Implementations of a new asynchronous primitive that converts synchronous | 
| +   * errors to asynchronous errors rarely need to invoke [errorCallback], since | 
| +   * errors are usually reported through future completers or stream | 
| +   * controllers. | 
| */ | 
| AsyncError errorCallback(Object error, StackTrace stackTrace); | 
|  | 
| /** | 
| -   * Runs [f] asynchronously in this zone. | 
| +   * Runs [action] asynchronously in this zone. | 
| +   * | 
| +   * The global `scheduleMicrotask` delegates to the current zone's | 
| +   * [scheduleMicrotask]. The root zone's implementation interacts with the | 
| +   * underlying system to schedule the given callback as a microtask. | 
| +   * | 
| +   * Custom zones may intercept this operation (for example to wrap the given | 
| +   * callback [action]). | 
| */ | 
| -  void scheduleMicrotask(void f()); | 
| +  void scheduleMicrotask(void action()); | 
|  | 
| /** | 
| * Creates a Timer where the callback is executed in this zone. | 
| @@ -422,6 +604,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 printing. | 
| +   * | 
| +   * 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); | 
|  | 
|  |