diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 70d36deb1..ee9c922ae 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [18, 20, 22] + node-version: [18, 20, 22, 24] steps: - uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} diff --git a/packages/node_modules/@node-red/nodes/core/function/90-exec.js b/packages/node_modules/@node-red/nodes/core/function/90-exec.js index 23d94059e..02a908d4b 100644 --- a/packages/node_modules/@node-red/nodes/core/function/90-exec.js +++ b/packages/node_modules/@node-red/nodes/core/function/90-exec.js @@ -91,7 +91,13 @@ module.exports = function(RED) { const opts = isWindows ? { ...node.spawnOpt, shell: true } : node.spawnOpt /* istanbul ignore else */ node.debug(cmd+" ["+arg+"]"); - child = spawn(cmd,arg,opts); + if (opts.shell) { + // When called with shell: true, passing in separate args is deprecated in Node 24 + // so we need to join the command and args into a single string. + child = spawn([cmd].concat(arg).join(" "), opts); + } else { + child = spawn(cmd,arg,opts); + } node.status({fill:"blue",shape:"dot",text:"pid:"+child.pid}); var unknownCommand = (child.pid === undefined); if (node.timer !== 0) { diff --git a/packages/node_modules/@node-red/registry/lib/installer.js b/packages/node_modules/@node-red/registry/lib/installer.js index 3ffd65513..2d8cfe193 100644 --- a/packages/node_modules/@node-red/registry/lib/installer.js +++ b/packages/node_modules/@node-red/registry/lib/installer.js @@ -367,9 +367,10 @@ async function getModuleVersionFromNPM(module, version) { if (version) { installName += "@" + version; } + return new Promise((resolve, reject) => { - child_process.execFile(npmCommand,['info','--json',installName],{ shell: true },function(err,stdout,stderr) { + child_process.execFile(`${npmCommand} info --json ${installName}`, { shell: true },function(err,stdout,stderr) { try { if (!stdout) { log.warn(log._("server.install.install-failed-not-found",{name:module})); @@ -595,7 +596,7 @@ async function checkPrereq() { installerEnabled = false; } else { return new Promise(resolve => { - child_process.execFile(npmCommand,['-v'],{ shell: true },function(err,stdout) { + child_process.execFile(`${npmCommand} -v`,{ shell: true },function(err,stdout) { if (err) { log.info(log._("server.palette-editor.npm-not-found")); installerEnabled = false; diff --git a/packages/node_modules/@node-red/util/lib/exec.js b/packages/node_modules/@node-red/util/lib/exec.js index 15b81aa89..6345438a6 100644 --- a/packages/node_modules/@node-red/util/lib/exec.js +++ b/packages/node_modules/@node-red/util/lib/exec.js @@ -57,7 +57,15 @@ module.exports = { return new Promise((resolve, reject) => { let stdout = ""; let stderr = ""; - const child = child_process.spawn(command,args,options); + let child + if (args && options.shell) { + // If we are using a shell, we need to join the args into a single string + // as passing a separate array of args is deprecated in Node 24 + command = [command].concat(args).join(" "); + child = child_process.spawn(command, options) + } else { + child = child_process.spawn(command, args, options); + } child.stdout.on('data', (data) => { const str = ""+data; stdout += str; diff --git a/packages/node_modules/node-red/red.js b/packages/node_modules/node-red/red.js index af0c34fa7..fdd38ed47 100755 --- a/packages/node_modules/node-red/red.js +++ b/packages/node_modules/node-red/red.js @@ -529,18 +529,18 @@ httpsPromise.then(function(startupHttps) { }); process.on('uncaughtException',function(err) { - util.log('[red] Uncaught Exception:'); + console.log('[red] Uncaught Exception:'); if (err.stack) { try { RED.log.error(err.stack); } catch(err2) { - util.log(err.stack); + console.log(err.stack); } } else { try { RED.log.error(err); } catch(err2) { - util.log(err); + console.log(err); } } process.exit(1);