From 2717a31e9a79ed2bce95b08b6216dc2bf27641e8 Mon Sep 17 00:00:00 2001 From: AliMahmoudDev <123aliactionx5@gmail.com> Date: Tue, 26 May 2026 08:00:44 +0000 Subject: [PATCH 1/2] test: pass processExecArgv to run() instead of reading process.execArgv directly Captures process.execArgv at the CLI entry point (main/test_runner.js) and passes it through as an explicit option to run(). This removes direct reads of process.execArgv and process.argv inside getRunArgs() in the test runner. Changes: - Add processExecArgv option to run() (defaults to process.execArgv for backward compatibility) - Pass processExecArgv from main/test_runner.js to run() - Replace process.execArgv read in getRunArgs() with the passed option - Replace process.argv read in getRunArgs() with globPatterns Refs: #53867 Signed-off-by: AliMahmoudDev <123aliactionx5@gmail.com> --- lib/internal/main/test_runner.js | 1 + lib/internal/test_runner/runner.js | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/internal/main/test_runner.js b/lib/internal/main/test_runner.js index fda47897da9f06..9d446925c00b88 100644 --- a/lib/internal/main/test_runner.js +++ b/lib/internal/main/test_runner.js @@ -31,6 +31,7 @@ if (isUsingInspector() && options.isolation === 'process') { } options.globPatterns = ArrayPrototypeSlice(process.argv, 1); +options.processExecArgv = process.execArgv; debug('test runner configuration:', options); run(options).on('test:summary', (data) => { diff --git a/lib/internal/test_runner/runner.js b/lib/internal/test_runner/runner.js index d150943783e975..d018e6100602ef 100644 --- a/lib/internal/test_runner/runner.js +++ b/lib/internal/test_runner/runner.js @@ -187,6 +187,8 @@ function getRunArgs(path, { forceExit, only, argv: suppliedArgs, execArgv, + processExecArgv, + globPatterns, rerunFailuresFilePath, randomize, randomSeed, @@ -205,7 +207,7 @@ function getRunArgs(path, { forceExit, */ const nodeOptionsSet = new SafeSet(processNodeOptions); const unknownProcessExecArgv = ArrayPrototypeFilter( - process.execArgv, + processExecArgv, (arg) => !nodeOptionsSet.has(arg), ); ArrayPrototypePushApply(runArgs, unknownProcessExecArgv); @@ -245,7 +247,7 @@ function getRunArgs(path, { forceExit, if (path === kIsolatedProcessName) { ArrayPrototypePush(runArgs, '--test'); - ArrayPrototypePushApply(runArgs, ArrayPrototypeSlice(process.argv, 1)); + ArrayPrototypePushApply(runArgs, globPatterns); } else { ArrayPrototypePush(runArgs, path); } @@ -723,6 +725,7 @@ function run(options = kEmptyObject) { randomSeed: suppliedRandomSeed, execArgv = [], argv = [], + processExecArgv = process.execArgv, cwd = process.cwd(), rerunFailuresFilePath, env, @@ -981,6 +984,7 @@ function run(options = kEmptyObject) { isolation, argv, execArgv, + processExecArgv, rerunFailuresFilePath, env, workerIdPool: isolation === 'process' ? workerIdPool : null, From 328b482bf8c1fefb7e63c612fea0ce6542555c72 Mon Sep 17 00:00:00 2001 From: AliMahmoudDev <123aliactionx5@gmail.com> Date: Tue, 26 May 2026 08:36:06 +0000 Subject: [PATCH 2/2] test: add tests for processExecArgv option in run() Adds two tests to verify the new processExecArgv option: - Test that processExecArgv defaults to process.execArgv for backward compat - Test that an empty processExecArgv array works correctly Refs: #53867 Signed-off-by: AliMahmoudDev <123aliactionx5@gmail.com> --- test/parallel/test-runner-run.mjs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/parallel/test-runner-run.mjs b/test/parallel/test-runner-run.mjs index b6eb6b6af51877..d15f5b82ac96e1 100644 --- a/test/parallel/test-runner-run.mjs +++ b/test/parallel/test-runner-run.mjs @@ -727,6 +727,28 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { })); }); + it('should accept processExecArgv option and default to process.execArgv', async () => { + const stream = run({ + files: [join(testFixtures, 'default-behavior/test/random.cjs')], + processExecArgv: process.execArgv, + }); + stream.on('test:fail', common.mustNotCall()); + stream.on('test:pass', common.mustCall()); + // eslint-disable-next-line no-unused-vars + for await (const _ of stream); + }); + + it('should accept empty processExecArgv', async () => { + const stream = run({ + files: [join(testFixtures, 'default-behavior/test/random.cjs')], + processExecArgv: [], + }); + stream.on('test:fail', common.mustNotCall()); + stream.on('test:pass', common.mustCall()); + // eslint-disable-next-line no-unused-vars + for await (const _ of stream); + }); + it('should pass instance of stream to setup', async () => { const stream = run({ files: [join(testFixtures, 'default-behavior/test/random.cjs')],