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

Unified Diff: runtime/bin/process_impl.dart

Issue 11337019: Use patching for dart:io. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments Created 8 years, 2 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
Index: runtime/bin/process_impl.dart
diff --git a/runtime/bin/process_impl.dart b/runtime/bin/process_impl.dart
deleted file mode 100644
index ab8dfd080f98c11c7a261e9f6b8eaf6020d48d30..0000000000000000000000000000000000000000
--- a/runtime/bin/process_impl.dart
+++ /dev/null
@@ -1,359 +0,0 @@
-// Copyright (c) 2012, 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.
-
-_exit(int status) native "Exit";
-
-class _ProcessStartStatus {
- int _errorCode; // Set to OS error code if process start failed.
- String _errorMessage; // Set to OS error message if process start failed.
-}
-
-
-class _Process extends NativeFieldWrapperClass1 implements Process {
- static Future<ProcessResult> run(String path,
- List<String> arguments,
- [ProcessOptions options]) {
- return new _NonInteractiveProcess(path, arguments, options)._result;
- }
-
- static Future<Process> start(String path,
- List<String> arguments,
- ProcessOptions options) {
- _Process process = new _Process(path, arguments, options);
- return process._start();
- }
-
- _Process(String path, List<String> arguments, ProcessOptions options) {
- if (path is !String) {
- throw new ArgumentError("Path is not a String: $path");
- }
- _path = path;
-
- if (arguments is !List) {
- throw new ArgumentError("Arguments is not a List: $arguments");
- }
- int len = arguments.length;
- _arguments = new List<String>(len);
- for (int i = 0; i < len; i++) {
- var arg = arguments[i];
- if (arg is !String) {
- throw new ArgumentError("Non-string argument: $arg");
- }
- _arguments[i] = arguments[i];
- if (Platform.operatingSystem == 'windows') {
- _arguments[i] = _windowsArgumentEscape(_arguments[i]);
- }
- }
-
- if (options !== null && options.workingDirectory !== null) {
- _workingDirectory = options.workingDirectory;
- if (_workingDirectory is !String) {
- throw new ArgumentError(
- "WorkingDirectory is not a String: $_workingDirectory");
- }
- }
-
- if (options !== null && options.environment !== null) {
- var env = options.environment;
- if (env is !Map) {
- throw new ArgumentError("Environment is not a map: $env");
- }
- _environment = [];
- env.forEach((key, value) {
- if (key is !String || value is !String) {
- throw new ArgumentError(
- "Environment key or value is not a string: ($key, $value)");
- }
- _environment.add('$key=$value');
- });
- }
-
- _in = new _Socket._internalReadOnly(); // stdout coming from process.
- _out = new _Socket._internalWriteOnly(); // stdin going to process.
- _err = new _Socket._internalReadOnly(); // stderr coming from process.
- _exitHandler = new _Socket._internalReadOnly();
- _ended = false;
- _started = false;
- _onExit = null;
- }
-
- String _windowsArgumentEscape(String argument) {
- var result = argument;
- if (argument.contains('\t') || argument.contains(' ')) {
- // Produce something that the C runtime on Windows will parse
- // back as this string.
-
- // Replace any number of '\' followed by '"' with
- // twice as many '\' followed by '\"'.
- var backslash = '\\'.charCodeAt(0);
- var sb = new StringBuffer();
- var nextPos = 0;
- var quotePos = argument.indexOf('"', nextPos);
- while (quotePos != -1) {
- var numBackslash = 0;
- var pos = quotePos - 1;
- while (pos >= 0 && argument.charCodeAt(pos) == backslash) {
- numBackslash++;
- pos--;
- }
- sb.add(argument.substring(nextPos, quotePos - numBackslash));
- for (var i = 0; i < numBackslash; i++) {
- sb.add(r'\\');
- }
- sb.add(r'\"');
- nextPos = quotePos + 1;
- quotePos = argument.indexOf('"', nextPos);
- }
- sb.add(argument.substring(nextPos, argument.length));
- result = sb.toString();
-
- // Add '"' at the beginning and end and replace all '\' at
- // the end with two '\'.
- sb = new StringBuffer('"');
- sb.add(result);
- nextPos = argument.length - 1;
- while (argument.charCodeAt(nextPos) == backslash) {
- sb.add('\\');
- nextPos--;
- }
- sb.add('"');
- result = sb.toString();
- }
-
- return result;
- }
-
- int _intFromBytes(List<int> bytes, int offset) {
- return (bytes[offset] +
- (bytes[offset + 1] << 8) +
- (bytes[offset + 2] << 16) +
- (bytes[offset + 3] << 24));
- }
-
- Future<Process> _start() {
- var completer = new Completer();
- // TODO(ager): Make the actual process starting really async instead of
- // simulating it with a timer.
- new Timer(0, (_) {
- var status = new _ProcessStartStatus();
- bool success = _startNative(_path,
- _arguments,
- _workingDirectory,
- _environment,
- _in,
- _out,
- _err,
- _exitHandler,
- status);
- if (!success) {
- _in.close();
- _out.close();
- _err.close();
- _exitHandler.close();
- completer.completeException(
- new ProcessException(status._errorMessage, status._errorCode));
- return;
- }
- _started = true;
-
- _in._closed = false;
- _out._closed = false;
- _err._closed = false;
- _exitHandler._closed = false;
-
- // Make sure to activate socket handlers now that the file
- // descriptors have been set.
- _in._activateHandlers();
- _out._activateHandlers();
- _err._activateHandlers();
-
- // Setup an exit handler to handle internal cleanup and possible
- // callback when a process terminates.
- int exitDataRead = 0;
- final int EXIT_DATA_SIZE = 8;
- List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE);
- _exitHandler.inputStream.onData = () {
-
- int exitCode(List<int> ints) {
- var code = _intFromBytes(ints, 0);
- var negative = _intFromBytes(ints, 4);
- assert(negative == 0 || negative == 1);
- return (negative == 0) ? code : -code;
- }
-
- void handleExit() {
- _ended = true;
- if (_onExit !== null) {
- _onExit(exitCode(exitDataBuffer));
- }
- _out.close();
- }
-
- exitDataRead += _exitHandler.inputStream.readInto(
- exitDataBuffer, exitDataRead, EXIT_DATA_SIZE - exitDataRead);
- if (exitDataRead == EXIT_DATA_SIZE) handleExit();
- };
-
- completer.complete(this);
- });
- return completer.future;
- }
-
- 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 {
- return _in.inputStream;
- }
-
- InputStream get stderr {
- return _err.inputStream;
- }
-
- OutputStream get stdin {
- return _out.outputStream;
- }
-
- bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]) {
- if (signal is! ProcessSignal) {
- throw new ArgumentError(
- "Argument 'signal' must be a ProcessSignal");
- }
- assert(_started);
- if (_ended) return false;
- return _kill(this, signal._signalNumber);
- }
-
- bool _kill(Process p, int signal) native "Process_Kill";
-
- void set onExit(void callback(int exitCode)) {
- if (_ended) {
- throw new ProcessException("Process killed");
- }
- _onExit = callback;
- }
-
- String _path;
- List<String> _arguments;
- String _workingDirectory;
- List<String> _environment;
- // Private methods of _Socket are used by _in, _out, and _err.
- _Socket _in;
- _Socket _out;
- _Socket _err;
- Socket _exitHandler;
- bool _ended;
- bool _started;
- Function _onExit;
-}
-
-
-// _NonInteractiveProcess is a wrapper around an interactive process
-// that buffers output so it can be delivered when the process exits.
-// _NonInteractiveProcess is used to implement the Process.run
-// method.
-class _NonInteractiveProcess {
- _NonInteractiveProcess(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;
- if (options !== null) {
- if (options.stdoutEncoding !== null) {
- stdoutEncoding = options.stdoutEncoding;
- if (stdoutEncoding is !Encoding) {
- throw new ArgumentError(
- 'stdoutEncoding option is not an encoding: $stdoutEncoding');
- }
- }
- if (options.stderrEncoding !== null) {
- stderrEncoding = options.stderrEncoding;
- if (stderrEncoding is !Encoding) {
- throw new ArgumentError(
- 'stderrEncoding option is not an encoding: $stderrEncoding');
- }
- }
- }
-
- // Start the underlying process.
- var processFuture = new _Process(path, arguments, options)._start();
-
- processFuture.then((Process p) {
- // Make sure the process stdin is closed.
- p.stdin.close;
-
- // Setup process exit handling.
- p.onExit = (exitCode) {
- _exitCode = exitCode;
- _checkDone();
- };
-
- // Setup stdout handling.
- _stdoutBuffer = new StringBuffer();
- var stdoutStream = new StringInputStream(p.stdout, stdoutEncoding);
- stdoutStream.onData = () {
- var data = stdoutStream.read();
- if (data != null) _stdoutBuffer.add(data);
- };
- stdoutStream.onClosed = () {
- _stdoutClosed = true;
- _checkDone();
- };
-
- // Setup stderr handling.
- _stderrBuffer = new StringBuffer();
- var stderrStream = new StringInputStream(p.stderr, stderrEncoding);
- stderrStream.onData = () {
- var data = stderrStream.read();
- if (data != null) _stderrBuffer.add(data);
- };
- stderrStream.onClosed = () {
- _stderrClosed = true;
- _checkDone();
- };
- });
-
- processFuture.handleException((error) {
- _completer.completeException(error);
- return true;
- });
- }
-
- void _checkDone() {
- if (_exitCode != null && _stderrClosed && _stdoutClosed) {
- _completer.complete(new _ProcessResult(_exitCode,
- _stdoutBuffer.toString(),
- _stderrBuffer.toString()));
- }
- }
-
- Future<ProcessResult> get _result => _completer.future;
-
- Completer<ProcessResult> _completer;
- 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;
-}

Powered by Google App Engine
This is Rietveld 408576698