| Index: runtime/bin/process_impl.dart
|
| diff --git a/runtime/bin/process_impl.dart b/runtime/bin/process_impl.dart
|
| index b0092dc7318a87135b67498bf302c5f16d49cbb3..c786f9cb3ffbd1757a90bd2935d191f9aa4221ce 100644
|
| --- a/runtime/bin/process_impl.dart
|
| +++ b/runtime/bin/process_impl.dart
|
| @@ -8,37 +8,22 @@ class _ProcessStartStatus {
|
| }
|
|
|
|
|
| -// Abstract factory class capable of producing interactive and
|
| -// non-interactive processes.
|
| -class _Process {
|
| -
|
| - factory Process.start(String path,
|
| - List<String> arguments,
|
| - [ProcessOptions options]) {
|
| - return new _InteractiveProcess.start(path, arguments, options);
|
| +class _Process extends Process {
|
| + static Process start(String path,
|
| + List<String> arguments,
|
| + [ProcessOptions options]) {
|
| + return new _Process.start(path, arguments, options);
|
| }
|
|
|
| - factory Process.run(String path,
|
| - List<String> arguments,
|
| - ProcessOptions options,
|
| - void callback(int exitCode,
|
| - String stdout,
|
| - String stderr)) {
|
| - return new _NonInteractiveProcess.start(path,
|
| - arguments,
|
| - options,
|
| - callback);
|
| + static Future<ProcessResult> run(String path,
|
| + List<String> arguments,
|
| + [ProcessOptions options]) {
|
| + return new _NonInteractiveProcess._start(path, arguments, options)._result;
|
| }
|
| -}
|
| -
|
|
|
| -// _InteractiveProcess is the actual implementation of all processes
|
| -// started from Dart code.
|
| -class _InteractiveProcess implements Process {
|
| -
|
| - _InteractiveProcess.start(String path,
|
| - List<String> arguments,
|
| - ProcessOptions options) {
|
| + _Process.start(String path,
|
| + List<String> arguments,
|
| + ProcessOptions options) {
|
| if (path is !String) {
|
| throw new IllegalArgumentException("Path is not a String: $path");
|
| }
|
| @@ -97,7 +82,7 @@ class _InteractiveProcess implements Process {
|
| _onExit = null;
|
| // TODO(ager): Make the actual process starting really async instead of
|
| // simulating it with a timer.
|
| - new Timer(0, (Timer ignore) => start());
|
| + new Timer(0, (Timer ignore) => _start());
|
| }
|
|
|
| String _windowsArgumentEscape(String argument) {
|
| @@ -153,20 +138,21 @@ class _InteractiveProcess implements Process {
|
| (bytes[offset + 3] << 24));
|
| }
|
|
|
| - void start() {
|
| + void _start() {
|
| var status = new _ProcessStartStatus();
|
| - bool success = _start(_path,
|
| - _arguments,
|
| - _workingDirectory,
|
| - _environment,
|
| - _in,
|
| - _out,
|
| - _err,
|
| - _exitHandler,
|
| - status);
|
| + bool success = _startNative(_path,
|
| + _arguments,
|
| + _workingDirectory,
|
| + _environment,
|
| + _in,
|
| + _out,
|
| + _err,
|
| + _exitHandler,
|
| + status);
|
| if (!success) {
|
| close();
|
| - _reportError(new ProcessException(status._errorMessage, status._errorCode));
|
| + _reportError(new ProcessException(status._errorMessage,
|
| + status._errorCode));
|
| return;
|
| }
|
| _started = true;
|
| @@ -207,15 +193,15 @@ class _InteractiveProcess implements Process {
|
| }
|
| }
|
|
|
| - bool _start(String path,
|
| - List<String> arguments,
|
| - String workingDirectory,
|
| - List<String> environment,
|
| - Socket input,
|
| - Socket output,
|
| - Socket error,
|
| - Socket exitHandler,
|
| - _ProcessStartStatus status) native "Process_Start";
|
| + bool _startNative(String path,
|
| + List<String> arguments,
|
| + String workingDirectory,
|
| + List<String> environment,
|
| + Socket input,
|
| + Socket output,
|
| + Socket error,
|
| + Socket exitHandler,
|
| + _ProcessStartStatus status) native "Process_Start";
|
|
|
| InputStream get stdout() {
|
| if (_closed) {
|
| @@ -314,14 +300,14 @@ class _InteractiveProcess implements Process {
|
|
|
|
|
| // _NonInteractiveProcess is a wrapper around an interactive process
|
| -// that restricts the interface to disallow access to the streams and
|
| -// buffers output so it can be delivered to the callback when the
|
| -// process exits.
|
| -class _NonInteractiveProcess implements Process {
|
| - _NonInteractiveProcess.start(String path,
|
| - List<String> arguments,
|
| - ProcessOptions options,
|
| - Function this._callback) {
|
| +// that buffers output so it can be delivered when the process exits.
|
| +// _NonInteractiveProcess is used to implement the Process.run
|
| +// method.
|
| +class _NonInteractiveProcess {
|
| + _NonInteractiveProcess._start(String path,
|
| + List<String> arguments,
|
| + ProcessOptions options) {
|
| + _completer = new Completer<ProcessResult>();
|
| // Extract output encoding options and verify arguments.
|
| var stdoutEncoding = Encoding.UTF_8;
|
| var stderrEncoding = Encoding.UTF_8;
|
| @@ -343,7 +329,10 @@ class _NonInteractiveProcess implements Process {
|
| }
|
|
|
| // Start the underlying process.
|
| - _process = new _InteractiveProcess.start(path, arguments, options);
|
| + _process = new _Process.start(path, arguments, options);
|
| +
|
| + // Setup process error handling.
|
| + _process.onError = (e) => _completer.completeException(e);
|
|
|
| // Setup process exit handling.
|
| _process.onExit = (exitCode) {
|
| @@ -378,52 +367,30 @@ class _NonInteractiveProcess implements Process {
|
|
|
| void _checkDone() {
|
| if (_exitCode != null && _stderrClosed && _stdoutClosed) {
|
| - _callback(_exitCode, _stdoutBuffer.toString(), _stderrBuffer.toString());
|
| + _completer.complete(new _ProcessResult(_exitCode,
|
| + _stdoutBuffer.toString(),
|
| + _stderrBuffer.toString()));
|
| }
|
| }
|
|
|
| - InputStream get stdout() {
|
| - throw new UnsupportedOperationException(
|
| - 'Cannot get stdout stream for process started with '
|
| - 'the run constructor. The entire stdout '
|
| - 'will be supplied in the callback on completion.');
|
| - }
|
| -
|
| - InputStream get stderr() {
|
| - throw new UnsupportedOperationException(
|
| - 'Cannot get stderr stream for process started with '
|
| - 'the run constructor. The entire stderr '
|
| - 'will be supplied in the callback on completion.');
|
| - }
|
| -
|
| - OutputStream get stdin() {
|
| - throw new UnsupportedOperationException(
|
| - 'Cannot communicate via stdin with process started with '
|
| - 'the run constructor');
|
| - }
|
| -
|
| - void set onStart(void callback()) => _process.onStart = callback;
|
| -
|
| - void set onExit(void callback(int exitCode)) {
|
| - throw new UnsupportedOperationException(
|
| - 'Cannot set exit handler on process started with '
|
| - 'the run constructor. The exit code will '
|
| - 'be supplied in the callback on completion.');
|
| - }
|
| -
|
| - void set onError(void callback(e)) {
|
| - _process.onError = callback;
|
| - }
|
| -
|
| - void kill() => _process.kill();
|
| -
|
| - void close() => _process.close();
|
| + Future<ProcessResult> get _result() => _completer.future;
|
|
|
| + Completer<ProcessResult> _completer;
|
| Process _process;
|
| - Function _callback;
|
| StringBuffer _stdoutBuffer;
|
| StringBuffer _stderrBuffer;
|
| int _exitCode;
|
| bool _stdoutClosed = false;
|
| bool _stderrClosed = false;
|
| }
|
| +
|
| +
|
| +class _ProcessResult implements ProcessResult {
|
| + const _ProcessResult(int this.exitCode,
|
| + String this.stdout,
|
| + String this.stderr);
|
| +
|
| + final int exitCode;
|
| + final String stdout;
|
| + final String stderr;
|
| +}
|
|
|