Current Dev State

This commit is contained in:
Tim Lorsbach
2025-06-23 20:13:54 +02:00
parent b4f9bb277d
commit ded50edaa2
22617 changed files with 4345095 additions and 174 deletions

View File

@ -0,0 +1,22 @@
Copyright (c) 2014 Tyler Kellen
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,58 @@
# flagged-respawn [![Build Status](https://secure.travis-ci.org/js-cli/js-flagged-respawn.svg)](http://travis-ci.org/js-cli/js-flagged-respawn)
> A tool for respawning node binaries when special flags are present.
[![NPM](https://nodei.co/npm/flagged-respawn.png)](https://nodei.co/npm/flagged-respawn/)
## What is it?
Say you wrote a command line tool that runs arbitrary javascript (e.g. task runner, test framework, etc). For the sake of discussion, let's pretend it's a testing harness you've named `testify`.
Everything is going splendidly until one day you decide to test some code that relies on a feature behind a v8 flag in node (`--harmony`, for example). Without much thought, you run `testify --harmony spec tests.js`.
It doesn't work. After digging around for a bit, you realize this produces a [`process.argv`](http://nodejs.org/docs/latest/api/process.html#process_process_argv) of:
`['node', '/usr/local/bin/test', '--harmony', 'spec', 'tests.js']`
Crap. The `--harmony` flag is in the wrong place! It should be applied to the **node** command, not our binary. What we actually wanted was this:
`['node', '--harmony', '/usr/local/bin/test', 'spec', 'tests.js']`
Flagged-respawn fixes this problem and handles all the edge cases respawning creates, such as:
- Providing a method to determine if a respawn is needed.
- Piping stderr/stdout from the child into the parent.
- Making the parent process exit with the same code as the child.
- If the child is killed, making the parent exit with the same signal.
To see it in action, clone this repository and run `npm install` / `npm run respawn` / `npm run nospawn`.
## Sample Usage
```js
#!/usr/bin/env node
const flaggedRespawn = require('flagged-respawn');
// get a list of all possible v8 flags for the running version of node
const v8flags = require('v8flags').fetch();
flaggedRespawn(v8flags, process.argv, function (ready, child) {
if (ready) {
console.log('Running!');
// your cli code here
} else {
console.log('Special flags found, respawning.');
}
if (process.pid !== child.pid) {
console.log('Respawned to PID:', child.pid);
}
});
```
## Release History
* 2016-03-22 - v0.3.2 - fix issue with v8 flags values being dropped
* 2014-09-12 - v0.3.1 - use `{ stdio: 'inherit' }` for spawn to maintain colors
* 2014-09-11 - v0.3.0 - for real this time
* 2014-09-11 - v0.2.0 - cleanup
* 2014-09-04 - v0.1.1 - initial release

View File

@ -0,0 +1,18 @@
const reorder = require('./lib/reorder');
const respawn = require('./lib/respawn');
module.exports = function (flags, argv, execute) {
if (!flags) {
throw new Error('You must specify flags to respawn with.');
}
if (!argv) {
throw new Error('You must specify an argv array.');
}
var proc = process;
var reordered = reorder(flags, argv);
var ready = JSON.stringify(argv) === JSON.stringify(reordered);
if (!ready) {
proc = respawn(reordered);
}
execute(ready, proc);
};

View File

@ -0,0 +1,16 @@
module.exports = function (flags, argv) {
if (!argv) {
argv = process.argv;
}
var args = [argv[1]];
argv.slice(2).forEach(function (arg) {
var flag = arg.split('=')[0];
if (flags.indexOf(flag) !== -1) {
args.unshift(arg);
} else {
args.push(arg);
}
});
args.unshift(argv[0]);
return args;
};

View File

@ -0,0 +1,15 @@
const spawn = require('child_process').spawn;
module.exports = function (argv) {
var child = spawn(argv[0], argv.slice(1), { stdio: 'inherit' });
child.on('exit', function (code, signal) {
process.on('exit', function () {
if (signal) {
process.kill(process.pid, signal);
} else {
process.exit(code);
}
});
});
return child;
};

View File

@ -0,0 +1,65 @@
{
"_from": "flagged-respawn@^0.3.2",
"_id": "flagged-respawn@0.3.2",
"_inBundle": false,
"_integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=",
"_location": "/flagged-respawn",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "flagged-respawn@^0.3.2",
"name": "flagged-respawn",
"escapedName": "flagged-respawn",
"rawSpec": "^0.3.2",
"saveSpec": null,
"fetchSpec": "^0.3.2"
},
"_requiredBy": [
"/liftoff"
],
"_resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz",
"_shasum": "ff191eddcd7088a675b2610fffc976be9b8074b5",
"_spec": "flagged-respawn@^0.3.2",
"_where": "/home/manfred/enviPath/ketcher2/ketcher/node_modules/liftoff",
"author": {
"name": "Tyler Kellen",
"url": "http://goingslowly.com/"
},
"bugs": {
"url": "https://github.com/js-cli/js-flagged-respawn/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "A tool for respawning node binaries when special flags are present.",
"devDependencies": {
"chai": "~1.9.1",
"mocha": "~1.21.4",
"v8flags": "~1.0.1"
},
"engines": {
"node": ">= 0.8.0"
},
"homepage": "https://github.com/js-cli/js-flagged-respawn",
"keywords": [
"respawn flags"
],
"licenses": [
{
"type": "MIT",
"url": "https://github.com/js-cli/js-flagged-respawn/blob/master/LICENSE"
}
],
"main": "index.js",
"name": "flagged-respawn",
"repository": {
"type": "git",
"url": "git://github.com/js-cli/js-flagged-respawn.git"
},
"scripts": {
"nospawn": "node test/bin/respawner test",
"respawn": "node test/bin/respawner --harmony test",
"test": "mocha -R spec test"
},
"version": "0.3.2"
}

View File

@ -0,0 +1,13 @@
#!/usr/bin/env node
const flaggedRespawn = require('../../');
flaggedRespawn(['--harmony'], process.argv, function (ready) {
if (ready) {
setTimeout(function () {
process.exit(100);
}, 100);
}
});

View File

@ -0,0 +1,17 @@
#!/usr/bin/env node
const flaggedRespawn = require('../../');
// get a list of all possible v8 flags for the running version of node
const v8flags = require('v8flags').fetch();
flaggedRespawn(v8flags, process.argv, function (ready, child) {
if (ready) {
console.log('Running!');
} else {
console.log('Special flags found, respawning.');
}
if (child.pid !== process.pid) {
console.log('Respawned to PID:', child.pid);
}
});

View File

@ -0,0 +1,16 @@
#!/usr/bin/env node
const flaggedRespawn = require('../../');
flaggedRespawn(['--harmony'], process.argv, function (ready, child) {
if (ready) {
setTimeout(function() {
process.exit();
}, 100);
} else {
console.log('got child!');
child.kill('SIGHUP');
}
});

View File

@ -0,0 +1,99 @@
const expect = require('chai').expect;
const exec = require('child_process').exec;
const reorder = require('../lib/reorder');
const flaggedRespawn = require('../');
describe('flaggedRespawn', function () {
var flags = ['--harmony', '--use_strict', '--stack_size']
describe('reorder', function () {
it('should re-order args, placing special flags first', function () {
var needsRespawn = ['node', 'file.js', '--flag', '--harmony', 'command'];
var noRespawnNeeded = ['node', 'bin/flagged-respawn', 'thing'];
expect(reorder(flags, needsRespawn))
.to.deep.equal(['node', '--harmony', 'file.js', '--flag', 'command']);
expect(reorder(flags, noRespawnNeeded))
.to.deep.equal(noRespawnNeeded);
});
it('should keep flags values when not placed first', function () {
var args = ['node', 'file.js', '--stack_size=2048'];
var expected = ['node', '--stack_size=2048', 'file.js'];
expect(reorder(flags, args)).to.deep.equal(expected);
});
it('should ignore special flags when they are in the correct position', function () {
var args = ['node', '--harmony', 'file.js', '--flag'];
expect(reorder(flags, reorder(flags, args))).to.deep.equal(args);
});
});
describe('execute', function () {
it('should throw if no flags are specified', function () {
expect(function () { flaggedRespawn.execute(); }).to.throw;
});
it('should throw if no argv is specified', function () {
expect(function () { flaggedRespawn.execute(flags); }).to.throw;
});
it('should respawn and pipe stderr/stdout to parent', function (done) {
exec('node ./test/bin/respawner.js --harmony', function (err, stdout, stderr) {
expect(stdout.replace(/[0-9]/g, '')).to.equal('Special flags found, respawning.\nRespawned to PID: \nRunning!\n');
done();
});
});
it('should respawn and pass exit code from child to parent', function (done) {
exec('node ./test/bin/exit_code.js --harmony', function (err, stdout, stderr) {
expect(err.code).to.equal(100);
done();
});
});
it.skip('should respawn; if child is killed, parent should exit with same signal', function (done) {
// TODO: figure out why travis hates this
exec('node ./test/bin/signal.js --harmony', function (err, stdout, stderr) {
console.log('err', err);
console.log('stdout', stdout);
console.log('stderr', stderr);
expect(err.signal).to.equal('SIGHUP');
done();
});
});
it('should call back with ready as true when respawn is not needed', function () {
var argv = ['node', './test/bin/respawner'];
flaggedRespawn(flags, argv, function (ready) {
expect(ready).to.be.true;
});
});
it('should call back with ready as false when respawn is needed', function () {
var argv = ['node', './test/bin/respawner', '--harmony'];
flaggedRespawn(flags, argv, function (ready) {
expect(ready).to.be.false;
});
});
it('should call back with the child process when ready', function () {
var argv = ['node', './test/bin/respawner', '--harmony'];
flaggedRespawn(flags, argv, function (ready, child) {
expect(child.pid).to.not.equal(process.pid);
});
});
it('should call back with own process when respawn not needed', function () {
var argv = ['node', './test/bin/respawner'];
flaggedRespawn(flags, argv, function (ready, child) {
expect(child.pid).to.equal(process.pid);
});
});
});
});