From 15edc7191419716c1be1b05e70db457617e24bc5 Mon Sep 17 00:00:00 2001 From: morluto <76467478+morluto@users.noreply.github.com> Date: Sat, 24 Oct 2026 05:32:43 +0800 Subject: [PATCH] refactor(javascript): remove obsolete in-process projection runner --- .../javascript/JavaScriptArtifactAnalysis.ts | 40 ------------------- .../javascriptApplicationService.test.ts | 28 +++++++------ .../javascriptArtifactReconstruction.test.ts | 28 ++++++++++--- 3 files changed, 39 insertions(+), 57 deletions(-) diff --git a/src/application/javascript/JavaScriptArtifactAnalysis.ts b/src/application/javascript/JavaScriptArtifactAnalysis.ts index 38836f40fd..e8b315ebde 100644 --- a/src/application/javascript/JavaScriptArtifactAnalysis.ts +++ b/src/application/javascript/JavaScriptArtifactAnalysis.ts @@ -94,46 +94,6 @@ export const analyzeJavaScriptArtifactFiles = ( return ir; }); -/** - * Project each file's full IR immediately, retaining only later module facts. - * Parsing, analysis and each projection pass run as separate steps, so control - * messages and cancellation are handled within one large file as well. - */ -export const analyzeAndProjectJavaScriptArtifactFiles = async ( - fileSet: JavaScriptArtifactFileSet, - projectSemantics: ( - file: JavaScriptArtifactFile, - ir: JavaScriptSemanticIr, - ) => Iterator | void, - beforeFile?: ( - file: JavaScriptArtifactFile, - completed: number, - total: number, - ) => Promise, - signal?: AbortSignal, -): Promise => { - const state = emptyArtifactAnalysis(); - const projectFileSemantics = function* ( - file: JavaScriptArtifactFile, - ir: JavaScriptSemanticIr, - ): Generator { - const projection = projectSemantics(file, ir); - if (projection !== undefined) while (projection.next().done !== true) yield; - return projectJavaScriptModuleSemantics(ir); - }; - const context = { state, projectSemantics: projectFileSemantics }; - for (const [index, file] of fileSet.files.entries()) { - // Let progress, cancellation and garbage collection run between files. - await setImmediate(); - await beforeFile?.(file, index, fileSet.files.length); - await completeJavaScriptAnalysisSteps( - analyzeArtifactFileSteps(file, context), - signal, - ); - } - return finalizeArtifactAnalysis(state); -}; - /** Analyze sources behind a hard heap boundary, retaining collected facts on interruption. */ export const analyzeAndAdoptJavaScriptArtifactFiles = async ( fileSet: JavaScriptArtifactFileSet, diff --git a/tests/boundary/filesystem/javascript-applications/javascriptApplicationService.test.ts b/tests/boundary/filesystem/javascript-applications/javascriptApplicationService.test.ts index 7bec8204a8..9bf2f1eecf 100644 --- a/tests/boundary/filesystem/javascript-applications/javascriptApplicationService.test.ts +++ b/tests/boundary/filesystem/javascript-applications/javascriptApplicationService.test.ts @@ -181,21 +181,25 @@ it("resolves lazy package and JSON facts without completing their skipped observ outcome.analysis, ); expect(graph.coverage.status).toBe("partial"); - expect( - graph.edges.find( - ({ relation, properties }) => - relation === "imports" && properties.specifier === "late-pkg", - )?.properties, - ).toMatchObject({ + const packageRelationships = graph.edges.filter( + ({ relation, properties }) => + relation === "imports" && + properties.module_link_kind === "require" && + properties.specifier === "late-pkg", + ); + expect(packageRelationships).toHaveLength(1); + expect(packageRelationships[0]?.properties).toMatchObject({ resolution_status: "resolved", resolved_path: "app/node_modules/late-pkg/index.cjs", }); - expect( - graph.edges.find( - ({ relation, properties }) => - relation === "imports" && properties.specifier === "./config.json", - )?.properties, - ).toMatchObject({ + const jsonRelationships = graph.edges.filter( + ({ relation, properties }) => + relation === "imports" && + properties.module_link_kind === "require" && + properties.specifier === "./config.json", + ); + expect(jsonRelationships).toHaveLength(1); + expect(jsonRelationships[0]?.properties).toMatchObject({ target_file_kind: "json", target_json_status: "included", }); diff --git a/tests/boundary/filesystem/javascript-applications/javascriptArtifactReconstruction.test.ts b/tests/boundary/filesystem/javascript-applications/javascriptArtifactReconstruction.test.ts index fc40ec29da..714d5b8e5b 100644 --- a/tests/boundary/filesystem/javascript-applications/javascriptArtifactReconstruction.test.ts +++ b/tests/boundary/filesystem/javascript-applications/javascriptArtifactReconstruction.test.ts @@ -19,7 +19,7 @@ import { } from "../../../support/javascriptApplicationScope.js"; import { analyzeJavaScriptArtifactFiles, - analyzeAndProjectJavaScriptArtifactFiles, + analyzeAndAdoptJavaScriptArtifactFiles, } from "../../../../src/application/javascript/JavaScriptArtifactAnalysis.js"; import { buildJavaScriptArtifactGraph } from "../../../../src/application/javascript/JavaScriptArtifactGraphBuilder.js"; import { @@ -40,6 +40,7 @@ import { } from "../../../../src/javascript/analysis/JavaScriptAnalysisTransfer.js"; import { javaScriptWorkerStaticAnalysisSchema } from "../../../../src/javascript/analysis/JavaScriptAnalysisWorkerSchemas.js"; import { createJavaScriptArtifactReader } from "../../../../src/artifacts/javascript/JavaScriptArtifactReader.js"; +import { createJavaScriptSourceAnalysis } from "../../../../src/artifacts/javascript/JavaScriptSourceAnalysis.js"; import { scanCanonicalArtifactInventory, scanArtifactInventory, @@ -556,7 +557,7 @@ it("reports file progress and honors cancellation before the next source", async expect(progress[0]).not.toBe(progress[1]); }); -it("preserves graph commitments and export shapes when consuming file-local IR", async () => { +it("preserves graph commitments and export shapes through worker adoption", async () => { const root = await fixtureDirectory(); await writeFile( join(root, "exports.mjs"), @@ -574,10 +575,27 @@ it("preserves graph commitments and export shapes when consuming file-local IR", const files = await readJavaScriptArtifactFiles(reader, snapshot); const full = analyzeJavaScriptArtifactFiles(files); const projection = createJavaScriptSemanticGraphProjection(); - const compact = await analyzeAndProjectJavaScriptArtifactFiles( - files, - projection.projectFile, + const worker = await createJavaScriptSourceAnalysis( + { heapMb: 512, timeoutMs: 30_000 }, + files.files.filter( + (file) => file.kind === "javascript" && file.text.included, + ).length, ); + let outcome: Awaited< + ReturnType + >; + try { + outcome = await analyzeAndAdoptJavaScriptArtifactFiles( + files, + worker, + projection, + async () => {}, + ); + } finally { + await worker.close(); + } + if (outcome.interruption !== null) throw outcome.interruption; + const compact = outcome.analysis; const graph = buildJavaScriptArtifactGraph(snapshot, files, full); expect(buildJavaScriptArtifactGraph(snapshot, files, compact)).toEqual( graph,