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 typedef R ZoneCallback<R>(); | 7 typedef R ZoneCallback<R>(); |
8 typedef R ZoneUnaryCallback<R, T>(T arg); | 8 typedef R ZoneUnaryCallback<R, T>(T arg); |
9 typedef R ZoneBinaryCallback<R, T1, T2>(T1 arg1, T2 arg2); | 9 typedef R ZoneBinaryCallback<R, T1, T2>(T1 arg1, T2 arg2); |
10 | |
10 typedef T TaskCreate<T, S extends TaskSpecification>( | 11 typedef T TaskCreate<T, S extends TaskSpecification>( |
11 S specification, Zone zone); | 12 S specification, Zone zone); |
12 typedef void TaskRun<T, A>(T task, A arg); | 13 typedef void TaskRun<T, A>(T task, A arg); |
13 | 14 |
14 | 15 |
15 // TODO(floitsch): we are abusing generic typedefs as typedefs for generic | 16 // TODO(floitsch): we are abusing generic typedefs as typedefs for generic |
16 // functions. | 17 // functions. |
17 /*ABUSE*/ | 18 /*ABUSE*/ |
18 typedef R HandleUncaughtErrorHandler<R>( | 19 typedef R HandleUncaughtErrorHandler<R>( |
19 Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace); | 20 Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace); |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
252 final PrintHandler print; | 253 final PrintHandler print; |
253 final ForkHandler fork; | 254 final ForkHandler fork; |
254 | 255 |
255 @deprecated | 256 @deprecated |
256 final CreateTimerHandler createTimer; | 257 final CreateTimerHandler createTimer; |
257 @deprecated | 258 @deprecated |
258 final CreatePeriodicTimerHandler createPeriodicTimer; | 259 final CreatePeriodicTimerHandler createPeriodicTimer; |
259 } | 260 } |
260 | 261 |
261 /** | 262 /** |
262 * This class wraps zones for delegation. | 263 * An adapted view of the parent zone. |
263 * | 264 * |
264 * When forwarding to parent zones one can't just invoke the parent zone's | 265 * This class allows the implementation of a zone method to invoke methods on |
265 * exposed functions (like [Zone.run]), but one needs to provide more | 266 * the parent zone while retaining knowledge of the originating zone. |
266 * information (like the zone the `run` was initiated). Zone callbacks thus | 267 * |
267 * receive more information including this [ZoneDelegate] class. When delegating | 268 * Custom zones (created through `Zone.fork` or `runZoned`) can provide |
268 * to the parent zone one should go through the given instance instead of | 269 * implementations of most methods of zones. This is similar to overriding |
269 * directly invoking the parent zone. | 270 * methods on [Zone], except that this mechanism doesn't require subclassing. |
271 * | |
272 * A custom zone function (provided through a [ZoneSpecification]) typically | |
273 * records or wraps its parameters and then delegates the operation to its | |
274 * parent zone using the provided [ZoneDelegate]. | |
275 * | |
276 * While zones have access to their parent zone (through [Zone.parent]) it is | |
277 * recommended to call the methods on the provided parent delegate for two | |
278 * reasons: | |
279 * 1. the delegate methods take an additional `zone` argument which is the | |
280 * zone the action has been initiated in. | |
281 * 2. delegate calls are more efficient way, since the implementation knows how | |
Lasse Reichstein Nielsen
2016/06/30 14:37:47
delete "way".
floitsch
2016/07/01 04:03:40
Done.
| |
282 * to skip zones that would just delegate to their parents. | |
270 */ | 283 */ |
271 abstract class ZoneDelegate { | 284 abstract class ZoneDelegate { |
272 /*=R*/ handleUncaughtError/*<R>*/( | 285 /*=R*/ handleUncaughtError/*<R>*/( |
273 Zone zone, error, StackTrace stackTrace); | 286 Zone zone, error, StackTrace stackTrace); |
274 /*=R*/ run/*<R>*/(Zone zone, /*=R*/ f()); | 287 /*=R*/ run/*<R>*/(Zone zone, /*=R*/ f()); |
275 /*=R*/ runUnary/*<R, T>*/(Zone zone, /*=R*/ f(/*=T*/ arg), /*=T*/ arg); | 288 /*=R*/ runUnary/*<R, T>*/(Zone zone, /*=R*/ f(/*=T*/ arg), /*=T*/ arg); |
276 /*=R*/ runBinary/*<R, T1, T2>*/(Zone zone, | 289 /*=R*/ runBinary/*<R, T1, T2>*/(Zone zone, |
277 /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2); | 290 /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2); |
278 ZoneCallback/*<R>*/ registerCallback/*<R>*/(Zone zone, /*=R*/ f()); | 291 ZoneCallback/*<R>*/ registerCallback/*<R>*/(Zone zone, /*=R*/ f()); |
279 ZoneUnaryCallback/*<R, T>*/ registerUnaryCallback/*<R, T>*/( | 292 ZoneUnaryCallback/*<R, T>*/ registerUnaryCallback/*<R, T>*/( |
280 Zone zone, /*=R*/ f(/*=T*/ arg)); | 293 Zone zone, /*=R*/ f(/*=T*/ arg)); |
281 ZoneBinaryCallback/*<R, T1, T2>*/ registerBinaryCallback/*<R, T1, T2>*/( | 294 ZoneBinaryCallback/*<R, T1, T2>*/ registerBinaryCallback/*<R, T1, T2>*/( |
282 Zone zone, /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2)); | 295 Zone zone, /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2)); |
283 AsyncError errorCallback(Zone zone, Object error, StackTrace stackTrace); | 296 AsyncError errorCallback(Zone zone, Object error, StackTrace stackTrace); |
284 void scheduleMicrotask(Zone zone, void f()); | 297 void scheduleMicrotask(Zone zone, void f()); |
285 Object/*=T*/ createTask/*<T, S>*/( | 298 Object/*=T*/ createTask/*<T, S>*/( |
286 Zone zone, TaskCreate/*<T, S>*/ create, TaskSpecification/*=S*/ task); | 299 Zone zone, TaskCreate/*<T, S>*/ create, TaskSpecification/*=S*/ task); |
287 void runTask/*T, A*/( | 300 void runTask/*T, A*/( |
288 Zone zone, TaskRun/*<T, A>*/ run, Object/*=T*/ task, Object/*=A*/ arg); | 301 Zone zone, TaskRun/*<T, A>*/ run, Object/*=T*/ task, Object/*=A*/ arg); |
289 void print(Zone zone, String line); | 302 void print(Zone zone, String line); |
290 Zone fork(Zone zone, ZoneSpecification specification, Map zoneValues); | 303 Zone fork(Zone zone, ZoneSpecification specification, Map zoneValues); |
291 | 304 |
292 @deprecated | 305 @deprecated |
293 Timer createTimer(Zone zone, Duration duration, void f()); | 306 Timer createTimer(Zone zone, Duration duration, void f()); |
294 @deprecated | 307 @deprecated |
295 Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer)); | 308 Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer)); |
296 } | 309 } |
297 | 310 |
298 /** | 311 /** |
299 * A Zone represents the asynchronous version of a dynamic extent. Asynchronous | 312 * A zone represents an environment that remains stable across asynchronous |
300 * callbacks are executed in the zone they have been queued in. For example, | 313 * calls, and which is responsible for handling uncaught asynchronous errors, |
301 * the callback of a `future.then` is executed in the same zone as the one where | 314 * or operations such as [print] and [scheduleMicrotask]. |
302 * the `then` was invoked. | 315 * |
316 * Asynchronous callbacks are executed in the zone they have been queued in. For | |
317 * example, the callback of a `future.then` is executed in the same zone as the | |
318 * one where the `then` was invoked. | |
319 * | |
320 * Code is always executed inside a zone. When a program is started, the | |
321 * default zone ([Zone.ROOT]) is installed. Users can provide | |
322 * shadowing, nested zones. | |
323 * | |
324 * The [Zone] class is not subclassable, but users can provide custom zones by | |
325 * forking an existing zone (usually [Zone.current]) with a [ZoneSpecification]. | |
326 * Zone specifications contain intercepting functions that are invoked when the | |
327 * zone members are invoked. As such, they provide the same functionality as | |
328 * subclassing (but allow for a more efficient implementation). | |
329 * | |
330 * Asynchronous callbacks always return in the zone in which they have been | |
331 * scheduled. This happens in two steps: | |
332 * - the callback is registered using one of [registerCallback], | |
333 * [registerUnaryCallback], or [registerBinaryCallback]. | |
334 * - the asynchronous operation (such as [Future.then] or [Stream.listen]) | |
335 * remember the current zone. Either, they store the zone in a data structure | |
336 * (as is done for [Future]s), or they wrap the callback to capture the | |
337 * current zone. A convenience function [bindCallback] (and the corresponding | |
338 * [bindUnaryCallback] or [bindBindaryCallback]) perform the registration and | |
339 * wrapping at the same time. | |
340 * | |
341 * Note that all asynchronous primitives (like [Timer.run]) have to be | |
342 * implemented by the embedder, and that users generally don't need to worry | |
343 * about keeping track of zones. However, new embedders (or native extensions) | |
344 * need to ensure that new asynchronous primitives (like for example | |
345 * `requestAnimationFrame` in the HTML library) respect this contract. | |
303 */ | 346 */ |
304 abstract class Zone { | 347 abstract class Zone { |
305 // Private constructor so that it is not possible instantiate a Zone class. | 348 // Private constructor so that it is not possible instantiate a Zone class. |
306 Zone._(); | 349 Zone._(); |
307 | 350 |
308 /** The root zone that is implicitly created. */ | 351 /** |
352 * The root zone that is implicitly created. | |
353 * | |
354 * The root zone implements the default behavior of all zone operations. | |
355 * Many methods, like [registerCallback] don't do anything, others, like | |
356 * [scheduleMicrotask] interact with the embedder to implement the desired | |
357 * behavior. | |
358 */ | |
309 static const Zone ROOT = _ROOT_ZONE; | 359 static const Zone ROOT = _ROOT_ZONE; |
310 | 360 |
311 /** The currently running zone. */ | 361 /** The currently running zone. */ |
312 static Zone _current = _ROOT_ZONE; | 362 static Zone _current = _ROOT_ZONE; |
313 | 363 |
364 /** The zone that is currently active. */ | |
314 static Zone get current => _current; | 365 static Zone get current => _current; |
315 | 366 |
367 /** | |
368 * Handles uncaught asynchronous errors. | |
369 * | |
370 * Most asynchronous classes, like [Future] or [Stream] push errors to their | |
371 * listeners. Errors are propagated this way, until, either a listener handles | |
372 * the error (for example with [Future.catchError]), or no listener is | |
373 * available anymore. In the latter case, futures and streams invoke the | |
374 * zone's [handleUncaughtError]. | |
375 * | |
376 * By default, in the root zone, uncaught asynchronous errors are treated | |
377 * like synchronous uncaught exceptions (although the root zone defers the | |
378 * reporting by a microtask, to give other microtasks the opportunity to run | |
379 * one last time). | |
380 */ | |
316 /*=R*/ handleUncaughtError/*<R>*/(error, StackTrace stackTrace); | 381 /*=R*/ handleUncaughtError/*<R>*/(error, StackTrace stackTrace); |
317 | 382 |
318 /** | 383 /** |
319 * Returns the parent zone. | 384 * Returns the parent zone. |
320 * | 385 * |
321 * Returns `null` if `this` is the [ROOT] zone. | 386 * Returns `null` if `this` is the [ROOT] zone. |
387 * | |
388 * Zones are created by [fork] (or [runZoned] which forks the [current] zone) | |
389 * on an existing zone. The new zone keeps the forking zone as [parent] zone. | |
322 */ | 390 */ |
323 Zone get parent; | 391 Zone get parent; |
324 | 392 |
325 /** | 393 /** |
326 * The error zone is the one that is responsible for dealing with uncaught | 394 * The error zone is the one that is responsible for dealing with uncaught |
327 * errors. | 395 * errors. |
328 * Errors are not allowed to cross between zones with different error-zones. | |
329 * | 396 * |
330 * This is the closest parent or ancestor zone of this zone that has a custom | 397 * This is the closest parent zone of this zone that provides a |
331 * [handleUncaughtError] method. | 398 * [handleUncaughtError] method. |
399 * | |
400 * Asynchronous errors never cross zone boundaries of zones with different | |
401 * error-zones. | |
402 * | |
403 * Example: | |
404 * ``` | |
405 * import 'dart:async'; | |
406 * | |
407 * main() { | |
408 * var future; | |
409 * runZoned(() { | |
410 * // The asynchronous error is caught by the custom zone which prints | |
411 * // 'asynchronous error'. | |
412 * future = new Future.error("asynchronous error"); | |
413 * }, onError: (e) { print(e); }); // Creates a zone with an error handler. | |
414 * // The following `catchError` is never reached, because the custom zone | |
415 * // that is created by the call to `runZoned` provides an error handler. | |
416 * future.catchError((e) { throw "is never reached"; }); | |
417 * } | |
418 * ``` | |
419 * | |
420 * Note that errors are not entering zones with different error handlers | |
421 * either: | |
422 * ``` | |
423 * import 'dart:async'; | |
424 * | |
425 * main() { | |
426 * runZoned(() { | |
427 * // The following asynchronous error is *not* caught by the `catchError` | |
428 * // in the nested zone, since errors are not to cross zone boundaries | |
429 * // with different error handlers. | |
430 * // Instead the error is handled by the current error handler, | |
431 * // printing "Caught by outer zone: asynchronous error". | |
432 * var future = new Future.error("asynchronous error"); | |
433 * runZoned(() { | |
434 * future.catchError((e) { throw "is never reached"; }); | |
435 * }, onError: (e) { throw "is never reached"; }); | |
436 * }, onError: (e) { print("Caught by outer zone: $e"); }); | |
437 * } | |
438 * ``` | |
332 */ | 439 */ |
333 Zone get errorZone; | 440 Zone get errorZone; |
334 | 441 |
335 /** | 442 /** |
336 * Returns true if `this` and [otherZone] are in the same error zone. | 443 * Returns true if `this` and [otherZone] are in the same error zone. |
337 * | 444 * |
338 * Two zones are in the same error zone if they inherit their | 445 * Two zones are in the same error zone if they inherit their |
339 * [handleUncaughtError] callback from the same [errorZone]. | 446 * [errorZone] is the same. |
340 */ | 447 */ |
341 bool inSameErrorZone(Zone otherZone); | 448 bool inSameErrorZone(Zone otherZone); |
342 | 449 |
343 /** | 450 /** |
344 * Creates a new zone as a child of `this`. | 451 * Creates a new zone as a child of `this`. |
345 * | 452 * |
346 * The new zone will have behavior like the current zone, except where | 453 * The new zone uses the closures in the given [specification] to override |
347 * overridden by functions in [specification]. | 454 * the current's zone behavior. All specification entries that are `null` |
455 * are automatically delegated to the parent zone (`this`). | |
348 * | 456 * |
349 * The new zone will have the same stored values (accessed through | 457 * The new zone has the same stored values (accessed through |
350 * `operator []`) as this zone, but updated with the keys and values | 458 * `operator []`) as this zone, but updated with the keys and values |
351 * in [zoneValues]. If a key is in both this zone's values and in | 459 * in [zoneValues]. If a key is in both this zone's values and in |
352 * `zoneValues`, the new zone will use the value from `zoneValues``. | 460 * `zoneValues`, the new zone uses the value from `zoneValues`. |
461 * | |
462 * Note that the fork operation is interceptible. A zone can thus replace | |
463 * the zone specification (or zone value), giving the parent zone full control | |
464 * over the child zone. | |
353 */ | 465 */ |
354 Zone fork({ ZoneSpecification specification, | 466 Zone fork({ZoneSpecification specification, |
355 Map zoneValues }); | 467 Map zoneValues}); |
356 | 468 |
357 /** | 469 /** |
358 * Executes the given function [f] in this zone. | 470 * Executes the given function [f] in this zone. |
471 * | |
472 * By default (as implemented in the [ROOT] zone, this updates the [current] | |
473 * zone to this zone, and executes [f]. | |
474 * | |
475 * Since the root zone is the only zone that can modify the [current] getter, | |
476 * custom zones have to delegate to their parent zone if they wish to run | |
477 * in their zone (which is generally the recommended behavior). | |
359 */ | 478 */ |
360 /*=R*/ run/*<R>*/(/*=R*/ f()); | 479 /*=R*/ run/*<R>*/(/*=R*/ f()); |
361 | 480 |
362 /** | 481 /** |
363 * Executes the given callback [f] with argument [arg] in this zone. | 482 * Executes the given callback [f] with argument [arg] in this zone. |
483 * | |
484 * See [run]. | |
364 */ | 485 */ |
365 /*=R*/ runUnary/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg); | 486 /*=R*/ runUnary/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg); |
366 | 487 |
367 /** | 488 /** |
368 * Executes the given callback [f] with argument [arg1] and [arg2] in this | 489 * Executes the given callback [f] with argument [arg1] and [arg2] in this |
369 * zone. | 490 * zone. |
491 * | |
492 * See [run]. | |
370 */ | 493 */ |
371 /*=R*/ runBinary/*<R, T1, T2>*/( | 494 /*=R*/ runBinary/*<R, T1, T2>*/( |
372 /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2); | 495 /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2); |
373 | 496 |
374 /** | 497 /** |
375 * Executes the given function [f] in this zone. | 498 * Executes the given function [f] in this zone and catches synchronous |
499 * errors. | |
376 * | 500 * |
377 * Same as [run] but catches uncaught errors and gives them to | 501 * This function is equivalent to: |
378 * [handleUncaughtError]. | 502 * ``` |
503 * try { | |
504 * return run(f); | |
505 * } catch (e, s) { | |
506 * return handleUncaughtError(e, s); | |
507 * } | |
508 * ``` | |
509 * | |
510 * See [run]. | |
379 */ | 511 */ |
380 /*=R*/ runGuarded/*<R>*/(/*=R*/ f()); | 512 /*=R*/ runGuarded/*<R>*/(/*=R*/ f()); |
381 | 513 |
382 /** | 514 /** |
383 * Executes the given callback [f] in this zone. | 515 * Executes the given callback [f] with argument [arg] in this zone and |
516 * catches synchronous errors. | |
384 * | 517 * |
385 * Same as [runUnary] but catches uncaught errors and gives them to | 518 * See [runGuarded]. |
386 * [handleUncaughtError]. | |
387 */ | 519 */ |
388 /*=R*/ runUnaryGuarded/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg); | 520 /*=R*/ runUnaryGuarded/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg); |
389 | 521 |
390 /** | 522 /** |
391 * Executes the given callback [f] in this zone. | 523 * Executes the given callback [f] with arguments [arg1] and [arg2] in this |
524 * zone. | |
392 * | 525 * |
393 * Same as [runBinary] but catches uncaught errors and gives them to | 526 * See [runGuarded]. |
394 * [handleUncaughtError]. | |
395 */ | 527 */ |
396 /*=R*/ runBinaryGuarded/*<R, T1, T2>*/( | 528 /*=R*/ runBinaryGuarded/*<R, T1, T2>*/( |
397 /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2); | 529 /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2); |
398 | 530 |
399 /** | 531 /** |
400 * Registers the given callback in this zone. | 532 * Registers the given callback in this zone. |
401 * | 533 * |
402 * It is good practice to register asynchronous or delayed callbacks before | 534 * It is good practice to register asynchronous or delayed callbacks before |
403 * invoking [run]. This gives the zone a chance to wrap the callback and | 535 * invoking [run]. This gives the zone a chance to wrap the callback and |
404 * to store information with the callback. For example, a zone may decide | 536 * to store information with the callback. For example, a zone may decide |
405 * to store the stack trace (at the time of the registration) with the | 537 * to store the stack trace (at the time of the registration) with the |
406 * callback. | 538 * callback. |
407 * | 539 * |
408 * Returns a potentially new callback that should be used in place of the | 540 * Returns a potentially new callback that should be used in place of the |
409 * given [callback]. | 541 * given [callback]. |
542 * | |
543 * Custom zones may intercept this operation. | |
410 */ | 544 */ |
411 ZoneCallback/*<R>*/ registerCallback/*<R>*/(/*=R*/ callback()); | 545 ZoneCallback/*<R>*/ registerCallback/*<R>*/(/*=R*/ callback()); |
412 | 546 |
413 /** | 547 /** |
414 * Registers the given callback in this zone. | 548 * Registers the given callback in this zone. |
415 * | 549 * |
416 * Similar to [registerCallback] but with a unary callback. | 550 * Similar to [registerCallback] but with a unary callback. |
417 */ | 551 */ |
418 ZoneUnaryCallback/*<R, T>*/ registerUnaryCallback/*<R, T>*/( | 552 ZoneUnaryCallback/*<R, T>*/ registerUnaryCallback/*<R, T>*/( |
419 /*=R*/ callback(/*=T*/ arg)); | 553 /*=R*/ callback(/*=T*/ arg)); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
453 * ZoneCallback registered = registerBinaryCallback(f); | 587 * ZoneCallback registered = registerBinaryCallback(f); |
454 * if (runGuarded) { | 588 * if (runGuarded) { |
455 * return (arg1, arg2) => this.runBinaryGuarded(registered, arg); | 589 * return (arg1, arg2) => this.runBinaryGuarded(registered, arg); |
456 * } | 590 * } |
457 * return (arg1, arg2) => thin.runBinary(registered, arg1, arg2); | 591 * return (arg1, arg2) => thin.runBinary(registered, arg1, arg2); |
458 */ | 592 */ |
459 ZoneBinaryCallback/*<R, T1, T2>*/ bindBinaryCallback/*<R, T1, T2>*/( | 593 ZoneBinaryCallback/*<R, T1, T2>*/ bindBinaryCallback/*<R, T1, T2>*/( |
460 /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), { bool runGuarded: true }); | 594 /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), { bool runGuarded: true }); |
461 | 595 |
462 /** | 596 /** |
463 * Intercepts errors when added programmatically to a `Future` or `Stream`. | 597 * Intercepts errors when added programatically to a `Future` or `Stream`. |
464 * | 598 * |
465 * When caling [Completer.completeError], [Stream.addError], | 599 * When calling [Completer.completeError], [Stream.addError], |
466 * or [Future] constructors that take an error or a callback that may throw, | 600 * or [Future] constructors that take an error or a callback that may throw, |
467 * the current zone is allowed to intercept and replace the error. | 601 * the current zone is allowed to intercept and replace the error. |
468 * | 602 * |
469 * When other libraries use intermediate controllers or completers, such | 603 * There is no guarantee that an error is only sent through [errorCallback] |
470 * calls may contain errors that have already been processed. | 604 * once. Libraries that use intermediate controllers or completers might |
605 * end up invoking [errorCallback] multiple times. | |
471 * | 606 * |
472 * Return `null` if no replacement is desired. | 607 * Returns `null` if no replacement is desired. Otherwise returns an instance |
473 * The original error is used unchanged in that case. | 608 * of [AsyncError] holding the new pair of error and stack trace. |
474 * Otherwise return an instance of [AsyncError] holding | 609 * |
475 * the new pair of error and stack trace. | 610 * Although not recommended, the returned instance may have its `error` member |
476 * If the [AsyncError.error] is `null`, it is replaced by a [NullThrownError]. | 611 * ([AsyncError.error]) be equal to `null` in which case the error should be |
612 * replaced by a [NullThrownError]. | |
613 * | |
614 * Custom zones may intercept this operation. | |
477 */ | 615 */ |
478 AsyncError errorCallback(Object error, StackTrace stackTrace); | 616 AsyncError errorCallback(Object error, StackTrace stackTrace); |
479 | 617 |
480 /** | 618 /** |
481 * Runs [f] asynchronously in this zone. | 619 * Runs [f] asynchronously in this zone. |
620 * | |
621 * The global `scheduleMicrotask` delegates to the current zone's | |
622 * [scheduleMicrotask]. The root zone's implementation interacts with the | |
623 * embedder to schedule the given callback as microtask. | |
624 * | |
625 * Custom zones may intercept this operation (for example to wrap the given | |
626 * callback [f]). | |
482 */ | 627 */ |
483 void scheduleMicrotask(void f()); | 628 void scheduleMicrotask(void f()); |
484 | 629 |
485 /** | 630 /** |
486 * Creates a task, given a [create] function and a [specification]. | 631 * Creates a task, given a [create] function and a [specification]. |
487 * | 632 * |
488 * The [create] function is invoked with the [specification] as argument. It | 633 * By default, in the root zone, the [create] function is invoked with the |
489 * returns a task object which is used for all future interactions with the | 634 * [specification] as argument. It returns a task object which is used for all |
490 * zone. | 635 * future interactions with the zone. Generally, the object is a unique |
636 * instance that is also returned to whoever initiated the action. | |
637 * For example, the HTML library uses the returned [StreamSubscription] as | |
638 * task object, when users register an event listener. | |
491 * | 639 * |
492 * Custom zones may replace the [specification] with a different one, thus | 640 * Tasks are created when the program starts an operation that returns |
493 * modifying the task parameters. | 641 * through the event loop. For example, a timer or an HTTP request both |
494 * | |
495 * Tasks are created when the program is starting an operation that returns | |
496 * through the event loop. For example, a timer or an http request both | |
497 * return through the event loop and are therefore tasks. | 642 * return through the event loop and are therefore tasks. |
498 * | 643 * |
499 * If the [create] function is not invoked (because a custom zone has | 644 * If the [create] function is not invoked (because a custom zone has |
500 * replaced or intercepted it), then the operation is *not* started. This | 645 * replaced or intercepted it), then the operation is *not* started. This |
501 * means that a custom zone can intercept tasks, like http requests. | 646 * means that a custom zone can intercept tasks, like HTTP requests. |
647 * | |
648 * A task goes through the following steps: | |
649 * - a user invokes a library function that should eventually return through | |
650 * the event loop (and not just as a microtask). | |
651 * - the library function creates a [TaskSpecification] that contains the | |
652 * necessary information to start the operation, and invokes | |
653 * `Zone.current.createTask` with the specification and a [create] closure. | |
654 * The closure, when invoked, uses the specification to start the operation | |
655 * (usually by interacting with the embedder, ar as a native extension), | |
656 * and returns a task object that identifies the running task. | |
657 * - custom zones handle the request and (unless completely intercepted and | |
658 * aborted), end up calling the root zone's [createTask] which runs the | |
659 * provided `create` closure (which may have been replaced at this point). | |
660 * - later, the asynchronous operation returns through the event loop. | |
661 * It invokes [Zone.runTask] on the zone the task should run on (which had | |
662 * been given to the create function). The [runTask] function receives the | |
663 * task object, a `run` function and an argument. As before, custom zones | |
664 * may intercept this call. Eventually (unless aborted), the `run` function | |
665 * is invoked, running Dart code that has been registered to run when the | |
666 * task returns. This last step may happen multiple times for tasks that are | |
667 * not oneshot tasks (see [ZoneSpecification.isOneShot]. | |
668 * | |
669 * Custom zones may replace the [specification] with a different one, thus | |
670 * modifying the task parameters. | |
502 */ | 671 */ |
503 Object/*=T*/ createTask/*<T, S>*/( | 672 Object/*=T*/ createTask/*<T, S>*/( |
504 TaskCreate/*<T, S>*/ create, TaskSpecification/*=S*/ specification); | 673 TaskCreate/*<T, S>*/ create, TaskSpecification/*=S*/ specification); |
505 | 674 |
506 /** | 675 /** |
507 * Runs a task callback. | 676 * Runs a task callback. |
508 * | 677 * |
509 * This function is invoked, when an operation, started through [createTask], | 678 * This function is invoked, when an operation, started through [createTask], |
510 * returns to Dart code. | 679 * returns to Dart code. |
511 * | 680 * |
512 * Generally, tasks schedule Dart code in the global event loop. As such, | 681 * Generally, tasks schedule Dart code in the global event loop. As such, |
513 * there is no return value, and [runTask] is a void function. | 682 * there is no return value, and [runTask] is a void function. |
514 * | 683 * |
515 * The [task] object must be the same as the one created with [createTask]. | 684 * The [task] object must be the same as the one created with [createTask]. |
516 * | 685 * |
517 * It is good practice, if task operations provide a meaningful [arg], so | 686 * It is good practice, if task operations provide a meaningful [arg], so |
518 * that custom zones can deal with it. They might want to log it, or | 687 * that custom zones can deal with it. They might want to log it, or |
519 * replace it. | 688 * replace it. |
689 * | |
690 * See [createTask]. | |
520 */ | 691 */ |
521 void runTask/*<T, A>*/( | 692 void runTask/*<T, A>*/( |
522 TaskRun/*<T, A>*/ run, Object/*=T*/ task, Object/*=A*/ arg); | 693 TaskRun/*<T, A>*/ run, Object/*=T*/ task, Object/*=A*/ arg); |
523 | 694 |
524 /** | 695 /** |
525 * Creates a Timer where the callback is executed in this zone. | 696 * Creates a Timer where the callback is executed in this zone. |
526 */ | 697 */ |
527 @deprecated | 698 @deprecated |
528 Timer createTimer(Duration duration, void callback()); | 699 Timer createTimer(Duration duration, void callback()); |
529 | 700 |
530 /** | 701 /** |
531 * Creates a periodic Timer where the callback is executed in this zone. | 702 * Creates a periodic Timer where the callback is executed in this zone. |
532 */ | 703 */ |
533 @deprecated | 704 @deprecated |
534 Timer createPeriodicTimer(Duration period, void callback(Timer timer)); | 705 Timer createPeriodicTimer(Duration period, void callback(Timer timer)); |
535 | 706 |
536 /** | 707 /** |
537 * Prints the given [line]. | 708 * Prints the given [line]. |
709 * | |
710 * The global `print` function delegates to the current zone's [print] | |
711 * function which makes it possible to intercept the print function. | |
712 * | |
713 * Example: | |
714 * ``` | |
715 * import 'dart:async'; | |
716 * | |
717 * main() { | |
718 * runZoned(() { | |
719 * // Ends up printing: "Intercepted: in zone". | |
720 * print("in zone"); | |
721 * }, zoneSpecification: new ZoneSpecification( | |
722 * print: (Zone self, ZoneDelegate parent, Zone zone, String line) { | |
723 * parent.print(zone, "Intercepted: $line"); | |
724 * })); | |
725 * } | |
726 * ``` | |
538 */ | 727 */ |
539 void print(String line); | 728 void print(String line); |
540 | 729 |
541 /** | 730 /** |
542 * Call to enter the Zone. | 731 * Call to enter the Zone. |
543 * | 732 * |
544 * The previous current zone is returned. | 733 * The previous current zone is returned. |
545 */ | 734 */ |
546 static Zone _enter(Zone zone) { | 735 static Zone _enter(Zone zone) { |
547 assert(zone != null); | 736 assert(zone != null); |
(...skipping 955 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1503 handleUncaughtError: errorHandler); | 1692 handleUncaughtError: errorHandler); |
1504 } | 1693 } |
1505 Zone zone = Zone.current.fork(specification: zoneSpecification, | 1694 Zone zone = Zone.current.fork(specification: zoneSpecification, |
1506 zoneValues: zoneValues); | 1695 zoneValues: zoneValues); |
1507 if (onError != null) { | 1696 if (onError != null) { |
1508 return zone.runGuarded(body); | 1697 return zone.runGuarded(body); |
1509 } else { | 1698 } else { |
1510 return zone.run(body); | 1699 return zone.run(body); |
1511 } | 1700 } |
1512 } | 1701 } |
OLD | NEW |