85 lines
3.7 KiB
JavaScript
85 lines
3.7 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
const {isCmd, isNode, isNpm, isSh, getExeBasename} = require("./exe-type")
|
||
|
const mungeCmd = require("./mungers/cmd")
|
||
|
const mungeEnv = require("./mungers/env")
|
||
|
const mungeNode = require("./mungers/node")
|
||
|
const mungeNpm = require("./mungers/npm")
|
||
|
const mungeSh = require("./mungers/sh")
|
||
|
const mungeShebang = require("./mungers/shebang")
|
||
|
|
||
|
/**
|
||
|
* @typedef {object} InternalSpawnOptions Options for the internal spawn functions
|
||
|
* `childProcess.ChildProcess.prototype.spawn` and `process.binding('spawn_sync').spawn`.
|
||
|
* These are the options mapped by the `munge` function to intercept spawned processes and
|
||
|
* handle the wrapping logic.
|
||
|
*
|
||
|
* @property {string} file File to execute: either an absolute system-dependent path or a
|
||
|
* command name.
|
||
|
* @property {string[]} args Command line arguments passed to the spawn process, including argv0.
|
||
|
* @property {string | undefined} cwd Optional path to the current working directory passed to the
|
||
|
* spawned process. Default: `process.cwd()`
|
||
|
* @property {boolean} windowsHide Boolean controlling if the process should be spawned as
|
||
|
* hidden (no GUI) on Windows.
|
||
|
* @property {boolean} windowsVerbatimArguments Boolean controlling if Node should preprocess
|
||
|
* the CLI arguments on Windows.
|
||
|
* @property {boolean} detached Boolean controlling if the child process should keep its parent
|
||
|
* alive or not.
|
||
|
* @property {string[]} envPairs Array of serialized environment variable key/value pairs. The
|
||
|
* variables serialized as `key + "=" + value`.
|
||
|
* @property {import("child_process").StdioOptions} stdio Stdio options, with the same semantics
|
||
|
* as the `stdio` parameter from the public API.
|
||
|
* @property {number | undefined} uid User id for the spawn process, same as the `uid` parameter
|
||
|
* from the public API.
|
||
|
* @property {number | undefined} gid Group id for the spawn process, same as the `gid` parameter
|
||
|
* from the public API.
|
||
|
*
|
||
|
* @property {string | undefined} originalNode Custom property only used by `spawn-wrap`. It is
|
||
|
* used to remember the original Node executable that was intended to be spawned by the user.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Returns updated internal spawn options to redirect the process through the shim and wrapper.
|
||
|
*
|
||
|
* This works on the options passed to `childProcess.ChildProcess.prototype.spawn` and
|
||
|
* `process.binding('spawn_sync').spawn`.
|
||
|
*
|
||
|
* This function works by trying to identify the spawn process and map the options accordingly.
|
||
|
* `spawn-wrap` recognizes most shells, Windows `cmd.exe`, Node and npm invocations; when spawn
|
||
|
* either directly or through a script with a shebang line.
|
||
|
* It also unconditionally updates the environment variables so bare `node` commands execute
|
||
|
* the shim script instead of Node's binary.
|
||
|
*
|
||
|
* @param workingDir {string} Absolute system-dependent path to the directory containing the shim files.
|
||
|
* @param options {InternalSpawnOptions} Original internal spawn options.
|
||
|
* @return {InternalSpawnOptions} Updated internal spawn options.
|
||
|
*/
|
||
|
function munge(workingDir, options) {
|
||
|
const basename = getExeBasename(options.file);
|
||
|
|
||
|
// XXX: dry this
|
||
|
if (isSh(basename)) {
|
||
|
options = mungeSh(workingDir, options)
|
||
|
} else if (isCmd(basename)) {
|
||
|
options = mungeCmd(workingDir, options)
|
||
|
} else if (isNode(basename)) {
|
||
|
options = mungeNode(workingDir, options)
|
||
|
} else if (isNpm(basename)) {
|
||
|
// XXX unnecessary? on non-windows, npm is just another shebang
|
||
|
options = mungeNpm(workingDir, options)
|
||
|
} else {
|
||
|
options = mungeShebang(workingDir, options)
|
||
|
}
|
||
|
|
||
|
// now the options are munged into shape.
|
||
|
// whether we changed something or not, we still update the PATH
|
||
|
// so that if a script somewhere calls `node foo`, it gets our
|
||
|
// wrapper instead.
|
||
|
|
||
|
options = mungeEnv(workingDir, options)
|
||
|
|
||
|
return options
|
||
|
}
|
||
|
|
||
|
module.exports = munge
|