Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: sindresorhus/execa
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v5.0.0
Choose a base ref
...
head repository: sindresorhus/execa
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v5.0.1
Choose a head ref
  • 9 commits
  • 9 files changed
  • 2 contributors

Commits on Jan 1, 2021

  1. Meta tweaks

    sindresorhus committed Jan 1, 2021
    Copy the full SHA
    4103ae9 View commit details

Commits on Jan 3, 2021

  1. Fix code coverage

    sindresorhus committed Jan 3, 2021
    Copy the full SHA
    02a8fe8 View commit details

Commits on Jan 24, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    fd3c7be View commit details

Commits on Feb 22, 2021

  1. Copy the full SHA
    2f61456 View commit details

Commits on May 30, 2021

  1. Fix linting errors (#462)

    ehmicky authored May 30, 2021
    Copy the full SHA
    8e4f901 View commit details
  2. Copy the full SHA
    edf28a6 View commit details
  3. Copy the full SHA
    427c5c2 View commit details
  4. Copy the full SHA
    0d939f3 View commit details
  5. 5.0.1

    sindresorhus committed May 30, 2021
    Copy the full SHA
    6bc7a1c View commit details
Showing with 38 additions and 29 deletions.
  1. +5 −5 .github/workflows/main.yml
  2. +1 −1 index.d.ts
  3. +6 −4 index.js
  4. +7 −4 lib/kill.js
  5. +1 −1 lib/stream.js
  6. +5 −1 package.json
  7. +2 −2 readme.md
  8. +1 −1 test/fixtures/detach
  9. +10 −10 test/kill.js
10 changes: 5 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -4,13 +4,13 @@ on:
- pull_request
jobs:
test:
name: Node.js ${{ matrix.node_version }} on ${{ matrix.os }}
name: Node.js ${{ matrix.node-version }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
node_version:
- 15
node-version:
- 16
- 14
- 12
- 10
@@ -22,10 +22,10 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node_version }}
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test
- uses: codecov/codecov-action@v1
if: matrix.os == 'ubuntu-latest' && matrix.node_version == 14
if: matrix.os == 'ubuntu-latest' && matrix.node-version == 14
with:
fail_ci_if_error: true
2 changes: 1 addition & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
@@ -497,7 +497,7 @@ declare const execa: {
If the file or an argument contains spaces, they must be escaped with backslashes. This matters especially if `command` is not a constant but a variable, for example with `__dirname` or `process.cwd()`. Except for spaces, no escaping/quoting is needed.
The `shell` option must be used if the `command` uses shell-specific features, as opposed to being a simple `file` followed by its `arguments`.
The `shell` option must be used if the `command` uses shell-specific features (for example, `&&` or `||`), as opposed to being a simple `file` followed by its `arguments`.
@param command - The program/script to execute and its arguments.
@returns A [`child_process` instance](https://nodejs.org/api/child_process.html#child_process_class_childprocess), which is enhanced to also be a `Promise` for a result `Object` with `stdout` and `stderr` properties.
10 changes: 6 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
@@ -7,10 +7,10 @@ const npmRunPath = require('npm-run-path');
const onetime = require('onetime');
const makeError = require('./lib/error');
const normalizeStdio = require('./lib/stdio');
const {spawnedKill, spawnedCancel, setupTimeout, setExitHandler} = require('./lib/kill');
const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = require('./lib/stream.js');
const {mergePromise, getSpawnedPromise} = require('./lib/promise.js');
const {joinCommand, parseCommand} = require('./lib/command.js');
const {spawnedKill, spawnedCancel, setupTimeout, validateTimeout, setExitHandler} = require('./lib/kill');
const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = require('./lib/stream');
const {mergePromise, getSpawnedPromise} = require('./lib/promise');
const {joinCommand, parseCommand} = require('./lib/command');

const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100;

@@ -75,6 +75,8 @@ const execa = (file, args, options) => {
const parsed = handleArguments(file, args, options);
const command = joinCommand(file, args);

validateTimeout(parsed.options);

let spawned;
try {
spawned = childProcess.spawn(parsed.file, parsed.args, parsed.options);
11 changes: 7 additions & 4 deletions lib/kill.js
Original file line number Diff line number Diff line change
@@ -71,10 +71,6 @@ const setupTimeout = (spawned, {timeout, killSignal = 'SIGTERM'}, spawnedPromise
return spawnedPromise;
}

if (!Number.isFinite(timeout) || timeout < 0) {
throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${timeout}\` (${typeof timeout})`);
}

let timeoutId;
const timeoutPromise = new Promise((resolve, reject) => {
timeoutId = setTimeout(() => {
@@ -89,6 +85,12 @@ const setupTimeout = (spawned, {timeout, killSignal = 'SIGTERM'}, spawnedPromise
return Promise.race([timeoutPromise, safeSpawnedPromise]);
};

const validateTimeout = ({timeout}) => {
if (timeout !== undefined && (!Number.isFinite(timeout) || timeout < 0)) {
throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${timeout}\` (${typeof timeout})`);
}
};

// `cleanup` option handling
const setExitHandler = async (spawned, {cleanup, detached}, timedPromise) => {
if (!cleanup || detached) {
@@ -108,5 +110,6 @@ module.exports = {
spawnedKill,
spawnedCancel,
setupTimeout,
validateTimeout,
setExitHandler
};
2 changes: 1 addition & 1 deletion lib/stream.js
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ const mergeStream = require('merge-stream');
// `input` option
const handleInput = (spawned, input) => {
// Checking for stdin is workaround for https://github.com/nodejs/node/issues/26852
// TODO: Remove `|| spawned.stdin === undefined` once we drop support for Node.js <=12.2.0
// @todo remove `|| spawned.stdin === undefined` once we drop support for Node.js <=12.2.0
if (input === undefined || spawned.stdin === undefined) {
return;
}
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "execa",
"version": "5.0.0",
"version": "5.0.1",
"description": "Process execution for humans",
"license": "MIT",
"repository": "sindresorhus/execa",
@@ -61,6 +61,10 @@
"xo": "^0.35.0"
},
"nyc": {
"reporter": [
"text",
"lcov"
],
"exclude": [
"**/fixtures/**",
"**/test.js",
4 changes: 2 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<img src="media/logo.svg" width="400">
<br>

[![Coverage Status](https://codecov.io/gh/sindresorhus/execa/branch/master/graph/badge.svg)](https://codecov.io/gh/sindresorhus/execa)
[![Coverage Status](https://codecov.io/gh/sindresorhus/execa/branch/main/graph/badge.svg)](https://codecov.io/gh/sindresorhus/execa)

> Process execution for humans
@@ -200,7 +200,7 @@ Same as [`execa()`](#execafile-arguments-options) except both file and arguments

If the file or an argument contains spaces, they must be escaped with backslashes. This matters especially if `command` is not a constant but a variable, for example with `__dirname` or `process.cwd()`. Except for spaces, no escaping/quoting is needed.

The [`shell` option](#shell) must be used if the `command` uses shell-specific features, as opposed to being a simple `file` followed by its `arguments`.
The [`shell` option](#shell) must be used if the `command` uses shell-specific features (for example, `&&` or `||`), as opposed to being a simple `file` followed by its `arguments`.

### execa.commandSync(command, options?)

2 changes: 1 addition & 1 deletion test/fixtures/detach
Original file line number Diff line number Diff line change
@@ -3,6 +3,6 @@

const execa = require('../..');

const subprocess = execa('node', ['./test/fixtures/noop'], {detached: true});
const subprocess = execa('node', ['./test/fixtures/forever'], {detached: true});
console.log(subprocess.pid);
process.exit();
20 changes: 10 additions & 10 deletions test/kill.js
Original file line number Diff line number Diff line change
@@ -138,7 +138,7 @@ test('spawnAndExit detached', spawnAndExit, false, true);
test('spawnAndExit cleanup detached', spawnAndExit, true, true);

// When parent process exits before child process
const spawnAndKill = async (t, signal, cleanup, detached, isKilled) => {
const spawnAndKill = async (t, [signal, cleanup, detached, isKilled]) => {
const subprocess = execa('sub-process', [cleanup, detached], {stdio: ['ignore', 'ignore', 'ignore', 'ipc']});

const pid = await pEvent(subprocess, 'message');
@@ -164,18 +164,18 @@ const spawnAndKill = async (t, signal, cleanup, detached, isKilled) => {
// With `options.cleanup`, subprocesses are always killed
// - `options.cleanup` with SIGKILL is a noop, since it cannot be handled
const exitIfWindows = process.platform === 'win32';
test('spawnAndKill SIGTERM', spawnAndKill, 'SIGTERM', false, false, exitIfWindows);
test('spawnAndKill SIGKILL', spawnAndKill, 'SIGKILL', false, false, exitIfWindows);
test('spawnAndKill cleanup SIGTERM', spawnAndKill, 'SIGTERM', true, false, true);
test('spawnAndKill cleanup SIGKILL', spawnAndKill, 'SIGKILL', true, false, exitIfWindows);
test('spawnAndKill detached SIGTERM', spawnAndKill, 'SIGTERM', false, true, false);
test('spawnAndKill detached SIGKILL', spawnAndKill, 'SIGKILL', false, true, false);
test('spawnAndKill cleanup detached SIGTERM', spawnAndKill, 'SIGTERM', true, true, false);
test('spawnAndKill cleanup detached SIGKILL', spawnAndKill, 'SIGKILL', true, true, false);
test('spawnAndKill SIGTERM', spawnAndKill, ['SIGTERM', false, false, exitIfWindows]);
test('spawnAndKill SIGKILL', spawnAndKill, ['SIGKILL', false, false, exitIfWindows]);
test('spawnAndKill cleanup SIGTERM', spawnAndKill, ['SIGTERM', true, false, true]);
test('spawnAndKill cleanup SIGKILL', spawnAndKill, ['SIGKILL', true, false, exitIfWindows]);
test('spawnAndKill detached SIGTERM', spawnAndKill, ['SIGTERM', false, true, false]);
test('spawnAndKill detached SIGKILL', spawnAndKill, ['SIGKILL', false, true, false]);
test('spawnAndKill cleanup detached SIGTERM', spawnAndKill, ['SIGTERM', true, true, false]);
test('spawnAndKill cleanup detached SIGKILL', spawnAndKill, ['SIGKILL', true, true, false]);

// See #128
test('removes exit handler on exit', async t => {
// FIXME: This relies on `signal-exit` internals
// @todo this relies on `signal-exit` internals
const emitter = process.__signal_exit_emitter__;

const subprocess = execa('noop');