Files
openclaw/scripts/vitest-process-group.mjs
2026-04-06 18:10:44 +01:00

79 lines
2.0 KiB
JavaScript

export function shouldUseDetachedVitestProcessGroup(platform = process.platform) {
return platform !== "win32";
}
export function resolveVitestProcessGroupSignalTarget(params) {
const pid = params.childPid;
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0) {
return null;
}
return shouldUseDetachedVitestProcessGroup(params.platform) ? -pid : pid;
}
export function forwardSignalToVitestProcessGroup(params) {
const target = resolveVitestProcessGroupSignalTarget({
childPid: params.child.pid,
platform: params.platform,
});
if (target === null) {
return false;
}
try {
params.kill(target, params.signal);
return true;
} catch (error) {
if (error && typeof error === "object" && "code" in error && error.code === "ESRCH") {
return false;
}
throw error;
}
}
export function installVitestProcessGroupCleanup(params) {
const processObject = params.processObject ?? process;
const platform = params.platform ?? process.platform;
const kill = params.kill ?? process.kill.bind(process);
const cleanupSignal = params.cleanupSignal ?? "SIGTERM";
const forwardedSignals = params.forwardedSignals ?? ["SIGINT", "SIGTERM"];
const child = params.child;
let active = true;
const forward = (signal) => {
if (!active) {
return;
}
forwardSignalToVitestProcessGroup({
child,
signal,
platform,
kill,
});
};
const signalHandlers = new Map();
for (const signal of forwardedSignals) {
const handler = () => {
forward(signal);
};
signalHandlers.set(signal, handler);
processObject.on(signal, handler);
}
const exitHandler = () => {
forward(cleanupSignal);
};
processObject.on("exit", exitHandler);
return () => {
if (!active) {
return;
}
active = false;
for (const [signal, handler] of signalHandlers) {
processObject.off(signal, handler);
}
processObject.off("exit", exitHandler);
};
}