From 6ee53df10447f263f7465a4bf108758c990d153d Mon Sep 17 00:00:00 2001 From: ehmicky Date: Thu, 30 May 2019 10:00:00 +0200 Subject: [PATCH] Child process errors should reject the promise right away --- index.js | 36 ++++++++++++------------------------ test.js | 6 ++++++ 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/index.js b/index.js index 0bdf14833c..362cd23cac 100644 --- a/index.js +++ b/index.js @@ -258,23 +258,12 @@ 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}); @@ -282,13 +271,13 @@ const execa = (file, args, options) => { spawned.on('error', error => { cleanup(); - resolve({error}); + reject(error); }); if (spawned.stdin) { spawned.stdin.on('error', error => { cleanup(); - resolve({error}); + reject(error); }); } }); @@ -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); diff --git a/test.js b/test.js index fb0cd8aecf..8938a35a16 100644 --- a/test.js +++ b/test.js @@ -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');