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

Side by Side Diff: sdk/lib/async/future.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/broadcast_stream_controller.dart ('k') | sdk/lib/async/future_impl.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 /** 7 /**
8 * An object representing a delayed computation. 8 * An object representing a delayed computation.
9 * 9 *
10 * A [Future] is used to represent a potential value, or error, 10 * A [Future] is used to represent a potential value, or error,
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 * 110 *
111 * If a non-future value is returned, the returned future is completed 111 * If a non-future value is returned, the returned future is completed
112 * with that value. 112 * with that value.
113 */ 113 */
114 factory Future(computation()) { 114 factory Future(computation()) {
115 _Future result = new _Future<T>(); 115 _Future result = new _Future<T>();
116 Timer.run(() { 116 Timer.run(() {
117 try { 117 try {
118 result._complete(computation()); 118 result._complete(computation());
119 } catch (e, s) { 119 } catch (e, s) {
120 result._completeError(e, s); 120 _completeWithErrorCallback(result, e, s);
121 } 121 }
122 }); 122 });
123 return result; 123 return result;
124 } 124 }
125 125
126 /** 126 /**
127 * Creates a future containing the result of calling [computation] 127 * Creates a future containing the result of calling [computation]
128 * asynchronously with [scheduleMicrotask]. 128 * asynchronously with [scheduleMicrotask].
129 * 129 *
130 * If executing [computation] throws, 130 * If executing [computation] throws,
131 * the returned future is completed with the thrown error. 131 * the returned future is completed with the thrown error.
132 * 132 *
133 * If calling [computation] returns a [Future], completion of 133 * If calling [computation] returns a [Future], completion of
134 * the created future will wait until the returned future completes, 134 * the created future will wait until the returned future completes,
135 * and will then complete with the same result. 135 * and will then complete with the same result.
136 * 136 *
137 * If calling [computation] returns a non-future value, 137 * If calling [computation] returns a non-future value,
138 * the returned future is completed with that value. 138 * the returned future is completed with that value.
139 */ 139 */
140 factory Future.microtask(computation()) { 140 factory Future.microtask(computation()) {
141 _Future result = new _Future<T>(); 141 _Future result = new _Future<T>();
142 scheduleMicrotask(() { 142 scheduleMicrotask(() {
143 try { 143 try {
144 result._complete(computation()); 144 result._complete(computation());
145 } catch (e, s) { 145 } catch (e, s) {
146 result._completeError(e, s); 146 _completeWithErrorCallback(result, e, s);
147 } 147 }
148 }); 148 });
149 return result; 149 return result;
150 } 150 }
151 151
152 /** 152 /**
153 * Creates a future containing the result of immediately calling 153 * Creates a future containing the result of immediately calling
154 * [computation]. 154 * [computation].
155 * 155 *
156 * If calling [computation] throws, the returned future is completed with the 156 * If calling [computation] throws, the returned future is completed with the
(...skipping 26 matching lines...) Expand all
183 factory Future.value([value]) { 183 factory Future.value([value]) {
184 return new _Future<T>.immediate(value); 184 return new _Future<T>.immediate(value);
185 } 185 }
186 186
187 /** 187 /**
188 * A future that completes with an error in the next event-loop iteration. 188 * A future that completes with an error in the next event-loop iteration.
189 * 189 *
190 * Use [Completer] to create a Future and complete it later. 190 * Use [Completer] to create a Future and complete it later.
191 */ 191 */
192 factory Future.error(Object error, [StackTrace stackTrace]) { 192 factory Future.error(Object error, [StackTrace stackTrace]) {
193 if (!identical(Zone.current, _ROOT_ZONE)) {
194 AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
195 if (replacement != null) {
196 error = replacement.error;
197 stackTrace = replacement.stackTrace;
198 }
199 }
193 return new _Future<T>.immediateError(error, stackTrace); 200 return new _Future<T>.immediateError(error, stackTrace);
194 } 201 }
195 202
196 /** 203 /**
197 * Creates a future that runs its computation after a delay. 204 * Creates a future that runs its computation after a delay.
198 * 205 *
199 * The [computation] will be executed after the given [duration] has passed, 206 * The [computation] will be executed after the given [duration] has passed,
200 * and the future is completed with the result. 207 * and the future is completed with the result.
201 * If the duration is 0 or less, 208 * If the duration is 0 or less,
202 * it completes no sooner than in the next event-loop iteration. 209 * it completes no sooner than in the next event-loop iteration.
203 * 210 *
204 * If [computation] is omitted, 211 * If [computation] is omitted,
205 * it will be treated as if [computation] was set to `() => null`, 212 * it will be treated as if [computation] was set to `() => null`,
206 * and the future will eventually complete with the `null` value. 213 * and the future will eventually complete with the `null` value.
207 * 214 *
208 * If calling [computation] throws, the created future will complete with the 215 * If calling [computation] throws, the created future will complete with the
209 * error. 216 * error.
210 * 217 *
211 * See also [Completer] for a way to create and complete a future at a 218 * See also [Completer] for a way to create and complete a future at a
212 * later time that isn't necessarily after a known fixed duration. 219 * later time that isn't necessarily after a known fixed duration.
213 */ 220 */
214 factory Future.delayed(Duration duration, [T computation()]) { 221 factory Future.delayed(Duration duration, [T computation()]) {
215 Completer completer = new Completer.sync(); 222 _Future result = new _Future<T>();
216 Future result = completer.future; 223 new Timer(duration, () {
217 if (computation != null) { 224 try {
218 result = result.then((ignored) => computation()); 225 result._complete(computation == null ? null : computation());
219 } 226 } catch (e, s) {
220 new Timer(duration, completer.complete); 227 _completeWithErrorCallback(result, e, s);
228 }
229 });
221 return result; 230 return result;
222 } 231 }
223 232
224 /** 233 /**
225 * Wait for all the given futures to complete and collect their values. 234 * Wait for all the given futures to complete and collect their values.
226 * 235 *
227 * Returns a future which will complete once all the futures in a list are 236 * Returns a future which will complete once all the futures in a list are
228 * complete. If any of the futures in the list completes with an error, 237 * complete. If any of the futures in the list completes with an error,
229 * the resulting future also completes with an error. Otherwise the value 238 * the resulting future also completes with an error. Otherwise the value
230 * of the returned future will be a list of all the values that were produced. 239 * of the returned future will be a list of all the values that were produced.
231 * 240 *
232 * If `eagerError` is true, the future completes with an error immediately on 241 * If `eagerError` is true, the future completes with an error immediately on
233 * the first error from one of the futures. Otherwise all futures must 242 * the first error from one of the futures. Otherwise all futures must
234 * complete before the returned future is completed (still with the first 243 * complete before the returned future is completed (still with the first
235 * error to occur, the remaining errors are silently dropped). 244 * error to occur, the remaining errors are silently dropped).
236 */ 245 */
237 static Future<List> wait(Iterable<Future> futures, {bool eagerError: false}) { 246 static Future<List> wait(Iterable<Future> futures, {bool eagerError: false}) {
238 Completer completer; // Completer for the returned future. 247 final _Future<List> result = new _Future<List>();
239 List values; // Collects the values. Set to null on error. 248 List values; // Collects the values. Set to null on error.
240 int remaining = 0; // How many futures are we waiting for. 249 int remaining = 0; // How many futures are we waiting for.
241 var error; // The first error from a future. 250 var error; // The first error from a future.
242 StackTrace stackTrace; // The stackTrace that came with the error. 251 StackTrace stackTrace; // The stackTrace that came with the error.
243 252
244 // Handle an error from any of the futures. 253 // Handle an error from any of the futures.
245 handleError(theError, theStackTrace) { 254 handleError(theError, theStackTrace) {
246 bool isFirstError = values != null; 255 final bool isFirstError = (values != null);
247 values = null; 256 values = null;
248 remaining--; 257 remaining--;
249 if (isFirstError) { 258 if (isFirstError) {
250 if (remaining == 0 || eagerError) { 259 if (remaining == 0 || eagerError) {
251 completer.completeError(theError, theStackTrace); 260 result._completeError(theError, theStackTrace);
252 } else { 261 } else {
253 error = theError; 262 error = theError;
254 stackTrace = theStackTrace; 263 stackTrace = theStackTrace;
255 } 264 }
256 } else if (remaining == 0 && !eagerError) { 265 } else if (remaining == 0 && !eagerError) {
257 completer.completeError(error, stackTrace); 266 result._completeError(error, stackTrace);
258 } 267 }
259 } 268 }
260 269
261 // As each future completes, put its value into the corresponding 270 // As each future completes, put its value into the corresponding
262 // position in the list of values. 271 // position in the list of values.
263 for (Future future in futures) { 272 for (Future future in futures) {
264 int pos = remaining++; 273 int pos = remaining++;
265 future.then((Object value) { 274 future.then((Object value) {
266 remaining--; 275 remaining--;
267 if (values != null) { 276 if (values != null) {
268 values[pos] = value; 277 values[pos] = value;
269 if (remaining == 0) { 278 if (remaining == 0) {
270 completer.complete(values); 279 result._completeWithValue(values);
271 } 280 }
272 } else if (remaining == 0 && !eagerError) { 281 } else if (remaining == 0 && !eagerError) {
273 completer.completeError(error, stackTrace); 282 result._completeError(error, stackTrace);
274 } 283 }
275 }, onError: handleError); 284 }, onError: handleError);
276 } 285 }
277 if (remaining == 0) { 286 if (remaining == 0) {
278 return new Future.value(const []); 287 return new Future.value(const []);
279 } 288 }
280 values = new List(remaining); 289 values = new List(remaining);
281 completer = new Completer<List>(); 290 return result;
282 return completer.future;
283 } 291 }
284 292
285 /** 293 /**
286 * Perform an async operation for each element of the iterable, in turn. 294 * Perform an async operation for each element of the iterable, in turn.
287 * 295 *
288 * Runs [f] for each element in [input] in order, moving to the next element 296 * Runs [f] for each element in [input] in order, moving to the next element
289 * only when the [Future] returned by [f] completes. Returns a [Future] that 297 * only when the [Future] returned by [f] completes. Returns a [Future] that
290 * completes when all elements have been processed. 298 * completes when all elements have been processed.
291 * 299 *
292 * The return values of all [Future]s are discarded. Any errors will cause the 300 * The return values of all [Future]s are discarded. Any errors will cause the
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 * theFuture.catchError(thisCompleter.completeError); 651 * theFuture.catchError(thisCompleter.completeError);
644 * 652 *
645 */ 653 */
646 void completeError(Object error, [StackTrace stackTrace]); 654 void completeError(Object error, [StackTrace stackTrace]);
647 655
648 /** 656 /**
649 * Whether the future has been completed. 657 * Whether the future has been completed.
650 */ 658 */
651 bool get isCompleted; 659 bool get isCompleted;
652 } 660 }
661
662 // Helper function completing a _Future with error, but checking the zone
663 // for error replacement first.
664 void _completeWithErrorCallback(_Future result, error, stackTrace) {
665 AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
666 if (replacement == null) {
667 result._completeError(error, stackTrace);
668 } else {
669 result._completeError(replacement.error, replacement.stackTrace);
670 }
671 }
672
OLDNEW
« no previous file with comments | « sdk/lib/async/broadcast_stream_controller.dart ('k') | sdk/lib/async/future_impl.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698