OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library test.util.compiler_pool; | 5 library test.util.compiler_pool; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:collection'; | 8 import 'dart:collection'; |
9 import 'dart:io'; | 9 import 'dart:io'; |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... |
28 final bool _color; | 28 final bool _color; |
29 | 29 |
30 /// The currently-active compilers. | 30 /// The currently-active compilers. |
31 /// | 31 /// |
32 /// The first one is the only visible the compiler; the rest will become | 32 /// The first one is the only visible the compiler; the rest will become |
33 /// visible in queue order. Note that some of these processes may actually | 33 /// visible in queue order. Note that some of these processes may actually |
34 /// have already exited; they're kept around so that their output can be | 34 /// have already exited; they're kept around so that their output can be |
35 /// emitted once they become visible. | 35 /// emitted once they become visible. |
36 final _compilers = new Queue<_Compiler>(); | 36 final _compilers = new Queue<_Compiler>(); |
37 | 37 |
| 38 /// Whether [close] has been called. |
| 39 bool get _closed => _closeCompleter != null; |
| 40 |
| 41 /// The completer for the [Future] returned by [close]. |
| 42 Completer _closeCompleter; |
| 43 |
38 /// Creates a compiler pool that runs up to [parallel] instances of `dart2js` | 44 /// Creates a compiler pool that runs up to [parallel] instances of `dart2js` |
39 /// at once. | 45 /// at once. |
40 /// | 46 /// |
41 /// If [parallel] isn't provided, it defaults to 4. | 47 /// If [parallel] isn't provided, it defaults to 4. |
42 /// | 48 /// |
43 /// If [color] is true, `dart2js` will be run with colors enabled. | 49 /// If [color] is true, `dart2js` will be run with colors enabled. |
44 CompilerPool({int parallel, bool color: false}) | 50 CompilerPool({int parallel, bool color: false}) |
45 : _pool = new Pool(parallel == null ? 4 : parallel), | 51 : _pool = new Pool(parallel == null ? 4 : parallel), |
46 _color = color; | 52 _color = color; |
47 | 53 |
48 /// Compile the Dart code at [dartPath] to [jsPath]. | 54 /// Compile the Dart code at [dartPath] to [jsPath]. |
49 /// | 55 /// |
50 /// This wraps the Dart code in the standard browser-testing wrapper. If | 56 /// This wraps the Dart code in the standard browser-testing wrapper. If |
51 /// [packageRoot] is provided, it's used as the package root for the | 57 /// [packageRoot] is provided, it's used as the package root for the |
52 /// compilation. | 58 /// compilation. |
53 /// | 59 /// |
54 /// The returned [Future] will complete once the `dart2js` process completes | 60 /// The returned [Future] will complete once the `dart2js` process completes |
55 /// *and* all its output has been printed to the command line. | 61 /// *and* all its output has been printed to the command line. |
56 Future compile(String dartPath, String jsPath, {String packageRoot}) { | 62 Future compile(String dartPath, String jsPath, {String packageRoot}) { |
57 return _pool.withResource(() { | 63 return _pool.withResource(() { |
| 64 if (_closed) return null; |
| 65 |
58 return withTempDir((dir) { | 66 return withTempDir((dir) { |
59 var wrapperPath = p.join(dir, "runInBrowser.dart"); | 67 var wrapperPath = p.join(dir, "runInBrowser.dart"); |
60 new File(wrapperPath).writeAsStringSync(''' | 68 new File(wrapperPath).writeAsStringSync(''' |
61 import "package:test/src/runner/browser/iframe_listener.dart"; | 69 import "package:test/src/runner/browser/iframe_listener.dart"; |
62 | 70 |
63 import "${p.toUri(p.absolute(dartPath))}" as test; | 71 import "${p.toUri(p.absolute(dartPath))}" as test; |
64 | 72 |
65 void main(_) { | 73 void main(_) { |
66 IframeListener.start(() => test.main); | 74 IframeListener.start(() => test.main); |
67 } | 75 } |
(...skipping 28 matching lines...) Expand all Loading... |
96 void _showProcess(_Compiler compiler) { | 104 void _showProcess(_Compiler compiler) { |
97 print("Compiling ${compiler.path}..."); | 105 print("Compiling ${compiler.path}..."); |
98 | 106 |
99 // We wait for stdout and stderr to close and for exitCode to fire to ensure | 107 // We wait for stdout and stderr to close and for exitCode to fire to ensure |
100 // that we're done printing everything about one process before we start the | 108 // that we're done printing everything about one process before we start the |
101 // next. | 109 // next. |
102 Future.wait([ | 110 Future.wait([ |
103 compiler.process.stdout.listen(stdout.add).asFuture(), | 111 compiler.process.stdout.listen(stdout.add).asFuture(), |
104 compiler.process.stderr.listen(stderr.add).asFuture(), | 112 compiler.process.stderr.listen(stderr.add).asFuture(), |
105 compiler.process.exitCode.then((exitCode) { | 113 compiler.process.exitCode.then((exitCode) { |
106 if (exitCode == 0) return; | 114 if (exitCode == 0 || _closed) return; |
107 throw new LoadException(compiler.path, "dart2js failed."); | 115 throw new LoadException(compiler.path, "dart2js failed."); |
108 }) | 116 }) |
109 ]).then(compiler.onDoneCompleter.complete) | 117 ]).then((_) { |
110 .catchError(compiler.onDoneCompleter.completeError) | 118 if (_closed) return; |
111 .then((_) { | 119 compiler.onDoneCompleter.complete(); |
| 120 }).catchError((error, stackTrace) { |
| 121 if (_closed) return; |
| 122 compiler.onDoneCompleter.completeError(error, stackTrace); |
| 123 }).then((_) { |
| 124 if (_closed) return; |
| 125 |
112 _compilers.removeFirst(); | 126 _compilers.removeFirst(); |
113 if (_compilers.isEmpty) return; | 127 if (_compilers.isEmpty) return; |
114 | 128 |
115 var next = _compilers.first; | 129 var next = _compilers.first; |
116 | 130 |
117 // Wait a bit before printing the next progress in case the current one | 131 // Wait a bit before printing the next progress in case the current one |
118 // threw an error that needs to be printed. | 132 // threw an error that needs to be printed. |
119 Timer.run(() => _showProcess(next)); | 133 Timer.run(() => _showProcess(next)); |
120 }); | 134 }); |
121 } | 135 } |
| 136 |
| 137 /// Closes the compiler pool. |
| 138 /// |
| 139 /// This kills all currently-running compilers and ensures that no more will |
| 140 /// be started. It returns a [Future] that completes once all the compilers |
| 141 /// have been killed and all resources released. |
| 142 Future close() { |
| 143 if (_closed) return _closeCompleter.future; |
| 144 _closeCompleter = new Completer(); |
| 145 |
| 146 return Future.wait(_compilers.map((compiler) { |
| 147 compiler.process.kill(); |
| 148 return compiler.process.exitCode.then(compiler.onDoneCompleter.complete); |
| 149 })).then((_) { |
| 150 _compilers.clear(); |
| 151 _closeCompleter.complete(); |
| 152 }).catchError(_closeCompleter.completeError); |
| 153 } |
122 } | 154 } |
123 | 155 |
124 /// A running instance of `dart2js`. | 156 /// A running instance of `dart2js`. |
125 class _Compiler { | 157 class _Compiler { |
126 /// The path of the Dart file being compiled. | 158 /// The path of the Dart file being compiled. |
127 final String path; | 159 final String path; |
128 | 160 |
129 /// The underlying process. | 161 /// The underlying process. |
130 final Process process; | 162 final Process process; |
131 | 163 |
132 /// A future that will complete once this instance has finished running and | 164 /// A future that will complete once this instance has finished running and |
133 /// all its output has been printed. | 165 /// all its output has been printed. |
134 Future get onDone => onDoneCompleter.future; | 166 Future get onDone => onDoneCompleter.future; |
135 final onDoneCompleter = new Completer(); | 167 final onDoneCompleter = new Completer(); |
136 | 168 |
137 _Compiler(this.path, this.process); | 169 _Compiler(this.path, this.process); |
138 } | 170 } |
OLD | NEW |