Skip to content

Commit

Permalink
Child process errors should reject the promise right away
Browse files Browse the repository at this point in the history
  • Loading branch information
ehmicky committed May 30, 2019
1 parent e5ed8de commit 6ee53df
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 24 deletions.
36 changes: 12 additions & 24 deletions index.js
Expand Up @@ -258,37 +258,26 @@ const execa = (file, args, options) => {
}, parsed.options.timeout);
}

const resolvable = (() => {
let extracted;
const promise = new Promise(resolve => {
extracted = resolve;
});
promise.resolve = extracted;
return promise;
})();

const processDone = new Promise(resolve => {
const processDone = new Promise((resolve, reject) => {
spawned.on('exit', (code, signal) => {
cleanup();

if (timedOut) {
resolvable.resolve([
{code, signal}, '', '', ''
]);
return reject(Object.assign(new Error('Timed out'), {code, signal}));
}

resolve({code, signal});
});

spawned.on('error', error => {
cleanup();
resolve({error});
reject(error);
});

if (spawned.stdin) {
spawned.stdin.on('error', error => {
cleanup();
resolve({error});
reject(error);
});
}
});
Expand All @@ -308,22 +297,21 @@ const execa = (file, args, options) => {
}

const handlePromise = () => {
let processComplete = Promise.all([
const processComplete = Promise.all([
processDone,
getStream(spawned, 'stdout', {encoding, buffer, maxBuffer}),
getStream(spawned, 'stderr', {encoding, buffer, maxBuffer}),
getStream(spawned, 'all', {encoding, buffer, maxBuffer: maxBuffer * 2})
]);

if (timeoutId) {
processComplete = Promise.race([
processComplete,
resolvable
]);
}

const finalize = async () => {
const results = await processComplete;
let results;
try {
results = await processComplete;
} catch (error) {
const {stream, code, signal} = error;
results = [{error, stream, code, signal}, '', '', ''];
}

const [result, stdout, stderr, all] = results;
result.stdout = handleOutput(parsed.options, stdout);
Expand Down
6 changes: 6 additions & 0 deletions test.js
Expand Up @@ -211,6 +211,12 @@ test('helpful error trying to provide an input stream in sync mode', t => {
);
});

test('child process errors rejects promise right away', async t => {
const child = execa('forever');
child.emit('error', new Error('test'));
await t.throwsAsync(child, /test/);
});

test('execa() returns a promise with kill() and pid', t => {
const {kill, pid} = execa('noop', ['foo']);
t.is(typeof kill, 'function');
Expand Down

0 comments on commit 6ee53df

Please sign in to comment.