|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- # spawn-wrap
-
- Wrap all spawned Node.js child processes by adding environs and
- arguments ahead of the main JavaScript file argument.
-
- Any child processes launched by that child process will also be
- wrapped in a similar fashion.
-
- This is a bit of a brutal hack, designed primarily to support code
- coverage reporting in cases where tests or the system under test are
- loaded via child processes rather than via `require()`.
-
- It can also be handy if you want to run your own mock executable
- instead of some other thing when child procs call into it.
-
- [![Build Status](https://travis-ci.org/istanbuljs/spawn-wrap.svg)](https://travis-ci.org/istanbuljs/spawn-wrap)
-
- ## USAGE
-
- ```javascript
- var wrap = require('spawn-wrap')
-
- // wrap(wrapperArgs, environs)
- var unwrap = wrap(['/path/to/my/main.js', 'foo=bar'], { FOO: 1 })
-
- // later to undo the wrapping, you can call the returned function
- unwrap()
- ```
-
- In this example, the `/path/to/my/main.js` file will be used as the
- "main" module, whenever any Node or io.js child process is started,
- whether via a call to `spawn` or `exec`, whether node is invoked
- directly as the command or as the result of a shebang `#!` lookup.
-
- In `/path/to/my/main.js`, you can do whatever instrumentation or
- environment manipulation you like. When you're done, and ready to run
- the "real" main.js file (ie, the one that was spawned in the first
- place), you can do this:
-
- ```javascript
- // /path/to/my/main.js
- // process.argv[1] === 'foo=bar'
- // and process.env.FOO === '1'
-
- // my wrapping manipulations
- setupInstrumentationOrCoverageOrWhatever()
- process.on('exit', function (code) {
- storeCoverageInfoSynchronously()
- })
-
- // now run the instrumented and covered or whatever codes
- require('spawn-wrap').runMain()
- ```
-
- ## ENVIRONMENT VARIABLES
-
- Spawn-wrap responds to two environment variables, both of which are
- preserved through child processes.
-
- `SPAWN_WRAP_DEBUG=1` in the environment will make this module dump a
- lot of information to stderr.
-
- `SPAWN_WRAP_SHIM_ROOT` can be set to a path on the filesystem where
- the shim files are written in a `.node-spawn-wrap-<id>` folder. By
- default this is done in `$HOME`, but in some environments you may wish
- to point it at some other root. (For example, if `$HOME` is mounted
- as read-only in a virtual machine or container.)
-
- ## CONTRACTS and CAVEATS
-
- The initial wrap call uses synchronous I/O. Probably you should not
- be using this script in any production environments anyway.
-
- Also, this will slow down child process execution by a lot, since
- we're adding a few layers of indirection.
-
- The contract which this library aims to uphold is:
-
- * Wrapped processes behave identical to their unwrapped counterparts
- for all intents and purposes. That means that the wrapper script
- propagates all signals and exit codes.
- * If you send a signal to the wrapper, the child gets the signal.
- * If the child exits with a numeric status code, then the wrapper
- exits with that code.
- * If the child dies with a signal, then the wrapper dies with the
- same signal.
- * If you execute any Node child process, in any of the various ways
- that such a thing can be done, it will be wrapped.
- * Children of wrapped processes are also wrapped.
-
- (Much of this made possible by
- [foreground-child](http://npm.im/foreground-child).)
-
- There are a few ways situations in which this contract cannot be
- adhered to, despite best efforts:
-
- 1. In order to handle cases where `node` is invoked in a shell script,
- the `PATH` environment variable is modified such that the the shim
- will be run before the "real" node. However, since Windows does
- not allow executing shebang scripts like regular programs, a
- `node.cmd` file is required.
- 2. Signal propagation through `dash` doesn't always work. So, if you
- use `child_process.exec()` on systems where `/bin/sh` is actually
- `dash`, then the process may exit with a status code > 128 rather
- than indicating that it received a signal.
- 3. `cmd.exe` is even stranger with how it propagates and interprets
- unix signals. If you want your programs to be portable, then
- probably you wanna not rely on signals too much.
- 4. It *is* possible to escape the wrapping, if you spawn a bash
- script, and that script modifies the `PATH`, and then calls a
- specific `node` binary explicitly.
|