| Index: third_party/pkg/angular/lib/core/zone.dart
|
| diff --git a/third_party/pkg/angular/lib/core/zone.dart b/third_party/pkg/angular/lib/core/zone.dart
|
| index 600b775aac78232178964cb43a85ee9ce49879d9..737e6de6cc445decfd804211719b3741ed9f71ad 100644
|
| --- a/third_party/pkg/angular/lib/core/zone.dart
|
| +++ b/third_party/pkg/angular/lib/core/zone.dart
|
| @@ -1,11 +1,23 @@
|
| -part of angular.core;
|
| +part of angular.core_internal;
|
|
|
| -typedef void ZoneOnTurn();
|
| +/**
|
| + * Handles an [VmTurnZone] onTurnDone event.
|
| + */
|
| +typedef void ZoneOnTurnDone();
|
| +
|
| +/**
|
| + * Handles an [VmTurnZone] onTurnDone event.
|
| + */
|
| +typedef void ZoneOnTurnStart();
|
| +
|
| +/**
|
| + * Handles an [VmTurnZone] onError event.
|
| + */
|
| typedef void ZoneOnError(dynamic error, dynamic stacktrace,
|
| LongStackTrace longStacktrace);
|
|
|
| /**
|
| - * Contains the locations of runAsync calls across VM turns.
|
| + * Contains the locations of async calls across VM turns.
|
| */
|
| class LongStackTrace {
|
| final String reason;
|
| @@ -26,30 +38,56 @@ class LongStackTrace {
|
| }
|
|
|
| /**
|
| - * A better zone API which implements onTurnDone.
|
| + * A [Zone] wrapper that lets you schedule tasks after its private microtask
|
| + * queue is exhausted but before the next "turn", i.e. event loop iteration.
|
| + * This lets you freely schedule microtasks that prepare data, and set an
|
| + * [onTurnDone] handler that will consume that data after it's ready but before
|
| + * the browser has a chance to re-render.
|
| + * The wrapper maintains an "inner" and "outer" [Zone] and a private queue of
|
| + * all the microtasks scheduled on the inner [Zone].
|
| + *
|
| + * In a typical app, [ngDynamicApp] or [ngStaticApp] will create a singleton
|
| + * [VmTurnZone] whose outer [Zone] is the root [Zone] and whose default [onTurnDone]
|
| + * runs the Angular digest. A component may want to inject this singleton if it
|
| + * needs to run code _outside_ the Angular digest.
|
| */
|
| -class NgZone {
|
| - final async.Zone _outerZone;
|
| - async.Zone _zone;
|
| -
|
| - NgZone()
|
| - : _outerZone = async.Zone.current
|
| - {
|
| - _zone = _outerZone.fork(specification: new async.ZoneSpecification(
|
| +class VmTurnZone {
|
| + /// an "outer" [Zone], which is the one that created this.
|
| + async.Zone _outerZone;
|
| +
|
| + /// an "inner" [Zone], which is a child of the outer [Zone].
|
| + async.Zone _innerZone;
|
| +
|
| + /**
|
| + * Associates with this
|
| + *
|
| + * Defaults [onError] to forward errors to the outer [Zone].
|
| + * Defaults [onTurnDone] to a no-op.
|
| + */
|
| + VmTurnZone() {
|
| + _outerZone = async.Zone.current;
|
| + _innerZone = _outerZone.fork(specification: new async.ZoneSpecification(
|
| run: _onRun,
|
| runUnary: _onRunUnary,
|
| scheduleMicrotask: _onScheduleMicrotask,
|
| handleUncaughtError: _uncaughtError
|
| ));
|
| + onError = _defaultOnError;
|
| + onTurnDone = _defaultOnTurnDone;
|
| + onTurnStart = _defaultOnTurnStart;
|
| }
|
|
|
| -
|
| List _asyncQueue = [];
|
| bool _errorThrownFromOnRun = false;
|
|
|
| + var _currentlyInTurn = false;
|
| _onRunBase(async.Zone self, async.ZoneDelegate delegate, async.Zone zone, fn()) {
|
| _runningInTurn++;
|
| try {
|
| + if (!_currentlyInTurn) {
|
| + _currentlyInTurn = true;
|
| + delegate.run(zone, onTurnStart);
|
| + }
|
| return fn();
|
| } catch (e, s) {
|
| onError(e, s, _longStacktrace);
|
| @@ -62,11 +100,11 @@ class NgZone {
|
| }
|
| // Called from the parent zone.
|
| _onRun(async.Zone self, async.ZoneDelegate delegate, async.Zone zone, fn()) =>
|
| - _onRunBase(self, delegate, zone, () => delegate.run(zone, fn));
|
| + _onRunBase(self, delegate, zone, () => delegate.run(zone, fn));
|
|
|
| _onRunUnary(async.Zone self, async.ZoneDelegate delegate, async.Zone zone,
|
| fn(args), args) =>
|
| - _onRunBase(self, delegate, zone, () => delegate.runUnary(zone, fn, args));
|
| + _onRunBase(self, delegate, zone, () => delegate.runUnary(zone, fn, args));
|
|
|
| _onScheduleMicrotask(async.Zone self, async.ZoneDelegate delegate,
|
| async.Zone zone, fn()) {
|
| @@ -88,39 +126,65 @@ class NgZone {
|
| // Two loops here: the inner one runs all queued microtasks,
|
| // the outer runs onTurnDone (e.g. scope.digest) and then
|
| // any microtasks which may have been queued from onTurnDone.
|
| + // If any microtasks were scheduled during onTurnDone, onTurnStart
|
| + // will be executed before those microtasks.
|
| do {
|
| + if (!_currentlyInTurn) {
|
| + _currentlyInTurn = true;
|
| + delegate.run(zone, onTurnStart);
|
| + }
|
| while (!_asyncQueue.isEmpty) {
|
| delegate.run(zone, _asyncQueue.removeAt(0));
|
| }
|
| delegate.run(zone, onTurnDone);
|
| + _currentlyInTurn = false;
|
| } while (!_asyncQueue.isEmpty);
|
| } catch (e, s) {
|
| onError(e, s, _longStacktrace);
|
| _errorThrownFromOnRun = true;
|
| rethrow;
|
| } finally {
|
| - _inFinishTurn = false;
|
| + _inFinishTurn = false;
|
| }
|
| }
|
|
|
| int _runningInTurn = 0;
|
|
|
| /**
|
| - * A function called with any errors from the zone.
|
| + * Called with any errors from the inner zone.
|
| */
|
| - var onError = (e, s, ls) => null;
|
| + ZoneOnError onError;
|
| +
|
| + /// Prevent silently ignoring uncaught exceptions by forwarding such exceptions to the outer zone.
|
| + void _defaultOnError(dynamic e, dynamic s, LongStackTrace ls) =>
|
| + _outerZone.handleUncaughtError(e, s);
|
|
|
| /**
|
| - * A function that is called at the end of each VM turn in which the
|
| - * in-zone code or any runAsync callbacks were run.
|
| + * Called at the beginning of each VM turn in which inner zone code runs.
|
| + * "At the beginning" means before any of the microtasks from the private
|
| + * microtask queue of the inner zone is executed. Notes
|
| + * - [onTurnStart] runs repeatedly until no more microstasks are scheduled
|
| + * within [onTurnStart], [run] or [onTurnDone]. You usually don't want it to
|
| + * schedule any. For example, if its first line of code is `new Future.value()`,
|
| + * the turn will _never_ end.
|
| */
|
| - var onTurnDone = () => null; // Type was ZoneOnTurn: dartbug 13519
|
| + ZoneOnTurnStart onTurnStart;
|
| + void _defaultOnTurnStart() => null;
|
| +
|
|
|
| /**
|
| - * A function that is called when uncaught errors are thrown inside the zone.
|
| + * Called at the end of each VM turn in which inner zone code runs.
|
| + * "At the end" means after the private microtask queue of the inner zone is
|
| + * exhausted but before the next VM turn. Notes
|
| + * - This won't wait for microtasks scheduled in zones other than the inner
|
| + * zone, e.g. those scheduled with [runOutsideAngular].
|
| + * - [onTurnDone] runs repeatedly until no more tasks are scheduled within
|
| + * [onTurnStart], [run] or [onTurnDone]. You usually don't want it to
|
| + * schedule any. For example, if its first line of code is `new Future.value()`,
|
| + * the turn will _never_ end.
|
| */
|
| - // var onError = (dynamic e, dynamic s, LongStackTrace ls) => print('EXCEPTION: $e\n$s\n$ls');
|
| - // Type was ZoneOnError: dartbug 13519
|
| + ZoneOnTurnDone onTurnDone;
|
| + void _defaultOnTurnDone() => null;
|
|
|
| LongStackTrace _longStacktrace = null;
|
|
|
| @@ -130,7 +194,7 @@ class NgZone {
|
| return new LongStackTrace(name, shortStacktrace, _longStacktrace);
|
| }
|
|
|
| - _getStacktrace() {
|
| + StackTrace _getStacktrace() {
|
| try {
|
| throw [];
|
| } catch (e, s) {
|
| @@ -139,17 +203,16 @@ class NgZone {
|
| }
|
|
|
| /**
|
| - * Runs the provided function in the zone. Any runAsync calls (e.g. futures)
|
| - * will also be run in this zone.
|
| - *
|
| - * Returns the return value of body.
|
| + * Runs [body] in the inner zone and returns whatever it returns.
|
| */
|
| - run(body()) => _zone.run(body);
|
| + dynamic run(body()) => _innerZone.run(body);
|
|
|
| /**
|
| - * Allows one to escape the auto-digest mechanism of Angular.
|
| + * Runs [body] in the outer zone and returns whatever it returns.
|
| + * In a typical app where the inner zone is the Angular zone, this allows
|
| + * one to escape Angular's auto-digest mechanism.
|
| *
|
| - * myFunction(NgZone zone, Element element) {
|
| + * myFunction(VmTurnZone zone, Element element) {
|
| * element.onClick.listen(() {
|
| * // auto-digest will run after element click.
|
| * });
|
| @@ -160,13 +223,22 @@ class NgZone {
|
| * });
|
| * }
|
| */
|
| - runOutsideAngular(body()) => _outerZone.run(body);
|
| + dynamic runOutsideAngular(body()) => _outerZone.run(body);
|
|
|
| - assertInTurn() {
|
| + /**
|
| + * Throws an [AssertionError] if no task is currently running in the inner
|
| + * zone. In a typical app where the inner zone is the Angular zone, this can
|
| + * be used to assert that the digest will indeed run at the end of the current
|
| + * turn.
|
| + */
|
| + void assertInTurn() {
|
| assert(_runningInTurn > 0 || _inFinishTurn);
|
| }
|
|
|
| - assertInZone() {
|
| + /**
|
| + * Same as [assertInTurn].
|
| + */
|
| + void assertInZone() {
|
| assertInTurn();
|
| }
|
| }
|
|
|