Skip to content

Commit 68dff4a

Browse files
SirR4Taddaleax
authored andcommitted
child_process: allow typed arrays for input
doc: Update child_process docs, stating typed arrays are allowed. error: Update error message for `ERR_INVALID_SYNC_FORK_INPUT` lib: Use isArrayBufferView instead of isUint8Array test: Update test-child-process-spawnsync-input to test for all typed arrays and data view. PR-URL: #22409 Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]>
1 parent 31b3273 commit 68dff4a

File tree

6 files changed

+46
-22
lines changed

6 files changed

+46
-22
lines changed

doc/api/child_process.md

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,10 @@ configuration at startup.
688688
<!-- YAML
689689
added: v0.11.12
690690
changes:
691+
- version: REPLACEME
692+
pr-url: https://github.com/nodejs/node/pull/22409
693+
description: The `input` option can now be any `TypedArray` or a
694+
`DataView`.
691695
- version: REPLACEME
692696
pr-url: https://github.com/nodejs/node/pull/21316
693697
description: The `windowsHide` option now defaults to `true`.
@@ -706,8 +710,9 @@ changes:
706710
* `args` {string[]} List of string arguments.
707711
* `options` {Object}
708712
* `cwd` {string} Current working directory of the child process.
709-
* `input` {string|Buffer|Uint8Array} The value which will be passed as stdin
710-
to the spawned process. Supplying this value will override `stdio[0]`.
713+
* `input` {string|Buffer|TypedArray|DataView} The value which will be passed
714+
as stdin to the spawned process. Supplying this value will override
715+
`stdio[0]`.
711716
* `stdio` {string|Array} Child's stdio configuration. `stderr` by default will
712717
be output to the parent process' stderr unless `stdio` is specified.
713718
**Default:** `'pipe'`.
@@ -753,6 +758,10 @@ arbitrary command execution.**
753758
<!-- YAML
754759
added: v0.11.12
755760
changes:
761+
- version: REPLACEME
762+
pr-url: https://github.com/nodejs/node/pull/22409
763+
description: The `input` option can now be any `TypedArray` or a
764+
`DataView`.
756765
- version: REPLACEME
757766
pr-url: https://github.com/nodejs/node/pull/21316
758767
description: The `windowsHide` option now defaults to `true`.
@@ -767,8 +776,9 @@ changes:
767776
* `command` {string} The command to run.
768777
* `options` {Object}
769778
* `cwd` {string} Current working directory of the child process.
770-
* `input` {string|Buffer|Uint8Array} The value which will be passed as stdin
771-
to the spawned process. Supplying this value will override `stdio[0]`.
779+
* `input` {string|Buffer|TypedArray|DataView} The value which will be passed
780+
as stdin to the spawned process. Supplying this value will override
781+
`stdio[0]`.
772782
* `stdio` {string|Array} Child's stdio configuration. `stderr` by default will
773783
be output to the parent process' stderr unless `stdio` is specified.
774784
**Default:** `'pipe'`.
@@ -810,6 +820,10 @@ metacharacters may be used to trigger arbitrary command execution.**
810820
<!-- YAML
811821
added: v0.11.12
812822
changes:
823+
- version: REPLACEME
824+
pr-url: https://github.com/nodejs/node/pull/22409
825+
description: The `input` option can now be any `TypedArray` or a
826+
`DataView`.
813827
- version: REPLACEME
814828
pr-url: https://github.com/nodejs/node/pull/21316
815829
description: The `windowsHide` option now defaults to `true`.
@@ -831,8 +845,9 @@ changes:
831845
* `args` {string[]} List of string arguments.
832846
* `options` {Object}
833847
* `cwd` {string} Current working directory of the child process.
834-
* `input` {string|Buffer|Uint8Array} The value which will be passed as stdin
835-
to the spawned process. Supplying this value will override `stdio[0]`.
848+
* `input` {string|Buffer|TypedArray|DataView} The value which will be passed
849+
as stdin to the spawned process. Supplying this value will override
850+
`stdio[0]`.
836851
* `argv0` {string} Explicitly set the value of `argv[0]` sent to the child
837852
process. This will be set to `command` if not specified.
838853
* `stdio` {string|Array} Child's stdio configuration.

doc/api/errors.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,8 +1249,8 @@ For example when a function is expected to return a promise.
12491249
<a id="ERR_INVALID_SYNC_FORK_INPUT"></a>
12501250
### ERR_INVALID_SYNC_FORK_INPUT
12511251

