Bug 1350646: Part 3 - Remove sdk/system/child_process modules. r=Mossop
authorKris Maglione <maglione.k@gmail.com>
Wed, 02 Aug 2017 13:52:47 -0700
changeset 373701 dce8af021eda7913c23ba529d81fcd49955b6b93
parent 373700 ec5c715bf59294fa36bf90581ccd8066d85b5a5f
child 373702 5d4019ce62a92d23cc207e07103ff6aa1ddb134e
push id93584
push usermaglione.k@gmail.com
push dateThu, 10 Aug 2017 03:41:19 +0000
treeherdermozilla-inbound@24d5dbf3a9dc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMossop
bugs1350646
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1350646: Part 3 - Remove sdk/system/child_process modules. r=Mossop MozReview-Commit-ID: LQgUe8E8M4k
addon-sdk/moz.build
addon-sdk/source/lib/sdk/system/child_process.js
addon-sdk/source/lib/sdk/system/child_process/subprocess.js
--- a/addon-sdk/moz.build
+++ b/addon-sdk/moz.build
@@ -179,18 +179,16 @@ modules = [
     'sdk/request.js',
     'sdk/selection.js',
     'sdk/self.js',
     'sdk/simple-prefs.js',
     'sdk/simple-storage.js',
     'sdk/stylesheet/style.js',
     'sdk/stylesheet/utils.js',
     'sdk/system.js',
-    'sdk/system/child_process.js',
-    'sdk/system/child_process/subprocess.js',
     'sdk/system/environment.js',
     'sdk/system/events-shimmed.js',
     'sdk/system/events.js',
     'sdk/system/globals.js',
     'sdk/system/process.js',
     'sdk/system/runtime.js',
     'sdk/system/unload.js',
     'sdk/system/xul-app.js',
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/system/child_process.js
+++ /dev/null
@@ -1,332 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-module.metadata = {
-  'stability': 'experimental'
-};
-
-var { Ci } = require('chrome');
-var subprocess = require('./child_process/subprocess');
-var { EventTarget } = require('../event/target');
-var { Stream } = require('../io/stream');
-var { on, emit, off } = require('../event/core');
-var { Class } = require('../core/heritage');
-var { platform } = require('../system');
-var { isFunction, isArray } = require('../lang/type');
-var { delay } = require('../lang/functional');
-var { merge } = require('../util/object');
-var { setTimeout, clearTimeout } = require('../timers');
-var isWindows = platform.indexOf('win') === 0;
-
-var processes = new WeakMap();
-
-
-/**
- * The `Child` class wraps a subprocess command, exposes
- * the stdio streams, and methods to manipulate the subprocess
- */
-var Child = Class({
-  implements: [EventTarget],
-  initialize: function initialize (options) {
-    let child = this;
-    let proc;
-
-    this.killed = false;
-    this.exitCode = undefined;
-    this.signalCode = undefined;
-
-    this.stdin = Stream();
-    this.stdout = Stream();
-    this.stderr = Stream();
-
-    try {
-      proc = subprocess.call({
-        command: options.file,
-        arguments: options.cmdArgs,
-        environment: serializeEnv(options.env),
-        workdir: options.cwd,
-        charset: options.encoding,
-        stdout: data => emit(child.stdout, 'data', data),
-        stderr: data => emit(child.stderr, 'data', data),
-        stdin: stream => {
-          child.stdin.on('data', pumpStdin);
-          child.stdin.on('end', function closeStdin () {
-            child.stdin.off('data', pumpStdin);
-            child.stdin.off('end', closeStdin);
-            stream.close();
-          });
-          function pumpStdin (data) {
-            stream.write(data);
-          }
-        },
-        done: function (result, error) {
-          if (error)
-            return handleError(error);
-
-          // Only emit if child is not killed; otherwise,
-          // the `kill` method will handle this
-          if (!child.killed) {
-            child.exitCode = result.exitCode;
-            child.signalCode = null;
-
-            // If process exits with < 0, there was an error
-            if (child.exitCode < 0) {
-              handleError(new Error('Process exited with exit code ' + child.exitCode));
-            }
-            else {
-              // Also do 'exit' event as there's not much of
-              // a difference in our implementation as we're not using
-              // node streams
-              emit(child, 'exit', child.exitCode, child.signalCode);
-            }
-
-            // Emit 'close' event with exit code and signal,
-            // which is `null`, as it was not a killed process
-            emit(child, 'close', child.exitCode, child.signalCode);
-          }
-        }
-      });
-      processes.set(child, proc);
-    } catch (e) {
-      // Delay the error handling so an error handler can be set
-      // during the same tick that the Child was created
-      delay(() => handleError(e));
-    }
-
-    // `handleError` is called when process could not even
-    // be spawned
-    function handleError (e) {
-      // If error is an nsIObject, make a fresh error object
-      // so we're not exposing nsIObjects, and we can modify it
-      // with additional process information, like node
-      let error = e;
-      if (e instanceof Ci.nsISupports) {
-        error = new Error(e.message, e.filename, e.lineNumber);
-      }
-      emit(child, 'error', error);
-      child.exitCode = -1;
-      child.signalCode = null;
-      emit(child, 'close', child.exitCode, child.signalCode);
-    }
-  },
-  kill: function kill (signal) {
-    let proc = processes.get(this);
-    proc.kill(signal);
-    this.killed = true;
-    this.exitCode = null;
-    this.signalCode = signal;
-    emit(this, 'exit', this.exitCode, this.signalCode);
-    emit(this, 'close', this.exitCode, this.signalCode);
-  },
-  get pid() { return processes.get(this, {}).pid || -1; }
-});
-
-function spawn (file, ...args) {
-  let cmdArgs = [];
-  // Default options
-  let options = {
-    cwd: null,
-    env: null,
-    encoding: 'UTF-8'
-  };
-
-  if (args[1]) {
-    merge(options, args[1]);
-    cmdArgs = args[0];
-  }
-  else {
-    if (isArray(args[0]))
-      cmdArgs = args[0];
-    else
-      merge(options, args[0]);
-  }
-
-  if ('gid' in options)
-    console.warn('`gid` option is not yet supported for `child_process`');
-  if ('uid' in options)
-    console.warn('`uid` option is not yet supported for `child_process`');
-  if ('detached' in options)
-    console.warn('`detached` option is not yet supported for `child_process`');
-
-  options.file = file;
-  options.cmdArgs = cmdArgs;
-
-  return Child(options);
-}
-
-exports.spawn = spawn;
-
-/**
- * exec(command, options, callback)
- */
-function exec (cmd, ...args) {
-  let file, cmdArgs, callback, options = {};
-
-  if (isFunction(args[0]))
-    callback = args[0];
-  else {
-    merge(options, args[0]);
-    callback = args[1];
-  }
-
-  if (isWindows) {
-    file = 'C:\\Windows\\System32\\cmd.exe';
-    cmdArgs = ['/S/C', cmd || ''];
-  }
-  else {
-    file = '/bin/sh';
-    cmdArgs = ['-c', cmd];
-  }
-
-  // Undocumented option from node being able to specify shell
-  if (options && options.shell)
-    file = options.shell;
-
-  return execFile(file, cmdArgs, options, callback);
-}
-exports.exec = exec;
-/**
- * execFile (file, args, options, callback)
- */
-function execFile (file, ...args) {
-  let cmdArgs = [], callback;
-  // Default options
-  let options = {
-    cwd: null,
-    env: null,
-    encoding: 'utf8',
-    timeout: 0,
-    maxBuffer: 204800,    //200 KB (200*1024 bytes)
-    killSignal: 'SIGTERM'
-  };
-
-  if (isFunction(args[args.length - 1]))
-    callback = args[args.length - 1];
-
-  if (isArray(args[0])) {
-    cmdArgs = args[0];
-    merge(options, args[1]);
-  } else if (!isFunction(args[0]))
-    merge(options, args[0]);
-
-  let child = spawn(file, cmdArgs, options);
-  let exited = false;
-  let stdout = '';
-  let stderr = '';
-  let error = null;
-  let timeoutId = null;
-
-  child.stdout.setEncoding(options.encoding);
-  child.stderr.setEncoding(options.encoding);
-
-  on(child.stdout, 'data', pumpStdout);
-  on(child.stderr, 'data', pumpStderr);
-  on(child, 'close', exitHandler);
-  on(child, 'error', errorHandler);
-
-  if (options.timeout > 0) {
-    setTimeout(() => {
-      kill();
-      timeoutId = null;
-    }, options.timeout);
-  }
-
-  function exitHandler (code, signal) {
-
-    // Return if exitHandler called previously, occurs
-    // when multiple maxBuffer errors thrown and attempt to kill multiple
-    // times
-    if (exited) return;
-    exited = true;
-
-    if (!isFunction(callback)) return;
-
-    if (timeoutId) {
-      clearTimeout(timeoutId);
-      timeoutId = null;
-    }
-
-    if (!error && (code !== 0 || signal !== null))
-      error = createProcessError(new Error('Command failed: ' + stderr), {
-        code: code,
-        signal: signal,
-        killed: !!child.killed
-      });
-
-    callback(error, stdout, stderr);
-
-    off(child.stdout, 'data', pumpStdout);
-    off(child.stderr, 'data', pumpStderr);
-    off(child, 'close', exitHandler);
-    off(child, 'error', errorHandler);
-  }
-
-  function errorHandler (e) {
-    error = e;
-    exitHandler();
-  }
-
-  function kill () {
-    try {
-      child.kill(options.killSignal);
-    } catch (e) {
-      // In the scenario where the kill signal happens when
-      // the process is already closing, just abort the kill fail
-      if (/library is not open/.test(e))
-        return;
-      error = e;
-      exitHandler(-1, options.killSignal);
-    }
-  }
-
-  function pumpStdout (data) {
-    stdout += data;
-    if (stdout.length > options.maxBuffer) {
-      error = new Error('stdout maxBuffer exceeded');
-      kill();
-    }
-  }
-
-  function pumpStderr (data) {
-    stderr += data;
-    if (stderr.length > options.maxBuffer) {
-      error = new Error('stderr maxBuffer exceeded');
-      kill();
-    }
-  }
-
-  return child;
-}
-exports.execFile = execFile;
-
-exports.fork = function fork () {
-  throw new Error("child_process#fork is not currently supported");
-};
-
-function serializeEnv (obj) {
-  return Object.keys(obj || {}).map(prop => prop + '=' + obj[prop]);
-}
-
-function createProcessError (err, options = {}) {
-  // If code and signal look OK, this was probably a failure
-  // attempting to spawn the process (like ENOENT in node) -- use
-  // the code from the error message
-  if (!options.code && !options.signal) {
-    let match = err.message.match(/(NS_ERROR_\w*)/);
-    if (match && match.length > 1)
-      err.code = match[1];
-    else {
-      // If no good error message found, use the passed in exit code;
-      // this occurs when killing a process that's already closing,
-      // where we want both a valid exit code (0) and the error
-      err.code = options.code != null ? options.code : null;
-    }
-  }
-  else
-    err.code = options.code != null ? options.code : null;
-  err.signal = options.signal || null;
-  err.killed = options.killed || false;
-  return err;
-}
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/system/child_process/subprocess.js
+++ /dev/null
@@ -1,184 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-'use strict';
-
-const { Ci, Cu } = require("chrome");
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Subprocess.jsm");
-
-const Runtime = require("sdk/system/runtime");
-const Environment = require("sdk/system/environment").env;
-const DEFAULT_ENVIRONMENT = [];
-if (Runtime.OS == "Linux" && "DISPLAY" in Environment) {
-  DEFAULT_ENVIRONMENT.push("DISPLAY=" + Environment.DISPLAY);
-}
-
-function awaitPromise(promise) {
-  let value;
-  let resolved = null;
-  promise.then(val => {
-    resolved = true;
-    value = val;
-  }, val => {
-    resolved = false;
-    value = val;
-  });
-
-  Services.tm.spinEventLoopUntil(() => resolved !== null);
-
-  if (resolved === true)
-    return value;
-  throw value;
-}
-
-let readAllData = async function(pipe, read, callback) {
-  let string;
-  while (string = await read(pipe))
-    callback(string);
-};
-
-let write = (pipe, data) => {
-  let buffer = new Uint8Array(Array.from(data, c => c.charCodeAt(0)));
-  return pipe.write(data);
-};
-
-var subprocess = {
-  call: function(options) {
-    var result;
-
-    let procPromise = (async function() {
-      let opts = {};
-
-      if (options.mergeStderr) {
-        opts.stderr = "stdout"
-      } else if (options.stderr) {
-        opts.stderr = "pipe";
-      }
-
-      if (options.command instanceof Ci.nsIFile) {
-        opts.command = options.command.path;
-      } else {
-        opts.command = await Subprocess.pathSearch(options.command);
-      }
-
-      if (options.workdir) {
-        opts.workdir = options.workdir;
-      }
-
-      opts.arguments = options.arguments || [];
-
-
-      // Set up environment
-
-      let envVars = options.environment || DEFAULT_ENVIRONMENT;
-      if (envVars.length) {
-        let environment = {};
-        for (let val of envVars) {
-          let idx = val.indexOf("=");
-          if (idx >= 0)
-            environment[val.slice(0, idx)] = val.slice(idx + 1);
-        }
-
-        opts.environment = environment;
-      }
-
-
-      let proc = await Subprocess.call(opts);
-
-      Object.defineProperty(result, "pid", {
-        value: proc.pid,
-        enumerable: true,
-        configurable: true,
-      });
-
-
-      let promises = [];
-
-      // Set up IO handlers.
-
-      let read = pipe => pipe.readString();
-      if (options.charset === null) {
-        read = pipe => {
-          return pipe.read().then(buffer => {
-            return String.fromCharCode(...buffer);
-          });
-        };
-      }
-
-      if (options.stdout)
-        promises.push(readAllData(proc.stdout, read, options.stdout));
-
-      if (options.stderr && proc.stderr)
-        promises.push(readAllData(proc.stderr, read, options.stderr));
-
-      // Process stdin
-
-      if (typeof options.stdin === "string") {
-        write(proc.stdin, options.stdin);
-        proc.stdin.close();
-      }
-
-
-      // Handle process completion
-
-      if (options.done)
-        Promise.all(promises)
-          .then(() => proc.wait())
-          .then(options.done);
-
-      return proc;
-    })();
-
-    procPromise.catch(e => {
-      if (options.done)
-        options.done({exitCode: -1}, e);
-      else
-        Cu.reportError(e instanceof Error ? e : e.message || e);
-    });
-
-    if (typeof options.stdin === "function") {
-      // Unfortunately, some callers (child_process.js) depend on this
-      // being called synchronously.
-      options.stdin({
-        write(val) {
-          procPromise.then(proc => {
-            write(proc.stdin, val);
-          });
-        },
-
-        close() {
-          procPromise.then(proc => {
-            proc.stdin.close();
-          });
-        },
-      });
-    }
-
-    result = {
-      get pid() {
-        return awaitPromise(procPromise.then(proc => {
-          return proc.pid;
-        }));
-      },
-
-      wait() {
-        return awaitPromise(procPromise.then(proc => {
-          return proc.wait().then(({exitCode}) => exitCode);
-        }));
-      },
-
-      kill(hard = false) {
-        procPromise.then(proc => {
-          proc.kill(hard ? 0 : undefined);
-        });
-      },
-    };
-
-    return result;
-  },
-};
-
-module.exports = subprocess;