From 3308eb3d00aaf9219ab88609ee24d4150765a94a Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Tue, 13 Oct 2026 17:16:03 -0700 Subject: [PATCH] fix(process-host): accept string stdin in synchronous runs (#28225) fix(process-host): accept string stdin in synchronous runs Request raw subprocess output with null encoding so Node can encode string stdin as UTF-8. Preserve explicit text decoding and byte capture, with real-runner coverage for both output modes. Co-authored-by: Joe Esposito --- .../process-host/src/run-process.test.ts | 23 +++++++++++++++++++ src/packages/process-host/src/run-process.ts | 3 ++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/packages/process-host/src/run-process.test.ts b/src/packages/process-host/src/run-process.test.ts index 2b333cf89fe..b91fb40c433 100644 --- a/src/packages/process-host/src/run-process.test.ts +++ b/src/packages/process-host/src/run-process.test.ts @@ -83,6 +83,29 @@ describe('resolveSpawn', () => { }) describe('runProcessSync', () => { + it.each([false, true])('accepts string stdin with byte capture %s', (captureStdoutAsBytes) => { + const input = 'nonsecret-probe-λ' + const result = runProcessSync({ + program: process.execPath, + args: [ + '-e', + 'process.stdin.pipe(process.stdout, { end: false }); process.stdin.on("end", () => { process.stdout.write(Buffer.from([0,255])); process.stderr.write("diagnostic λ") })' + ], + input, + captureStdoutAsBytes + }) + expect(result).toMatchObject({ + code: 0, + stdout: captureStdoutAsBytes ? '' : `${input}\u0000�`, + stderr: 'diagnostic λ', + timedOut: false, + outputTruncated: false + }) + expect(result.stdoutBytes).toEqual( + captureStdoutAsBytes ? Buffer.concat([Buffer.from(input), Buffer.from([0, 255])]) : undefined + ) + }) + it('reports a timeout as timedOut', () => { const result = runProcessSync({ program: process.execPath, diff --git a/src/packages/process-host/src/run-process.ts b/src/packages/process-host/src/run-process.ts index a5d5c2d2e37..5bc5a733bc9 100644 --- a/src/packages/process-host/src/run-process.ts +++ b/src/packages/process-host/src/run-process.ts @@ -357,7 +357,8 @@ function runResolvedProcessSync(spec: ProcessSpec, resolved: ResolvedSpawn): Pro input: spec.input, timeout: spec.timeoutMs === null ? undefined : (spec.timeoutMs ?? DEFAULT_PROCESS_TIMEOUT_MS), maxBuffer: spec.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES, - encoding: 'buffer' + // Keep raw output without applying the nonexistent 'buffer' encoding to string stdin. + encoding: null }) const timedOut = result.error ? 'code' in result.error && result.error.code === 'ETIMEDOUT'