1252-
A `Buffer`, `Uint8Array` or `string` was provided as stdio input to a
1253-
synchronous fork. See the documentation for the [`child_process`][] module
1252+
A `Buffer`, `TypedArray`, `DataView` or `string` was provided as stdio input to
1253+
an asynchronous fork. See the documentation for the [`child_process`][] module
12541254
for more information.
12551255

12561256
<a id="ERR_INVALID_THIS"></a>

lib/child_process.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const util = require('util');
2525
const {
2626
deprecate, convertToValidSignal, getSystemErrorName
2727
} = require('internal/util');
28-
const { isUint8Array } = require('internal/util/types');
28+
const { isArrayBufferView } = require('internal/util/types');
2929
const debug = util.debuglog('child_process');
3030
const { Buffer } = require('buffer');
3131
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
@@ -572,13 +572,16 @@ function spawnSync(/* file, args, options */) {
572572
var input = options.stdio[i] && options.stdio[i].input;
573573
if (input != null) {
574574
var pipe = options.stdio[i] = util._extend({}, options.stdio[i]);
575-
if (isUint8Array(input)) {
575+
if (isArrayBufferView(input)) {
576576
pipe.input = input;
577577
} else if (typeof input === 'string') {
578578
pipe.input = Buffer.from(input, options.encoding);
579579
} else {
580580
throw new ERR_INVALID_ARG_TYPE(`options.stdio[${i}]`,
581-
['Buffer', 'Uint8Array', 'string'],
581+
['Buffer',
582+
'TypedArray',
583+
'DataView',
584+
'string'],
582585
input);
583586
}
584587
}

lib/internal/child_process.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const { UDP } = process.binding('udp_wrap');
3232
const SocketList = require('internal/socket_list');
3333
const { owner_symbol } = require('internal/async_hooks').symbols;
3434
const { convertToValidSignal } = require('internal/util');
35-
const { isUint8Array } = require('internal/util/types');
35+
const { isArrayBufferView } = require('internal/util/types');
3636
const spawn_sync = process.binding('spawn_sync');
3737
const { HTTPParser } = internalBinding('http_parser');
3838
const { freeParser } = require('_http_common');
@@ -928,7 +928,7 @@ function _validateStdio(stdio, sync) {
928928
wrapType: getHandleWrapType(handle),
929929
handle: handle
930930
});
931-
} else if (isUint8Array(stdio) || typeof stdio === 'string') {
931+
} else if (isArrayBufferView(stdio) || typeof stdio === 'string') {
932932
if (!sync) {
933933
cleanup();
934934
throw new ERR_INVALID_SYNC_FORK_INPUT(util.inspect(stdio));

lib/internal/errors.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,8 @@ E('ERR_INVALID_RETURN_VALUE', (input, name, value) => {
712712
` function but got ${type}.`;
713713
}, TypeError);
714714
E('ERR_INVALID_SYNC_FORK_INPUT',
715-
'Asynchronous forks do not support Buffer, Uint8Array or string input: %s',
715+
'Asynchronous forks do not support ' +
716+
'Buffer, TypedArray, DataView or string input: %s',
716717
TypeError);
717718
E('ERR_INVALID_THIS', 'Value of "this" must be of type %s', TypeError);
718719
E('ERR_INVALID_TUPLE', '%s must be an iterable %s tuple', TypeError);

test/parallel/test-child-process-spawnsync-input.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,21 @@ checkSpawnSyncRet(ret);
100100
assert.deepStrictEqual(ret.stdout, options.input);
101101
assert.deepStrictEqual(ret.stderr, Buffer.from(''));
102102

103-
options = {
104-
input: Uint8Array.from(Buffer.from('hello world'))
105-
};
103+
// common.getArrayBufferViews expects a buffer
104+
// with length an multiple of 8
105+
const msgBuf = Buffer.from('hello world'.repeat(8));
106+
for (const arrayBufferView of common.getArrayBufferViews(msgBuf)) {
107+
options = {
108+
input: arrayBufferView
109+
};
106110

107-
ret = spawnSync('cat', [], options);
111+
ret = spawnSync('cat', [], options);
108112

109-
checkSpawnSyncRet(ret);
110-
// Wrap options.input because Uint8Array and Buffer have different prototypes.
111-
assert.deepStrictEqual(ret.stdout, Buffer.from(options.input));
112-
assert.deepStrictEqual(ret.stderr, Buffer.from(''));
113+
checkSpawnSyncRet(ret);
114+
115+
assert.deepStrictEqual(ret.stdout, msgBuf);
116+
assert.deepStrictEqual(ret.stderr, Buffer.from(''));
117+
}
113118

114119
verifyBufOutput(spawnSync(process.execPath, args));
115120

0 commit comments

Comments
 (0)