mirror of
https://github.com/mvschwarz/openrig.git
synced 2026-11-07 05:56:21 -10:00
fix(cli): avoid cold compile-cache writes for piped bare usage (#2643)
bin-wrapper enables Node's compile cache except for a bare invocation with stdin or stdout piped or redirected, which only prints usage. That case loaded the command tree only to print usage, and with a cold cache the deferred cache writes near exit could push it past a caller's deadline after the usage was already printed. Any script argument, including piped --help and --version, and a bare run with both streams on a terminal, keep the existing cache attempt, matching the front door's own predicate. A new bin-wrapper test covers the piped and terminal cases. Contributed by seanmcn; reported in #2642.
This commit is contained in:
1 parent
b1065870f6
commit
378d25301d
2 files changed
+39
-1
No files matched your search
@@ -12,7 +12,8 @@ const REEXEC_GUARD_ENV = "OPENRIG_BIN_REEXEC";
|
||||
// Each `rig` is a new process: Node's on-disk compile cache lets the next call skip compiling the modules
|
||||
// again. The cache dates from Node v22.1.0, but this JavaScript API from v22.8.0: before it, `?.()` does
|
||||
// nothing. NODE_COMPILE_CACHE and NODE_DISABLE_COMPILE_CACHE still control it.
|
||||
module.enableCompileCache?.();
|
||||
// A piped bare invocation only prints usage; cold-cache writes can otherwise delay its exit.
|
||||
if (process.argv.length > 2 || (process.stdin.isTTY && process.stdout.isTTY)) module.enableCompileCache?.();
|
||||
|
||||
export function resolveBinEntry(invokedPath = process.argv[1], moduleUrl = import.meta.url): string {
|
||||
const wrapperPath = invokedPath ? realpathSync(invokedPath) : realpathSync(fileURLToPath(moduleUrl));
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import ts from "typescript";
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import module from "node:module";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
import { resolveBinEntry, resolveNodeReexecBinary, run } from "../src/bin-wrapper.js";
|
||||
@@ -15,6 +18,40 @@ describe("bin-wrapper", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it.skipIf(!module.getCompileCacheDir || !module.enableCompileCache).each([
|
||||
{ args: [], interactive: false, explicitCache: false, expected: false },
|
||||
{ args: ["--version"], interactive: false, explicitCache: false, expected: true },
|
||||
{ args: [], interactive: false, explicitCache: true, expected: true },
|
||||
{ args: [], interactive: true, explicitCache: false, expected: true },
|
||||
])("compile cache for args=$args, interactive=$interactive, explicitCache=$explicitCache", ({ args, interactive, explicitCache, expected }) => {
|
||||
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openrig-bin-cache-"));
|
||||
const dist = path.join(tempDir, "dist");
|
||||
fs.mkdirSync(dist);
|
||||
fs.writeFileSync(path.join(tempDir, "package.json"), '{ "type": "module" }');
|
||||
const wrapper = path.join(dist, "bin-wrapper.js");
|
||||
const source = fs.readFileSync(new URL("../src/bin-wrapper.ts", import.meta.url), "utf8");
|
||||
const { outputText } = ts.transpileModule(source, {
|
||||
compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext },
|
||||
});
|
||||
fs.writeFileSync(wrapper, outputText);
|
||||
const report = `import { getCompileCacheDir } from "node:module";
|
||||
export async function runProgram() { console.log(JSON.stringify({ enabled: !!getCompileCacheDir() })); }
|
||||
`;
|
||||
fs.writeFileSync(path.join(dist, "index.js"), report + "export function createProgram() { return {}; }\n");
|
||||
fs.writeFileSync(path.join(dist, "lazy-program.js"), report + "export async function createLazyProgram() { return {}; }\n");
|
||||
const env = { ...process.env, TMPDIR: tempDir };
|
||||
delete env.NODE_DISABLE_COMPILE_CACHE;
|
||||
delete env.NODE_COMPILE_CACHE;
|
||||
if (explicitCache) env.NODE_COMPILE_CACHE = path.join(tempDir, "explicit-cache");
|
||||
// Set stream flags before the wrapper loads; front-door.test.ts covers a real PTY launch.
|
||||
const nodeArgs = interactive
|
||||
? ["--import", "data:text/javascript,process.stdin.isTTY=true;process.stdout.isTTY=true"]
|
||||
: [];
|
||||
const result = spawnSync(process.execPath, [...nodeArgs, wrapper, ...args], { env, encoding: "utf8", timeout: 5000 });
|
||||
expect(result.status, result.stderr).toBe(0);
|
||||
expect(JSON.parse(result.stdout)).toEqual({ enabled: expected });
|
||||
});
|
||||
|
||||
it("resolves the real dist entry from a symlinked wrapper path", () => {
|
||||
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openrig-bin-wrapper-"));
|
||||
const wrapperSource = fileURLToPath(new URL("../src/bin-wrapper.ts", import.meta.url));
|
||||
|
||||
Reference in new issue
Block a user