'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') } var util var doDebug = process.env.SPAWN_WRAP_DEBUG === '1' var fs function debug () { if (!doDebug) return if (!fs) { fs = require('fs') util = require('util') } var message = util.format.apply(util, arguments).trim() var pref = 'SW ' + process.pid + ': ' message = pref + message.split('\n').join('\n' + pref) fs.writeSync(2, message + '\n') } debug('shim', [process.argv[0]].concat(process.execArgv, process.argv.slice(1))) var Module = require('module') var assert = require('assert') var path = require('path') var settings = require('./settings.json') var foregroundChild = require(settings.deps.foregroundChild) var argv = settings.argv var nargs = argv.length var env = settings.env var key = settings.key var node = process.env['SW_ORIG_' + key] || process.execPath for (var k in env) { process.env[k] = env[k] } var 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 var hasMain = false for (var 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: if (process.argv[a].match(/^-/)) { 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. var addExecArgv = process.argv.splice(2, hasMain - 2) needExecArgv.push.apply(needExecArgv, addExecArgv) } if (!hasMain) { // we got loaded by mistake for a `node -pe script` or something. var 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) { var pexec = process.execArgv if (JSON.stringify(pexec) !== JSON.stringify(needExecArgv)) { debug('need execArgv for this', pexec, '=>', needExecArgv) var spawn = require('child_process').spawn var 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. var spliceArgs = [1, 1].concat(argv) process.argv.splice.apply(process.argv, spliceArgs) // Unwrap the PATH environment var so that we're not mucking // with the environment. It'll get re-added if they spawn anything var isWindows = ( process.platform === 'win32' || process.env.OSTYPE === 'cygwin' || process.env.OSTYPE === 'msys' ) if (isWindows) { for (var i in process.env) { if (i.match(/^path$/i)) { process.env[i] = process.env[i].replace(__dirname + ';', '') } } } else { process.env.PATH = process.env.PATH.replace(__dirname + ':', '') } var 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 })()