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 library fletchc.fletch_vm; | |
6 | |
7 // Please keep this file independent of other libraries in this package as we | |
8 // import this directly into test.dart. | |
9 import 'dart:async'; | |
10 import 'dart:convert'; | |
11 import 'dart:io'; | |
12 | |
13 class FletchVm { | |
14 final Process process; | |
15 | |
16 final String host; | |
17 | |
18 final int port; | |
19 | |
20 final Future<int> exitCode; | |
21 | |
22 final Stream<String> stdoutLines; | |
23 | |
24 final Stream<String> stderrLines; | |
25 | |
26 const FletchVm( | |
27 this.process, | |
28 this.host, | |
29 this.port, | |
30 this.exitCode, | |
31 this.stdoutLines, | |
32 this.stderrLines); | |
33 | |
34 Future<Socket> connect() => Socket.connect(host, port); | |
35 | |
36 static Future<FletchVm> start( | |
37 String vmPath, | |
38 {Uri workingDirectory, | |
39 List<String> arguments: const <String>[], | |
40 Map<String, String> environment}) async { | |
41 Process process = | |
42 await Process.start( | |
43 vmPath, arguments, environment: environment, | |
44 workingDirectory: workingDirectory?.toFilePath()); | |
45 | |
46 Completer<String> addressCompleter = new Completer<String>(); | |
47 Completer stdoutCompleter = new Completer(); | |
48 Stream<String> stdoutLines = convertStream( | |
49 process.stdout, stdoutCompleter, | |
50 (String line) { | |
51 const String prefix = "Waiting for compiler on "; | |
52 if (!addressCompleter.isCompleted && line.startsWith(prefix)) { | |
53 addressCompleter.complete(line.substring(prefix.length)); | |
54 return false; | |
55 } | |
56 return true; | |
57 }, () { | |
58 if (!addressCompleter.isCompleted) { | |
59 addressCompleter.completeError( | |
60 new StateError('The fletch-vm did not print an address on ' | |
61 'which it is listening on.')); | |
62 } | |
63 }); | |
64 | |
65 Completer stderrCompleter = new Completer(); | |
66 Stream<String> stderrLines = convertStream(process.stderr, stderrCompleter); | |
67 | |
68 await process.stdin.close(); | |
69 | |
70 Future exitCode = process.exitCode.then((int exitCode) async { | |
71 await stdoutCompleter.future; | |
72 await stderrCompleter.future; | |
73 if (!addressCompleter.isCompleted) { | |
74 addressCompleter.completeError( | |
75 "VM exited before print an address on stdout"); | |
76 } | |
77 return exitCode; | |
78 }); | |
79 | |
80 List<String> address = (await addressCompleter.future).split(":"); | |
81 | |
82 return new FletchVm( | |
83 process, address[0], int.parse(address[1]), exitCode, | |
84 stdoutLines, stderrLines); | |
85 } | |
86 | |
87 static Stream<String> convertStream( | |
88 Stream<List<int>> stream, | |
89 Completer doneCompleter, | |
90 [bool onData(String line), void onDone()]) { | |
91 StreamController<String> controller = new StreamController<String>(); | |
92 Function handleData; | |
93 if (onData == null) { | |
94 handleData = controller.add; | |
95 } else { | |
96 handleData = (String line) { | |
97 if (onData(line)) { | |
98 controller.add(line); | |
99 } | |
100 }; | |
101 } | |
102 stream | |
103 .transform(new Utf8Decoder()) | |
104 .transform(new LineSplitter()) | |
105 .listen( | |
106 handleData, | |
107 onError: controller.addError, | |
108 onDone: () { | |
109 if (onDone != null) onDone(); | |
110 controller.close(); | |
111 doneCompleter.complete(); | |
112 }); | |
113 return controller.stream; | |
114 } | |
115 } | |
OLD | NEW |