| OLD | NEW |
| 1 part of angular.core; | 1 part of angular.core; |
| 2 | 2 |
| 3 typedef void ZoneOnTurn(); | 3 typedef void ZoneOnTurn(); |
| 4 typedef void ZoneOnError(dynamic error, dynamic stacktrace, | 4 typedef void ZoneOnError(dynamic error, dynamic stacktrace, LongStackTrace longS
tacktrace); |
| 5 LongStackTrace longStacktrace); | |
| 6 | 5 |
| 7 /** | 6 /** |
| 8 * Contains the locations of runAsync calls across VM turns. | 7 * Contains the locations of runAsync calls across VM turns. |
| 9 */ | 8 */ |
| 10 class LongStackTrace { | 9 class LongStackTrace { |
| 11 final String reason; | 10 final String reason; |
| 12 final dynamic stacktrace; | 11 final dynamic stacktrace; |
| 13 final LongStackTrace parent; | 12 final LongStackTrace parent; |
| 14 | 13 |
| 15 LongStackTrace(this.reason, this.stacktrace, this.parent); | 14 LongStackTrace(this.reason, this.stacktrace, this.parent); |
| 16 | 15 |
| 17 toString() { | 16 toString() { |
| 18 List<String> frames = '${this.stacktrace}'.split('\n') | 17 List<String> frames = '${this.stacktrace}'.split('\n'); |
| 19 .where((frame) => | 18 frames = frames.where((frame) { |
| 20 frame.indexOf('(dart:') == -1 && // skip dart runtime libs | 19 return frame.indexOf('(dart:') == -1 && // skip dart runtime libs |
| 21 frame.indexOf('(package:angular/zone.dart') == -1 // skip angular zo
ne | 20 frame.indexOf('(package:angular/zone.dart') == -1; // skip angular
zone |
| 22 ).toList()..insert(0, reason); | 21 }).toList(); |
| 22 frames.insert(0, reason); |
| 23 var parent = this.parent == null ? '' : this.parent; | 23 var parent = this.parent == null ? '' : this.parent; |
| 24 return '${frames.join("\n ")}\n$parent'; | 24 return '${frames.join("\n ")}\n$parent'; |
| 25 } | 25 } |
| 26 } | 26 } |
| 27 | 27 |
| 28 /** | 28 /** |
| 29 * A better zone API which implements onTurnDone. | 29 * A better zone API which implements onTurnDone. |
| 30 */ | 30 */ |
| 31 class NgZone { | 31 class NgZone { |
| 32 final async.Zone _outerZone; | 32 NgZone() { |
| 33 async.Zone _zone; | 33 _zone = async.Zone.current.fork(specification: new async.ZoneSpecification( |
| 34 | |
| 35 NgZone() | |
| 36 : _outerZone = async.Zone.current | |
| 37 { | |
| 38 _zone = _outerZone.fork(specification: new async.ZoneSpecification( | |
| 39 run: _onRun, | 34 run: _onRun, |
| 40 runUnary: _onRunUnary, | 35 runUnary: _onRunUnary, |
| 41 scheduleMicrotask: _onScheduleMicrotask, | 36 scheduleMicrotask: _onScheduleMicrotask, |
| 42 handleUncaughtError: _uncaughtError | 37 handleUncaughtError: _uncaughtError |
| 43 )); | 38 )); |
| 44 } | 39 } |
| 45 | 40 |
| 41 async.Zone _zone; |
| 46 | 42 |
| 47 List _asyncQueue = []; | 43 List _asyncQueue = []; |
| 48 bool _errorThrownFromOnRun = false; | 44 bool _errorThrownFromOnRun = false; |
| 49 | 45 |
| 50 _onRunBase(async.Zone self, async.ZoneDelegate delegate, async.Zone zone, fn()
) { | 46 _onRunBase(async.Zone self, async.ZoneDelegate delegate, async.Zone zone, fn()
) { |
| 51 _runningInTurn++; | 47 _runningInTurn++; |
| 52 try { | 48 try { |
| 53 return fn(); | 49 return fn(); |
| 54 } catch (e, s) { | 50 } catch (e, s) { |
| 55 onError(e, s, _longStacktrace); | 51 onError(e, s, _longStacktrace); |
| 56 _errorThrownFromOnRun = true; | 52 _errorThrownFromOnRun = true; |
| 57 rethrow; | 53 rethrow; |
| 58 } finally { | 54 } finally { |
| 59 _runningInTurn--; | 55 _runningInTurn--; |
| 60 if (_runningInTurn == 0) _finishTurn(zone, delegate); | 56 if (_runningInTurn == 0) |
| 57 _finishTurn(zone, delegate); |
| 61 } | 58 } |
| 62 } | 59 } |
| 63 // Called from the parent zone. | 60 // Called from the parent zone. |
| 64 _onRun(async.Zone self, async.ZoneDelegate delegate, async.Zone zone, fn()) => | 61 _onRun(async.Zone self, async.ZoneDelegate delegate, async.Zone zone, fn()) { |
| 65 _onRunBase(self, delegate, zone, () => delegate.run(zone, fn)); | 62 return _onRunBase(self, delegate, zone, () => delegate.run(zone, fn)); |
| 66 | |
| 67 _onRunUnary(async.Zone self, async.ZoneDelegate delegate, async.Zone zone, | |
| 68 fn(args), args) => | |
| 69 _onRunBase(self, delegate, zone, () => delegate.runUnary(zone, fn, args)); | |
| 70 | |
| 71 _onScheduleMicrotask(async.Zone self, async.ZoneDelegate delegate, | |
| 72 async.Zone zone, fn()) { | |
| 73 _asyncQueue.add(() => delegate.run(zone, fn)); | |
| 74 if (_runningInTurn == 0 && !_inFinishTurn) _finishTurn(zone, delegate); | |
| 75 } | 63 } |
| 76 | 64 |
| 77 _uncaughtError(async.Zone self, async.ZoneDelegate delegate, async.Zone zone, | 65 _onRunUnary(async.Zone self, async.ZoneDelegate delegate, async.Zone zone, fn(
args), args) { |
| 78 e, StackTrace s) { | 66 return _onRunBase(self, delegate, zone, () => delegate.runUnary(zone, fn, ar
gs)); |
| 79 if (!_errorThrownFromOnRun) onError(e, s, _longStacktrace); | 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; | 80 _errorThrownFromOnRun = false; |
| 81 } | 81 } |
| 82 | 82 |
| 83 var _inFinishTurn = false; | 83 var _inFinishTurn = false; |
| 84 _finishTurn(zone, delegate) { | 84 _finishTurn(zone, delegate) { |
| 85 if (_inFinishTurn) return; | 85 if (_inFinishTurn) { |
| 86 return; |
| 87 } |
| 86 _inFinishTurn = true; | 88 _inFinishTurn = true; |
| 87 try { | 89 try { |
| 88 // Two loops here: the inner one runs all queued microtasks, | 90 // Two loops here: the inner one runs all queued microtasks, |
| 89 // the outer runs onTurnDone (e.g. scope.digest) and then | 91 // the outer runs onTurnDone (e.g. scope.$digest) and then |
| 90 // any microtasks which may have been queued from onTurnDone. | 92 // any microtasks which may have been queued from onTurnDone. |
| 91 do { | 93 do { |
| 92 while (!_asyncQueue.isEmpty) { | 94 while (!_asyncQueue.isEmpty) { |
| 93 delegate.run(zone, _asyncQueue.removeAt(0)); | 95 delegate.run(zone, _asyncQueue.removeAt(0)); |
| 94 } | 96 } |
| 95 delegate.run(zone, onTurnDone); | 97 delegate.run(zone, onTurnDone); |
| 96 } while (!_asyncQueue.isEmpty); | 98 } while (!_asyncQueue.isEmpty); |
| 97 } catch (e, s) { | 99 } catch (e, s) { |
| 98 onError(e, s, _longStacktrace); | 100 onError(e, s, _longStacktrace); |
| 99 _errorThrownFromOnRun = true; | 101 _errorThrownFromOnRun = true; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 124 | 126 |
| 125 LongStackTrace _longStacktrace = null; | 127 LongStackTrace _longStacktrace = null; |
| 126 | 128 |
| 127 LongStackTrace _getLongStacktrace(name) { | 129 LongStackTrace _getLongStacktrace(name) { |
| 128 var shortStacktrace = 'Long-stacktraces supressed in production.'; | 130 var shortStacktrace = 'Long-stacktraces supressed in production.'; |
| 129 assert((shortStacktrace = _getStacktrace()) != null); | 131 assert((shortStacktrace = _getStacktrace()) != null); |
| 130 return new LongStackTrace(name, shortStacktrace, _longStacktrace); | 132 return new LongStackTrace(name, shortStacktrace, _longStacktrace); |
| 131 } | 133 } |
| 132 | 134 |
| 133 _getStacktrace() { | 135 _getStacktrace() { |
| 134 try { | 136 try { throw []; } catch (e, s) { |
| 135 throw []; | |
| 136 } catch (e, s) { | |
| 137 return s; | 137 return s; |
| 138 } | 138 } |
| 139 } | 139 } |
| 140 | 140 |
| 141 /** | 141 /** |
| 142 * Runs the provided function in the zone. Any runAsync calls (e.g. futures) | 142 * Runs the provided function in the zone. Any runAsync calls (e.g. futures) |
| 143 * will also be run in this zone. | 143 * will also be run in this zone. |
| 144 * | 144 * |
| 145 * Returns the return value of body. | 145 * Returns the return value of body. |
| 146 */ | 146 */ |
| 147 run(body()) => _zone.run(body); | 147 run(body()) => _zone.run(body); |
| 148 | 148 |
| 149 /** | |
| 150 * Allows one to escape the auto-digest mechanism of Angular. | |
| 151 * | |
| 152 * myFunction(NgZone zone, Element element) { | |
| 153 * element.onClick.listen(() { | |
| 154 * // auto-digest will run after element click. | |
| 155 * }); | |
| 156 * zone.runOutsideAngular(() { | |
| 157 * element.onMouseMove.listen(() { | |
| 158 * // auto-digest will NOT run after mouse move | |
| 159 * }); | |
| 160 * }); | |
| 161 * } | |
| 162 */ | |
| 163 runOutsideAngular(body()) => _outerZone.run(body); | |
| 164 | |
| 165 assertInTurn() { | 149 assertInTurn() { |
| 166 assert(_runningInTurn > 0 || _inFinishTurn); | 150 assert(_runningInTurn > 0 || _inFinishTurn); |
| 167 } | 151 } |
| 168 | 152 |
| 169 assertInZone() { | 153 assertInZone() { |
| 170 assertInTurn(); | 154 assertInTurn(); |
| 171 } | 155 } |
| 172 } | 156 } |
| OLD | NEW |