mirror of
https://github.com/morluto/rea.git
synced 2026-11-03 21:36:13 +00:00
refactor(javascript): remove superseded full-IR analysis pipeline
This commit is contained in:
1 parent
cc7cc8155a
commit
e9abf39848
21 files changed
+410
-479
No files matched your search
@@ -1,17 +1,8 @@
|
||||
import { createHash } from "node:crypto";
|
||||
|
||||
import { moduleResolutionModeForJavaScriptReference } from "../../domain/javascript/javascriptModuleResolutionMode.js";
|
||||
import { setImmediate } from "node:timers/promises";
|
||||
|
||||
import { resolveJavaScriptSourceMapReferences } from "../../domain/javascript/javascriptSourceMapPaths.js";
|
||||
import { analyzeParsedJavaScriptStaticSourceSteps } from "../../domain/javascript/javascriptStaticAnalysis.js";
|
||||
import { analyzeParsedJavaScriptSemanticsSteps } from "../../domain/javascript/javascriptSemanticAnalysis.js";
|
||||
import type { JavaScriptSemanticIr } from "../../domain/javascript/javascriptSemanticIr.js";
|
||||
import {
|
||||
type JavaScriptModuleSemanticIr,
|
||||
projectJavaScriptModuleSemantics,
|
||||
} from "../../domain/javascript/javascriptModuleSemanticIr.js";
|
||||
import { parseJavaScriptSource } from "../../domain/javascript/javascriptSourceParser.js";
|
||||
import { hasValidSourceMapContents } from "../../domain/sourceMapContents.js";
|
||||
import {
|
||||
inspectSourceMapEnvelope,
|
||||
@@ -20,7 +11,6 @@ import {
|
||||
} from "../../domain/sourceMapEnvelope.js";
|
||||
import type { SourceMapLeaf } from "../../domain/sourceMapEnvelope.js";
|
||||
import type { JavaScriptStaticAnalysis } from "../../domain/javascript/javascriptStaticAnalysisTypes.js";
|
||||
import { failedJavaScriptStaticAnalysis } from "../../domain/javascript/javascriptStaticAnalysisHelpers.js";
|
||||
import type {
|
||||
JavaScriptArtifactFile,
|
||||
JavaScriptArtifactFileSet,
|
||||
@@ -34,7 +24,6 @@ import type {
|
||||
JavaScriptArtifactAnalysisFailure,
|
||||
JavaScriptArtifactAnalysisScope,
|
||||
JavaScriptArtifactAnalysis,
|
||||
JavaScriptModuleArtifactAnalysis,
|
||||
JavaScriptHtmlInlineScriptsObservation,
|
||||
JavaScriptHtmlScriptObservation,
|
||||
JavaScriptJsonModuleObservation,
|
||||
@@ -48,7 +37,7 @@ import {
|
||||
JavaScriptJsonDocuments,
|
||||
type JavaScriptJsonDocumentFacts,
|
||||
} from "./JavaScriptJsonDocuments.js";
|
||||
import { completeJavaScriptAnalysisSteps } from "./JavaScriptAnalysisControl.js";
|
||||
import { assertJavaScriptAnalysisActive } from "./JavaScriptAnalysisControl.js";
|
||||
import { htmlArtifactReferences } from "../../domain/javascript/htmlArtifactReferences.js";
|
||||
import type { JavaScriptSourceAnalysisPort } from "../../domain/javascript/javascriptSourceAnalysis.js";
|
||||
import type { JavaScriptSemanticGraphProjection } from "./JavaScriptSemanticGraphBuilder.js";
|
||||
@@ -62,11 +51,9 @@ import {
|
||||
AnalysisTimeoutError,
|
||||
} from "../../domain/analysisErrorCore.js";
|
||||
|
||||
interface MutableArtifactAnalysis<
|
||||
SemanticIr extends JavaScriptModuleSemanticIr,
|
||||
> {
|
||||
interface MutableArtifactAnalysis {
|
||||
readonly jsonDocuments: JavaScriptJsonDocuments;
|
||||
readonly files: AnalyzedJavaScriptArtifactFile<SemanticIr>[];
|
||||
readonly files: AnalyzedJavaScriptArtifactFile[];
|
||||
readonly packages: JavaScriptPackageObservation[];
|
||||
readonly jsonModules: JavaScriptJsonModuleObservation[];
|
||||
readonly htmlScripts: JavaScriptHtmlScriptObservation[];
|
||||
@@ -78,26 +65,6 @@ interface MutableArtifactAnalysis<
|
||||
parseFailures: number;
|
||||
}
|
||||
|
||||
interface ArtifactAnalysisContext<
|
||||
SemanticIr extends JavaScriptModuleSemanticIr,
|
||||
> {
|
||||
readonly state: MutableArtifactAnalysis<SemanticIr>;
|
||||
readonly projectSemantics: (
|
||||
file: JavaScriptArtifactFile,
|
||||
ir: JavaScriptSemanticIr,
|
||||
) => Generator<void, SemanticIr>;
|
||||
}
|
||||
|
||||
/** Analyze every text source from the artifact without a result quota. */
|
||||
export const analyzeJavaScriptArtifactFiles = (
|
||||
fileSet: JavaScriptArtifactFileSet,
|
||||
): JavaScriptArtifactAnalysis =>
|
||||
analyzeArtifactFiles(fileSet, function* (_file, ir) {
|
||||
// The full IR needs no projection; one step keeps the shared protocol.
|
||||
yield;
|
||||
return ir;
|
||||
});
|
||||
|
||||
/** Analyze sources behind a hard heap boundary, retaining collected facts on interruption. */
|
||||
export const analyzeAndAdoptJavaScriptArtifactFiles = async (
|
||||
fileSet: JavaScriptArtifactFileSet,
|
||||
@@ -111,10 +78,10 @@ export const analyzeAndAdoptJavaScriptArtifactFiles = async (
|
||||
signal?: AbortSignal,
|
||||
onPhase?: (file: JavaScriptArtifactFile, phase: string) => Promise<void>,
|
||||
): Promise<{
|
||||
readonly analysis: JavaScriptModuleArtifactAnalysis;
|
||||
readonly analysis: JavaScriptArtifactAnalysis;
|
||||
readonly interruption: AnalysisError | null;
|
||||
}> => {
|
||||
const state = emptyArtifactAnalysis<JavaScriptModuleSemanticIr>();
|
||||
const state = emptyArtifactAnalysis();
|
||||
let interruption: AnalysisError | null = null;
|
||||
const selectedFileCount =
|
||||
fileSet.files.length - (fileSet.source_selection?.unselected_files ?? 0);
|
||||
@@ -140,14 +107,9 @@ export const analyzeAndAdoptJavaScriptArtifactFiles = async (
|
||||
await beforeFile(file, selectedFileIndex++, selectedFileCount);
|
||||
analysisStarted = true;
|
||||
if (file.kind !== "javascript" || !file.text.included) {
|
||||
const steps = analyzeArtifactFileSteps(file, {
|
||||
state,
|
||||
projectSemantics: function* (_file, ir) {
|
||||
yield;
|
||||
return projectJavaScriptModuleSemantics(ir);
|
||||
},
|
||||
});
|
||||
await completeJavaScriptAnalysisSteps(steps, signal);
|
||||
assertJavaScriptAnalysisActive(signal);
|
||||
analyzeArtifactMetadata(file, state);
|
||||
assertJavaScriptAnalysisActive(signal);
|
||||
continue;
|
||||
}
|
||||
const result = await worker.analyze(
|
||||
@@ -317,24 +279,9 @@ export const analyzeAndAdoptJavaScriptArtifactFiles = async (
|
||||
return { analysis: finalizeArtifactAnalysis(state), interruption };
|
||||
};
|
||||
|
||||
const analyzeArtifactFiles = <SemanticIr extends JavaScriptModuleSemanticIr>(
|
||||
fileSet: JavaScriptArtifactFileSet,
|
||||
projectSemantics: ArtifactAnalysisContext<SemanticIr>["projectSemantics"],
|
||||
): JavaScriptArtifactAnalysis<SemanticIr> => {
|
||||
const state = emptyArtifactAnalysis<SemanticIr>();
|
||||
const context = { state, projectSemantics };
|
||||
for (const file of fileSet.files) {
|
||||
const steps = analyzeArtifactFileSteps(file, context);
|
||||
while (steps.next().done !== true);
|
||||
}
|
||||
return finalizeArtifactAnalysis(state);
|
||||
};
|
||||
|
||||
const finalizeArtifactAnalysis = <
|
||||
SemanticIr extends JavaScriptModuleSemanticIr,
|
||||
>(
|
||||
state: MutableArtifactAnalysis<SemanticIr>,
|
||||
): JavaScriptArtifactAnalysis<SemanticIr> => {
|
||||
const finalizeArtifactAnalysis = (
|
||||
state: MutableArtifactAnalysis,
|
||||
): JavaScriptArtifactAnalysis => {
|
||||
return {
|
||||
jsonDocuments: state.jsonDocuments,
|
||||
files: state.files,
|
||||
@@ -367,14 +314,10 @@ const finalizeArtifactAnalysis = <
|
||||
};
|
||||
};
|
||||
|
||||
function* analyzeArtifactFileSteps<
|
||||
SemanticIr extends JavaScriptModuleSemanticIr,
|
||||
>(
|
||||
const analyzeArtifactMetadata = (
|
||||
file: JavaScriptArtifactFile,
|
||||
context: ArtifactAnalysisContext<SemanticIr>,
|
||||
): Generator<void, void> {
|
||||
const { state } = context;
|
||||
if (classifyUnavailableSource(file, state)) return;
|
||||
state: MutableArtifactAnalysis,
|
||||
): void => {
|
||||
addStructuredObservations(file, state);
|
||||
if (file.kind === "html" && file.text.included) {
|
||||
const html = parseHtmlScripts(file.path, file.text.value);
|
||||
@@ -383,78 +326,23 @@ function* analyzeArtifactFileSteps<
|
||||
if (html.inlineScripts !== null)
|
||||
state.htmlInlineScripts.push(html.inlineScripts);
|
||||
}
|
||||
if (file.kind === "source-map") addSourceMap(file, context);
|
||||
if (file.kind !== "javascript" || !file.text.included) {
|
||||
state.files.push({ file, javascript: null, semantic: null });
|
||||
return;
|
||||
}
|
||||
const parsed = parseJavaScriptSource(file.text.value, file.path);
|
||||
yield;
|
||||
if (parsed === null) {
|
||||
const analysis = failedJavaScriptStaticAnalysis();
|
||||
state.files.push({ file, javascript: analysis, semantic: null });
|
||||
state.parseFailures += 1;
|
||||
return;
|
||||
}
|
||||
const analysis = yield* analyzeParsedJavaScriptStaticSourceSteps(
|
||||
file.text.value,
|
||||
parsed,
|
||||
);
|
||||
const staticFindings = findingCount(analysis);
|
||||
yield;
|
||||
const semantics =
|
||||
analysis.parse_status === "complete" || analysis.parse_status === "partial"
|
||||
? yield* analyzeParsedJavaScriptSemanticsSteps(
|
||||
parsed,
|
||||
moduleResolutionModeForJavaScriptReference(
|
||||
file.path,
|
||||
"static-import",
|
||||
),
|
||||
)
|
||||
: null;
|
||||
const projected =
|
||||
semantics === null
|
||||
? null
|
||||
: yield* context.projectSemantics(file, semantics);
|
||||
state.files.push({
|
||||
file,
|
||||
javascript: analysis,
|
||||
semantic: projected === null ? null : { ir: projected },
|
||||
});
|
||||
state.visitedNodes += analysis.visited_ast_nodes;
|
||||
state.findings += staticFindings + (semantics?.moduleLinks.length ?? 0);
|
||||
state.modules += analysis.bundler_registrations.reduce(
|
||||
(count, registration) => count + registration.modules.length,
|
||||
0,
|
||||
);
|
||||
if (analysis.parse_status === "failed") state.parseFailures += 1;
|
||||
}
|
||||
if (file.kind === "source-map") state.sourceMaps.push(parseSourceMap(file));
|
||||
state.files.push({ file, javascript: null, semantic: null });
|
||||
};
|
||||
|
||||
const classifyUnavailableSource = <
|
||||
SemanticIr extends JavaScriptModuleSemanticIr,
|
||||
>(
|
||||
const classifyUnavailableSource = (
|
||||
file: JavaScriptArtifactFile,
|
||||
state: MutableArtifactAnalysis<SemanticIr>,
|
||||
projection?: JavaScriptSemanticGraphProjection,
|
||||
state: MutableArtifactAnalysis,
|
||||
projection: JavaScriptSemanticGraphProjection,
|
||||
): boolean => {
|
||||
const reason = javaScriptArtifactTextExclusion(file);
|
||||
if (reason === null) return false;
|
||||
state.files.push({ file, javascript: null, semantic: null });
|
||||
projection?.recordUnavailableFile(file, reason, null, "incomplete-module");
|
||||
projection.recordUnavailableFile(file, reason, null, "incomplete-module");
|
||||
return true;
|
||||
};
|
||||
|
||||
const addSourceMap = (
|
||||
file: JavaScriptArtifactFile,
|
||||
context: ArtifactAnalysisContext<JavaScriptModuleSemanticIr>,
|
||||
): void => {
|
||||
const sourceMap = parseSourceMap(file);
|
||||
context.state.sourceMaps.push(sourceMap);
|
||||
};
|
||||
|
||||
const emptyArtifactAnalysis = <
|
||||
SemanticIr extends JavaScriptModuleSemanticIr,
|
||||
>(): MutableArtifactAnalysis<SemanticIr> => ({
|
||||
const emptyArtifactAnalysis = (): MutableArtifactAnalysis => ({
|
||||
jsonDocuments: new JavaScriptJsonDocuments(),
|
||||
files: [],
|
||||
packages: [],
|
||||
@@ -470,7 +358,7 @@ const emptyArtifactAnalysis = <
|
||||
|
||||
const addStructuredObservations = (
|
||||
file: JavaScriptArtifactFile,
|
||||
state: MutableArtifactAnalysis<JavaScriptModuleSemanticIr>,
|
||||
state: MutableArtifactAnalysis,
|
||||
): void => {
|
||||
if (file.kind === "package-json")
|
||||
state.packages.push(parsePackage(file, state.jsonDocuments.read(file)));
|
||||
|
||||
Reference in new issue
Block a user