mirror of
https://github.com/morluto/rea
synced 2026-10-26 14:25:49 -04:00
perf(javascript): reuse validated immutable graphs (#1112)
* perf(javascript): reuse validated immutable graphs * fix(ci): follow the moved process CLI boundary test
This commit is contained in:
@@ -1,7 +1,15 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { javascriptApplicationGraphSchema } from "./javascriptApplicationGraph.js";
|
||||
import { javaScriptSemanticGraphSchema } from "./javascriptSemanticGraph.js";
|
||||
import {
|
||||
javascriptApplicationGraphSchema,
|
||||
isValidatedImmutableJavaScriptApplicationGraph,
|
||||
type JavaScriptApplicationGraph,
|
||||
} from "./javascriptApplicationGraph.js";
|
||||
import {
|
||||
javaScriptSemanticGraphSchema,
|
||||
isValidatedImmutableJavaScriptSemanticGraph,
|
||||
type JavaScriptSemanticGraph,
|
||||
} from "./javascriptSemanticGraph.js";
|
||||
import { digestSchema } from "../digests.js";
|
||||
import { prefixedDigestSchema } from "../digests.js";
|
||||
|
||||
@@ -51,43 +59,62 @@ const reconstructionStatisticsSchema = z.strictObject({
|
||||
truncated_scopes: countSchema,
|
||||
});
|
||||
|
||||
/** JavaScript application analysis with an authenticated semantic companion. */
|
||||
export const javascriptApplicationAnalysisResultSchema = z
|
||||
.strictObject({
|
||||
input_path: z.string().min(1),
|
||||
format: z.enum(["asar", "directory"]),
|
||||
root_artifact_sha256: digestSchema,
|
||||
inventory_manifest_id: prefixedDigestSchema("agm"),
|
||||
inventory_graph_sha256: digestSchema,
|
||||
graph: javascriptApplicationGraphSchema,
|
||||
summary: electronBoundarySummarySchema,
|
||||
statistics: reconstructionStatisticsSchema,
|
||||
limitations: z.array(z.string().min(1)),
|
||||
semantic_graph: javaScriptSemanticGraphSchema,
|
||||
})
|
||||
.superRefine((result, context) => {
|
||||
if (result.semantic_graph.application_graph_id !== result.graph.graph_id)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["semantic_graph", "application_graph_id"],
|
||||
message: "Semantic graph must commit the containing application graph",
|
||||
});
|
||||
if (
|
||||
result.semantic_graph.root_artifact_sha256 !== result.root_artifact_sha256
|
||||
)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["semantic_graph", "root_artifact_sha256"],
|
||||
message: "Semantic graph must commit the containing root artifact",
|
||||
});
|
||||
const applicationNodeIds = new Set(
|
||||
result.graph.nodes.map(({ node_id }) => node_id),
|
||||
);
|
||||
for (const [nodeIndex, node] of result.semantic_graph.nodes.entries())
|
||||
const applicationAnalysisResultShape = z.strictObject({
|
||||
input_path: z.string().min(1),
|
||||
format: z.enum(["asar", "directory"]),
|
||||
root_artifact_sha256: digestSchema,
|
||||
inventory_manifest_id: prefixedDigestSchema("agm"),
|
||||
inventory_graph_sha256: digestSchema,
|
||||
graph: javascriptApplicationGraphSchema,
|
||||
summary: electronBoundarySummarySchema,
|
||||
statistics: reconstructionStatisticsSchema,
|
||||
limitations: z.array(z.string().min(1)),
|
||||
semantic_graph: javaScriptSemanticGraphSchema,
|
||||
});
|
||||
|
||||
type BindingIssue = {
|
||||
readonly code: "custom";
|
||||
readonly path: PropertyKey[];
|
||||
readonly message: string;
|
||||
};
|
||||
|
||||
function* checkApplicationBindingsSteps(
|
||||
result: z.infer<typeof applicationAnalysisResultShape>,
|
||||
context: { readonly addIssue: (issue: BindingIssue) => void },
|
||||
): Generator<void> {
|
||||
if (result.semantic_graph.application_graph_id !== result.graph.graph_id)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["semantic_graph", "application_graph_id"],
|
||||
message: "Semantic graph must commit the containing application graph",
|
||||
});
|
||||
if (
|
||||
result.semantic_graph.root_artifact_sha256 !== result.root_artifact_sha256
|
||||
)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["semantic_graph", "root_artifact_sha256"],
|
||||
message: "Semantic graph must commit the containing root artifact",
|
||||
});
|
||||
const applicationNodeIds = new Set<string>();
|
||||
let examined = 0;
|
||||
try {
|
||||
for (const node of result.graph.nodes) {
|
||||
applicationNodeIds.add(node.node_id);
|
||||
if (++examined === 4096) {
|
||||
examined = 0;
|
||||
yield;
|
||||
}
|
||||
}
|
||||
for (const [nodeIndex, node] of result.semantic_graph.nodes.entries()) {
|
||||
if (++examined === 4096) {
|
||||
examined = 0;
|
||||
yield;
|
||||
}
|
||||
for (const [
|
||||
identifierIndex,
|
||||
identifier,
|
||||
] of node.application_node_ids.entries())
|
||||
] of node.application_node_ids.entries()) {
|
||||
if (!applicationNodeIds.has(identifier))
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
@@ -100,8 +127,52 @@ export const javascriptApplicationAnalysisResultSchema = z
|
||||
],
|
||||
message: "Semantic node references an absent application node",
|
||||
});
|
||||
if (++examined === 4096) {
|
||||
examined = 0;
|
||||
yield;
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
applicationNodeIds.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/** JavaScript application analysis with an authenticated semantic companion. */
|
||||
export const javascriptApplicationAnalysisResultSchema =
|
||||
applicationAnalysisResultShape.superRefine((result, context) => {
|
||||
const steps = checkApplicationBindingsSteps(result, context);
|
||||
while (!steps.next().done) {
|
||||
// Public/imported results still receive complete synchronous validation.
|
||||
}
|
||||
});
|
||||
|
||||
const ownedAnalysisResultShape = applicationAnalysisResultShape.extend({
|
||||
graph: z.custom<JavaScriptApplicationGraph>(
|
||||
isValidatedImmutableJavaScriptApplicationGraph,
|
||||
),
|
||||
semantic_graph: z.custom<JavaScriptSemanticGraph>(
|
||||
isValidatedImmutableJavaScriptSemanticGraph,
|
||||
),
|
||||
});
|
||||
|
||||
/** Reuse exact owned graphs while validating metadata and cross-graph bindings. */
|
||||
export function* parseOwnedJavaScriptApplicationAnalysisSteps(
|
||||
input: unknown,
|
||||
): Generator<void, JavaScriptApplicationAnalysisResult> {
|
||||
const prepared = ownedAnalysisResultShape.safeParse(input);
|
||||
if (!prepared.success)
|
||||
return javascriptApplicationAnalysisResultSchema.parse(input);
|
||||
const issues: BindingIssue[] = [];
|
||||
yield* checkApplicationBindingsSteps(prepared.data, {
|
||||
addIssue: (issue) => {
|
||||
issues.push(issue);
|
||||
},
|
||||
});
|
||||
if (issues.length > 0) throw new z.ZodError(issues);
|
||||
return prepared.data;
|
||||
}
|
||||
|
||||
/** Parsed public JavaScript application analysis request. */
|
||||
export type AnalyzeJavaScriptApplicationInput = z.infer<
|
||||
typeof analyzeJavaScriptApplicationInputSchema
|
||||
|
||||
Reference in New Issue
Block a user