| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library stack_trace.stack_zone_specification; | 5 library stack_trace.stack_zone_specification; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'trace.dart'; | 9 import 'trace.dart'; |
| 10 import 'chain.dart'; | 10 import 'chain.dart'; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 _Node _currentNode; | 49 _Node _currentNode; |
| 50 | 50 |
| 51 StackZoneSpecification([this._onError]); | 51 StackZoneSpecification([this._onError]); |
| 52 | 52 |
| 53 /// Converts [this] to a real [ZoneSpecification]. | 53 /// Converts [this] to a real [ZoneSpecification]. |
| 54 ZoneSpecification toSpec() { | 54 ZoneSpecification toSpec() { |
| 55 return new ZoneSpecification( | 55 return new ZoneSpecification( |
| 56 handleUncaughtError: handleUncaughtError, | 56 handleUncaughtError: handleUncaughtError, |
| 57 registerCallback: registerCallback, | 57 registerCallback: registerCallback, |
| 58 registerUnaryCallback: registerUnaryCallback, | 58 registerUnaryCallback: registerUnaryCallback, |
| 59 registerBinaryCallback: registerBinaryCallback); | 59 registerBinaryCallback: registerBinaryCallback, |
| 60 errorCallback: errorCallback); |
| 60 } | 61 } |
| 61 | 62 |
| 62 /// Returns the current stack chain. | 63 /// Returns the current stack chain. |
| 63 /// | 64 /// |
| 64 /// By default, the first frame of the first trace will be the line where | 65 /// By default, the first frame of the first trace will be the line where |
| 65 /// [currentChain] is called. If [level] is passed, the first trace will start | 66 /// [currentChain] is called. If [level] is passed, the first trace will start |
| 66 /// that many frames up instead. | 67 /// that many frames up instead. |
| 67 Chain currentChain([int level=0]) => _createNode(level + 1).toChain(); | 68 Chain currentChain([int level=0]) => _createNode(level + 1).toChain(); |
| 68 | 69 |
| 69 /// Returns the stack chain associated with [trace], if one exists. | 70 /// Returns the stack chain associated with [trace], if one exists. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 81 /// information associated with it. | 82 /// information associated with it. |
| 82 /// | 83 /// |
| 83 /// By default, the first frame of the first trace will be the line where | 84 /// By default, the first frame of the first trace will be the line where |
| 84 /// [trackFuture] is called. If [level] is passed, the first trace will start | 85 /// [trackFuture] is called. If [level] is passed, the first trace will start |
| 85 /// that many frames up instead. | 86 /// that many frames up instead. |
| 86 Future trackFuture(Future future, [int level=0]) { | 87 Future trackFuture(Future future, [int level=0]) { |
| 87 var completer = new Completer.sync(); | 88 var completer = new Completer.sync(); |
| 88 var node = _createNode(level + 1); | 89 var node = _createNode(level + 1); |
| 89 future.then(completer.complete).catchError((e, stackTrace) { | 90 future.then(completer.complete).catchError((e, stackTrace) { |
| 90 if (stackTrace == null) stackTrace = new Trace.current(); | 91 if (stackTrace == null) stackTrace = new Trace.current(); |
| 91 if (_chains[stackTrace] == null) _chains[stackTrace] = node; | 92 if (stackTrace is! Chain && _chains[stackTrace] == null) { |
| 93 _chains[stackTrace] = node; |
| 94 } |
| 92 completer.completeError(e, stackTrace); | 95 completer.completeError(e, stackTrace); |
| 93 }); | 96 }); |
| 94 return completer.future; | 97 return completer.future; |
| 95 } | 98 } |
| 96 | 99 |
| 97 /// Ensures that any errors emitted by [stream] have the correct stack | 100 /// Ensures that any errors emitted by [stream] have the correct stack |
| 98 /// information associated with them. | 101 /// information associated with them. |
| 99 /// | 102 /// |
| 100 /// By default, the first frame of the first trace will be the line where | 103 /// By default, the first frame of the first trace will be the line where |
| 101 /// [trackStream] is called. If [level] is passed, the first trace will start | 104 /// [trackStream] is called. If [level] is passed, the first trace will start |
| 102 /// that many frames up instead. | 105 /// that many frames up instead. |
| 103 Stream trackStream(Stream stream, [int level=0]) { | 106 Stream trackStream(Stream stream, [int level=0]) { |
| 104 var node = _createNode(level + 1); | 107 var node = _createNode(level + 1); |
| 105 return stream.transform(new StreamTransformer.fromHandlers( | 108 return stream.transform(new StreamTransformer.fromHandlers( |
| 106 handleError: (error, stackTrace, sink) { | 109 handleError: (error, stackTrace, sink) { |
| 107 if (stackTrace == null) stackTrace = new Trace.current(); | 110 if (stackTrace == null) stackTrace = new Trace.current(); |
| 108 if (_chains[stackTrace] == null) _chains[stackTrace] = node; | 111 if (stackTrace is! Chain && _chains[stackTrace] == null) { |
| 112 _chains[stackTrace] = node; |
| 113 } |
| 109 sink.addError(error, stackTrace); | 114 sink.addError(error, stackTrace); |
| 110 })); | 115 })); |
| 111 } | 116 } |
| 112 | 117 |
| 113 /// Tracks the current stack chain so it can be set to [_currentChain] when | 118 /// Tracks the current stack chain so it can be set to [_currentChain] when |
| 114 /// [f] is run. | 119 /// [f] is run. |
| 115 ZoneCallback registerCallback(Zone self, ZoneDelegate parent, Zone zone, | 120 ZoneCallback registerCallback(Zone self, ZoneDelegate parent, Zone zone, |
| 116 Function f) { | 121 Function f) { |
| 117 if (f == null) return parent.registerCallback(zone, null); | 122 if (f == null) return parent.registerCallback(zone, null); |
| 118 var node = _createNode(1); | 123 var node = _createNode(1); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 return parent.runBinary(zone, _onError, error, stackChain); | 161 return parent.runBinary(zone, _onError, error, stackChain); |
| 157 } catch (newError, newStackTrace) { | 162 } catch (newError, newStackTrace) { |
| 158 if (identical(newError, error)) { | 163 if (identical(newError, error)) { |
| 159 return parent.handleUncaughtError(zone, error, stackChain); | 164 return parent.handleUncaughtError(zone, error, stackChain); |
| 160 } else { | 165 } else { |
| 161 return parent.handleUncaughtError(zone, newError, newStackTrace); | 166 return parent.handleUncaughtError(zone, newError, newStackTrace); |
| 162 } | 167 } |
| 163 } | 168 } |
| 164 } | 169 } |
| 165 | 170 |
| 171 /// Attaches the current stack chain to [stackTrace], replacing it if |
| 172 /// necessary. |
| 173 AsyncError errorCallback(Zone self, ZoneDelegate parent, Zone zone, |
| 174 Object error, StackTrace stackTrace) { |
| 175 var asyncError = parent.errorCallback(zone, error, stackTrace); |
| 176 if (asyncError != null) { |
| 177 error = asyncError.error; |
| 178 stackTrace = asyncError.stackTrace; |
| 179 } |
| 180 |
| 181 // Go up two levels to get through [_CustomZone.errorCallback]. |
| 182 if (stackTrace == null) { |
| 183 stackTrace = _createNode(2).toChain(); |
| 184 } else { |
| 185 if (_chains[stackTrace] == null) _chains[stackTrace] = _createNode(2); |
| 186 } |
| 187 |
| 188 return new AsyncError(error, stackTrace); |
| 189 } |
| 190 |
| 166 /// Creates a [_Node] with the current stack trace and linked to | 191 /// Creates a [_Node] with the current stack trace and linked to |
| 167 /// [_currentNode]. | 192 /// [_currentNode]. |
| 168 /// | 193 /// |
| 169 /// By default, the first frame of the first trace will be the line where | 194 /// By default, the first frame of the first trace will be the line where |
| 170 /// [_createNode] is called. If [level] is passed, the first trace will start | 195 /// [_createNode] is called. If [level] is passed, the first trace will start |
| 171 /// that many frames up instead. | 196 /// that many frames up instead. |
| 172 _Node _createNode([int level=0]) => | 197 _Node _createNode([int level=0]) => |
| 173 new _Node(new Trace.current(level + 1), _currentNode); | 198 new _Node(new Trace.current(level + 1), _currentNode); |
| 174 | 199 |
| 175 // TODO(nweiz): use a more robust way of detecting and tracking errors when | 200 // TODO(nweiz): use a more robust way of detecting and tracking errors when |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 Chain toChain() { | 232 Chain toChain() { |
| 208 var nodes = <Trace>[]; | 233 var nodes = <Trace>[]; |
| 209 var node = this; | 234 var node = this; |
| 210 while (node != null) { | 235 while (node != null) { |
| 211 nodes.add(node.trace); | 236 nodes.add(node.trace); |
| 212 node = node.previous; | 237 node = node.previous; |
| 213 } | 238 } |
| 214 return new Chain(nodes); | 239 return new Chain(nodes); |
| 215 } | 240 } |
| 216 } | 241 } |
| OLD | NEW |