Index: lib/src/runner/browser/compiler_pool.dart |
diff --git a/lib/src/runner/browser/compiler_pool.dart b/lib/src/runner/browser/compiler_pool.dart |
index 20f555bcf4013420e974941667cddcef3f046876..d881a9406f1dcd447d005d98b2e7ec758d7b74e8 100644 |
--- a/lib/src/runner/browser/compiler_pool.dart |
+++ b/lib/src/runner/browser/compiler_pool.dart |
@@ -5,7 +5,7 @@ |
library test.util.compiler_pool; |
import 'dart:async'; |
-import 'dart:collection'; |
+import 'dart:convert'; |
import 'dart:io'; |
import 'package:path/path.dart' as p; |
@@ -13,15 +13,11 @@ import 'package:pool/pool.dart'; |
import '../../util/async_thunk.dart'; |
import '../../util/io.dart'; |
-import '../../utils.dart'; |
import '../load_exception.dart'; |
/// A pool of `dart2js` instances. |
/// |
-/// This limits the number of compiler instances running concurrently. It also |
-/// ensures that their output doesn't intermingle; only one instance is |
-/// "visible" (that is, having its output printed) at a time, and the other |
-/// instances' output is buffered until it's their turn to be visible. |
+/// This limits the number of compiler instances running concurrently. |
class CompilerPool { |
/// The internal pool that controls the number of process running at once. |
final Pool _pool; |
@@ -29,13 +25,8 @@ class CompilerPool { |
/// Whether to enable colors on dart2js. |
final bool _color; |
- /// The currently-active compilers. |
- /// |
- /// The first one is the only visible the compiler; the rest will become |
- /// visible in queue order. Note that some of these processes may actually |
- /// have already exited; they're kept around so that their output can be |
- /// emitted once they become visible. |
- final _compilers = new Queue<_Compiler>(); |
+ /// The currently-active dart2js processes. |
+ final _processes = new Set<Process>(); |
/// Whether [close] has been called. |
bool get _closed => _closeThunk.hasRun; |
@@ -89,56 +80,45 @@ void main(_) { |
if (_color) args.add("--enable-diagnostic-colors"); |
var process = await Process.start(dart2jsPath, args); |
- var compiler = new _Compiler(dartPath, process); |
+ if (_closed) { |
+ process.kill(); |
+ return; |
+ } |
- if (_compilers.isEmpty) _showProcess(compiler); |
- _compilers.add(compiler); |
+ _processes.add(process); |
- await compiler.onDone; |
- }); |
- }); |
- } |
+ /// Wait until the process is entirely done to print out any output. |
+ /// This can produce a little extra time for users to wait with no |
+ /// update, but it also avoids some really nasty-looking interleaved |
+ /// output. Write both stdout and stderr to the same buffer in case |
+ /// they're intended to be printed in order. |
+ var buffer = new StringBuffer(); |
- /// Mark [compiler] as the visible instance. |
- /// |
- /// This prints all [compiler]'s standard output and error. |
- void _showProcess(_Compiler compiler) { |
- print("Compiling ${compiler.path}..."); |
- |
- invoke(() async { |
- try { |
- // We wait for stdout and stderr to close and for exitCode to fire to |
- // ensure that we're done printing everything about one process before |
- // we start the next. |
await Future.wait([ |
- sanitizeForWindows(compiler.process.stdout).listen(stdout.add) |
- .asFuture(), |
- sanitizeForWindows(compiler.process.stderr).listen(stderr.add) |
- .asFuture(), |
- compiler.process.exitCode.then((exitCode) { |
- if (exitCode == 0 || _closed) return; |
- throw new LoadException(compiler.path, "dart2js failed."); |
- }) |
+ _printOutputStream(process.stdout, buffer), |
+ _printOutputStream(process.stderr, buffer), |
]); |
+ var exitCode = await process.exitCode; |
+ _processes.remove(process); |
if (_closed) return; |
- compiler.onDoneCompleter.complete(); |
- } catch (error, stackTrace) { |
- if (_closed) return; |
- compiler.onDoneCompleter.completeError(error, stackTrace); |
- } |
- _compilers.removeFirst(); |
- if (_compilers.isEmpty) return; |
+ if (buffer.isNotEmpty) print(buffer); |
- var next = _compilers.first; |
- |
- // Wait a bit before printing the next process in case the current one |
- // threw an error that needs to be printed. |
- Timer.run(() => _showProcess(next)); |
+ if (exitCode != 0) { |
+ throw new LoadException(dartPath, "dart2js failed."); |
+ } |
+ }); |
}); |
} |
+ /// Sanitizes the bytes emitted by [stream], converts them to text, and writes |
+ /// them to [buffer]. |
+ Future _printOutputStream(Stream<List<int>> stream, StringBuffer buffer) { |
+ return sanitizeForWindows(stream) |
+ .listen((data) => buffer.write(UTF8.decode(data))).asFuture(); |
+ } |
+ |
/// Closes the compiler pool. |
/// |
/// This kills all currently-running compilers and ensures that no more will |
@@ -146,29 +126,10 @@ void main(_) { |
/// have been killed and all resources released. |
Future close() { |
return _closeThunk.run(() async { |
- await Future.wait(_compilers.map((compiler) async { |
- compiler.process.kill(); |
- await compiler.process.exitCode; |
- compiler.onDoneCompleter.complete(); |
+ await Future.wait(_processes.map((process) async { |
+ process.kill(); |
+ await process.exitCode; |
})); |
- |
- _compilers.clear(); |
}); |
} |
} |
- |
-/// A running instance of `dart2js`. |
-class _Compiler { |
- /// The path of the Dart file being compiled. |
- final String path; |
- |
- /// The underlying process. |
- final Process process; |
- |
- /// A future that will complete once this instance has finished running and |
- /// all its output has been printed. |
- Future get onDone => onDoneCompleter.future; |
- final onDoneCompleter = new Completer(); |
- |
- _Compiler(this.path, this.process); |
-} |