| 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 import "dart:math"; | 5 import "dart:math"; |
| 6 import "dart:typed_data"; | 6 import "dart:typed_data"; |
| 7 | 7 |
| 8 // Equivalent of calling FATAL from C++ code. | 8 // Equivalent of calling FATAL from C++ code. |
| 9 _fatal(msg) native "DartCore_fatal"; | 9 _fatal(msg) native "DartCore_fatal"; |
| 10 | 10 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 | 29 |
| 30 | 30 |
| 31 // _AsyncStarStreamController is used by the compiler to implement | 31 // _AsyncStarStreamController is used by the compiler to implement |
| 32 // async* generator functions. | 32 // async* generator functions. |
| 33 class _AsyncStarStreamController { | 33 class _AsyncStarStreamController { |
| 34 StreamController controller; | 34 StreamController controller; |
| 35 Function asyncStarBody; | 35 Function asyncStarBody; |
| 36 bool isAdding = false; | 36 bool isAdding = false; |
| 37 bool onListenReceived = false; | 37 bool onListenReceived = false; |
| 38 bool isScheduled = false; | 38 bool isScheduled = false; |
| 39 Completer cancellationCompleter = null; |
| 39 | 40 |
| 40 Stream get stream => controller.stream; | 41 Stream get stream => controller.stream; |
| 41 | 42 |
| 42 void runBody() { | 43 void runBody() { |
| 43 isScheduled = false; | 44 isScheduled = false; |
| 44 asyncStarBody(); | 45 asyncStarBody(); |
| 45 } | 46 } |
| 46 | 47 |
| 47 void scheduleGenerator() { | 48 void scheduleGenerator() { |
| 48 if (isScheduled || controller.isPaused || isAdding) { | 49 if (isScheduled || controller.isPaused || isAdding) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 var whenDoneAdding = | 87 var whenDoneAdding = |
| 87 controller.addStream(stream as Stream, cancelOnError: false); | 88 controller.addStream(stream as Stream, cancelOnError: false); |
| 88 whenDoneAdding.then((_) { | 89 whenDoneAdding.then((_) { |
| 89 isAdding = false; | 90 isAdding = false; |
| 90 scheduleGenerator(); | 91 scheduleGenerator(); |
| 91 }); | 92 }); |
| 92 return false; | 93 return false; |
| 93 } | 94 } |
| 94 | 95 |
| 95 void addError(error, stackTrace) { | 96 void addError(error, stackTrace) { |
| 97 if ((cancellationCompleter != null) && !cancellationCompleter.isCompleted) { |
| 98 // If the stream has been cancelled, complete the cancellation future |
| 99 // with the error. |
| 100 cancellationCompleter.completeError(error, stackTrace); |
| 101 return; |
| 102 } |
| 96 // If stream is cancelled, tell caller to exit the async generator. | 103 // If stream is cancelled, tell caller to exit the async generator. |
| 97 if (!controller.hasListener) return; | 104 if (!controller.hasListener) return; |
| 98 controller.addError(error, stackTrace); | 105 controller.addError(error, stackTrace); |
| 99 // No need to schedule the generator body here. This code is only | 106 // No need to schedule the generator body here. This code is only |
| 100 // called from the catch clause of the implicit try-catch-finally | 107 // called from the catch clause of the implicit try-catch-finally |
| 101 // around the generator body. That is, we are on the error path out | 108 // around the generator body. That is, we are on the error path out |
| 102 // of the generator and do not need to run the generator again. | 109 // of the generator and do not need to run the generator again. |
| 103 } | 110 } |
| 104 | 111 |
| 105 close() { | 112 close() { |
| 113 if ((cancellationCompleter != null) && !cancellationCompleter.isCompleted) { |
| 114 // If the stream has been cancelled, complete the cancellation future |
| 115 // with the error. |
| 116 cancellationCompleter.complete(); |
| 117 } |
| 106 controller.close(); | 118 controller.close(); |
| 107 } | 119 } |
| 108 | 120 |
| 109 _AsyncStarStreamController(this.asyncStarBody) { | 121 _AsyncStarStreamController(this.asyncStarBody) { |
| 110 controller = new StreamController(onListen: this.onListen, | 122 controller = new StreamController(onListen: this.onListen, |
| 111 onResume: this.onResume, | 123 onResume: this.onResume, |
| 112 onCancel: this.onCancel); | 124 onCancel: this.onCancel); |
| 113 } | 125 } |
| 114 | 126 |
| 115 onListen() { | 127 onListen() { |
| 116 assert(!onListenReceived); | 128 assert(!onListenReceived); |
| 117 onListenReceived = true; | 129 onListenReceived = true; |
| 118 scheduleGenerator(); | 130 scheduleGenerator(); |
| 119 } | 131 } |
| 120 | 132 |
| 121 onResume() { | 133 onResume() { |
| 122 scheduleGenerator(); | 134 scheduleGenerator(); |
| 123 } | 135 } |
| 124 | 136 |
| 125 onCancel() { | 137 onCancel() { |
| 126 scheduleGenerator(); | 138 if (controller.isClosed) { |
| 139 return null; |
| 140 } |
| 141 if (cancellationCompleter == null) { |
| 142 cancellationCompleter = new Completer(); |
| 143 scheduleGenerator(); |
| 144 } |
| 145 return cancellationCompleter.future; |
| 127 } | 146 } |
| 128 } | 147 } |
| 129 | 148 |
| 130 | 149 |
| 131 // _SyncIterable and _syncIterator are used by the compiler to | 150 // _SyncIterable and _syncIterator are used by the compiler to |
| 132 // implement sync* generator functions. A sync* generator allocates | 151 // implement sync* generator functions. A sync* generator allocates |
| 133 // and returns a new _SyncIterable object. | 152 // and returns a new _SyncIterable object. |
| 134 | 153 |
| 135 typedef bool SyncGeneratorCallback(Iterator iterator); | 154 typedef bool SyncGeneratorCallback(Iterator iterator); |
| 136 | 155 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 if (isYieldEach) { | 193 if (isYieldEach) { |
| 175 // Spec mandates: it is a dynamic error if the class of [the object | 194 // Spec mandates: it is a dynamic error if the class of [the object |
| 176 // returned by yield*] does not implement Iterable. | 195 // returned by yield*] does not implement Iterable. |
| 177 yieldEachIterator = (current as Iterable).iterator; | 196 yieldEachIterator = (current as Iterable).iterator; |
| 178 continue; | 197 continue; |
| 179 } | 198 } |
| 180 return true; | 199 return true; |
| 181 } | 200 } |
| 182 } | 201 } |
| 183 } | 202 } |
| OLD | NEW |