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