Skip to content

Commit 1ac5b91

Browse files
authored
Fix Node 24-specific deprecation warning (#1199)
1 parent 2f1012f commit 1ac5b91

File tree

6 files changed

+29
-4
lines changed

6 files changed

+29
-4
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
fail-fast: false
1111
matrix:
1212
node-version:
13-
- 23
13+
- 24
1414
- 18
1515
os:
1616
- ubuntu
@@ -31,7 +31,7 @@ jobs:
3131
with:
3232
args: --cache --verbose --no-progress --include-fragments --exclude packagephobia --exclude /pull/ --exclude linkedin --exclude stackoverflow --exclude stackexchange --exclude github.com/nodejs/node --exclude file:///test --exclude invalid.com '*.md' 'docs/*.md' '.github/**/*.md' '*.json' '*.js' 'lib/**/*.js' 'test/**/*.js' '*.ts' 'test-d/**/*.ts'
3333
fail: true
34-
if: ${{ matrix.os == 'ubuntu' && matrix.node-version == 23 }}
34+
if: ${{ matrix.os == 'ubuntu' && matrix.node-version == 24 }}
3535
- run: npm run lint
3636
- run: npm run type
3737
- run: npm run unit

lib/arguments/shell.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// When the `shell` option is set, any command argument is concatenated as a single string by Node.js:
2+
// https://github.com/nodejs/node/blob/e38ce27f3ca0a65f68a31cedd984cddb927d4002/lib/child_process.js#L614-L624
3+
// However, since Node 24, it also prints a deprecation warning.
4+
// To avoid this warning, we perform that same operation before calling `node:child_process`.
5+
// Shells only understand strings, which is why Node.js performs that concatenation.
6+
// However, we rely on users splitting command arguments as an array.
7+
// For example, this allows us to easily detect which arguments are passed.
8+
// So we do want users to pass array of arguments even with `shell: true`, but we also want to avoid any warning.
9+
export const concatenateShell = (file, commandArguments, options) => options.shell && commandArguments.length > 0
10+
? [[file, ...commandArguments].join(' '), [], options]
11+
: [file, commandArguments, options];
12+

lib/methods/main-async.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {MaxBufferError} from 'get-stream';
44
import {handleCommand} from '../arguments/command.js';
55
import {normalizeOptions} from '../arguments/options.js';
66
import {SUBPROCESS_OPTIONS} from '../arguments/fd-options.js';
7+
import {concatenateShell} from '../arguments/shell.js';
78
import {addIpcMethods} from '../ipc/methods.js';
89
import {makeError, makeSuccessResult} from '../return/result.js';
910
import {handleResult} from '../return/reject.js';
@@ -75,7 +76,7 @@ const handleAsyncOptions = ({timeout, signal, ...options}) => {
7576
const spawnSubprocessAsync = ({file, commandArguments, options, startTime, verboseInfo, command, escapedCommand, fileDescriptors}) => {
7677
let subprocess;
7778
try {
78-
subprocess = spawn(file, commandArguments, options);
79+
subprocess = spawn(...concatenateShell(file, commandArguments, options));
7980
} catch (error) {
8081
return handleEarlyError({
8182
error,

lib/methods/main-sync.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {spawnSync} from 'node:child_process';
22
import {handleCommand} from '../arguments/command.js';
33
import {normalizeOptions} from '../arguments/options.js';
4+
import {concatenateShell} from '../arguments/shell.js';
45
import {makeError, makeEarlyError, makeSuccessResult} from '../return/result.js';
56
import {handleResult} from '../return/reject.js';
67
import {handleStdioSync} from '../stdio/handle-sync.js';
@@ -115,7 +116,7 @@ const runSubprocessSync = ({file, commandArguments, options, command, escapedCom
115116
try {
116117
addInputOptionsSync(fileDescriptors, options);
117118
const normalizedOptions = normalizeSpawnSyncOptions(options);
118-
return spawnSync(file, commandArguments, normalizedOptions);
119+
return spawnSync(...concatenateShell(file, commandArguments, normalizedOptions));
119120
} catch (error) {
120121
return makeEarlyError({
121122
error,

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
"get-node": "^15.0.0",
7272
"is-in-ci": "^1.0.0",
7373
"is-running": "^2.1.0",
74+
"log-process-errors": "^12.0.1",
7475
"path-exists": "^5.0.0",
7576
"path-key": "^4.0.0",
7677
"tempfile": "^5.0.0",

test/helpers/fixtures-directory.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
import path from 'node:path';
22
import process from 'node:process';
33
import {fileURLToPath} from 'node:url';
4+
import logProcessErrors from 'log-process-errors';
45
import pathKey from 'path-key';
56

7+
// Make tests fail if any warning (such as a deprecation warning) is emitted
8+
logProcessErrors({
9+
onError(error, event) {
10+
if (event === 'warning') {
11+
throw error;
12+
}
13+
},
14+
});
15+
616
export const PATH_KEY = pathKey();
717
export const FIXTURES_DIRECTORY_URL = new URL('../fixtures/', import.meta.url);
818
// @todo: use import.meta.dirname after dropping support for Node <20.11.0

0 commit comments

Comments
 (0)