Skip to content

Commit

Permalink
child_process: allow options.cwd receive a URL
Browse files Browse the repository at this point in the history
PR-URL: #38862
Fixes: #38861
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
  • Loading branch information
XadillaX authored and targos committed Jun 11, 2021
1 parent 0706565 commit 69fa9e1
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 10 deletions.
42 changes: 35 additions & 7 deletions doc/api/child_process.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ exec('"my script.cmd" a b', (err, stdout, stderr) => {
<!-- YAML
added: v0.1.90
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/38862
description: The `cwd` option can be a WHATWG `URL` object using
`file:` protocol.
- version: v15.4.0
pr-url: https://github.com/nodejs/node/pull/36308
description: AbortSignal support was added.
Expand All @@ -156,7 +160,7 @@ changes:

* `command` {string} The command to run, with space-separated arguments.
* `options` {Object}
* `cwd` {string} Current working directory of the child process.
* `cwd` {string|URL} Current working directory of the child process.
**Default:** `process.cwd()`.
* `env` {Object} Environment key-value pairs. **Default:** `process.env`.
* `encoding` {string} **Default:** `'utf8'`
Expand Down Expand Up @@ -271,6 +275,10 @@ controller.abort();
<!-- YAML
added: v0.1.91
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/38862
description: The `cwd` option can be a WHATWG `URL` object using
`file:` protocol.
- version: v15.4.0
pr-url: https://github.com/nodejs/node/pull/36308
description: AbortSignal support was added.
Expand All @@ -282,7 +290,7 @@ changes:
* `file` {string} The name or path of the executable file to run.
* `args` {string[]} List of string arguments.
* `options` {Object}
* `cwd` {string} Current working directory of the child process.
* `cwd` {string|URL} Current working directory of the child process.
* `env` {Object} Environment key-value pairs. **Default:** `process.env`.
* `encoding` {string} **Default:** `'utf8'`
* `timeout` {number} **Default:** `0`
Expand Down Expand Up @@ -374,6 +382,10 @@ controller.abort();
<!-- YAML
added: v0.5.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/38862
description: The `cwd` option can be a WHATWG `URL` object using
`file:` protocol.
- version: v15.13.0
pr-url: https://github.com/nodejs/node/pull/37256
description: timeout was added.
Expand All @@ -399,7 +411,7 @@ changes:
* `modulePath` {string} The module to run in the child.
* `args` {string[]} List of string arguments.
* `options` {Object}
* `cwd` {string} Current working directory of the child process.
* `cwd` {string|URL} Current working directory of the child process.
* `detached` {boolean} Prepare child to run independently of its parent
process. Specific behavior depends on the platform, see
[`options.detached`][]).
Expand Down Expand Up @@ -483,6 +495,10 @@ if (process.argv[2] === 'child') {
<!-- YAML
added: v0.1.90
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/38862
description: The `cwd` option can be a WHATWG `URL` object using
`file:` protocol.
- version: v15.13.0
pr-url: https://github.com/nodejs/node/pull/37256
description: timeout was added.
Expand Down Expand Up @@ -511,7 +527,7 @@ changes:
* `command` {string} The command to run.
* `args` {string[]} List of string arguments.
* `options` {Object}
* `cwd` {string} Current working directory of the child process.
* `cwd` {string|URL} Current working directory of the child process.
* `env` {Object} Environment key-value pairs. **Default:** `process.env`.
* `argv0` {string} Explicitly set the value of `argv[0]` sent to the child
process. This will be set to `command` if not specified.
Expand Down Expand Up @@ -839,6 +855,10 @@ configuration at startup.
<!-- YAML
added: v0.11.12
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/38862
description: The `cwd` option can be a WHATWG `URL` object using
`file:` protocol.
- version: v10.10.0
pr-url: https://github.com/nodejs/node/pull/22409
description: The `input` option can now be any `TypedArray` or a
Expand All @@ -859,7 +879,7 @@ changes:
* `file` {string} The name or path of the executable file to run.
* `args` {string[]} List of string arguments.
* `options` {Object}
* `cwd` {string} Current working directory of the child process.
* `cwd` {string|URL} Current working directory of the child process.
* `input` {string|Buffer|TypedArray|DataView} The value which will be passed
as stdin to the spawned process. Supplying this value will override
`stdio[0]`.
Expand Down Expand Up @@ -908,6 +928,10 @@ arbitrary command execution.**
<!-- YAML
added: v0.11.12
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/38862
description: The `cwd` option can be a WHATWG `URL` object using
`file:` protocol.
- version: v10.10.0
pr-url: https://github.com/nodejs/node/pull/22409
description: The `input` option can now be any `TypedArray` or a
Expand All @@ -922,7 +946,7 @@ changes:

* `command` {string} The command to run.
* `options` {Object}
* `cwd` {string} Current working directory of the child process.
* `cwd` {string|URL} Current working directory of the child process.
* `input` {string|Buffer|TypedArray|DataView} The value which will be passed
as stdin to the spawned process. Supplying this value will override
`stdio[0]`.
Expand Down Expand Up @@ -968,6 +992,10 @@ metacharacters may be used to trigger arbitrary command execution.**
<!-- YAML
added: v0.11.12
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/38862
description: The `cwd` option can be a WHATWG `URL` object using
`file:` protocol.
- version: v10.10.0
pr-url: https://github.com/nodejs/node/pull/22409
description: The `input` option can now be any `TypedArray` or a
Expand All @@ -991,7 +1019,7 @@ changes:
* `command` {string} The command to run.
* `args` {string[]} List of string arguments.
* `options` {Object}
* `cwd` {string} Current working directory of the child process.
* `cwd` {string|URL} Current working directory of the child process.
* `input` {string|Buffer|TypedArray|DataView} The value which will be passed
as stdin to the spawned process. Supplying this value will override
`stdio[0]`.
Expand Down
10 changes: 7 additions & 3 deletions lib/child_process.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const {
ERR_OUT_OF_RANGE,
} = errorCodes;
const { clearTimeout, setTimeout } = require('timers');
const { getValidatedPath } = require('internal/fs/utils');
const {
isInt32,
validateAbortSignal,
Expand Down Expand Up @@ -450,9 +451,11 @@ function normalizeSpawnArguments(file, args, options) {
else
validateObject(options, 'options');

let cwd = options.cwd;

// Validate the cwd, if present.
if (options.cwd != null) {
validateString(options.cwd, 'options.cwd');
if (cwd != null) {
cwd = getValidatedPath(cwd, 'options.cwd');
}

// Validate detached, if present.
Expand Down Expand Up @@ -577,11 +580,12 @@ function normalizeSpawnArguments(file, args, options) {
// Make a shallow copy so we don't clobber the user's options object.
...options,
args,
cwd,
detached: !!options.detached,
envPairs,
file,
windowsHide: !!options.windowsHide,
windowsVerbatimArguments: !!windowsVerbatimArguments
windowsVerbatimArguments: !!windowsVerbatimArguments,
};
}

Expand Down
19 changes: 19 additions & 0 deletions test/parallel/test-child-process-cwd.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.

'use strict';

const common = require('../common');
const tmpdir = require('../common/tmpdir');
tmpdir.refresh();

const assert = require('assert');
const { spawn } = require('child_process');
const { pathToFileURL, URL } = require('url');

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

{
assert.throws(() => {
testCwd({
cwd: new URL('http://example.com/'),
}, 'number', 0, tmpdir.path);
}, /The URL must be of scheme file/);

if (process.platform !== 'win32') {
assert.throws(() => {
testCwd({
cwd: new URL('file://host/dev/null'),
}, 'number', 0, tmpdir.path);
}, /File URL host must be "localhost" or empty on/);
}
}

// Assume these exist, and 'pwd' gives us the right directory back
testCwd({ cwd: tmpdir.path }, 'number', 0, tmpdir.path);
const shouldExistDir = common.isWindows ? process.env.windir : '/dev';
testCwd({ cwd: shouldExistDir }, 'number', 0, shouldExistDir);
testCwd({ cwd: pathToFileURL(tmpdir.path) }, 'number', 0, tmpdir.path);

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

0 comments on commit 69fa9e1

Please sign in to comment.