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 error_group; | 5 library error_group; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import 'utils.dart'; | 9 import 'utils.dart'; |
10 | 10 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 _streams.add(wrapped); | 96 _streams.add(wrapped); |
97 return wrapped; | 97 return wrapped; |
98 } | 98 } |
99 | 99 |
100 /// Sends [error] to all members of [this]. Like errors that come from | 100 /// Sends [error] to all members of [this]. Like errors that come from |
101 /// members, this will only be passed to the top-level error handler if no | 101 /// members, this will only be passed to the top-level error handler if no |
102 /// members have listeners. | 102 /// members have listeners. |
103 /// | 103 /// |
104 /// If all members of [this] have already completed successfully or with an | 104 /// If all members of [this] have already completed successfully or with an |
105 /// error, it's a [StateError] to try to signal an error. | 105 /// error, it's a [StateError] to try to signal an error. |
106 void signalError(AsyncError error) { | 106 void signalError(var error) { |
107 if (_isDone) { | 107 if (_isDone) { |
108 throw new StateError("Can't signal errors on a complete ErrorGroup."); | 108 throw new StateError("Can't signal errors on a complete ErrorGroup."); |
109 } | 109 } |
110 | 110 |
111 _signalError(error); | 111 _signalError(error); |
112 } | 112 } |
113 | 113 |
114 /// Signal an error internally. This is just like [signalError], but instead | 114 /// Signal an error internally. This is just like [signalError], but instead |
115 /// of throwing an error if [this] is complete, it just does nothing. | 115 /// of throwing an error if [this] is complete, it just does nothing. |
116 void _signalError(AsyncError error) { | 116 void _signalError(var error) { |
117 if (_isDone) return; | 117 if (_isDone) return; |
118 | 118 |
119 var caught = false; | 119 var caught = false; |
120 for (var future in _futures) { | 120 for (var future in _futures) { |
121 if (future._isDone || future._hasListeners) caught = true; | 121 if (future._isDone || future._hasListeners) caught = true; |
122 future._signalError(error); | 122 future._signalError(error); |
123 } | 123 } |
124 | 124 |
125 for (var stream in _streams) { | 125 for (var stream in _streams) { |
126 if (stream._isDone || stream._hasListeners) caught = true; | 126 if (stream._isDone || stream._hasListeners) caught = true; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 if (!_isDone) _completer.complete(value); | 174 if (!_isDone) _completer.complete(value); |
175 _isDone = true; | 175 _isDone = true; |
176 _group._signalFutureComplete(this); | 176 _group._signalFutureComplete(this); |
177 }).catchError((error) => _group._signalError(error)); | 177 }).catchError((error) => _group._signalError(error)); |
178 | 178 |
179 // Make sure _completer.future doesn't automatically send errors to the | 179 // Make sure _completer.future doesn't automatically send errors to the |
180 // top-level. | 180 // top-level. |
181 _completer.future.catchError((_) {}); | 181 _completer.future.catchError((_) {}); |
182 } | 182 } |
183 | 183 |
184 Future then(onValue(value), {onError(AsyncError asyncError)}) { | 184 Future then(onValue(value), {onError(error)}) { |
185 _hasListeners = true; | 185 _hasListeners = true; |
186 return _completer.future.then(onValue, onError: onError); | 186 return _completer.future.then(onValue, onError: onError); |
187 } | 187 } |
188 | 188 |
189 Future catchError(onError(AsyncError asyncError), {bool test(Object error)}) { | 189 Future catchError(onError(error), {bool test(Object error)}) { |
190 _hasListeners = true; | 190 _hasListeners = true; |
191 return _completer.future.catchError(onError, test: test); | 191 return _completer.future.catchError(onError, test: test); |
192 } | 192 } |
193 | 193 |
194 Future whenComplete(void action()) { | 194 Future whenComplete(void action()) { |
195 _hasListeners = true; | 195 _hasListeners = true; |
196 return _completer.future.whenComplete(action); | 196 return _completer.future.whenComplete(action); |
197 } | 197 } |
198 | 198 |
199 Stream asStream() { | 199 Stream asStream() { |
200 _hasListeners = true; | 200 _hasListeners = true; |
201 return _completer.future.asStream(); | 201 return _completer.future.asStream(); |
202 } | 202 } |
203 | 203 |
204 /// Signal that an error from [_group] should be propagated through [this], | 204 /// Signal that an error from [_group] should be propagated through [this], |
205 /// unless it's already complete. | 205 /// unless it's already complete. |
206 void _signalError(AsyncError error) { | 206 void _signalError(var error) { |
207 if (!_isDone) _completer.completeError(error.error, error.stackTrace); | 207 if (!_isDone) _completer.completeError(error); |
208 _isDone = true; | 208 _isDone = true; |
209 } | 209 } |
210 } | 210 } |
211 | 211 |
212 // TODO(nweiz): currently streams never top-level unhandled errors (issue 7843). | 212 // TODO(nweiz): currently streams never top-level unhandled errors (issue 7843). |
213 // When this is fixed, this class will need to prevent such errors from being | 213 // When this is fixed, this class will need to prevent such errors from being |
214 // top-leveled. | 214 // top-leveled. |
215 /// A [Stream] wrapper that keeps track of whether it's been completed and | 215 /// A [Stream] wrapper that keeps track of whether it's been completed and |
216 /// whether it has any listeners. It also notifies its parent [ErrorGroup] when | 216 /// whether it has any listeners. It also notifies its parent [ErrorGroup] when |
217 /// it completes successfully or receives an error. | 217 /// it completes successfully or receives an error. |
(...skipping 25 matching lines...) Expand all Loading... |
243 }, onError: (e) { | 243 }, onError: (e) { |
244 _group._signalError(e); | 244 _group._signalError(e); |
245 }, onDone: () { | 245 }, onDone: () { |
246 _isDone = true; | 246 _isDone = true; |
247 _group._signalStreamComplete(this); | 247 _group._signalStreamComplete(this); |
248 _controller.close(); | 248 _controller.close(); |
249 }); | 249 }); |
250 } | 250 } |
251 | 251 |
252 StreamSubscription listen(void onData(value), | 252 StreamSubscription listen(void onData(value), |
253 {void onError(AsyncError error), void onDone(), | 253 {void onError(var error), void onDone(), |
254 bool cancelOnError}) { | 254 bool cancelOnError}) { |
255 return _controller.stream.listen(onData, | 255 return _controller.stream.listen(onData, |
256 onError: onError, | 256 onError: onError, |
257 onDone: onDone, | 257 onDone: onDone, |
258 cancelOnError: true); | 258 cancelOnError: true); |
259 } | 259 } |
260 | 260 |
261 /// Signal that an error from [_group] should be propagated through [this], | 261 /// Signal that an error from [_group] should be propagated through [this], |
262 /// unless it's already complete. | 262 /// unless it's already complete. |
263 void _signalError(AsyncError e) { | 263 void _signalError(var e) { |
264 if (_isDone) return; | 264 if (_isDone) return; |
265 _subscription.cancel(); | 265 _subscription.cancel(); |
266 // Call these asynchronously to work around issue 7913. | 266 // Call these asynchronously to work around issue 7913. |
267 new Future.immediate(null).then((_) { | 267 new Future.immediate(null).then((_) { |
268 _controller.addError(e.error, e.stackTrace); | 268 _controller.addError(e); |
269 _controller.close(); | 269 _controller.close(); |
270 }); | 270 }); |
271 } | 271 } |
272 } | 272 } |
OLD | NEW |