mirror of
https://github.com/nodejs/node.git
synced 2024-12-01 16:10:02 +01:00
child_process: promisify includes stdio in error
This converts the initial implementation of a promised exec that used the customPromisifyArgs support in util.promisify with a custom implementation. This is because exec and execFile, when there is an error, still supply the stdout and stderr of the process, and yet the promisified version with customPromisifyArgs does not supply this ability. I created a custom implementation and attached it to exec and execFile using the util.promisify.custom key. Fixes: https://github.com/nodejs/node/issues/13364 PR-URL: https://github.com/nodejs/node/pull/13388 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
parent
55f9c85a05
commit
8d7f07f379
@ -215,7 +215,9 @@ child runs longer than `timeout` milliseconds.
|
||||
replace the existing process and uses a shell to execute the command.
|
||||
|
||||
If this method is invoked as its [`util.promisify()`][]ed version, it returns
|
||||
a Promise for an object with `stdout` and `stderr` properties.
|
||||
a Promise for an object with `stdout` and `stderr` properties. In case of an
|
||||
error, a rejected promise is returned, with the same `error` object given in the
|
||||
callback, but with an additional two properties `stdout` and `stderr`.
|
||||
|
||||
For example:
|
||||
|
||||
@ -281,7 +283,9 @@ stderr output. If `encoding` is `'buffer'`, or an unrecognized character
|
||||
encoding, `Buffer` objects will be passed to the callback instead.
|
||||
|
||||
If this method is invoked as its [`util.promisify()`][]ed version, it returns
|
||||
a Promise for an object with `stdout` and `stderr` properties.
|
||||
a Promise for an object with `stdout` and `stderr` properties. In case of an
|
||||
error, a rejected promise is returned, with the same `error` object given in the
|
||||
callback, but with an additional two properties `stdout` and `stderr`.
|
||||
|
||||
```js
|
||||
const util = require('util');
|
||||
|
@ -22,9 +22,9 @@
|
||||
'use strict';
|
||||
|
||||
const util = require('util');
|
||||
const {
|
||||
deprecate, convertToValidSignal, customPromisifyArgs
|
||||
} = require('internal/util');
|
||||
const { deprecate, convertToValidSignal } = require('internal/util');
|
||||
const { createPromise,
|
||||
promiseResolve, promiseReject } = process.binding('util');
|
||||
const debug = util.debuglog('child_process');
|
||||
|
||||
const uv = process.binding('uv');
|
||||
@ -140,9 +140,27 @@ exports.exec = function(command /*, options, callback*/) {
|
||||
opts.callback);
|
||||
};
|
||||
|
||||
Object.defineProperty(exports.exec, customPromisifyArgs,
|
||||
{ value: ['stdout', 'stderr'], enumerable: false });
|
||||
const customPromiseExecFunction = (orig) => {
|
||||
return (...args) => {
|
||||
const promise = createPromise();
|
||||
|
||||
orig(...args, (err, stdout, stderr) => {
|
||||
if (err !== null) {
|
||||
err.stdout = stdout;
|
||||
err.stderr = stderr;
|
||||
promiseReject(promise, err);
|
||||
} else {
|
||||
promiseResolve(promise, { stdout, stderr });
|
||||
}
|
||||
});
|
||||
return promise;
|
||||
};
|
||||
};
|
||||
|
||||
Object.defineProperty(exports.exec, util.promisify.custom, {
|
||||
enumerable: false,
|
||||
value: customPromiseExecFunction(exports.exec)
|
||||
});
|
||||
|
||||
exports.execFile = function(file /*, args, options, callback*/) {
|
||||
var args = [];
|
||||
@ -338,8 +356,10 @@ exports.execFile = function(file /*, args, options, callback*/) {
|
||||
return child;
|
||||
};
|
||||
|
||||
Object.defineProperty(exports.execFile, customPromisifyArgs,
|
||||
{ value: ['stdout', 'stderr'], enumerable: false });
|
||||
Object.defineProperty(exports.execFile, util.promisify.custom, {
|
||||
enumerable: false,
|
||||
value: customPromiseExecFunction(exports.execFile)
|
||||
});
|
||||
|
||||
const _deprecatedCustomFds = deprecate(
|
||||
function deprecateCustomFds(options) {
|
||||
|
@ -32,3 +32,22 @@ const execFile = promisify(child_process.execFile);
|
||||
assert(err.message.includes('doesntexist'));
|
||||
}));
|
||||
}
|
||||
const failingCodeWithStdoutErr =
|
||||
'console.log(42);console.error(43);process.exit(1)';
|
||||
{
|
||||
exec(`${process.execPath} -e "${failingCodeWithStdoutErr}"`)
|
||||
.catch(common.mustCall((err) => {
|
||||
assert.strictEqual(err.code, 1);
|
||||
assert.strictEqual(err.stdout, '42\n');
|
||||
assert.strictEqual(err.stderr, '43\n');
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
execFile(process.execPath, ['-e', failingCodeWithStdoutErr])
|
||||
.catch(common.mustCall((err) => {
|
||||
assert.strictEqual(err.code, 1);
|
||||
assert.strictEqual(err.stdout, '42\n');
|
||||
assert.strictEqual(err.stderr, '43\n');
|
||||
}));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user