Chromium Code Reviews| Index: sdk/lib/async/zone.dart |
| diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart |
| index 4f067dd7fdecd75efac0bf4730f03499ab2ed8f1..ab35bc3a486a2ef30d6242568a1c80961f7f0d50 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); |
|
Lasse Reichstein Nielsen
2013/10/04 09:17:39
Maybe make a
typedef ZoneErrorCallback(arg1, Stac
floitsch
2013/10/05 17:22:59
started doing this, but then decided against it. I
|
| 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 ZoneUnaryCallback RegisterBinaryCallbackHandler( |
|
Lasse Reichstein Nielsen
2013/10/04 09:17:39
return type should be ZoneBinaryCallback.
floitsch
2013/10/05 17:22:59
Good catch. thanks.
(Not tested yet because of bug
|
| + 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,22 @@ 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) |
|
Lasse Reichstein Nielsen
2013/10/04 09:17:39
Braces for if-body.
floitsch
2013/10/05 17:22:59
Done.
|
| + 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)); |
| + // TODO(floitsch): should there be a way to get to the old stack |
| + // trace? |
|
Lasse Reichstein Nielsen
2013/10/04 09:17:39
No.
You caught the error and handled it, and then
floitsch
2013/10/05 17:22:59
ok.
|
| + return parent.handleUncaughtError(zone, e, s); |
| } |
| } |
| }; |
| @@ -704,14 +834,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); |
| } |
| } |
| }; |