Chromium Code Reviews| 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 |