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...) 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...) 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...) 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...) 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 |