| 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 part of dart.async; | 5 part of dart.async; |
| 6 | 6 |
| 7 // ------------------------------------------------------------------- | 7 // ------------------------------------------------------------------- |
| 8 // Core Stream types | 8 // Core Stream types |
| 9 // ------------------------------------------------------------------- | 9 // ------------------------------------------------------------------- |
| 10 | 10 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 /** | 77 /** |
| 78 * Creates a new single-subscription stream from the future. | 78 * Creates a new single-subscription stream from the future. |
| 79 * | 79 * |
| 80 * When the future completes, the stream will fire one event, either | 80 * When the future completes, the stream will fire one event, either |
| 81 * data or error, and then close with a done-event. | 81 * data or error, and then close with a done-event. |
| 82 */ | 82 */ |
| 83 factory Stream.fromFuture(Future<T> future) { | 83 factory Stream.fromFuture(Future<T> future) { |
| 84 // Use the controller's buffering to fill in the value even before | 84 // Use the controller's buffering to fill in the value even before |
| 85 // the stream has a listener. For a single value, it's not worth it | 85 // the stream has a listener. For a single value, it's not worth it |
| 86 // to wait for a listener before doing the `then` on the future. | 86 // to wait for a listener before doing the `then` on the future. |
| 87 StreamController<T> controller = new StreamController<T>(sync: true); | 87 _StreamController<T> controller = new StreamController<T>(sync: true); |
| 88 future.then((value) { | 88 future.then((value) { |
| 89 controller.add(value); | 89 controller._add(value); |
| 90 controller.close(); | 90 controller._closeUnchecked(); |
| 91 }, | 91 }, |
| 92 onError: (error, stackTrace) { | 92 onError: (error, stackTrace) { |
| 93 controller.addError(error, stackTrace); | 93 controller._addError(error, stackTrace); |
| 94 controller.close(); | 94 controller._closeUnchecked(); |
| 95 }); | 95 }); |
| 96 return controller.stream; | 96 return controller.stream; |
| 97 } | 97 } |
| 98 | 98 |
| 99 /** | 99 /** |
| 100 * Creates a single-subscription stream that gets its data from [data]. | 100 * Creates a single-subscription stream that gets its data from [data]. |
| 101 * | 101 * |
| 102 * The iterable is iterated when the stream receives a listener, and stops | 102 * The iterable is iterated when the stream receives a listener, and stops |
| 103 * iterating if the listener cancels the subscription. | 103 * iterating if the listener cancels the subscription. |
| 104 * | 104 * |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 * This acts like [map], except that [convert] may return a [Future], | 306 * This acts like [map], except that [convert] may return a [Future], |
| 307 * and in that case, the stream waits for that future to complete before | 307 * and in that case, the stream waits for that future to complete before |
| 308 * continuing with its result. | 308 * continuing with its result. |
| 309 * | 309 * |
| 310 * The returned stream is a broadcast stream if this stream is. | 310 * The returned stream is a broadcast stream if this stream is. |
| 311 */ | 311 */ |
| 312 Stream asyncMap(convert(T event)) { | 312 Stream asyncMap(convert(T event)) { |
| 313 StreamController controller; | 313 StreamController controller; |
| 314 StreamSubscription subscription; | 314 StreamSubscription subscription; |
| 315 void onListen () { | 315 void onListen () { |
| 316 var add = controller.add; | 316 final add = controller.add; |
| 317 var addError = controller.addError; | 317 assert(controller is _StreamController || |
| 318 controller is _BroadcastStreamController); |
| 319 final eventSink = controller; |
| 320 final addError = eventSink._addError; |
| 318 subscription = this.listen( | 321 subscription = this.listen( |
| 319 (T event) { | 322 (T event) { |
| 320 var newValue; | 323 var newValue; |
| 321 try { | 324 try { |
| 322 newValue = convert(event); | 325 newValue = convert(event); |
| 323 } catch (e, s) { | 326 } catch (e, s) { |
| 324 controller.addError(e, s); | 327 controller.addError(e, s); |
| 325 return; | 328 return; |
| 326 } | 329 } |
| 327 if (newValue is Future) { | 330 if (newValue is Future) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 * | 367 * |
| 365 * If [convert] returns `null`, no value is put on the output stream, | 368 * If [convert] returns `null`, no value is put on the output stream, |
| 366 * just as if it returned an empty stream. | 369 * just as if it returned an empty stream. |
| 367 * | 370 * |
| 368 * The returned stream is a broadcast stream if this stream is. | 371 * The returned stream is a broadcast stream if this stream is. |
| 369 */ | 372 */ |
| 370 Stream asyncExpand(Stream convert(T event)) { | 373 Stream asyncExpand(Stream convert(T event)) { |
| 371 StreamController controller; | 374 StreamController controller; |
| 372 StreamSubscription subscription; | 375 StreamSubscription subscription; |
| 373 void onListen() { | 376 void onListen() { |
| 377 assert(controller is _StreamController || |
| 378 controller is _BroadcastStreamController); |
| 379 final eventSink = controller; |
| 374 subscription = this.listen( | 380 subscription = this.listen( |
| 375 (T event) { | 381 (T event) { |
| 376 Stream newStream; | 382 Stream newStream; |
| 377 try { | 383 try { |
| 378 newStream = convert(event); | 384 newStream = convert(event); |
| 379 } catch (e, s) { | 385 } catch (e, s) { |
| 380 controller.addError(e, s); | 386 controller.addError(e, s); |
| 381 return; | 387 return; |
| 382 } | 388 } |
| 383 if (newStream != null) { | 389 if (newStream != null) { |
| 384 subscription.pause(); | 390 subscription.pause(); |
| 385 controller.addStream(newStream) | 391 controller.addStream(newStream) |
| 386 .whenComplete(subscription.resume); | 392 .whenComplete(subscription.resume); |
| 387 } | 393 } |
| 388 }, | 394 }, |
| 389 onError: controller.addError, | 395 onError: eventSink._addError, // Avoid Zone error replacement. |
| 390 onDone: controller.close | 396 onDone: controller.close |
| 391 ); | 397 ); |
| 392 } | 398 } |
| 393 if (this.isBroadcast) { | 399 if (this.isBroadcast) { |
| 394 controller = new StreamController.broadcast( | 400 controller = new StreamController.broadcast( |
| 395 onListen: onListen, | 401 onListen: onListen, |
| 396 onCancel: () { subscription.cancel(); }, | 402 onCancel: () { subscription.cancel(); }, |
| 397 sync: true | 403 sync: true |
| 398 ); | 404 ); |
| 399 } else { | 405 } else { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 value = element; | 503 value = element; |
| 498 seenFirst = true; | 504 seenFirst = true; |
| 499 } | 505 } |
| 500 }, | 506 }, |
| 501 onError: result._completeError, | 507 onError: result._completeError, |
| 502 onDone: () { | 508 onDone: () { |
| 503 if (!seenFirst) { | 509 if (!seenFirst) { |
| 504 try { | 510 try { |
| 505 throw IterableElementError.noElement(); | 511 throw IterableElementError.noElement(); |
| 506 } catch (e, s) { | 512 } catch (e, s) { |
| 507 result._completeError(e, s); | 513 _completeWithErrorCallback(result, e, s); |
| 508 } | 514 } |
| 509 } else { | 515 } else { |
| 510 result._complete(value); | 516 result._complete(value); |
| 511 } | 517 } |
| 512 }, | 518 }, |
| 513 cancelOnError: true | 519 cancelOnError: true |
| 514 ); | 520 ); |
| 515 return result; | 521 return result; |
| 516 } | 522 } |
| 517 | 523 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 bool first = true; | 561 bool first = true; |
| 556 subscription = this.listen( | 562 subscription = this.listen( |
| 557 (T element) { | 563 (T element) { |
| 558 if (!first) { | 564 if (!first) { |
| 559 buffer.write(separator); | 565 buffer.write(separator); |
| 560 } | 566 } |
| 561 first = false; | 567 first = false; |
| 562 try { | 568 try { |
| 563 buffer.write(element); | 569 buffer.write(element); |
| 564 } catch (e, s) { | 570 } catch (e, s) { |
| 565 _cancelAndError(subscription, result, e, s); | 571 _cancelAndErrorWithReplacement(subscription, result, e, s); |
| 566 } | 572 } |
| 567 }, | 573 }, |
| 568 onError: (e) { | 574 onError: (e) { |
| 569 result._completeError(e); | 575 result._completeError(e); |
| 570 }, | 576 }, |
| 571 onDone: () { | 577 onDone: () { |
| 572 result._complete(buffer.toString()); | 578 result._complete(buffer.toString()); |
| 573 }, | 579 }, |
| 574 cancelOnError: true); | 580 cancelOnError: true); |
| 575 return result; | 581 return result; |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 902 StreamSubscription subscription; | 908 StreamSubscription subscription; |
| 903 subscription = this.listen( | 909 subscription = this.listen( |
| 904 (T value) { | 910 (T value) { |
| 905 _cancelAndValue(subscription, future, value); | 911 _cancelAndValue(subscription, future, value); |
| 906 }, | 912 }, |
| 907 onError: future._completeError, | 913 onError: future._completeError, |
| 908 onDone: () { | 914 onDone: () { |
| 909 try { | 915 try { |
| 910 throw IterableElementError.noElement(); | 916 throw IterableElementError.noElement(); |
| 911 } catch (e, s) { | 917 } catch (e, s) { |
| 912 future._completeError(e, s); | 918 _completeWithErrorCallback(future, e, s); |
| 913 } | 919 } |
| 914 }, | 920 }, |
| 915 cancelOnError: true); | 921 cancelOnError: true); |
| 916 return future; | 922 return future; |
| 917 } | 923 } |
| 918 | 924 |
| 919 /** | 925 /** |
| 920 * Returns the last element of the stream. | 926 * Returns the last element of the stream. |
| 921 * | 927 * |
| 922 * If an error event occurs before the first data event, the resulting future | 928 * If an error event occurs before the first data event, the resulting future |
| (...skipping 14 matching lines...) Expand all Loading... |
| 937 }, | 943 }, |
| 938 onError: future._completeError, | 944 onError: future._completeError, |
| 939 onDone: () { | 945 onDone: () { |
| 940 if (foundResult) { | 946 if (foundResult) { |
| 941 future._complete(result); | 947 future._complete(result); |
| 942 return; | 948 return; |
| 943 } | 949 } |
| 944 try { | 950 try { |
| 945 throw IterableElementError.noElement(); | 951 throw IterableElementError.noElement(); |
| 946 } catch (e, s) { | 952 } catch (e, s) { |
| 947 future._completeError(e, s); | 953 _completeWithErrorCallback(future, e, s); |
| 948 } | 954 } |
| 949 }, | 955 }, |
| 950 cancelOnError: true); | 956 cancelOnError: true); |
| 951 return future; | 957 return future; |
| 952 } | 958 } |
| 953 | 959 |
| 954 /** | 960 /** |
| 955 * Returns the single element. | 961 * Returns the single element. |
| 956 * | 962 * |
| 957 * If an error event occurs before or after the first data event, the | 963 * If an error event occurs before or after the first data event, the |
| 958 * resulting future is completed with that error. | 964 * resulting future is completed with that error. |
| 959 * | 965 * |
| 960 * If [this] is empty or has more than one element throws a [StateError]. | 966 * If [this] is empty or has more than one element throws a [StateError]. |
| 961 */ | 967 */ |
| 962 Future<T> get single { | 968 Future<T> get single { |
| 963 _Future<T> future = new _Future<T>(); | 969 _Future<T> future = new _Future<T>(); |
| 964 T result = null; | 970 T result = null; |
| 965 bool foundResult = false; | 971 bool foundResult = false; |
| 966 StreamSubscription subscription; | 972 StreamSubscription subscription; |
| 967 subscription = this.listen( | 973 subscription = this.listen( |
| 968 (T value) { | 974 (T value) { |
| 969 if (foundResult) { | 975 if (foundResult) { |
| 970 // This is the second element we get. | 976 // This is the second element we get. |
| 971 try { | 977 try { |
| 972 throw IterableElementError.tooMany(); | 978 throw IterableElementError.tooMany(); |
| 973 } catch (e, s) { | 979 } catch (e, s) { |
| 974 _cancelAndError(subscription, future, e, s); | 980 _cancelAndErrorWithReplacement(subscription, future, e, s); |
| 975 } | 981 } |
| 976 return; | 982 return; |
| 977 } | 983 } |
| 978 foundResult = true; | 984 foundResult = true; |
| 979 result = value; | 985 result = value; |
| 980 }, | 986 }, |
| 981 onError: future._completeError, | 987 onError: future._completeError, |
| 982 onDone: () { | 988 onDone: () { |
| 983 if (foundResult) { | 989 if (foundResult) { |
| 984 future._complete(result); | 990 future._complete(result); |
| 985 return; | 991 return; |
| 986 } | 992 } |
| 987 try { | 993 try { |
| 988 throw IterableElementError.noElement(); | 994 throw IterableElementError.noElement(); |
| 989 } catch (e, s) { | 995 } catch (e, s) { |
| 990 future._completeError(e, s); | 996 _completeWithErrorCallback(future, e, s); |
| 991 } | 997 } |
| 992 }, | 998 }, |
| 993 cancelOnError: true); | 999 cancelOnError: true); |
| 994 return future; | 1000 return future; |
| 995 } | 1001 } |
| 996 | 1002 |
| 997 /** | 1003 /** |
| 998 * Finds the first element of this stream matching [test]. | 1004 * Finds the first element of this stream matching [test]. |
| 999 * | 1005 * |
| 1000 * Returns a future that is filled with the first element of this stream | 1006 * Returns a future that is filled with the first element of this stream |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1032 }, | 1038 }, |
| 1033 onError: future._completeError, | 1039 onError: future._completeError, |
| 1034 onDone: () { | 1040 onDone: () { |
| 1035 if (defaultValue != null) { | 1041 if (defaultValue != null) { |
| 1036 _runUserCode(defaultValue, future._complete, future._completeError); | 1042 _runUserCode(defaultValue, future._complete, future._completeError); |
| 1037 return; | 1043 return; |
| 1038 } | 1044 } |
| 1039 try { | 1045 try { |
| 1040 throw IterableElementError.noElement(); | 1046 throw IterableElementError.noElement(); |
| 1041 } catch (e, s) { | 1047 } catch (e, s) { |
| 1042 future._completeError(e, s); | 1048 _completeWithErrorCallback(future, e, s); |
| 1043 } | 1049 } |
| 1044 }, | 1050 }, |
| 1045 cancelOnError: true); | 1051 cancelOnError: true); |
| 1046 return future; | 1052 return future; |
| 1047 } | 1053 } |
| 1048 | 1054 |
| 1049 /** | 1055 /** |
| 1050 * Finds the last element in this stream matching [test]. | 1056 * Finds the last element in this stream matching [test]. |
| 1051 * | 1057 * |
| 1052 * As [firstWhere], except that the last matching element is found. | 1058 * As [firstWhere], except that the last matching element is found. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1077 future._complete(result); | 1083 future._complete(result); |
| 1078 return; | 1084 return; |
| 1079 } | 1085 } |
| 1080 if (defaultValue != null) { | 1086 if (defaultValue != null) { |
| 1081 _runUserCode(defaultValue, future._complete, future._completeError); | 1087 _runUserCode(defaultValue, future._complete, future._completeError); |
| 1082 return; | 1088 return; |
| 1083 } | 1089 } |
| 1084 try { | 1090 try { |
| 1085 throw IterableElementError.noElement(); | 1091 throw IterableElementError.noElement(); |
| 1086 } catch (e, s) { | 1092 } catch (e, s) { |
| 1087 future._completeError(e, s); | 1093 _completeWithErrorCallback(future, e, s); |
| 1088 } | 1094 } |
| 1089 }, | 1095 }, |
| 1090 cancelOnError: true); | 1096 cancelOnError: true); |
| 1091 return future; | 1097 return future; |
| 1092 } | 1098 } |
| 1093 | 1099 |
| 1094 /** | 1100 /** |
| 1095 * Finds the single element in this stream matching [test]. | 1101 * Finds the single element in this stream matching [test]. |
| 1096 * | 1102 * |
| 1097 * Like [lastMatch], except that it is an error if more than one | 1103 * Like [lastMatch], except that it is an error if more than one |
| 1098 * matching element occurs in the stream. | 1104 * matching element occurs in the stream. |
| 1099 */ | 1105 */ |
| 1100 Future<T> singleWhere(bool test(T element)) { | 1106 Future<T> singleWhere(bool test(T element)) { |
| 1101 _Future<T> future = new _Future<T>(); | 1107 _Future<T> future = new _Future<T>(); |
| 1102 T result = null; | 1108 T result = null; |
| 1103 bool foundResult = false; | 1109 bool foundResult = false; |
| 1104 StreamSubscription subscription; | 1110 StreamSubscription subscription; |
| 1105 subscription = this.listen( | 1111 subscription = this.listen( |
| 1106 (T value) { | 1112 (T value) { |
| 1107 _runUserCode( | 1113 _runUserCode( |
| 1108 () => true == test(value), | 1114 () => true == test(value), |
| 1109 (bool isMatch) { | 1115 (bool isMatch) { |
| 1110 if (isMatch) { | 1116 if (isMatch) { |
| 1111 if (foundResult) { | 1117 if (foundResult) { |
| 1112 try { | 1118 try { |
| 1113 throw IterableElementError.tooMany(); | 1119 throw IterableElementError.tooMany(); |
| 1114 } catch (e, s) { | 1120 } catch (e, s) { |
| 1115 _cancelAndError(subscription, future, e, s); | 1121 _cancelAndErrorWithReplacement(subscription, future, e, s); |
| 1116 } | 1122 } |
| 1117 return; | 1123 return; |
| 1118 } | 1124 } |
| 1119 foundResult = true; | 1125 foundResult = true; |
| 1120 result = value; | 1126 result = value; |
| 1121 } | 1127 } |
| 1122 }, | 1128 }, |
| 1123 _cancelAndErrorClosure(subscription, future) | 1129 _cancelAndErrorClosure(subscription, future) |
| 1124 ); | 1130 ); |
| 1125 }, | 1131 }, |
| 1126 onError: future._completeError, | 1132 onError: future._completeError, |
| 1127 onDone: () { | 1133 onDone: () { |
| 1128 if (foundResult) { | 1134 if (foundResult) { |
| 1129 future._complete(result); | 1135 future._complete(result); |
| 1130 return; | 1136 return; |
| 1131 } | 1137 } |
| 1132 try { | 1138 try { |
| 1133 throw IterableElementError.noElement(); | 1139 throw IterableElementError.noElement(); |
| 1134 } catch (e, s) { | 1140 } catch (e, s) { |
| 1135 future._completeError(e, s); | 1141 _completeWithErrorCallback(future, e, s); |
| 1136 } | 1142 } |
| 1137 }, | 1143 }, |
| 1138 cancelOnError: true); | 1144 cancelOnError: true); |
| 1139 return future; | 1145 return future; |
| 1140 } | 1146 } |
| 1141 | 1147 |
| 1142 /** | 1148 /** |
| 1143 * Returns the value of the [index]th data event of this stream. | 1149 * Returns the value of the [index]th data event of this stream. |
| 1144 * | 1150 * |
| 1145 * Stops listening to the stream after the [index]th data event has been | 1151 * Stops listening to the stream after the [index]th data event has been |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1205 Zone zone; | 1211 Zone zone; |
| 1206 Function timeout; | 1212 Function timeout; |
| 1207 | 1213 |
| 1208 void onData(T event) { | 1214 void onData(T event) { |
| 1209 timer.cancel(); | 1215 timer.cancel(); |
| 1210 controller.add(event); | 1216 controller.add(event); |
| 1211 timer = zone.createTimer(timeLimit, timeout); | 1217 timer = zone.createTimer(timeLimit, timeout); |
| 1212 } | 1218 } |
| 1213 void onError(error, StackTrace stackTrace) { | 1219 void onError(error, StackTrace stackTrace) { |
| 1214 timer.cancel(); | 1220 timer.cancel(); |
| 1215 controller.addError(error, stackTrace); | 1221 assert(controller is _StreamController || |
| 1222 controller is _BroadcastStreamController); |
| 1223 var eventSink = controller; |
| 1224 eventSink._addError(error, stackTrace); // Avoid Zone error replacement. |
| 1216 timer = zone.createTimer(timeLimit, timeout); | 1225 timer = zone.createTimer(timeLimit, timeout); |
| 1217 } | 1226 } |
| 1218 void onDone() { | 1227 void onDone() { |
| 1219 timer.cancel(); | 1228 timer.cancel(); |
| 1220 controller.close(); | 1229 controller.close(); |
| 1221 } | 1230 } |
| 1222 void onListen() { | 1231 void onListen() { |
| 1223 // This is the onListen callback for of controller. | 1232 // This is the onListen callback for of controller. |
| 1224 // It runs in the same zone that the subscription was created in. | 1233 // It runs in the same zone that the subscription was created in. |
| 1225 // Use that zone for creating timers and running the onTimeout | 1234 // Use that zone for creating timers and running the onTimeout |
| 1226 // callback. | 1235 // callback. |
| 1227 zone = Zone.current; | 1236 zone = Zone.current; |
| 1228 if (onTimeout == null) { | 1237 if (onTimeout == null) { |
| 1229 timeout = () { | 1238 timeout = () { |
| 1230 controller.addError(new TimeoutException("No stream event", | 1239 controller.addError(new TimeoutException("No stream event", |
| 1231 timeLimit)); | 1240 timeLimit), null); |
| 1232 }; | 1241 }; |
| 1233 } else { | 1242 } else { |
| 1234 onTimeout = zone.registerUnaryCallback(onTimeout); | 1243 onTimeout = zone.registerUnaryCallback(onTimeout); |
| 1235 _ControllerEventSinkWrapper wrapper = | 1244 _ControllerEventSinkWrapper wrapper = |
| 1236 new _ControllerEventSinkWrapper(null); | 1245 new _ControllerEventSinkWrapper(null); |
| 1237 timeout = () { | 1246 timeout = () { |
| 1238 wrapper._sink = controller; // Only valid during call. | 1247 wrapper._sink = controller; // Only valid during call. |
| 1239 zone.runUnaryGuarded(onTimeout, wrapper); | 1248 zone.runUnaryGuarded(onTimeout, wrapper); |
| 1240 wrapper._sink = null; | 1249 wrapper._sink = null; |
| 1241 }; | 1250 }; |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1627 class _ControllerEventSinkWrapper<T> implements EventSink<T> { | 1636 class _ControllerEventSinkWrapper<T> implements EventSink<T> { |
| 1628 EventSink _sink; | 1637 EventSink _sink; |
| 1629 _ControllerEventSinkWrapper(this._sink); | 1638 _ControllerEventSinkWrapper(this._sink); |
| 1630 | 1639 |
| 1631 void add(T data) { _sink.add(data); } | 1640 void add(T data) { _sink.add(data); } |
| 1632 void addError(error, [StackTrace stackTrace]) { | 1641 void addError(error, [StackTrace stackTrace]) { |
| 1633 _sink.addError(error, stackTrace); | 1642 _sink.addError(error, stackTrace); |
| 1634 } | 1643 } |
| 1635 void close() { _sink.close(); } | 1644 void close() { _sink.close(); } |
| 1636 } | 1645 } |
| OLD | NEW |