Files
rea/src/composition/javascriptAnalysisWorkerProcess.ts
T
morluto b8fab74297 fix(javascript): preserve execution and invocation provenance
Keep direct empty bridge objects observed, reject unexecuted initializers,
invalidate modified bootstrap tables and Electron identities, and retain
selection predicates through symbolic values and wrapper paths. Track lexical
binding identity and completed activation boundaries without leaking analysis
order into earlier reads.

Separate wrapper invocation provenance from the underlying IPC source range
so repeated registrations remain ambiguous through transfer and graph joins.
Use the same offered transfer budget for module preflight and final writing.

Index static literal properties once instead of rescanning every member. Keep
the original 10,001-member capacity fixture; Flameox confirmed the repeated
lookup cost and the optimized fixture completes in under one second locally.
Prune the stale compact-schema tool inventory assertion and update the public
call-graph registration expectation to its declared result envelope.

Validation: build, check, docs:check, 83 focused tests, 10 Electron identity
acceptance cases, 2 full-scale finding-capacity cases, and 7 compact-schema
transport tests. No real Electron runtime execution is claimed.
2026-10-12 10:03:17 +08:00

94 lines
3.4 KiB
TypeScript

import { parseJavaScriptSource } from "../domain/javascript/javascriptSourceParser.js";
import { analyzeParsedJavaScriptStaticSourceSteps } from "../domain/javascript/javascriptStaticAnalysis.js";
import {
analyzeParsedJavaScriptSemanticsSteps,
classifyParsedJavaScriptOpenReceiversSteps,
} from "../domain/javascript/javascriptSemanticAnalysis.js";
import { failedJavaScriptStaticAnalysis } from "../domain/javascript/javascriptStaticAnalysisHelpers.js";
import { projectJavaScriptModuleSemantics } from "../domain/javascript/javascriptModuleSemanticIr.js";
import {
javaScriptTransferByteBudget,
measureJavaScriptModuleTransfer,
} from "../javascript/analysis/JavaScriptAnalysisTransfer.js";
import { AnalysisResourceConstraintError } from "../domain/analysisErrorCore.js";
import { projectJavaScriptSemanticFileSteps } from "../application/javascript/JavaScriptSemanticGraphBuilder.js";
import { completeJavaScriptAnalysisSteps } from "../application/javascript/JavaScriptAnalysisControl.js";
import {
serveJavaScriptAnalysisWorker,
type JavaScriptSourceWorkerAnalyzer,
} from "../javascript/analysis/JavaScriptAnalysisWorkerServer.js";
const analyze: JavaScriptSourceWorkerAnalyzer = async (
file,
nodeBudget,
callbacks,
) => {
if (!file.text.included)
throw new TypeError("JavaScript worker requires decoded source text");
await callbacks.phase("parse");
let parsed = parseJavaScriptSource(file.text.value, file.path);
if (parsed === null) {
await callbacks.checkpoint(failedJavaScriptStaticAnalysis());
return null;
}
await callbacks.phase("static");
const receivers = await completeJavaScriptAnalysisSteps(
classifyParsedJavaScriptOpenReceiversSteps(parsed),
);
const facts = await completeJavaScriptAnalysisSteps(
analyzeParsedJavaScriptStaticSourceSteps(
file.text.value,
parsed,
receivers,
),
);
const resultBudgetBytes = await callbacks.checkpoint(facts);
if (facts.parse_status === "failed") return null;
if (resultBudgetBytes === 0)
throw new AnalysisResourceConstraintError(
"analyze_javascript_application",
"memory",
`The parent reserved its remaining result capacity for static observations; semantic analysis of ${file.path} was not started`,
{ semantic_result_budget_bytes: 0 },
);
await callbacks.phase("semantic");
const ir = await completeJavaScriptAnalysisSteps(
analyzeParsedJavaScriptSemanticsSteps(parsed),
);
parsed = null;
const module = projectJavaScriptModuleSemantics(ir);
const measured = measureJavaScriptModuleTransfer(
module,
javaScriptTransferByteBudget(resultBudgetBytes),
);
if (measured.retentionBytes > resultBudgetBytes)
throw new AnalysisResourceConstraintError(
"analyze_javascript_application",
"memory",
`Completed module facts for ${file.path} exceed the parent's offered result budget; static facts were retained`,
{
semantic_result_budget_bytes: resultBudgetBytes,
module_transfer_bytes: measured.bytes,
},
);
await callbacks.phase("projection");
const projection = await completeJavaScriptAnalysisSteps(
projectJavaScriptSemanticFileSteps(
file,
ir,
nodeBudget,
facts.electron.call_paths,
),
);
return { module, projection };
};
try {
await serveJavaScriptAnalysisWorker(analyze);
} catch (cause: unknown) {
process.stderr.write(
`${cause instanceof Error ? cause.message : String(cause)}\n`,
);
process.exitCode = 1;
}