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