| Index: sdk/lib/async/zone.dart
|
| diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
|
| index 4f067dd7fdecd75efac0bf4730f03499ab2ed8f1..39ce0c550018b07905e58fdbd43bb278d5c999fc 100644
|
| --- a/sdk/lib/async/zone.dart
|
| +++ b/sdk/lib/async/zone.dart
|
| @@ -6,16 +6,21 @@ part of dart.async;
|
|
|
| typedef dynamic ZoneCallback();
|
| typedef dynamic ZoneUnaryCallback(arg);
|
| +typedef dynamic ZoneBinaryCallback(arg1, arg2);
|
|
|
| typedef dynamic HandleUncaughtErrorHandler(
|
| - Zone self, ZoneDelegate parent, Zone zone, e);
|
| + Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace);
|
| typedef dynamic RunHandler(Zone self, ZoneDelegate parent, Zone zone, f());
|
| typedef dynamic RunUnaryHandler(
|
| Zone self, ZoneDelegate parent, Zone zone, f(arg), arg);
|
| +typedef dynamic RunBinaryHandler(
|
| + Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2), arg1, arg2);
|
| typedef ZoneCallback RegisterCallbackHandler(
|
| Zone self, ZoneDelegate parent, Zone zone, f());
|
| typedef ZoneUnaryCallback RegisterUnaryCallbackHandler(
|
| Zone self, ZoneDelegate parent, Zone zone, f(arg));
|
| +typedef ZoneBinaryCallback RegisterBinaryCallbackHandler(
|
| + Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2));
|
| typedef void ScheduleMicrotaskHandler(
|
| Zone self, ZoneDelegate parent, Zone zone, f());
|
| typedef Timer CreateTimerHandler(
|
| @@ -51,15 +56,19 @@ abstract class ZoneSpecification {
|
| * Creates a specification with the provided handlers.
|
| */
|
| const factory ZoneSpecification({
|
| - void handleUncaughtError(
|
| - Zone self, ZoneDelegate parent, Zone zone, e): null,
|
| + dynamic handleUncaughtError(Zone self, ZoneDelegate parent, Zone zone,
|
| + error, StackTrace stackTrace): null,
|
| dynamic run(Zone self, ZoneDelegate parent, Zone zone, f()): null,
|
| dynamic runUnary(
|
| Zone self, ZoneDelegate parent, Zone zone, f(arg), arg): null,
|
| + dynamic runBinary(Zone self, ZoneDelegate parent, Zone zone,
|
| + f(arg1, arg2), arg1, arg2): null,
|
| ZoneCallback registerCallback(
|
| Zone self, ZoneDelegate parent, Zone zone, f()): null,
|
| ZoneUnaryCallback registerUnaryCallback(
|
| Zone self, ZoneDelegate parent, Zone zone, f(arg)): null,
|
| + ZoneBinaryCallback registerBinaryCallback(
|
| + Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2)): null,
|
| void scheduleMicrotask(
|
| Zone self, ZoneDelegate parent, Zone zone, f()): null,
|
| Timer createTimer(Zone self, ZoneDelegate parent, Zone zone,
|
| @@ -75,15 +84,19 @@ abstract class ZoneSpecification {
|
| * the ones in [other].
|
| */
|
| factory ZoneSpecification.from(ZoneSpecification other, {
|
| - void handleUncaughtError(
|
| - Zone self, ZoneDelegate parent, Zone zone, e): null,
|
| + dynamic handleUncaughtError(Zone self, ZoneDelegate parent, Zone zone,
|
| + error, StackTrace stackTrace): null,
|
| dynamic run(Zone self, ZoneDelegate parent, Zone zone, f()): null,
|
| dynamic runUnary(
|
| Zone self, ZoneDelegate parent, Zone zone, f(arg), arg): null,
|
| + dynamic runBinary(Zone self, ZoneDelegate parent, Zone zone,
|
| + f(arg1, arg2), arg1, arg2): null,
|
| ZoneCallback registerCallback(
|
| Zone self, ZoneDelegate parent, Zone zone, f()): null,
|
| ZoneUnaryCallback registerUnaryCallback(
|
| Zone self, ZoneDelegate parent, Zone zone, f(arg)): null,
|
| + ZoneBinaryCallback registerBinaryCallback(
|
| + Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2)): null,
|
| void scheduleMicrotask(
|
| Zone self, ZoneDelegate parent, Zone zone, f()): null,
|
| Timer createTimer(Zone self, ZoneDelegate parent, Zone zone,
|
| @@ -100,12 +113,16 @@ abstract class ZoneSpecification {
|
| : other.handleUncaughtError,
|
| run: run != null ? run : other.run,
|
| runUnary: runUnary != null ? runUnary : other.runUnary,
|
| + runBinary: runBinary != null ? runBinary : other.runBinary,
|
| registerCallback: registerCallback != null
|
| ? registerCallback
|
| : other.registerCallback,
|
| registerUnaryCallback: registerUnaryCallback != null
|
| ? registerUnaryCallback
|
| : other.registerUnaryCallback,
|
| + registerBinaryCallback: registerBinaryCallback != null
|
| + ? registerBinaryCallback
|
| + : other.registerBinaryCallback,
|
| scheduleMicrotask: scheduleMicrotask != null
|
| ? scheduleMicrotask
|
| : other.scheduleMicrotask,
|
| @@ -119,8 +136,10 @@ abstract class ZoneSpecification {
|
| HandleUncaughtErrorHandler get handleUncaughtError;
|
| RunHandler get run;
|
| RunUnaryHandler get runUnary;
|
| + RunBinaryHandler get runBinary;
|
| RegisterCallbackHandler get registerCallback;
|
| RegisterUnaryCallbackHandler get registerUnaryCallback;
|
| + RegisterBinaryCallbackHandler get registerBinaryCallback;
|
| ScheduleMicrotaskHandler get scheduleMicrotask;
|
| CreateTimerHandler get createTimer;
|
| CreatePeriodicTimerHandler get createPeriodicTimer;
|
| @@ -139,8 +158,10 @@ class _ZoneSpecification implements ZoneSpecification {
|
| this.handleUncaughtError: null,
|
| this.run: null,
|
| this.runUnary: null,
|
| + this.runBinary: null,
|
| this.registerCallback: null,
|
| this.registerUnaryCallback: null,
|
| + this.registerBinaryCallback: null,
|
| this.scheduleMicrotask: null,
|
| this.createTimer: null,
|
| this.createPeriodicTimer: null,
|
| @@ -151,8 +172,10 @@ class _ZoneSpecification implements ZoneSpecification {
|
| final /*HandleUncaughtErrorHandler*/ handleUncaughtError;
|
| final /*RunHandler*/ run;
|
| final /*RunUnaryHandler*/ runUnary;
|
| + final /*RunBinaryHandler*/ runBinary;
|
| final /*RegisterCallbackHandler*/ registerCallback;
|
| final /*RegisterUnaryCallbackHandler*/ registerUnaryCallback;
|
| + final /*RegisterBinaryCallbackHandler*/ registerBinaryCallback;
|
| final /*ScheduleMicrotaskHandler*/ scheduleMicrotask;
|
| final /*CreateTimerHandler*/ createTimer;
|
| final /*CreatePeriodicTimerHandler*/ createPeriodicTimer;
|
| @@ -173,11 +196,13 @@ abstract class ZoneDelegate {
|
| /// The [Zone] this class wraps.
|
| Zone get _zone;
|
|
|
| - dynamic handleUncaughtError(Zone zone, e);
|
| + dynamic handleUncaughtError(Zone zone, error, StackTrace stackTrace);
|
| dynamic run(Zone zone, f());
|
| dynamic runUnary(Zone zone, f(arg), arg);
|
| + dynamic runBinary(Zone zone, f(arg1, arg2), arg1, arg2);
|
| ZoneCallback registerCallback(Zone zone, f());
|
| ZoneUnaryCallback registerUnaryCallback(Zone zone, f(arg));
|
| + ZoneBinaryCallback registerBinaryCallback(Zone zone, f(arg1, arg2));
|
| void scheduleMicrotask(Zone zone, f());
|
| Timer createTimer(Zone zone, Duration duration, void f());
|
| Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer));
|
| @@ -202,7 +227,7 @@ abstract class Zone {
|
|
|
| static Zone get current => _current;
|
|
|
| - dynamic handleUncaughtError(error);
|
| + dynamic handleUncaughtError(error, StackTrace stackTrace);
|
|
|
| /**
|
| * Returns the parent zone.
|
| @@ -236,6 +261,12 @@ abstract class Zone {
|
| dynamic runUnary(f(arg), var arg);
|
|
|
| /**
|
| + * Executes the given callback [f] with argument [arg1] and [arg2] in this
|
| + * zone.
|
| + */
|
| + dynamic runBinary(f(arg1, arg2), var arg1, var arg2);
|
| +
|
| + /**
|
| * Executes the given function [f] in this zone.
|
| *
|
| * Same as [run] but catches uncaught errors and gives them to
|
| @@ -252,6 +283,14 @@ abstract class Zone {
|
| dynamic runUnaryGuarded(f(arg), var arg);
|
|
|
| /**
|
| + * Executes the given callback [f] in this zone.
|
| + *
|
| + * Same as [runBinary] but catches uncaught errors and gives them to
|
| + * [handleUncaughtError].
|
| + */
|
| + dynamic runBinaryGuarded(f(arg1, arg2), var arg1, var arg2);
|
| +
|
| + /**
|
| * Registers the given callback in this zone.
|
| *
|
| * It is good practice to register asynchronous or delayed callbacks before
|
| @@ -273,6 +312,13 @@ abstract class Zone {
|
| ZoneUnaryCallback registerUnaryCallback(callback(arg));
|
|
|
| /**
|
| + * Registers the given callback in this zone.
|
| + *
|
| + * Similar to [registerCallback] but with a unary callback.
|
| + */
|
| + ZoneBinaryCallback registerBinaryCallback(callback(arg1, arg2));
|
| +
|
| + /**
|
| * Equivalent to:
|
| *
|
| * ZoneCallback registered = registerCallback(f);
|
| @@ -281,16 +327,29 @@ abstract class Zone {
|
| *
|
| */
|
| ZoneCallback bindCallback(f(), { bool runGuarded: true });
|
| +
|
| /**
|
| * Equivalent to:
|
| *
|
| - * ZoneCallback registered = registerCallback1(f);
|
| + * ZoneCallback registered = registerUnaryCallback(f);
|
| * if (runGuarded) return (arg) => this.runUnaryGuarded(registered, arg);
|
| * return (arg) => thin.runUnary(registered, arg);
|
| */
|
| ZoneUnaryCallback bindUnaryCallback(f(arg), { bool runGuarded: true });
|
|
|
| /**
|
| + * Equivalent to:
|
| + *
|
| + * ZoneCallback registered = registerBinaryCallback(f);
|
| + * if (runGuarded) {
|
| + * return (arg1, arg2) => this.runBinaryGuarded(registered, arg);
|
| + * }
|
| + * return (arg1, arg2) => thin.runBinary(registered, arg1, arg2);
|
| + */
|
| + ZoneBinaryCallback bindBinaryCallback(
|
| + f(arg1, arg2), { bool runGuarded: true });
|
| +
|
| + /**
|
| * Runs [f] asynchronously.
|
| */
|
| void scheduleMicrotask(void f());
|
| @@ -327,13 +386,13 @@ class _ZoneDelegate implements ZoneDelegate {
|
|
|
| const _ZoneDelegate(this._degelationTarget);
|
|
|
| - dynamic handleUncaughtError(Zone zone, e) {
|
| + dynamic handleUncaughtError(Zone zone, error, StackTrace stackTrace) {
|
| _CustomizedZone parent = _degelationTarget;
|
| while (parent._specification.handleUncaughtError == null) {
|
| parent = parent.parent;
|
| }
|
| return (parent._specification.handleUncaughtError)(
|
| - parent, new _ZoneDelegate(parent.parent), zone, e);
|
| + parent, new _ZoneDelegate(parent.parent), zone, error, stackTrace);
|
| }
|
|
|
| dynamic run(Zone zone, f()) {
|
| @@ -354,6 +413,15 @@ class _ZoneDelegate implements ZoneDelegate {
|
| parent, new _ZoneDelegate(parent.parent), zone, f, arg);
|
| }
|
|
|
| + dynamic runBinary(Zone zone, f(arg1, arg2), arg1, arg2) {
|
| + _CustomizedZone parent = _degelationTarget;
|
| + while (parent._specification.runBinary == null) {
|
| + parent = parent.parent;
|
| + }
|
| + return (parent._specification.runBinary)(
|
| + parent, new _ZoneDelegate(parent.parent), zone, f, arg1, arg2);
|
| + }
|
| +
|
| ZoneCallback registerCallback(Zone zone, f()) {
|
| _CustomizedZone parent = _degelationTarget;
|
| while (parent._specification.registerCallback == null) {
|
| @@ -372,6 +440,15 @@ class _ZoneDelegate implements ZoneDelegate {
|
| parent, new _ZoneDelegate(parent.parent), zone, f);
|
| }
|
|
|
| + ZoneBinaryCallback registerBinaryCallback(Zone zone, f(arg1, arg2)) {
|
| + _CustomizedZone parent = _degelationTarget;
|
| + while (parent._specification.registerBinaryCallback == null) {
|
| + parent = parent.parent;
|
| + }
|
| + return (parent._specification.registerBinaryCallback)(
|
| + parent, new _ZoneDelegate(parent.parent), zone, f);
|
| + }
|
| +
|
| void scheduleMicrotask(Zone zone, f()) {
|
| _CustomizedZone parent = _degelationTarget;
|
| while (parent._specification.scheduleMicrotask == null) {
|
| @@ -436,7 +513,7 @@ class _CustomizedZone implements Zone {
|
| try {
|
| return run(f);
|
| } catch (e, s) {
|
| - return handleUncaughtError(_asyncError(e, s));
|
| + return handleUncaughtError(e, s);
|
| }
|
| }
|
|
|
| @@ -444,7 +521,15 @@ class _CustomizedZone implements Zone {
|
| try {
|
| return runUnary(f, arg);
|
| } catch (e, s) {
|
| - return handleUncaughtError(_asyncError(e, s));
|
| + return handleUncaughtError(e, s);
|
| + }
|
| + }
|
| +
|
| + dynamic runBinaryGuarded(f(arg1, arg2), arg1, arg2) {
|
| + try {
|
| + return runBinary(f, arg1, arg2);
|
| + } catch (e, s) {
|
| + return handleUncaughtError(e, s);
|
| }
|
| }
|
|
|
| @@ -466,6 +551,16 @@ class _CustomizedZone implements Zone {
|
| }
|
| }
|
|
|
| + ZoneBinaryCallback bindBinaryCallback(
|
| + f(arg1, arg2), { bool runGuarded: true }) {
|
| + ZoneBinaryCallback registered = registerBinaryCallback(f);
|
| + if (runGuarded) {
|
| + return (arg1, arg2) => this.runBinaryGuarded(registered, arg1, arg2);
|
| + } else {
|
| + return (arg1, arg2) => this.runBinary(registered, arg1, arg2);
|
| + }
|
| + }
|
| +
|
| operator [](Symbol key) {
|
| var result = _map[key];
|
| if (result != null || _map.containsKey(key)) return result;
|
| @@ -477,8 +572,8 @@ class _CustomizedZone implements Zone {
|
|
|
| // Methods that can be customized by the zone specification.
|
|
|
| - dynamic handleUncaughtError(error) {
|
| - return new _ZoneDelegate(this).handleUncaughtError(this, error);
|
| + dynamic handleUncaughtError(error, StackTrace stackTrace) {
|
| + return new _ZoneDelegate(this).handleUncaughtError(this, error, stackTrace);
|
| }
|
|
|
| Zone fork({ZoneSpecification specification, Map zoneValues}) {
|
| @@ -493,6 +588,10 @@ class _CustomizedZone implements Zone {
|
| return new _ZoneDelegate(this).runUnary(this, f, arg);
|
| }
|
|
|
| + dynamic runBinary(f(arg1, arg2), arg1, arg2) {
|
| + return new _ZoneDelegate(this).runBinary(this, f, arg1, arg2);
|
| + }
|
| +
|
| ZoneCallback registerCallback(f()) {
|
| return new _ZoneDelegate(this).registerCallback(this, f);
|
| }
|
| @@ -501,6 +600,10 @@ class _CustomizedZone implements Zone {
|
| return new _ZoneDelegate(this).registerUnaryCallback(this, f);
|
| }
|
|
|
| + ZoneBinaryCallback registerBinaryCallback(f(arg1, arg2)) {
|
| + return new _ZoneDelegate(this).registerBinaryCallback(this, f);
|
| + }
|
| +
|
| void scheduleMicrotask(void f()) {
|
| new _ZoneDelegate(this).scheduleMicrotask(this, f);
|
| }
|
| @@ -515,13 +618,15 @@ class _CustomizedZone implements Zone {
|
| }
|
|
|
| void _rootHandleUncaughtError(
|
| - Zone self, ZoneDelegate parent, Zone zone, error) {
|
| + Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) {
|
| _scheduleAsyncCallback(() {
|
| print("Uncaught Error: ${error}");
|
| - var trace = getAttachedStackTrace(error);
|
| + var trace = stackTrace;
|
| + if (trace == null) trace = getAttachedStackTrace(error);
|
| + // Clear the attached stack trace (if any).
|
| _attachStackTrace(error, null);
|
| if (trace != null) {
|
| - print("Stack Trace:\n$trace\n");
|
| + print("Stack Trace: \n$trace\n");
|
| }
|
| throw error;
|
| });
|
| @@ -551,6 +656,19 @@ dynamic _rootRunUnary(Zone self, ZoneDelegate parent, Zone zone, f(arg), arg) {
|
| }
|
| }
|
|
|
| +dynamic _rootRunBinary(Zone self, ZoneDelegate parent, Zone zone,
|
| + f(arg1, arg2), arg1, arg2) {
|
| + if (Zone._current == zone) return f(arg1, arg2);
|
| +
|
| + Zone old = Zone._current;
|
| + try {
|
| + Zone._current = zone;
|
| + return f(arg1, arg2);
|
| + } finally {
|
| + Zone._current = old;
|
| + }
|
| +}
|
| +
|
| ZoneCallback _rootRegisterCallback(
|
| Zone self, ZoneDelegate parent, Zone zone, f()) {
|
| return f;
|
| @@ -561,6 +679,11 @@ ZoneUnaryCallback _rootRegisterUnaryCallback(
|
| return f;
|
| }
|
|
|
| +ZoneBinaryCallback _rootRegisterBinaryCallback(
|
| + Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2)) {
|
| + return f;
|
| +}
|
| +
|
| void _rootScheduleMicrotask(Zone self, ZoneDelegate parent, Zone zone, f()) {
|
| _scheduleAsyncCallback(f);
|
| }
|
| @@ -601,8 +724,10 @@ const _ROOT_SPECIFICATION = const ZoneSpecification(
|
| handleUncaughtError: _rootHandleUncaughtError,
|
| run: _rootRun,
|
| runUnary: _rootRunUnary,
|
| + runBinary: _rootRunBinary,
|
| registerCallback: _rootRegisterCallback,
|
| registerUnaryCallback: _rootRegisterUnaryCallback,
|
| + registerBinaryCallback: _rootRegisterBinaryCallback,
|
| scheduleMicrotask: _rootScheduleMicrotask,
|
| createTimer: _rootCreateTimer,
|
| createPeriodicTimer: _rootCreatePeriodicTimer,
|
| @@ -641,17 +766,21 @@ const _ROOT_ZONE =
|
| dynamic runZoned(body(),
|
| { Map<Symbol, dynamic> zoneValues,
|
| ZoneSpecification zoneSpecification,
|
| - void onError(error) }) {
|
| + Function onError }) {
|
| HandleUncaughtErrorHandler errorHandler;
|
| if (onError != null) {
|
| - errorHandler = (Zone self, ZoneDelegate parent, Zone zone, error) {
|
| + errorHandler = (Zone self, ZoneDelegate parent, Zone zone,
|
| + error, StackTrace stackTrace) {
|
| try {
|
| + if (onError is ZoneBinaryCallback) {
|
| + return self.parent.runBinary(onError, error, stackTrace);
|
| + }
|
| return self.parent.runUnary(onError, error);
|
| } catch(e, s) {
|
| if (identical(e, error)) {
|
| - return parent.handleUncaughtError(zone, error);
|
| + return parent.handleUncaughtError(zone, error, stackTrace);
|
| } else {
|
| - return parent.handleUncaughtError(zone, _asyncError(e, s));
|
| + return parent.handleUncaughtError(zone, e, s);
|
| }
|
| }
|
| };
|
| @@ -704,14 +833,15 @@ runZonedExperimental(body(),
|
| }
|
| HandleUncaughtErrorHandler errorHandler;
|
| if (onError != null) {
|
| - errorHandler = (Zone self, ZoneDelegate parent, Zone zone, error) {
|
| + errorHandler = (Zone self, ZoneDelegate parent, Zone zone,
|
| + error, StackTrace stackTrace) {
|
| try {
|
| return self.parent.runUnary(onError, error);
|
| } catch(e, s) {
|
| if (identical(e, error)) {
|
| - return parent.handleUncaughtError(zone, error);
|
| + return parent.handleUncaughtError(zone, error, stackTrace);
|
| } else {
|
| - return parent.handleUncaughtError(zone, _asyncError(e, s));
|
| + return parent.handleUncaughtError(zone, _asyncError(e, s), s);
|
| }
|
| }
|
| };
|
|
|