1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
'use strict'
// This module should *only* be loaded as a main script
// by child processes wrapped by spawn-wrap. It sets up
// argv to include the injected argv (including the user's
// wrapper script) and any environment variables specified.
//
// If any argv were passed in (ie, if it's used to force
// a wrapper script, and not just ensure that an env is kept
// around through all the child procs), then we also set up
// a require('spawn-wrap').runMain() function that will strip
// off the injected arguments and run the main file.
// wrap in iife for babylon to handle module-level return
;(function () {
if (module !== require.main) {
throw new Error('spawn-wrap: cli wrapper invoked as non-main script')
}
const Module = require('module')
const path = require('path')
const settings = require('./settings.json')
const {debug} = require(settings.deps.debug)
debug('shim', [process.argv[0]].concat(process.execArgv, process.argv.slice(1)))
const foregroundChild = require(settings.deps.foregroundChild)
const IS_WINDOWS = settings.isWindows
const argv = settings.argv
const nargs = argv.length
const env = settings.env
const key = settings.key
const node = process.env['SW_ORIG_' + key] || process.execPath
Object.assign(process.env, env)
const needExecArgv = settings.execArgv || []
// If the user added their OWN wrapper pre-load script, then
// this will pop that off of the argv, and load the "real" main
function runMain () {
debug('runMain pre', process.argv)
process.argv.splice(1, nargs)
process.argv[1] = path.resolve(process.argv[1])
delete require.cache[process.argv[1]]
debug('runMain post', process.argv)
Module.runMain()
debug('runMain after')
}
// Argv coming in looks like:
// bin shim execArgv main argv
//
// Turn it into:
// bin settings.execArgv execArgv settings.argv main argv
//
// If we don't have a main script, then just run with the necessary
// execArgv
let hasMain = false
for (let a = 2; !hasMain && a < process.argv.length; a++) {
switch (process.argv[a]) {
case '-i':
case '--interactive':
case '--eval':
case '-e':
case '-p':
case '-pe':
hasMain = false
a = process.argv.length
continue
case '-r':
case '--require':
a += 1
continue
default:
// TODO: Double-check what's going on
if (process.argv[a].startsWith('-')) {
continue
} else {
hasMain = a
a = process.argv.length
break
}
}
}
debug('after argv parse hasMain=%j', hasMain)
if (hasMain > 2) {
// if the main file is above #2, then it means that there
// was a --exec_arg *before* it. This means that we need
// to slice everything from 2 to hasMain, and pass that
// directly to node. This also splices out the user-supplied
// execArgv from the argv.
const addExecArgv = process.argv.splice(2, hasMain - 2)
needExecArgv.push(...addExecArgv)
}
if (!hasMain) {
// we got loaded by mistake for a `node -pe script` or something.
const args = process.execArgv.concat(needExecArgv, process.argv.slice(2))
debug('no main file!', args)
foregroundChild(node, args)
return
}
// If there are execArgv, and they're not the same as how this module
// was executed, then we need to inject those. This is for stuff like
// --harmony or --use_strict that needs to be *before* the main
// module.
if (needExecArgv.length) {
const pexec = process.execArgv
if (JSON.stringify(pexec) !== JSON.stringify(needExecArgv)) {
debug('need execArgv for this', pexec, '=>', needExecArgv)
const sargs = pexec.concat(needExecArgv).concat(process.argv.slice(1))
foregroundChild(node, sargs)
return
}
}
// At this point, we've verified that we got the correct execArgv,
// and that we have a main file, and that the main file is sitting at
// argv[2]. Splice this shim off the list so it looks like the main.
process.argv.splice(1, 1, ...argv)
// Unwrap the PATH environment var so that we're not mucking
// with the environment. It'll get re-added if they spawn anything
if (IS_WINDOWS) {
for (const i in process.env) {
if (/^path$/i.test(i)) {
process.env[i] = process.env[i].replace(__dirname + ';', '')
}
}
} else {
process.env.PATH = process.env.PATH.replace(__dirname + ':', '')
}
const spawnWrap = require(settings.module)
if (nargs) {
spawnWrap.runMain = function (original) {
return function () {
spawnWrap.runMain = original
runMain()
}
}(spawnWrap.runMain)
}
spawnWrap(argv, env, __dirname)
debug('shim runMain', process.argv)
delete require.cache[process.argv[1]]
Module.runMain()
// end iife wrapper for babylon
})()
|