| OLD | NEW |
| (Empty) | |
| 1 part of angular.core; |
| 2 |
| 3 typedef void ZoneOnTurn(); |
| 4 typedef void ZoneOnError(dynamic error, dynamic stacktrace, LongStackTrace longS
tacktrace); |
| 5 |
| 6 /** |
| 7 * Contains the locations of runAsync calls across VM turns. |
| 8 */ |
| 9 class LongStackTrace { |
| 10 final String reason; |
| 11 final dynamic stacktrace; |
| 12 final LongStackTrace parent; |
| 13 |
| 14 LongStackTrace(this.reason, this.stacktrace, this.parent); |
| 15 |
| 16 toString() { |
| 17 List<String> frames = '${this.stacktrace}'.split('\n'); |
| 18 frames = frames.where((frame) { |
| 19 return frame.indexOf('(dart:') == -1 && // skip dart runtime libs |
| 20 frame.indexOf('(package:angular/zone.dart') == -1; // skip angular
zone |
| 21 }).toList(); |
| 22 frames.insert(0, reason); |
| 23 var parent = this.parent == null ? '' : this.parent; |
| 24 return '${frames.join("\n ")}\n$parent'; |
| 25 } |
| 26 } |
| 27 |
| 28 /** |
| 29 * A better zone API which implements onTurnDone. |
| 30 */ |
| 31 class NgZone { |
| 32 NgZone() { |
| 33 _zone = async.Zone.current.fork(specification: new async.ZoneSpecification( |
| 34 run: _onRun, |
| 35 runUnary: _onRunUnary, |
| 36 scheduleMicrotask: _onScheduleMicrotask, |
| 37 handleUncaughtError: _uncaughtError |
| 38 )); |
| 39 } |
| 40 |
| 41 async.Zone _zone; |
| 42 |
| 43 List _asyncQueue = []; |
| 44 bool _errorThrownFromOnRun = false; |
| 45 |
| 46 _onRunBase(async.Zone self, async.ZoneDelegate delegate, async.Zone zone, fn()
) { |
| 47 _runningInTurn++; |
| 48 try { |
| 49 return fn(); |
| 50 } catch (e, s) { |
| 51 onError(e, s, _longStacktrace); |
| 52 _errorThrownFromOnRun = true; |
| 53 rethrow; |
| 54 } finally { |
| 55 _runningInTurn--; |
| 56 if (_runningInTurn == 0) |
| 57 _finishTurn(zone, delegate); |
| 58 } |
| 59 } |
| 60 // Called from the parent zone. |
| 61 _onRun(async.Zone self, async.ZoneDelegate delegate, async.Zone zone, fn()) { |
| 62 return _onRunBase(self, delegate, zone, () => delegate.run(zone, fn)); |
| 63 } |
| 64 |
| 65 _onRunUnary(async.Zone self, async.ZoneDelegate delegate, async.Zone zone, fn(
args), args) { |
| 66 return _onRunBase(self, delegate, zone, () => delegate.runUnary(zone, fn, ar
gs)); |
| 67 } |
| 68 |
| 69 _onScheduleMicrotask(async.Zone self, async.ZoneDelegate delegate, async.Zone
zone, fn()) { |
| 70 _asyncQueue.add(() => delegate.run(zone, fn)); |
| 71 if (_runningInTurn == 0 && !_inFinishTurn) { |
| 72 _finishTurn(zone, delegate); |
| 73 } |
| 74 } |
| 75 |
| 76 _uncaughtError(async.Zone self, async.ZoneDelegate delegate, async.Zone zone,
e, StackTrace s) { |
| 77 if (!_errorThrownFromOnRun) { |
| 78 onError(e, s, _longStacktrace); |
| 79 } |
| 80 _errorThrownFromOnRun = false; |
| 81 } |
| 82 |
| 83 var _inFinishTurn = false; |
| 84 _finishTurn(zone, delegate) { |
| 85 if (_inFinishTurn) { |
| 86 return; |
| 87 } |
| 88 _inFinishTurn = true; |
| 89 try { |
| 90 // Two loops here: the inner one runs all queued microtasks, |
| 91 // the outer runs onTurnDone (e.g. scope.$digest) and then |
| 92 // any microtasks which may have been queued from onTurnDone. |
| 93 do { |
| 94 while (!_asyncQueue.isEmpty) { |
| 95 delegate.run(zone, _asyncQueue.removeAt(0)); |
| 96 } |
| 97 delegate.run(zone, onTurnDone); |
| 98 } while (!_asyncQueue.isEmpty); |
| 99 } catch (e, s) { |
| 100 onError(e, s, _longStacktrace); |
| 101 _errorThrownFromOnRun = true; |
| 102 rethrow; |
| 103 } finally { |
| 104 _inFinishTurn = false; |
| 105 } |
| 106 } |
| 107 |
| 108 int _runningInTurn = 0; |
| 109 |
| 110 /** |
| 111 * A function called with any errors from the zone. |
| 112 */ |
| 113 var onError = (e, s, ls) => null; |
| 114 |
| 115 /** |
| 116 * A function that is called at the end of each VM turn in which the |
| 117 * in-zone code or any runAsync callbacks were run. |
| 118 */ |
| 119 var onTurnDone = () => null; // Type was ZoneOnTurn: dartbug 13519 |
| 120 |
| 121 /** |
| 122 * A function that is called when uncaught errors are thrown inside the zone. |
| 123 */ |
| 124 // var onError = (dynamic e, dynamic s, LongStackTrace ls) => print('EXCEPTION
: $e\n$s\n$ls'); |
| 125 // Type was ZoneOnError: dartbug 13519 |
| 126 |
| 127 LongStackTrace _longStacktrace = null; |
| 128 |
| 129 LongStackTrace _getLongStacktrace(name) { |
| 130 var shortStacktrace = 'Long-stacktraces supressed in production.'; |
| 131 assert((shortStacktrace = _getStacktrace()) != null); |
| 132 return new LongStackTrace(name, shortStacktrace, _longStacktrace); |
| 133 } |
| 134 |
| 135 _getStacktrace() { |
| 136 try { throw []; } catch (e, s) { |
| 137 return s; |
| 138 } |
| 139 } |
| 140 |
| 141 /** |
| 142 * Runs the provided function in the zone. Any runAsync calls (e.g. futures) |
| 143 * will also be run in this zone. |
| 144 * |
| 145 * Returns the return value of body. |
| 146 */ |
| 147 run(body()) => _zone.run(body); |
| 148 |
| 149 assertInTurn() { |
| 150 assert(_runningInTurn > 0 || _inFinishTurn); |
| 151 } |
| 152 |
| 153 assertInZone() { |
| 154 assertInTurn(); |
| 155 } |
| 156 } |
| OLD | NEW |