Skip to content

Commit fc4b9c1

Browse files
committed
child_process: allow options.cwd receive a URL
PR-URL: #38862 Fixes: #38861 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
1 parent e7f941c commit fc4b9c1

File tree

3 files changed

+61
-10
lines changed

3 files changed

+61
-10
lines changed

doc/api/child_process.md

+35-7
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ exec('"my script.cmd" a b', (err, stdout, stderr) => {
146146
<!-- YAML
147147
added: v0.1.90
148148
changes:
149+
- version: REPLACEME
150+
pr-url: https://github.com/nodejs/node/pull/38862
151+
description: The `cwd` option can be a WHATWG `URL` object using
152+
`file:` protocol.
149153
- version: v15.4.0
150154
pr-url: https://github.com/nodejs/node/pull/36308
151155
description: AbortSignal support was added.
@@ -156,7 +160,7 @@ changes:
156160

157161
* `command` {string} The command to run, with space-separated arguments.
158162
* `options` {Object}
159-
* `cwd` {string} Current working directory of the child process.
163+
* `cwd` {string|URL} Current working directory of the child process.
160164
**Default:** `process.cwd()`.
161165
* `env` {Object} Environment key-value pairs. **Default:** `process.env`.
162166
* `encoding` {string} **Default:** `'utf8'`
@@ -271,6 +275,10 @@ controller.abort();
271275
<!-- YAML
272276
added: v0.1.91
273277
changes:
278+
- version: REPLACEME
279+
pr-url: https://github.com/nodejs/node/pull/38862
280+
description: The `cwd` option can be a WHATWG `URL` object using
281+
`file:` protocol.
274282
- version:
275283
- v15.4.0
276284
- v14.17.0
@@ -284,7 +292,7 @@ changes:
284292
* `file` {string} The name or path of the executable file to run.
285293
* `args` {string[]} List of string arguments.
286294
* `options` {Object}
287-
* `cwd` {string} Current working directory of the child process.
295+
* `cwd` {string|URL} Current working directory of the child process.
288296
* `env` {Object} Environment key-value pairs. **Default:** `process.env`.
289297
* `encoding` {string} **Default:** `'utf8'`
290298
* `timeout` {number} **Default:** `0`
@@ -376,6 +384,10 @@ controller.abort();
376384
<!-- YAML
377385
added: v0.5.0
378386
changes:
387+
- version: REPLACEME
388+
pr-url: https://github.com/nodejs/node/pull/38862
389+
description: The `cwd` option can be a WHATWG `URL` object using
390+
`file:` protocol.
379391
- version: v15.13.0
380392
pr-url: https://github.com/nodejs/node/pull/37256
381393
description: timeout was added.
@@ -403,7 +415,7 @@ changes:
403415
* `modulePath` {string} The module to run in the child.
404416
* `args` {string[]} List of string arguments.
405417
* `options` {Object}
406-
* `cwd` {string} Current working directory of the child process.
418+
* `cwd` {string|URL} Current working directory of the child process.
407419
* `detached` {boolean} Prepare child to run independently of its parent
408420
process. Specific behavior depends on the platform, see
409421
[`options.detached`][]).
@@ -487,6 +499,10 @@ if (process.argv[2] === 'child') {
487499
<!-- YAML
488500
added: v0.1.90
489501
changes:
502+
- version: REPLACEME
503+
pr-url: https://github.com/nodejs/node/pull/38862
504+
description: The `cwd` option can be a WHATWG `URL` object using
505+
`file:` protocol.
490506
- version: v15.13.0
491507
pr-url: https://github.com/nodejs/node/pull/37256
492508
description: timeout was added.
@@ -517,7 +533,7 @@ changes:
517533
* `command` {string} The command to run.
518534
* `args` {string[]} List of string arguments.
519535
* `options` {Object}
520-
* `cwd` {string} Current working directory of the child process.
536+
* `cwd` {string|URL} Current working directory of the child process.
521537
* `env` {Object} Environment key-value pairs. **Default:** `process.env`.
522538
* `argv0` {string} Explicitly set the value of `argv[0]` sent to the child
523539
process. This will be set to `command` if not specified.
@@ -845,6 +861,10 @@ configuration at startup.
845861
<!-- YAML
846862
added: v0.11.12
847863
changes:
864+
- version: REPLACEME
865+
pr-url: https://github.com/nodejs/node/pull/38862
866+
description: The `cwd` option can be a WHATWG `URL` object using
867+
`file:` protocol.
848868
- version: v10.10.0
849869
pr-url: https://github.com/nodejs/node/pull/22409
850870
description: The `input` option can now be any `TypedArray` or a
@@ -865,7 +885,7 @@ changes:
865885
* `file` {string} The name or path of the executable file to run.
866886
* `args` {string[]} List of string arguments.
867887
* `options` {Object}
868-
* `cwd` {string} Current working directory of the child process.
888+
* `cwd` {string|URL} Current working directory of the child process.
869889
* `input` {string|Buffer|TypedArray|DataView} The value which will be passed
870890
as stdin to the spawned process. Supplying this value will override
871891
`stdio[0]`.
@@ -914,6 +934,10 @@ arbitrary command execution.**
914934
<!-- YAML
915935
added: v0.11.12
916936
changes:
937+
- version: REPLACEME
938+
pr-url: https://github.com/nodejs/node/pull/38862
939+
description: The `cwd` option can be a WHATWG `URL` object using
940+
`file:` protocol.
917941
- version: v10.10.0
918942
pr-url: https://github.com/nodejs/node/pull/22409
919943
description: The `input` option can now be any `TypedArray` or a
@@ -928,7 +952,7 @@ changes:
928952

929953
* `command` {string} The command to run.
930954
* `options` {Object}
931-
* `cwd` {string} Current working directory of the child process.
955+
* `cwd` {string|URL} Current working directory of the child process.
932956
* `input` {string|Buffer|TypedArray|DataView} The value which will be passed
933957
as stdin to the spawned process. Supplying this value will override
934958
`stdio[0]`.
@@ -974,6 +998,10 @@ metacharacters may be used to trigger arbitrary command execution.**
974998
<!-- YAML
975999
added: v0.11.12
9761000
changes:
1001+
- version: REPLACEME
1002+
pr-url: https://github.com/nodejs/node/pull/38862
1003+
description: The `cwd` option can be a WHATWG `URL` object using
1004+
`file:` protocol.
9771005
- version: v10.10.0
9781006
pr-url: https://github.com/nodejs/node/pull/22409
9791007
description: The `input` option can now be any `TypedArray` or a
@@ -997,7 +1025,7 @@ changes:
9971025
* `command` {string} The command to run.
9981026
* `args` {string[]} List of string arguments.
9991027
* `options` {Object}
1000-
* `cwd` {string} Current working directory of the child process.
1028+
* `cwd` {string|URL} Current working directory of the child process.
10011029
* `input` {string|Buffer|TypedArray|DataView} The value which will be passed
10021030
as stdin to the spawned process. Supplying this value will override
10031031
`stdio[0]`.

lib/child_process.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ const {
7171
ERR_OUT_OF_RANGE,
7272
} = errorCodes;
7373
const { clearTimeout, setTimeout } = require('timers');
74+
const { getValidatedPath } = require('internal/fs/utils');
7475
const {
7576
isInt32,
7677
validateAbortSignal,
@@ -450,9 +451,11 @@ function normalizeSpawnArguments(file, args, options) {
450451
else
451452
validateObject(options, 'options');
452453

454+
let cwd = options.cwd;
455+
453456
// Validate the cwd, if present.
454-
if (options.cwd != null) {
455-
validateString(options.cwd, 'options.cwd');
457+
if (cwd != null) {
458+
cwd = getValidatedPath(cwd, 'options.cwd');
456459
}
457460

458461
// Validate detached, if present.
@@ -577,11 +580,12 @@ function normalizeSpawnArguments(file, args, options) {
577580
// Make a shallow copy so we don't clobber the user's options object.
578581
...options,
579582
args,
583+
cwd,
580584
detached: !!options.detached,
581585
envPairs,
582586
file,
583587
windowsHide: !!options.windowsHide,
584-
windowsVerbatimArguments: !!windowsVerbatimArguments
588+
windowsVerbatimArguments: !!windowsVerbatimArguments,
585589
};
586590
}
587591

test/parallel/test-child-process-cwd.js

+19
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@
2020
// USE OR OTHER DEALINGS IN THE SOFTWARE.
2121

2222
'use strict';
23+
2324
const common = require('../common');
2425
const tmpdir = require('../common/tmpdir');
2526
tmpdir.refresh();
2627

2728
const assert = require('assert');
2829
const { spawn } = require('child_process');
30+
const { pathToFileURL, URL } = require('url');
2931

3032
// Spawns 'pwd' with given options, then test
3133
// - whether the child pid is undefined or number,
@@ -66,10 +68,27 @@ function testCwd(options, expectPidType, expectCode = 0, expectData) {
6668
}));
6769
}
6870

71+
{
72+
assert.throws(() => {
73+
testCwd({
74+
cwd: new URL('http://example.com/'),
75+
}, 'number', 0, tmpdir.path);
76+
}, /The URL must be of scheme file/);
77+
78+
if (process.platform !== 'win32') {
79+
assert.throws(() => {
80+
testCwd({
81+
cwd: new URL('file://host/dev/null'),
82+
}, 'number', 0, tmpdir.path);
83+
}, /File URL host must be "localhost" or empty on/);
84+
}
85+
}
86+
6987
// Assume these exist, and 'pwd' gives us the right directory back
7088
testCwd({ cwd: tmpdir.path }, 'number', 0, tmpdir.path);
7189
const shouldExistDir = common.isWindows ? process.env.windir : '/dev';
7290
testCwd({ cwd: shouldExistDir }, 'number', 0, shouldExistDir);
91+
testCwd({ cwd: pathToFileURL(tmpdir.path) }, 'number', 0, tmpdir.path);
7392

7493
// Spawn() shouldn't try to chdir() to invalid arg, so this should just work
7594
testCwd({ cwd: '' }, 'number');

0 commit comments

Comments
 (0)