Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: sdk/lib/async/stream_pipe.dart

Issue 555153002: Add error-intercept for Completer.completeError and StreamController.addError. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Intercept all errors thrown by unregistered callbacks. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sdk/lib/async/stream_impl.dart ('k') | sdk/lib/async/zone.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 part of dart.async; 5 part of dart.async;
6 6
7 /** Runs user code and takes actions depending on success or failure. */ 7 /** Runs user code and takes actions depending on success or failure. */
8 _runUserCode(userCode(), 8 _runUserCode(userCode(),
9 onSuccess(value), 9 onSuccess(value),
10 onError(error, StackTrace stackTrace)) { 10 onError(error, StackTrace stackTrace)) {
11 try { 11 try {
12 onSuccess(userCode()); 12 onSuccess(userCode());
13 } catch (e, s) { 13 } catch (e, s) {
14 onError(e, s); 14 AsyncError replacement = Zone.current.errorCallback(e, s);
15 if (replacement == null) {
16 onError(e, s);
17 } else {
18 onError(replacement.error, replacement.stackTrace);
19 }
15 } 20 }
16 } 21 }
17 22
18 /** Helper function to cancel a subscription and wait for the potential future, 23 /** Helper function to cancel a subscription and wait for the potential future,
19 before completing with an error. */ 24 before completing with an error. */
20 void _cancelAndError(StreamSubscription subscription, 25 void _cancelAndError(StreamSubscription subscription,
21 _Future future, 26 _Future future,
22 error, 27 error,
23 StackTrace stackTrace) { 28 StackTrace stackTrace) {
24 var cancelFuture = subscription.cancel(); 29 var cancelFuture = subscription.cancel();
25 if (cancelFuture is Future) { 30 if (cancelFuture is Future) {
26 cancelFuture.whenComplete(() => future._completeError(error, stackTrace)); 31 cancelFuture.whenComplete(() => future._completeError(error, stackTrace));
27 } else { 32 } else {
28 future._completeError(error, stackTrace); 33 future._completeError(error, stackTrace);
29 } 34 }
30 } 35 }
31 36
37 void _cancelAndErrorWithReplacement(StreamSubscription subscription,
38 _Future future,
39 error, StackTrace stackTrace) {
40 AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
41 if (replacement != null) {
42 error = replacement.error;
43 stackTrace = replacement.stackTrace;
44 }
45 _cancelAndError(subscription, future, error, stackTrace);
46 }
47
32 /** Helper function to make an onError argument to [_runUserCode]. */ 48 /** Helper function to make an onError argument to [_runUserCode]. */
33 _cancelAndErrorClosure(StreamSubscription subscription, _Future future) => 49 _cancelAndErrorClosure(StreamSubscription subscription, _Future future) =>
34 ((error, StackTrace stackTrace) => _cancelAndError( 50 ((error, StackTrace stackTrace) => _cancelAndError(
35 subscription, future, error, stackTrace)); 51 subscription, future, error, stackTrace));
36 52
37 /** Helper function to cancel a subscription and wait for the potential future, 53 /** Helper function to cancel a subscription and wait for the potential future,
38 before completing with a value. */ 54 before completing with a value. */
39 void _cancelAndValue(StreamSubscription subscription, _Future future, value) { 55 void _cancelAndValue(StreamSubscription subscription, _Future future, value) {
40 var cancelFuture = subscription.cancel(); 56 var cancelFuture = subscription.cancel();
41 if (cancelFuture is Future) { 57 if (cancelFuture is Future) {
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 _stream._handleDone(this); 178 _stream._handleDone(this);
163 } 179 }
164 } 180 }
165 181
166 // ------------------------------------------------------------------- 182 // -------------------------------------------------------------------
167 // Stream transformers used by the default Stream implementation. 183 // Stream transformers used by the default Stream implementation.
168 // ------------------------------------------------------------------- 184 // -------------------------------------------------------------------
169 185
170 typedef bool _Predicate<T>(T value); 186 typedef bool _Predicate<T>(T value);
171 187
188 void _addErrorWithReplacement(_EventSink sink, error, stackTrace) {
189 AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
190 if (replacement == null) {
191 sink._addError(error, stackTrace);
192 } else {
193 sink._addError(replacement.error, replacement.stackTrace);
194 }
195 }
196
197
172 class _WhereStream<T> extends _ForwardingStream<T, T> { 198 class _WhereStream<T> extends _ForwardingStream<T, T> {
173 final _Predicate<T> _test; 199 final _Predicate<T> _test;
174 200
175 _WhereStream(Stream<T> source, bool test(T value)) 201 _WhereStream(Stream<T> source, bool test(T value))
176 : _test = test, super(source); 202 : _test = test, super(source);
177 203
178 void _handleData(T inputEvent, _EventSink<T> sink) { 204 void _handleData(T inputEvent, _EventSink<T> sink) {
179 bool satisfies; 205 bool satisfies;
180 try { 206 try {
181 satisfies = _test(inputEvent); 207 satisfies = _test(inputEvent);
182 } catch (e, s) { 208 } catch (e, s) {
183 sink._addError(e, s); 209 _addErrorWithReplacement(sink, e, s);
184 return; 210 return;
185 } 211 }
186 if (satisfies) { 212 if (satisfies) {
187 sink._add(inputEvent); 213 sink._add(inputEvent);
188 } 214 }
189 } 215 }
190 } 216 }
191 217
192 218
193 typedef T _Transformation<S, T>(S value); 219 typedef T _Transformation<S, T>(S value);
194 220
195 /** 221 /**
196 * A stream pipe that converts data events before passing them on. 222 * A stream pipe that converts data events before passing them on.
197 */ 223 */
198 class _MapStream<S, T> extends _ForwardingStream<S, T> { 224 class _MapStream<S, T> extends _ForwardingStream<S, T> {
199 final _Transformation _transform; 225 final _Transformation _transform;
200 226
201 _MapStream(Stream<S> source, T transform(S event)) 227 _MapStream(Stream<S> source, T transform(S event))
202 : this._transform = transform, super(source); 228 : this._transform = transform, super(source);
203 229
204 void _handleData(S inputEvent, _EventSink<T> sink) { 230 void _handleData(S inputEvent, _EventSink<T> sink) {
205 T outputEvent; 231 T outputEvent;
206 try { 232 try {
207 outputEvent = _transform(inputEvent); 233 outputEvent = _transform(inputEvent);
208 } catch (e, s) { 234 } catch (e, s) {
209 sink._addError(e, s); 235 _addErrorWithReplacement(sink, e, s);
210 return; 236 return;
211 } 237 }
212 sink._add(outputEvent); 238 sink._add(outputEvent);
213 } 239 }
214 } 240 }
215 241
216 /** 242 /**
217 * A stream pipe that converts data events before passing them on. 243 * A stream pipe that converts data events before passing them on.
218 */ 244 */
219 class _ExpandStream<S, T> extends _ForwardingStream<S, T> { 245 class _ExpandStream<S, T> extends _ForwardingStream<S, T> {
220 final _Transformation<S, Iterable<T>> _expand; 246 final _Transformation<S, Iterable<T>> _expand;
221 247
222 _ExpandStream(Stream<S> source, Iterable<T> expand(S event)) 248 _ExpandStream(Stream<S> source, Iterable<T> expand(S event))
223 : this._expand = expand, super(source); 249 : this._expand = expand, super(source);
224 250
225 void _handleData(S inputEvent, _EventSink<T> sink) { 251 void _handleData(S inputEvent, _EventSink<T> sink) {
226 try { 252 try {
227 for (T value in _expand(inputEvent)) { 253 for (T value in _expand(inputEvent)) {
228 sink._add(value); 254 sink._add(value);
229 } 255 }
230 } catch (e, s) { 256 } catch (e, s) {
231 // If either _expand or iterating the generated iterator throws, 257 // If either _expand or iterating the generated iterator throws,
232 // we abort the iteration. 258 // we abort the iteration.
233 sink._addError(e, s); 259 _addErrorWithReplacement(sink, e, s);
234 } 260 }
235 } 261 }
236 } 262 }
237 263
238 264
239 typedef bool _ErrorTest(error); 265 typedef bool _ErrorTest(error);
240 266
241 /** 267 /**
242 * A stream pipe that converts or disposes error events 268 * A stream pipe that converts or disposes error events
243 * before passing them on. 269 * before passing them on.
244 */ 270 */
245 class _HandleErrorStream<T> extends _ForwardingStream<T, T> { 271 class _HandleErrorStream<T> extends _ForwardingStream<T, T> {
246 final Function _transform; 272 final Function _transform;
247 final _ErrorTest _test; 273 final _ErrorTest _test;
248 274
249 _HandleErrorStream(Stream<T> source, 275 _HandleErrorStream(Stream<T> source,
250 Function onError, 276 Function onError,
251 bool test(error)) 277 bool test(error))
252 : this._transform = onError, this._test = test, super(source); 278 : this._transform = onError, this._test = test, super(source);
253 279
254 void _handleError(Object error, StackTrace stackTrace, _EventSink<T> sink) { 280 void _handleError(Object error, StackTrace stackTrace, _EventSink<T> sink) {
255 bool matches = true; 281 bool matches = true;
256 if (_test != null) { 282 if (_test != null) {
257 try { 283 try {
258 matches = _test(error); 284 matches = _test(error);
259 } catch (e, s) { 285 } catch (e, s) {
260 sink._addError(e, s); 286 _addErrorWithReplacement(sink, e, s);
261 return; 287 return;
262 } 288 }
263 } 289 }
264 if (matches) { 290 if (matches) {
265 try { 291 try {
266 _invokeErrorHandler(_transform, error, stackTrace); 292 _invokeErrorHandler(_transform, error, stackTrace);
267 } catch (e, s) { 293 } catch (e, s) {
268 if (identical(e, error)) { 294 if (identical(e, error)) {
269 sink._addError(error, stackTrace); 295 sink._addError(error, stackTrace);
270 } else { 296 } else {
271 sink._addError(e, s); 297 _addErrorWithReplacement(sink, e, s);
272 } 298 }
273 return; 299 return;
274 } 300 }
275 } else { 301 } else {
276 sink._addError(error, stackTrace); 302 sink._addError(error, stackTrace);
277 } 303 }
278 } 304 }
279 } 305 }
280 306
281 307
(...skipping 25 matching lines...) Expand all
307 final _Predicate<T> _test; 333 final _Predicate<T> _test;
308 334
309 _TakeWhileStream(Stream<T> source, bool test(T value)) 335 _TakeWhileStream(Stream<T> source, bool test(T value))
310 : this._test = test, super(source); 336 : this._test = test, super(source);
311 337
312 void _handleData(T inputEvent, _EventSink<T> sink) { 338 void _handleData(T inputEvent, _EventSink<T> sink) {
313 bool satisfies; 339 bool satisfies;
314 try { 340 try {
315 satisfies = _test(inputEvent); 341 satisfies = _test(inputEvent);
316 } catch (e, s) { 342 } catch (e, s) {
317 sink._addError(e, s); 343 _addErrorWithReplacement(sink, e, s);
318 // The test didn't say true. Didn't say false either, but we stop anyway. 344 // The test didn't say true. Didn't say false either, but we stop anyway.
319 sink._close(); 345 sink._close();
320 return; 346 return;
321 } 347 }
322 if (satisfies) { 348 if (satisfies) {
323 sink._add(inputEvent); 349 sink._add(inputEvent);
324 } else { 350 } else {
325 sink._close(); 351 sink._close();
326 } 352 }
327 } 353 }
(...skipping 27 matching lines...) Expand all
355 381
356 void _handleData(T inputEvent, _EventSink<T> sink) { 382 void _handleData(T inputEvent, _EventSink<T> sink) {
357 if (_hasFailed) { 383 if (_hasFailed) {
358 sink._add(inputEvent); 384 sink._add(inputEvent);
359 return; 385 return;
360 } 386 }
361 bool satisfies; 387 bool satisfies;
362 try { 388 try {
363 satisfies = _test(inputEvent); 389 satisfies = _test(inputEvent);
364 } catch (e, s) { 390 } catch (e, s) {
365 sink._addError(e, s); 391 _addErrorWithReplacement(sink, e, s);
366 // A failure to return a boolean is considered "not matching". 392 // A failure to return a boolean is considered "not matching".
367 _hasFailed = true; 393 _hasFailed = true;
368 return; 394 return;
369 } 395 }
370 if (!satisfies) { 396 if (!satisfies) {
371 _hasFailed = true; 397 _hasFailed = true;
372 sink._add(inputEvent); 398 sink._add(inputEvent);
373 } 399 }
374 } 400 }
375 } 401 }
(...skipping 15 matching lines...) Expand all
391 return sink._add(inputEvent); 417 return sink._add(inputEvent);
392 } else { 418 } else {
393 bool isEqual; 419 bool isEqual;
394 try { 420 try {
395 if (_equals == null) { 421 if (_equals == null) {
396 isEqual = (_previous == inputEvent); 422 isEqual = (_previous == inputEvent);
397 } else { 423 } else {
398 isEqual = _equals(_previous, inputEvent); 424 isEqual = _equals(_previous, inputEvent);
399 } 425 }
400 } catch (e, s) { 426 } catch (e, s) {
401 sink._addError(e, s); 427 _addErrorWithReplacement(sink, e, s);
402 return null; 428 return null;
403 } 429 }
404 if (!isEqual) { 430 if (!isEqual) {
405 sink._add(inputEvent); 431 sink._add(inputEvent);
406 _previous = inputEvent; 432 _previous = inputEvent;
407 } 433 }
408 } 434 }
409 } 435 }
410 } 436 }
OLDNEW
« no previous file with comments | « sdk/lib/async/stream_impl.dart ('k') | sdk/lib/async/zone.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698