aboutsummaryrefslogtreecommitdiff
path: root/node_modules/spawn-wrap/index.js
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-05-28 00:38:50 +0200
committerFlorian Dold <florian.dold@gmail.com>2017-05-28 00:40:43 +0200
commit7fff4499fd915bcea3fa93b1aa8b35f4fe7a6027 (patch)
tree6de9a1aebd150a23b7f8c273ec657a5d0a18fe3e /node_modules/spawn-wrap/index.js
parent963b7a41feb29cc4be090a2446bdfe0c1f1bcd81 (diff)
add linting (and some initial fixes)
Diffstat (limited to 'node_modules/spawn-wrap/index.js')
-rw-r--r--node_modules/spawn-wrap/index.js326
1 files changed, 326 insertions, 0 deletions
diff --git a/node_modules/spawn-wrap/index.js b/node_modules/spawn-wrap/index.js
new file mode 100644
index 000000000..a25cedb10
--- /dev/null
+++ b/node_modules/spawn-wrap/index.js
@@ -0,0 +1,326 @@
+module.exports = wrap
+wrap.runMain = runMain
+
+var Module = require('module')
+var fs = require('fs')
+var cp = require('child_process')
+var ChildProcess = cp.ChildProcess
+var assert = require('assert')
+var crypto = require('crypto')
+var mkdirp = require('mkdirp')
+var rimraf = require('rimraf')
+var path = require('path')
+var signalExit = require('signal-exit')
+var homedir = require('os-homedir')() + '/.node-spawn-wrap-'
+var winRebase = require('./lib/win-rebase')
+var which = require('which')
+
+var cmdname = path.basename(process.execPath, '.exe')
+
+var shim = '#!' + process.execPath + '\n' +
+ fs.readFileSync(__dirname + '/shim.js')
+
+var isWindows = require('./lib/is-windows')()
+
+var pathRe = /^PATH=/
+if (isWindows) pathRe = /^PATH=/i
+
+var colon = isWindows ? ';' : ':'
+
+function wrap (argv, env, workingDir) {
+ if (!ChildProcess) {
+ var child = cp.spawn(process.execPath, [])
+ ChildProcess = child.constructor
+ child.kill('SIGKILL')
+ }
+
+ // spawn_sync available since Node v0.11
+ var spawnSyncBinding, spawnSync
+ try {
+ spawnSyncBinding = process.binding('spawn_sync')
+ } catch (e) {}
+
+ // if we're passed in the working dir, then it means that setup
+ // was already done, so no need.
+ var doSetup = !workingDir
+ if (doSetup) {
+ workingDir = setup(argv, env)
+ }
+ var spawn = ChildProcess.prototype.spawn
+ if (spawnSyncBinding) {
+ spawnSync = spawnSyncBinding.spawn
+ }
+
+ function unwrap () {
+ if (doSetup) {
+ rimraf.sync(workingDir)
+ }
+ ChildProcess.prototype.spawn = spawn
+ if (spawnSyncBinding) {
+ spawnSync = spawnSyncBinding.spawn
+ }
+ }
+
+ if (spawnSyncBinding) {
+ spawnSyncBinding.spawn = wrappedSpawnFunction(spawnSync, workingDir)
+ }
+ ChildProcess.prototype.spawn = wrappedSpawnFunction(spawn, workingDir)
+
+ return unwrap
+}
+
+function wrappedSpawnFunction (fn, workingDir) {
+ return wrappedSpawn
+
+ function wrappedSpawn (options) {
+ var pathEnv
+ var cmdi, c, re, match, exe
+
+ // handle case where node/iojs is exec'd
+ // this doesn't handle EVERYTHING, but just the most common
+ // case of doing `exec(process.execPath + ' file.js')
+ var file = path.basename(options.file, '.exe')
+ if (file === 'dash' ||
+ file === 'sh' ||
+ file === 'bash' ||
+ file === 'zsh') {
+ cmdi = options.args.indexOf('-c')
+ if (cmdi !== -1) {
+ c = options.args[cmdi + 1]
+ re = /^\s*((?:[^\= ]*\=[^\=\s]*\s*)*)([^\s]+|"[^"]+"|'[^']+')/
+ match = c.match(re)
+ if (match) {
+ exe = path.basename(match[2])
+ // Strip a trailing quote from the basename if it matches a
+ // leading quote.
+ var quote = match[2].charAt(0)
+ if ((quote === '"' || quote === '\'') && quote === exe.slice(-1)) {
+ exe = exe.slice(0, -1)
+ }
+
+ if (exe === 'iojs' ||
+ exe === 'node' ||
+ exe === cmdname) {
+ c = c.replace(re, '$1 ' + workingDir + '/node')
+ options.args[cmdi + 1] = c
+ } else if (exe === 'npm' && !isWindows) {
+ var npmPath = whichOrUndefined('npm')
+
+ if (npmPath) {
+ c = c.replace(re, '$1 ' + workingDir + '/node ' + npmPath)
+ options.args[cmdi + 1] = c
+ }
+ }
+ }
+ }
+ } else if (isWindows && (
+ file === path.basename(process.env.comspec || '') ||
+ file === 'cmd'
+ )) {
+ cmdi = options.args.indexOf('/c')
+ if (cmdi !== -1) {
+ options.args[cmdi + 1] = winRebase(options.args[cmdi + 1],
+ workingDir + '/node.cmd',
+ whichOrUndefined)
+ }
+ } else if (file === 'node' || file === 'iojs' || cmdname === file) {
+ // make sure it has a main script.
+ // otherwise, just let it through.
+ var a = 0
+ var hasMain = false
+ for (var a = 1; !hasMain && a < options.args.length; a++) {
+ switch (options.args[a]) {
+ case '-i':
+ case '--interactive':
+ case '--eval':
+ case '-e':
+ case '-pe':
+ hasMain = false
+ a = options.args.length
+ continue
+
+ case '-r':
+ case '--require':
+ a += 1
+ continue
+
+ default:
+ if (options.args[a].match(/^-/)) {
+ continue
+ } else {
+ hasMain = true
+ a = options.args.length
+ break
+ }
+ }
+ }
+
+ if (hasMain) {
+ options.file = workingDir + '/' + file
+ options.args[0] = workingDir + '/' + file
+ }
+
+ } else {
+ try {
+ var resolved = which.sync(options.file)
+ } catch (er) {}
+ if (resolved) {
+ var shebang = fs.readFileSync(resolved, 'utf8')
+ var match = shebang.match(/^#!([^\r\n]+)/)
+ if (match) {
+ var shebangbin = match[1].split(' ')[0]
+ var maybeNode = path.basename(shebangbin)
+ if (maybeNode === 'node' || maybeNode === 'iojs' || cmdname === maybeNode) {
+ file = options.file = shebangbin
+ options.args = [shebangbin, workingDir + '/' + maybeNode]
+ .concat(resolved)
+ .concat(match[1].split(' ').slice(1))
+ .concat(options.args.slice(1))
+ }
+ }
+ }
+ }
+
+ for (var i = 0; i < options.envPairs.length; i++) {
+ var ep = options.envPairs[i]
+ if (ep.match(pathRe)) {
+ pathEnv = ep.substr(5)
+ var k = ep.substr(0, 5)
+ options.envPairs[i] = k + workingDir + colon + pathEnv
+ }
+ }
+ if (!pathEnv) {
+ options.envPairs.push((isWindows ? 'Path=' : 'PATH=') + workingDir)
+ }
+
+ if (file === 'npm' && !isWindows) {
+ var npmPath = whichOrUndefined('npm')
+
+ if (npmPath) {
+ options.args[0] = npmPath
+
+ options.file = workingDir + '/node'
+ options.args.unshift(workingDir + '/node')
+ }
+ }
+
+ if (isWindows) fixWindowsBins(workingDir, options)
+
+ return fn.call(this, options)
+ }
+}
+
+function whichOrUndefined (executable) {
+ var path
+ try {
+ path = which.sync(executable)
+ } catch (er) {}
+ return path
+}
+
+// by default Windows will reference the full
+// path to the node.exe or iojs.exe as the bin,
+// we should instead point spawn() at our .cmd shim.
+function fixWindowsBins (workingDir, options) {
+ var re = /.*\b(node|iojs)(\.exe)?$/
+ if (options.file.match(re)) {
+ options.file = process.execPath
+ var shim = workingDir + '/node'
+ options.args.splice(0, 1, options.file, workingDir + '/node')
+ }
+}
+
+function setup (argv, env) {
+ if (argv && typeof argv === 'object' && !env && !Array.isArray(argv)) {
+ env = argv
+ argv = []
+ }
+
+ if (!argv && !env) {
+ throw new Error('at least one of "argv" and "env" required')
+ }
+
+ if (argv) {
+ assert(Array.isArray(argv), 'argv must be array')
+ } else {
+ argv = []
+ }
+
+ if (env) {
+ assert(typeof env === 'object', 'env must be an object')
+ } else {
+ env = {}
+ }
+
+ // For stuff like --use_strict or --harmony, we need to inject
+ // the argument *before* the wrap-main.
+ var execArgv = []
+ for (var i = 0; i < argv.length; i++) {
+ if (argv[i].match(/^-/)) {
+ execArgv.push(argv[i])
+ if (argv[i] === '-r' || argv[i] === '--require') {
+ execArgv.push(argv[++i])
+ }
+ } else {
+ break
+ }
+ }
+ if (execArgv.length) {
+ if (execArgv.length === argv.length) {
+ argv.length = 0
+ } else {
+ argv = argv.slice(execArgv.length)
+ }
+ }
+
+ var settings = JSON.stringify({
+ module: __filename,
+ deps: {
+ foregroundChild: require.resolve('foreground-child'),
+ signalExit: require.resolve('signal-exit'),
+ },
+ argv: argv,
+ execArgv: execArgv,
+ env: env,
+ root: process.pid
+ }, null, 2) + '\n'
+
+ var workingDir = homedir + process.pid + '-' +
+ crypto.randomBytes(6).toString('hex')
+
+ signalExit(function () {
+ rimraf.sync(workingDir)
+ })
+
+ mkdirp.sync(workingDir)
+ workingDir = fs.realpathSync(workingDir)
+ if (isWindows) {
+ var cmdShim =
+ '@echo off\r\n' +
+ 'SETLOCAL\r\n' +
+ 'SET PATHEXT=%PATHEXT:;.JS;=;%\r\n' +
+ '"' + process.execPath + '"' + ' "%~dp0\\.\\node" %*\r\n'
+
+ fs.writeFileSync(workingDir + '/node.cmd', cmdShim)
+ fs.chmodSync(workingDir + '/node.cmd', '0755')
+ fs.writeFileSync(workingDir + '/iojs.cmd', cmdShim)
+ fs.chmodSync(workingDir + '/iojs.cmd', '0755')
+ }
+ fs.writeFileSync(workingDir + '/node', shim)
+ fs.chmodSync(workingDir + '/node', '0755')
+ fs.writeFileSync(workingDir + '/iojs', shim)
+ fs.chmodSync(workingDir + '/iojs', '0755')
+ if (cmdname !== 'iojs' && cmdname !== 'node') {
+ fs.writeFileSync(workingDir + '/' + cmdname, shim)
+ fs.chmodSync(workingDir + '/' + cmdname, '0755')
+ }
+ fs.writeFileSync(workingDir + '/settings.json', settings)
+
+ return workingDir
+}
+
+function runMain () {
+ process.argv.splice(1, 1)
+ process.argv[1] = path.resolve(process.argv[1])
+ Module.runMain()
+}