| 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 * Common behavior of [StreamSubscription] classes. |
| 93 * |
| 94 * Stores and allows updating of the event handlers of a [StreamSubscription]. |
| 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. |
| 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 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 return null; | 454 return null; |
| 422 } | 455 } |
| 423 if (!isEqual) { | 456 if (!isEqual) { |
| 424 sink._sendData(inputEvent); | 457 sink._sendData(inputEvent); |
| 425 _previous = inputEvent; | 458 _previous = inputEvent; |
| 426 } | 459 } |
| 427 } | 460 } |
| 428 } | 461 } |
| 429 } | 462 } |
| 430 | 463 |
| 464 // Stream transformations and event transformations. |
| 431 | 465 |
| 432 typedef void _TransformDataHandler<S, T>(S data, StreamSink<T> sink); | 466 typedef void _TransformDataHandler<S, T>(S data, StreamSink<T> sink); |
| 433 typedef void _TransformErrorHandler<T>(AsyncError data, StreamSink<T> sink); | 467 typedef void _TransformErrorHandler<T>(AsyncError data, StreamSink<T> sink); |
| 434 typedef void _TransformDoneHandler<T>(StreamSink<T> sink); | 468 typedef void _TransformDoneHandler<T>(StreamSink<T> sink); |
| 435 | 469 |
| 470 /** Default data handler forwards all data. */ |
| 471 void _defaultHandleData(var data, StreamSink sink) { |
| 472 sink.add(data); |
| 473 } |
| 474 |
| 475 /** Default error handler forwards all errors. */ |
| 476 void _defaultHandleError(AsyncError error, StreamSink sink) { |
| 477 sink.signalError(error); |
| 478 } |
| 479 |
| 480 /** Default done handler forwards done. */ |
| 481 void _defaultHandleDone(StreamSink sink) { |
| 482 sink.close(); |
| 483 } |
| 484 |
| 485 |
| 436 /** | 486 /** |
| 437 * A stream transformer that intercepts all events and can generate any event as | 487 * A stream transformer that intercepts all events and can generate any event as |
| 438 * output. | 488 * output. |
| 439 * | 489 * |
| 440 * Each incoming event on the source stream is passed to the corresponding | 490 * Each incoming event on the source stream is passed to the corresponding |
| 441 * provided event handler, along with a [StreamSink] linked to the output | 491 * provided event handler, along with a [StreamSink] linked to the output |
| 442 * Stream. | 492 * Stream. |
| 443 * The handler can then decide exactly which events to send to the output. | 493 * The handler can then decide exactly which events to send to the output. |
| 444 */ | 494 */ |
| 445 class _StreamTransformerImpl<S, T> implements StreamTransformer<S, T> { | 495 class _StreamTransformerImpl<S, T> implements StreamTransformer<S, T> { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 460 // Cache a Sink object to avoid creating a new one for each event. | 510 // Cache a Sink object to avoid creating a new one for each event. |
| 461 _sink = new _StreamImplSink(stream); | 511 _sink = new _StreamImplSink(stream); |
| 462 source.listen(_handleData, onError: _handleError, onDone: _handleDone); | 512 source.listen(_handleData, onError: _handleError, onDone: _handleDone); |
| 463 return stream; | 513 return stream; |
| 464 } | 514 } |
| 465 | 515 |
| 466 void _handleData(S data) { | 516 void _handleData(S data) { |
| 467 try { | 517 try { |
| 468 _onData(data, _sink); | 518 _onData(data, _sink); |
| 469 } catch (e, s) { | 519 } catch (e, s) { |
| 470 _stream._signalError(_asyncError(e, s)); | 520 _sink.signalError(_asyncError(e, s)); |
| 471 } | 521 } |
| 472 } | 522 } |
| 473 | 523 |
| 474 void _handleError(AsyncError error) { | 524 void _handleError(AsyncError error) { |
| 475 try { | 525 try { |
| 476 _onError(error, _sink); | 526 _onError(error, _sink); |
| 477 } catch (e, s) { | 527 } catch (e, s) { |
| 478 _stream._signalError(_asyncError(e, s, error)); | 528 _sink.signalError(_asyncError(e, s, error)); |
| 479 } | 529 } |
| 480 } | 530 } |
| 481 | 531 |
| 482 void _handleDone() { | 532 void _handleDone() { |
| 483 try { | 533 try { |
| 484 _onDone(_sink); | 534 _onDone(_sink); |
| 485 } catch (e, s) { | 535 } catch (e, s) { |
| 486 _stream._signalError(_asyncError(e, s)); | 536 _sink.signalError(_asyncError(e, s)); |
| 487 } | 537 } |
| 488 } | 538 } |
| 489 | |
| 490 /** Default data handler forwards all data. */ | |
| 491 static void _defaultHandleData(var data, StreamSink sink) { | |
| 492 sink.add(data); | |
| 493 } | |
| 494 /** Default error handler forwards all errors. */ | |
| 495 static void _defaultHandleError(AsyncError error, StreamSink sink) { | |
| 496 sink.signalError(error); | |
| 497 } | |
| 498 /** Default done handler forwards done. */ | |
| 499 static void _defaultHandleDone(StreamSink sink) { | |
| 500 sink.close(); | |
| 501 } | |
| 502 } | 539 } |
| 503 | 540 |
| 504 /** Creates a [StreamSink] from a [_StreamImpl]'s input methods. */ | 541 /** Creates a [StreamSink] from a [_StreamImpl]'s input methods. */ |
| 505 class _StreamImplSink<T> implements StreamSink<T> { | 542 class _StreamImplSink<T> implements StreamSink<T> { |
| 506 _StreamImpl<T> _target; | 543 _StreamImpl<T> _target; |
| 507 _StreamImplSink(this._target); | 544 _StreamImplSink(this._target); |
| 508 void add(T data) { _target._add(data); } | 545 void add(T data) { _target._add(data); } |
| 509 void signalError(AsyncError error) { _target._signalError(error); } | 546 void signalError(AsyncError error) { _target._signalError(error); } |
| 510 void close() { _target._close(); } | 547 void close() { _target._close(); } |
| 511 } | 548 } |
| 549 |
| 550 |
| 551 /** |
| 552 * A stream transformer that intercepts all events and can generate any event as |
| 553 * output. |
| 554 * |
| 555 * Each incoming event on the source stream is passed to the corresponding |
| 556 * provided event handler, along with a [StreamSink] linked to the output |
| 557 * Stream. |
| 558 * The handler can then decide exactly which events to send to the output. |
| 559 */ |
| 560 class _StreamEventTransformerImpl<S, T> |
| 561 implements StreamEventTransformer<S, T> { |
| 562 final _TransformDataHandler<S, T> _handleData; |
| 563 final _TransformErrorHandler<T> _handleError; |
| 564 final _TransformDoneHandler<T> _handleDone; |
| 565 |
| 566 _StreamEventTransformerImpl(void onData(S data, StreamSink<T> sink), |
| 567 void onError(AsyncError data, StreamSink<T> sink), |
| 568 void onDone(StreamSink<T> sink)) |
| 569 : this._handleData = (onData == null ? _defaultHandleData : onData), |
| 570 this._handleError = (onError == null ? _defaultHandleError : onError), |
| 571 this._handleDone = (onDone == null ? _defaultHandleDone : onDone); |
| 572 |
| 573 void handleData(S data, StreamSink<T> sink) { |
| 574 try { |
| 575 _handleData(data, sink); |
| 576 } catch (e, s) { |
| 577 sink.signalError(_asyncError(e, s)); |
| 578 } |
| 579 } |
| 580 |
| 581 void handleError(AsyncError error, StreamSink<T> sink) { |
| 582 try { |
| 583 _handleError(error, sink); |
| 584 } catch (e, s) { |
| 585 sink.signalError(_asyncError(e, s, error)); |
| 586 } |
| 587 } |
| 588 |
| 589 void handleDone(StreamSink<T> sink) { |
| 590 try { |
| 591 _handleDone(sink); |
| 592 } catch (e, s) { |
| 593 sink.signalError(_asyncError(e, s)); |
| 594 } |
| 595 } |
| 596 } |
| OLD | NEW |