OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 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.md file. |
| 4 |
| 5 /// Helper functions for running code in a Zone. |
| 6 library testing.zone_helper; |
| 7 |
| 8 import 'dart:async' show |
| 9 Completer, |
| 10 Future, |
| 11 ZoneSpecification, |
| 12 runZoned; |
| 13 |
| 14 import 'dart:isolate' show |
| 15 Capability, |
| 16 Isolate, |
| 17 ReceivePort; |
| 18 |
| 19 import 'log.dart' show |
| 20 logUncaughtError; |
| 21 |
| 22 Future runGuarded( |
| 23 Future f(), |
| 24 {void printLineOnStdout(line), |
| 25 void handleLateError(error, StackTrace stackTrace)}) { |
| 26 |
| 27 var printWrapper; |
| 28 if (printLineOnStdout != null) { |
| 29 printWrapper = (_1, _2, _3, String line) { |
| 30 printLineOnStdout(line); |
| 31 }; |
| 32 } |
| 33 |
| 34 Completer completer = new Completer(); |
| 35 |
| 36 handleUncaughtError(error, StackTrace stackTrace) { |
| 37 logUncaughtError(error, stackTrace); |
| 38 if (!completer.isCompleted) { |
| 39 completer.completeError(error, stackTrace); |
| 40 } else if (handleLateError != null) { |
| 41 handleLateError(error, stackTrace); |
| 42 } else { |
| 43 // Delegate to parent. |
| 44 throw error; |
| 45 } |
| 46 } |
| 47 |
| 48 ZoneSpecification specification = new ZoneSpecification(print: printWrapper); |
| 49 |
| 50 ReceivePort errorPort = new ReceivePort(); |
| 51 Future errorFuture = errorPort.listen((List errors) { |
| 52 Isolate.current.removeErrorListener(errorPort.sendPort); |
| 53 errorPort.close(); |
| 54 var error = errors[0]; |
| 55 var stackTrace = errors[1]; |
| 56 if (stackTrace != null) { |
| 57 stackTrace = new StackTrace.fromString(stackTrace); |
| 58 } |
| 59 handleUncaughtError(error, stackTrace); |
| 60 }).asFuture(); |
| 61 |
| 62 Isolate.current.addErrorListener(errorPort.sendPort); |
| 63 return acknowledgeControlMessages(Isolate.current).then((_) { |
| 64 runZoned( |
| 65 () => new Future(f).then(completer.complete), |
| 66 zoneSpecification: specification, |
| 67 onError: handleUncaughtError); |
| 68 |
| 69 return completer.future.whenComplete(() { |
| 70 errorPort.close(); |
| 71 Isolate.current.removeErrorListener(errorPort.sendPort); |
| 72 return acknowledgeControlMessages(Isolate.current) |
| 73 .then((_) => errorFuture); |
| 74 }); |
| 75 }); |
| 76 } |
| 77 |
| 78 /// Ping [isolate] to ensure control messages have been delivered. Control |
| 79 /// messages are things like [Isolate.addErrorListener] and |
| 80 /// [Isolate.addOnExitListener]. |
| 81 Future acknowledgeControlMessages(Isolate isolate, {Capability resume}) { |
| 82 ReceivePort ping = new ReceivePort(); |
| 83 Isolate.current.ping(ping.sendPort); |
| 84 if (resume == null) { |
| 85 return ping.first; |
| 86 } else { |
| 87 return ping.first.then((_) => isolate.resume(resume)); |
| 88 } |
| 89 } |
OLD | NEW |