fix(javascript): preserve selected inputs and completed source evidence

This commit is contained in:
morluto committed 2026-10-26 17:39:29 +08:00
1 parent 3864c7d667
commit 721dd3d1aa
11 files changed
+453 -177

No files matched your search

+3 -91
View File
@@ -3,25 +3,18 @@ import type { WebSourceMapPort } from "../../application/WebSourceLocationPorts.
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
import {
AnalysisCancelledError,
AnalysisCapabilityUnavailableError,
AnalysisInputError,
AnalysisOutputError,
} from "../../domain/analysisErrorCore.js";
import { ArtifactOperationError } from "../../domain/artifactOperationError.js";
import { err, ok, type Result } from "../../domain/result.js";
import { javaScriptRuntime } from "../../domain/runtimeVersion.js";
import { err, type Result } from "../../domain/result.js";
import { noRuntimeOverrideSentence } from "../../domain/browserDeadline.js";
import {
DEFAULT_WEB_SOURCE_MAP_DECODE_TIMEOUT_MS,
WEB_SOURCE_MAP_LIMITS,
type WebSourceMapReport,
} from "../../domain/webSourceLocation.js";
import { sourceMapCodecInputSchema } from "./SourceMapCodecProtocol.js";
import {
sourceMapCodecInputSchema,
sourceMapCodecReplySchema,
} from "./SourceMapCodecProtocol.js";
import {
SOURCE_MAP_CODEC_MEMORY_LIMIT_BYTES,
runSourceMapCommand,
type SourceMapCleanupOwner,
type SourceMapCleanupRetention,
@@ -125,36 +118,7 @@ export class SourceMapDecoder implements WebSourceMapPort {
);
if (retainedCleanup.owner !== undefined)
this.#pendingCleanup = retainedCleanup.owner;
if (!response.ok) return response;
let value: unknown;
try {
value = JSON.parse(response.value);
} catch (cause: unknown) {
return err(
new AnalysisOutputError(
OPERATION,
`Malformed codec JSON reply: ${cause instanceof Error ? cause.message : String(cause)}`,
),
);
}
const reply = sourceMapCodecReplySchema.safeParse(value);
if (!reply.success)
return err(
new AnalysisOutputError(
OPERATION,
`Malformed codec reply: ${reply.error.message}`,
),
);
if (options?.signal?.aborted)
return err(
new AnalysisCancelledError(OPERATION, { cause: options.signal.reason }),
);
if (reply.data.state === "failure")
return codecFailure(input.path, reply.data.reason, reply.data.message);
const runtimeFailure = codecRuntimeFailure(reply.data.report.runtime);
return runtimeFailure === undefined
? ok(reply.data.report)
: err(new AnalysisOutputError(OPERATION, runtimeFailure));
return response;
}
async close(): Promise<void> {
@@ -180,55 +144,3 @@ export class SourceMapDecoder implements WebSourceMapPort {
return undefined;
}
}
/**
* The codec runs on this process's executable. Only a V8 report carries a heap
* limit; a Bun report must name the process limit its launcher enforced.
*/
const codecRuntimeFailure = (
runtime: WebSourceMapReport["runtime"],
): string | undefined => {
if (
runtime.id !==
(javaScriptRuntime(process.versions).id === "bun" ? "bun" : "node-v8")
)
return `Codec reported runtime ${runtime.id}, not the runtime that launched it.`;
if (
runtime.id === "node-v8" &&
runtime.v8_heap_limit_bytes > 256 * 1024 * 1024
)
return "Codec reported a V8 heap limit exceeding its independent process budget.";
if (
runtime.id === "bun" &&
runtime.process_memory_limit_bytes !== SOURCE_MAP_CODEC_MEMORY_LIMIT_BYTES
)
return "Codec reported a process memory limit other than the one its launcher enforced.";
return undefined;
};
const codecFailure = (
path: string,
reason: "format" | "unsupported" | "limit",
detail: string,
): Result<never, AnalysisError> =>
err(
reason === "limit"
? new ArtifactOperationError(
OPERATION,
"limit",
undefined,
`${path}: ${detail}`,
)
: reason === "unsupported"
? new AnalysisCapabilityUnavailableError(
"source-map-decoder",
OPERATION,
"unsupported_source_map_profile",
{ userMessage: `${path}: ${detail}` },
)
: new AnalysisInputError(OPERATION, undefined, [
{
path: ["source_map", "path"],
reason: "invalid_format",
message: `${path}: ${detail}`,
},
]),
);