Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 /** Utility function to create an [AsyncError] if [error] isn't one already. */ | 7 /** Utility function to create an [AsyncError] if [error] isn't one already. */ |
| 8 AsyncError _asyncError(Object error, Object stackTrace, [AsyncError cause]) { | 8 AsyncError _asyncError(Object error, Object stackTrace, [AsyncError cause]) { |
| 9 if (error is AsyncError) return error; | 9 if (error is AsyncError) return error; |
| 10 if (cause == null) return new AsyncError(error, stackTrace); | 10 if (cause == null) return new AsyncError(error, stackTrace); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 * | 46 * |
| 47 * This class is intended for internal use only. | 47 * This class is intended for internal use only. |
| 48 */ | 48 */ |
| 49 abstract class _ForwardingStream<S, T> extends Stream<T> { | 49 abstract class _ForwardingStream<S, T> extends Stream<T> { |
| 50 final Stream<S> _source; | 50 final Stream<S> _source; |
| 51 | 51 |
| 52 _ForwardingStream(this._source); | 52 _ForwardingStream(this._source); |
| 53 | 53 |
| 54 bool get isBroadcast => _source.isBroadcast; | 54 bool get isBroadcast => _source.isBroadcast; |
| 55 | 55 |
| 56 bool asBroadcastStream() => _source.asBroadcastStream; | 56 StreamSubscription<T> listen(void onData(T value), |
| 57 | 57 { void onError(AsyncError error), |
| 58 StreamSubscription listen(void onData(T value), | 58 void onDone(), |
| 59 { void onError(AsyncError error), | 59 bool unsubscribeOnError }) { |
| 60 void onDone(), | |
| 61 bool unsubscribeOnError }) { | |
| 62 if (onData == null) onData = _nullDataHandler; | 60 if (onData == null) onData = _nullDataHandler; |
| 63 if (onError == null) onError = _nullErrorHandler; | 61 if (onError == null) onError = _nullErrorHandler; |
| 64 if (onDone == null) onDone = _nullDoneHandler; | 62 if (onDone == null) onDone = _nullDoneHandler; |
| 65 unsubscribeOnError = identical(true, unsubscribeOnError); | 63 unsubscribeOnError = identical(true, unsubscribeOnError); |
| 66 StreamSubscription subscription = | 64 return _createSubscription(onData, onError, onDone, unsubscribeOnError); |
| 67 new _ForwardingStreamSubscription<S, T>( | 65 } |
| 68 this, onData, onError, onDone, unsubscribeOnError); | 66 |
| 69 return subscription; | 67 StreamSubscription<T> _createSubscription(void onData(T value), |
| 68 void onError(AsyncError error), | |
| 69 void onDone(), | |
| 70 bool unsubscribeOnError) { | |
| 71 return new _ForwardingStreamSubscription<S, T>( | |
| 72 this, onData, onError, onDone, unsubscribeOnError); | |
| 70 } | 73 } |
| 71 | 74 |
| 72 // Override the following methods in subclasses to change the behavior. | 75 // Override the following methods in subclasses to change the behavior. |
| 73 | 76 |
| 74 void _handleData(S data, _StreamOutputSink<T> sink) { | 77 void _handleData(S data, _StreamOutputSink<T> sink) { |
| 75 var outputData = data; | 78 var outputData = data; |
| 76 sink._sendData(outputData); | 79 sink._sendData(outputData); |
| 77 } | 80 } |
| 78 | 81 |
| 79 void _handleError(AsyncError error, _StreamOutputSink<T> sink) { | 82 void _handleError(AsyncError error, _StreamOutputSink<T> sink) { |
| 80 sink._sendError(error); | 83 sink._sendError(error); |
| 81 } | 84 } |
| 82 | 85 |
| 83 void _handleDone(_StreamOutputSink<T> sink) { | 86 void _handleDone(_StreamOutputSink<T> sink) { |
| 84 sink._sendDone(); | 87 sink._sendDone(); |
| 85 } | 88 } |
| 86 } | 89 } |
| 87 | 90 |
| 88 /** | 91 /** |
| 89 * Abstract superclass for subscriptions that forward to other subscriptions. | 92 * Basic implemnetation of the handler features of a [StreamSubscription]. |
|
floitsch
2013/01/28 14:45:09
implementation.
I don't understand the sentence.
Lasse Reichstein Nielsen
2013/01/29 08:42:54
Rewritten.
| |
| 93 * | |
| 94 * Supports storing and updating of event handlers on a subscription. | |
| 90 */ | 95 */ |
| 91 class _ForwardingStreamSubscription<S, T> | 96 abstract class _BaseStreamSubscription<T> implements StreamSubscription<T> { |
| 92 implements StreamSubscription<T>, _StreamOutputSink<T> { | |
| 93 final _ForwardingStream<S, T> _stream; | |
| 94 // TODO(ahe): Restore type when feature is implemented in dart2js | 97 // TODO(ahe): Restore type when feature is implemented in dart2js |
| 95 // checked mode. http://dartbug.com/7733 | 98 // checked mode. http://dartbug.com/7733 |
| 96 var /* _DataHandler<T> */ _onData; | 99 var /* _DataHandler<T> */ _onData; |
| 97 _ErrorHandler _onError; | 100 _ErrorHandler _onError; |
| 98 _DoneHandler _onDone; | 101 _DoneHandler _onDone; |
| 99 | 102 |
| 100 StreamSubscription<S> _subscription; | 103 _BaseStreamSubscription(this._onData, |
| 101 | 104 this._onError, |
| 102 _ForwardingStreamSubscription(this._stream, | 105 this._onDone) { |
| 103 this._onData, | 106 if (_onData == null) _onData = _nullDataHandler; |
| 104 this._onError, | 107 if (_onError == null) _onError = _nullErrorHandler; |
| 105 this._onDone, | 108 if (_onDone == null) _onDone = _nullDoneHandler; |
| 106 bool unsubscribeOnError) { | |
| 107 _subscription = | |
| 108 _stream._source.listen(_handleData, | |
| 109 onError: _handleError, | |
| 110 onDone: _handleDone, | |
| 111 unsubscribeOnError: unsubscribeOnError); | |
| 112 } | 109 } |
| 113 | 110 |
| 114 // StreamSubscription interface. | 111 // StreamSubscription interface. |
| 115 | |
| 116 void onData(void handleData(T event)) { | 112 void onData(void handleData(T event)) { |
| 117 if (handleData == null) handleData = _nullDataHandler; | 113 if (handleData == null) handleData = _nullDataHandler; |
| 118 _onData = handleData; | 114 _onData = handleData; |
| 119 } | 115 } |
| 120 | 116 |
| 121 void onError(void handleError(AsyncError error)) { | 117 void onError(void handleError(AsyncError error)) { |
| 122 if (handleError == null) handleError = _nullErrorHandler; | 118 if (handleError == null) handleError = _nullErrorHandler; |
| 123 _onError = handleError; | 119 _onError = handleError; |
| 124 } | 120 } |
| 125 | 121 |
| 126 void onDone(void handleDone()) { | 122 void onDone(void handleDone()) { |
| 127 if (handleDone == null) handleDone = _nullDoneHandler; | 123 if (handleDone == null) handleDone = _nullDoneHandler; |
| 128 _onDone = handleDone; | 124 _onDone = handleDone; |
| 129 } | 125 } |
| 130 | 126 |
| 127 void pause([Future resumeSignal]); | |
| 128 | |
| 129 void resume(); | |
| 130 | |
| 131 void cancel(); | |
| 132 } | |
| 133 | |
| 134 | |
| 135 /** | |
| 136 * Abstract superclass for subscriptions that forward to other subscriptions. | |
| 137 */ | |
| 138 class _ForwardingStreamSubscription<S, T> | |
| 139 extends _BaseStreamSubscription<T> implements _StreamOutputSink<T> { | |
| 140 final _ForwardingStream<S, T> _stream; | |
| 141 final bool _unsubscribeOnError; | |
| 142 | |
| 143 StreamSubscription<S> _subscription; | |
| 144 | |
| 145 _ForwardingStreamSubscription(this._stream, | |
| 146 void onData(T data), | |
| 147 void onError(AsyncError error), | |
| 148 void onDone(), | |
| 149 this._unsubscribeOnError) | |
| 150 : super(onData, onError, onDone) { | |
| 151 // Don't unsubscribe on incoming error, only if we send an error forwards. | |
|
floitsch
2013/01/28 14:45:09
Took me way too long to understand the comment...
| |
| 152 _subscription = | |
| 153 _stream._source.listen(_handleData, | |
| 154 onError: _handleError, | |
| 155 onDone: _handleDone); | |
| 156 } | |
| 157 | |
| 158 // StreamSubscription interface. | |
| 159 | |
| 131 void pause([Future resumeSignal]) { | 160 void pause([Future resumeSignal]) { |
| 132 if (_subscription == null) { | 161 if (_subscription == null) { |
| 133 throw new StateError("Subscription has been unsubscribed"); | 162 throw new StateError("Subscription has been unsubscribed"); |
| 134 } | 163 } |
| 135 _subscription.pause(resumeSignal); | 164 _subscription.pause(resumeSignal); |
| 136 } | 165 } |
| 137 | 166 |
| 138 void resume() { | 167 void resume() { |
| 139 if (_subscription == null) { | 168 if (_subscription == null) { |
| 140 throw new StateError("Subscription has been unsubscribed"); | 169 throw new StateError("Subscription has been unsubscribed"); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 151 } | 180 } |
| 152 | 181 |
| 153 // _StreamOutputSink interface. Sends data to this subscription. | 182 // _StreamOutputSink interface. Sends data to this subscription. |
| 154 | 183 |
| 155 void _sendData(T data) { | 184 void _sendData(T data) { |
| 156 _onData(data); | 185 _onData(data); |
| 157 } | 186 } |
| 158 | 187 |
| 159 void _sendError(AsyncError error) { | 188 void _sendError(AsyncError error) { |
| 160 _onError(error); | 189 _onError(error); |
| 190 if (_unsubscribeOnError) { | |
| 191 _subscription.cancel(); | |
| 192 _subscription = null; | |
| 193 } | |
| 161 } | 194 } |
| 162 | 195 |
| 163 void _sendDone() { | 196 void _sendDone() { |
| 164 // If the transformation sends a done signal, we stop the subscription. | 197 // If the transformation sends a done signal, we stop the subscription. |
| 165 if (_subscription != null) { | 198 if (_subscription != null) { |
| 166 _subscription.cancel(); | 199 _subscription.cancel(); |
| 167 _subscription = null; | 200 _subscription = null; |
| 168 } | 201 } |
| 169 _onDone(); | 202 _onDone(); |
| 170 } | 203 } |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 419 return null; | 452 return null; |
| 420 } | 453 } |
| 421 if (!isEqual) { | 454 if (!isEqual) { |
| 422 sink._sendData(inputEvent); | 455 sink._sendData(inputEvent); |
| 423 _previous = inputEvent; | 456 _previous = inputEvent; |
| 424 } | 457 } |
| 425 } | 458 } |
| 426 } | 459 } |
| 427 } | 460 } |
| 428 | 461 |
| 462 // Stream transformations and event transformations. | |
| 429 | 463 |
| 430 typedef void _TransformDataHandler<S, T>(S data, StreamSink<T> sink); | 464 typedef void _TransformDataHandler<S, T>(S data, StreamSink<T> sink); |
| 431 typedef void _TransformErrorHandler<T>(AsyncError data, StreamSink<T> sink); | 465 typedef void _TransformErrorHandler<T>(AsyncError data, StreamSink<T> sink); |
| 432 typedef void _TransformDoneHandler<T>(StreamSink<T> sink); | 466 typedef void _TransformDoneHandler<T>(StreamSink<T> sink); |
| 433 | 467 |
| 468 /** Default data handler forwards all data. */ | |
| 469 void _defaultHandleData(var data, StreamSink sink) { | |
| 470 sink.add(data); | |
| 471 } | |
| 472 | |
| 473 /** Default error handler forwards all errors. */ | |
| 474 void _defaultHandleError(AsyncError error, StreamSink sink) { | |
| 475 sink.signalError(error); | |
| 476 } | |
| 477 | |
| 478 /** Default done handler forwards done. */ | |
| 479 void _defaultHandleDone(StreamSink sink) { | |
| 480 sink.close(); | |
| 481 } | |
| 482 | |
| 483 | |
| 434 /** | 484 /** |
| 435 * A stream transformer that intercepts all events and can generate any event as | 485 * A stream transformer that intercepts all events and can generate any event as |
| 436 * output. | 486 * output. |
| 437 * | 487 * |
| 438 * Each incoming event on the source stream is passed to the corresponding | 488 * Each incoming event on the source stream is passed to the corresponding |
| 439 * provided event handler, along with a [StreamSink] linked to the output | 489 * provided event handler, along with a [StreamSink] linked to the output |
| 440 * Stream. | 490 * Stream. |
| 441 * The handler can then decide exactly which events to send to the output. | 491 * The handler can then decide exactly which events to send to the output. |
| 442 */ | 492 */ |
| 443 class _StreamTransformerImpl<S, T> implements StreamTransformer<S, T> { | 493 class _StreamTransformerImpl<S, T> implements StreamTransformer<S, T> { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 458 // Cache a Sink object to avoid creating a new one for each event. | 508 // Cache a Sink object to avoid creating a new one for each event. |
| 459 _sink = new _StreamImplSink(stream); | 509 _sink = new _StreamImplSink(stream); |
| 460 source.listen(_handleData, onError: _handleError, onDone: _handleDone); | 510 source.listen(_handleData, onError: _handleError, onDone: _handleDone); |
| 461 return stream; | 511 return stream; |
| 462 } | 512 } |
| 463 | 513 |
| 464 void _handleData(S data) { | 514 void _handleData(S data) { |
| 465 try { | 515 try { |
| 466 _onData(data, _sink); | 516 _onData(data, _sink); |
| 467 } catch (e, s) { | 517 } catch (e, s) { |
| 468 _stream._signalError(_asyncError(e, s)); | 518 _sink.signalError(_asyncError(e, s)); |
| 469 } | 519 } |
| 470 } | 520 } |
| 471 | 521 |
| 472 void _handleError(AsyncError error) { | 522 void _handleError(AsyncError error) { |
| 473 try { | 523 try { |
| 474 _onError(error, _sink); | 524 _onError(error, _sink); |
| 475 } catch (e, s) { | 525 } catch (e, s) { |
| 476 _stream._signalError(_asyncError(e, s, error)); | 526 _sink.signalError(_asyncError(e, s, error)); |
| 477 } | 527 } |
| 478 } | 528 } |
| 479 | 529 |
| 480 void _handleDone() { | 530 void _handleDone() { |
| 481 try { | 531 try { |
| 482 _onDone(_sink); | 532 _onDone(_sink); |
| 483 } catch (e, s) { | 533 } catch (e, s) { |
| 484 _stream._signalError(_asyncError(e, s)); | 534 _sink.signalError(_asyncError(e, s)); |
| 485 } | 535 } |
| 486 } | 536 } |
| 487 | |
| 488 /** Default data handler forwards all data. */ | |
| 489 static void _defaultHandleData(var data, StreamSink sink) { | |
| 490 sink.add(data); | |
| 491 } | |
| 492 /** Default error handler forwards all errors. */ | |
| 493 static void _defaultHandleError(AsyncError error, StreamSink sink) { | |
| 494 sink.signalError(error); | |
| 495 } | |
| 496 /** Default done handler forwards done. */ | |
| 497 static void _defaultHandleDone(StreamSink sink) { | |
| 498 sink.close(); | |
| 499 } | |
| 500 } | 537 } |
| 501 | 538 |
| 502 /** Creates a [StreamSink] from a [_StreamImpl]'s input methods. */ | 539 /** Creates a [StreamSink] from a [_StreamImpl]'s input methods. */ |
| 503 class _StreamImplSink<T> implements StreamSink<T> { | 540 class _StreamImplSink<T> implements StreamSink<T> { |
| 504 _StreamImpl<T> _target; | 541 _StreamImpl<T> _target; |
| 505 _StreamImplSink(this._target); | 542 _StreamImplSink(this._target); |
| 506 void add(T data) { _target._add(data); } | 543 void add(T data) { _target._add(data); } |
| 507 void signalError(AsyncError error) { _target._signalError(error); } | 544 void signalError(AsyncError error) { _target._signalError(error); } |
| 508 void close() { _target._close(); } | 545 void close() { _target._close(); } |
| 509 } | 546 } |
| 510 | 547 |
| 511 | 548 |
| 549 | |
| 550 /** | |
| 551 * A stream transformer that intercepts all events and can generate any event as | |
| 552 * output. | |
| 553 * | |
| 554 * Each incoming event on the source stream is passed to the corresponding | |
| 555 * provided event handler, along with a [StreamSink] linked to the output | |
| 556 * Stream. | |
| 557 * The handler can then decide exactly which events to send to the output. | |
| 558 */ | |
| 559 class _StreamEventTransformerImpl<S, T> | |
| 560 implements StreamEventTransformer<S, T> { | |
| 561 final _TransformDataHandler<S, T> _handleData; | |
| 562 final _TransformErrorHandler<T> _handleError; | |
| 563 final _TransformDoneHandler<T> _handleDone; | |
| 564 | |
| 565 _StreamEventTransformerImpl(void onData(S data, StreamSink<T> sink), | |
| 566 void onError(AsyncError data, StreamSink<T> sink), | |
| 567 void onDone(StreamSink<T> sink)) | |
| 568 : this._handleData = (onData == null ? _defaultHandleData : onData), | |
| 569 this._handleError = (onError == null ? _defaultHandleError : onError), | |
| 570 this._handleDone = (onDone == null ? _defaultHandleDone : onDone); | |
| 571 | |
| 572 void handleData(S data, StreamSink<T> sink) { | |
| 573 try { | |
| 574 _handleData(data, sink); | |
| 575 } catch (e, s) { | |
| 576 sink.signalError(_asyncError(e, s)); | |
| 577 } | |
| 578 } | |
| 579 | |
| 580 void handleError(AsyncError error, StreamSink<T> sink) { | |
| 581 try { | |
| 582 _handleError(error, sink); | |
| 583 } catch (e, s) { | |
| 584 sink.signalError(_asyncError(e, s, error)); | |
| 585 } | |
| 586 } | |
| 587 | |
| 588 void handleDone(StreamSink<T> sink) { | |
| 589 try { | |
| 590 _handleDone(sink); | |
| 591 } catch (e, s) { | |
| 592 sink.signalError(_asyncError(e, s)); | |
| 593 } | |
| 594 } | |
| 595 } | |
| OLD | NEW |