Remove setBlocking calls and simplify file-redirect approach

Remove fragile process.stdout._handle.setBlocking calls from CLI test
commands. Revert the preload workaround in repo-tools since the root
cause is removed.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
This commit is contained in:
Patrik Oldsberg
2026-02-27 08:48:19 +01:00
parent 5e01ab714a
commit 2481126013
3 changed files with 6 additions and 49 deletions
@@ -87,11 +87,6 @@ export default async (_opts: OptionValues, cmd: Command) => {
}--no-node-snapshot`;
}
// This ensures that the process doesn't exit too early before stdout is flushed
if (args.includes('--help')) {
(process.stdout as any)._handle.setBlocking(true);
}
// Because of the ongoing migration to v30 of jest, jest is no longer hard-depended to allow
// opt-in migration. Users instead need to add jest as a devDependency themselves and specify
// the version they want. This prints a helpful error message if jest is not found, i.e. they
@@ -304,11 +304,9 @@ export async function command(opts: OptionValues, cmd: Command): Promise<void> {
}--no-node-snapshot`;
}
// This ensures that the process doesn't exit too early before stdout is flushed
if (args.includes('--jest-help')) {
removeOptionArg(args, '--jest-help');
args.push('--help');
(process.stdout as any)._handle.setBlocking(true);
}
// This code path is enabled by the --successCache flag, which is specific to
+6 -42
View File
@@ -15,42 +15,10 @@
*/
import { spawnSync } from 'node:child_process';
import {
openSync,
closeSync,
readFileSync,
unlinkSync,
writeFileSync,
} from 'node:fs';
import { openSync, closeSync, readFileSync, unlinkSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
// Preload script that stubs process.stdout._handle when stdout is backed by a
// file (SyncWriteStream). Some CLI code accesses _handle.setBlocking directly
// and would crash without this.
const preloadContent = `
if (process.stdout && !process.stdout._handle) {
process.stdout._handle = { setBlocking() {} };
}
`;
let preloadPath: string | undefined;
function getPreloadPath() {
if (!preloadPath) {
preloadPath = join(tmpdir(), `backstage-stdout-preload-${process.pid}.cjs`);
writeFileSync(preloadPath, preloadContent);
process.on('exit', () => {
try {
unlinkSync(preloadPath!);
} catch {
/* ignore */
}
});
}
return preloadPath;
}
/**
* Redirect stdout to a temp file so that Node.js creates a SyncWriteStream
* (synchronous writes) in the child instead of an async pipe stream. This
@@ -67,15 +35,11 @@ export function createBinRunner(cwd: string, path: string) {
const outFd = openSync(outPath, 'w');
try {
const result = spawnSync(
'node',
['--require', getPreloadPath(), ...args],
{
cwd,
stdio: ['ignore', outFd, 'pipe'],
maxBuffer: 10 * 1024 * 1024,
},
);
const result = spawnSync('node', args, {
cwd,
stdio: ['ignore', outFd, 'pipe'],
maxBuffer: 10 * 1024 * 1024,
});
closeSync(outFd);
const stdout = readFileSync(outPath, 'utf8');