mirror of
https://github.com/morluto/rea
synced 2026-10-27 06:33:32 -04:00
9aca543f46
Run inert captured-script analysis in owned children with per-script and aggregate deadlines, bounded source/result transfer and explicit per-script coverage. Preserve completed facts and exact cleanup authority across cancellation, mixed descriptor/process failures and cross-consumer retry. Share aggregate source admission across page and Electron capture, expose CLI/MCP resource controls and retain selected parameters in Evidence. Verified with controlled CDP public workflows, real owned Node failure controls and the reporter-matching ReactDOM UMD artifact; real Chrome/Electron and Windows/Bun remain unqualified.
175 lines
5.8 KiB
TypeScript
175 lines
5.8 KiB
TypeScript
import { createHash } from "node:crypto";
|
|
import { access } from "node:fs/promises";
|
|
import { expect, it, vi } from "vitest";
|
|
|
|
const closeFailure = vi.hoisted(() => ({
|
|
enabled: false,
|
|
resultCloseAttempts: 0,
|
|
root: undefined as string | undefined,
|
|
rootRemovedBeforeResultClose: false,
|
|
}));
|
|
|
|
vi.mock("node:fs/promises", async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import("node:fs/promises")>();
|
|
return {
|
|
...actual,
|
|
rm: async (...args: Parameters<typeof actual.rm>) => {
|
|
if (
|
|
closeFailure.root !== undefined &&
|
|
String(args[0]) === closeFailure.root &&
|
|
closeFailure.resultCloseAttempts < 2
|
|
)
|
|
closeFailure.rootRemovedBeforeResultClose = true;
|
|
return await actual.rm(...args);
|
|
},
|
|
open: async (...args: Parameters<typeof actual.open>) => {
|
|
const handle = await actual.open(...args);
|
|
const path = args[0];
|
|
if (closeFailure.enabled && String(path).endsWith(".result")) {
|
|
closeFailure.enabled = false;
|
|
const close = handle.close.bind(handle);
|
|
let failOnce = true;
|
|
Object.defineProperty(handle, "close", {
|
|
configurable: true,
|
|
value: async () => {
|
|
closeFailure.resultCloseAttempts += 1;
|
|
if (failOnce) {
|
|
failOnce = false;
|
|
throw new Error("controlled completed-read close failure");
|
|
}
|
|
await close();
|
|
},
|
|
});
|
|
}
|
|
return handle;
|
|
},
|
|
};
|
|
});
|
|
|
|
import { createWebTextArtifact } from "../domain/webContentArtifact.js";
|
|
import type { IncludedScript } from "../domain/webBundleAnalyzerInspection.js";
|
|
import { ProviderCleanupError } from "../domain/providerCleanupError.js";
|
|
import { cleanupOwnedProcessGroup } from "../process/ProcessOwnership.js";
|
|
import {
|
|
spawnOwnedProviderProcess,
|
|
type ProviderProcessHandle,
|
|
} from "../process/ProviderProcess.js";
|
|
import { OwnedWorkerRuntime } from "../process/OwnedWorkerRuntime.js";
|
|
import { WebBundleAnalysisWorker } from "./WebBundleAnalysisWorker.js";
|
|
import { WEB_BUNDLE_WORKER_LIMITS } from "./WebBundleAnalysisWorkerProtocol.js";
|
|
|
|
const makeScript = (text: string): IncludedScript => ({
|
|
script_key: `scr_${createHash("sha256").update(text).digest("hex")}`,
|
|
frame_id: "frame-1",
|
|
url: "https://app.example.test/app.js",
|
|
origin: "https://app.example.test",
|
|
cdp_hash: null,
|
|
length: Buffer.byteLength(text),
|
|
is_module: false,
|
|
language: "JavaScript",
|
|
source_map_url: null,
|
|
resource_reconciliation: {
|
|
status: "unmatched",
|
|
reason: "no_exact_sanitized_url",
|
|
},
|
|
source: {
|
|
included: true,
|
|
artifact: createWebTextArtifact(text, "application/javascript"),
|
|
},
|
|
});
|
|
|
|
const ownedSourceLauncher = (
|
|
failCleanupOnce = false,
|
|
): typeof spawnOwnedProviderProcess => {
|
|
let failCleanup = failCleanupOnce;
|
|
return async (request) => {
|
|
const loader = import.meta.resolve("tsx");
|
|
const server = new URL(
|
|
"./WebBundleAnalysisWorkerServer.ts",
|
|
import.meta.url,
|
|
);
|
|
const analyzer = new URL("../domain/webBundleAnalyzer.ts", import.meta.url);
|
|
const program = `
|
|
const { serveWebBundleAnalysisWorker } = await import(${JSON.stringify(server.href)});
|
|
const { analyzeCapturedWebScript } = await import(${JSON.stringify(analyzer.href)});
|
|
await serveWebBundleAnalysisWorker(analyzeCapturedWebScript);
|
|
`;
|
|
const spawned = await spawnOwnedProviderProcess({
|
|
...request,
|
|
arguments: [
|
|
`--max-old-space-size=${String(WEB_BUNDLE_WORKER_LIMITS.heapMb)}`,
|
|
"--expose-gc",
|
|
"--import",
|
|
loader,
|
|
"--input-type=module",
|
|
"-e",
|
|
program,
|
|
],
|
|
});
|
|
closeFailure.root = request.cwd;
|
|
return {
|
|
...spawned,
|
|
cleanup: async () => {
|
|
if (failCleanup) {
|
|
failCleanup = false;
|
|
return {
|
|
cleaned: false,
|
|
reason: "controlled first process cleanup failure",
|
|
};
|
|
}
|
|
return spawned.cleanup === undefined
|
|
? cleanupOwnedProcessGroup(spawned.ownership)
|
|
: spawned.cleanup();
|
|
},
|
|
};
|
|
};
|
|
};
|
|
|
|
it("retains completed facts and resolves a result-file lease through another cleanup consumer", async () => {
|
|
const children: ProviderProcessHandle[] = [];
|
|
const launch = ownedSourceLauncher(true);
|
|
const worker = new WebBundleAnalysisWorker(
|
|
WEB_BUNDLE_WORKER_LIMITS.heapMb,
|
|
async (request) => {
|
|
const spawned = await launch(request);
|
|
children.push(spawned.process);
|
|
return spawned;
|
|
},
|
|
);
|
|
closeFailure.resultCloseAttempts = 0;
|
|
closeFailure.rootRemovedBeforeResultClose = false;
|
|
closeFailure.enabled = true;
|
|
try {
|
|
const result = await worker.analyze(
|
|
makeScript("fetch('/retained');"),
|
|
10_000,
|
|
);
|
|
expect(result.ok).toBe(false);
|
|
if (result.ok) throw new Error("Expected retained result cleanup failure");
|
|
expect(result.error.completed).toMatchObject({
|
|
status: "analyzed",
|
|
script_key: makeScript("fetch('/retained');").script_key,
|
|
observations: {
|
|
endpoints: [{ value: "/retained", mechanism: "call:fetch" }],
|
|
},
|
|
});
|
|
expect(result.error.error.cleanupPrimary).toBeInstanceOf(
|
|
ProviderCleanupError,
|
|
);
|
|
expect(result.error.error.cleanupIncomplete).toBe(true);
|
|
expect(closeFailure.resultCloseAttempts).toBe(1);
|
|
expect(closeFailure.root).toBeDefined();
|
|
await access(closeFailure.root ?? "");
|
|
expect(children).toHaveLength(1);
|
|
|
|
await OwnedWorkerRuntime.retryPending();
|
|
expect(result.error.error.cleanupIncomplete).toBe(false);
|
|
expect(closeFailure.resultCloseAttempts).toBeGreaterThanOrEqual(2);
|
|
expect(closeFailure.rootRemovedBeforeResultClose).toBe(false);
|
|
await expect(access(closeFailure.root ?? "")).rejects.toThrow();
|
|
} finally {
|
|
await worker.close().catch(() => undefined);
|
|
await OwnedWorkerRuntime.retryPending().catch(() => undefined);
|
|
}
|
|
});
|