Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Unified Diff: lib/src/runner/browser/compiler_pool.dart

Issue 960723002: Add a CompilerPool class. (Closed) Base URL: git@github.com:dart-lang/unittest@master
Patch Set: Fix library name. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | lib/src/util/io.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
new file mode 100644
index 0000000000000000000000000000000000000000..cf77fe06ed553ba04f020fe2b8a707dc9caf2a4f
--- /dev/null
+++ b/lib/src/runner/browser/compiler_pool.dart
@@ -0,0 +1,134 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library unittest.util.compiler_pool;
+
+import 'dart:async';
+import 'dart:collection';
+import 'dart:io';
+
+import 'package:path/path.dart' as p;
+import 'package:pool/pool.dart';
+
+import '../../util/io.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.
+class CompilerPool {
+ /// The internal pool that controls the number of process running at once.
+ final Pool _pool;
+
+ /// 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>();
+
+ /// Creates a compiler pool that runs up to [parallel] instances of `dart2js`
+ /// at once.
+ ///
+ /// If [parallel] isn't provided, it defaults to 4.
+ CompilerPool({int parallel})
+ : _pool = new Pool(parallel == null ? 4 : parallel);
+
+ /// Compile the Dart code at [dartPath] to [jsPath].
+ ///
+ /// This wraps the Dart code in the standard browser-testing wrapper. If
+ /// [packageRoot] is provided, it's used as the package root for the
+ /// compilation.
+ ///
+ /// The returned [Future] will complete once the `dart2js` process completes
+ /// *and* all its output has been printed to the command line.
+ Future compile(String dartPath, String jsPath, {String packageRoot}) {
+ return _pool.withResource(() {
+ return withTempDir((dir) {
+ var wrapperPath = p.join(dir, "runInBrowser.dart");
+ new File(wrapperPath).writeAsStringSync('''
+import "package:unittest/src/runner/browser/iframe_listener.dart";
+
+import "${p.toUri(p.absolute(dartPath))}" as test;
+
+void main(_) {
+ IframeListener.start(() => test.main);
+}
+''');
+
+ var dart2jsPath = p.join(sdkDir, 'bin', 'dart2js');
+ if (Platform.isWindows) dart2jsPath += '.bat';
+
+ var args = ["--checked", wrapperPath, "--out=$jsPath"];
+
+ if (packageRoot != null) {
+ args.add("--package-root=${p.absolute(packageRoot)}");
+ }
+
+ if (canUseSpecialChars) {
+ args.add("--enable-diagnostic-colors");
+ }
+
+ return Process.start(dart2jsPath, args).then((process) {
+ var compiler = new _Compiler(dartPath, process);
+
+ if (_compilers.isEmpty) _showProcess(compiler);
+ _compilers.add(compiler);
+
+ return compiler.onDone;
+ });
+ });
+ });
+ }
+
+ /// Mark [compiler] as the visible instance.
+ ///
+ /// This prints all [compiler]'s standard output and error.
+ void _showProcess(_Compiler compiler) {
+ print("Compiling ${compiler.path}...");
+
+ // 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.
+ Future.wait([
+ compiler.process.stdout.listen(stdout.add).asFuture(),
+ compiler.process.stderr.listen(stderr.add).asFuture(),
+ compiler.process.exitCode.then((exitCode) {
+ if (exitCode == 0) return;
+ throw new LoadException(compiler.path, "dart2js failed.");
+ })
+ ]).then(compiler.onDoneCompleter.complete)
+ .catchError(compiler.onDoneCompleter.completeError)
+ .then((_) {
+ _compilers.removeFirst();
+ if (_compilers.isEmpty) return;
+
+ var next = _compilers.first;
+
+ // Wait a bit before printing the next progress in case the current one
+ // threw an error that needs to be printed.
+ Timer.run(() => _showProcess(next));
+ });
+ }
+}
+
+/// 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);
+}
« no previous file with comments | « no previous file | lib/src/util/io.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698