perf(javascript): derive the application graph ID once
createJavaScriptApplicationGraph hashed the whole graph to derive its graph_id, then parsed it with the public schema, whose invariant check hashed the same content again to verify that ID. Validate the content with every other invariant first, then derive graph_id once from the validated copy. The public schema still verifies graph_id for stored and untrusted graphs, and created graphs are unchanged.
This commit is contained in:
parent
79f6756239
commit
934ffd28d1
|
|
@ -547,6 +547,21 @@ describe("JavaScript Application Graph: source maps and observations", () => {
|
|||
/Edge identifier/u,
|
||||
);
|
||||
});
|
||||
|
||||
it("creates exactly the graph the public schema accepts", () => {
|
||||
const graph = buildSyntheticJavaScriptApplicationGraph();
|
||||
expect(JSON.stringify(graph)).toBe(
|
||||
JSON.stringify(
|
||||
javascriptApplicationGraphSchema.parse(structuredClone(graph)),
|
||||
),
|
||||
);
|
||||
|
||||
const { graph_id: _graphId, ...semantic } = structuredClone(graph);
|
||||
firstOf(semantic.edges, "edge").edge_id = `jag_edge_${"f".repeat(64)}`;
|
||||
expect(() => createJavaScriptApplicationGraph(semantic)).toThrow(
|
||||
/Edge identifier/u,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("JavaScript Application Graph: duplicate and orphan rejection", () => {
|
||||
|
|
|
|||
|
|
@ -304,8 +304,8 @@ const checkNode = (
|
|||
|
||||
type GraphRecord = z.infer<typeof javascriptApplicationGraphRecordSchema>;
|
||||
|
||||
const checkGraphInvariants = (
|
||||
graph: GraphRecord,
|
||||
const checkGraphContent = (
|
||||
graph: JavaScriptApplicationGraphInput,
|
||||
context: z.RefinementCtx,
|
||||
): void => {
|
||||
sortedUniqueIssue(
|
||||
|
|
@ -394,7 +394,13 @@ const checkGraphInvariants = (
|
|||
context,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const checkGraphInvariants = (
|
||||
graph: GraphRecord,
|
||||
context: z.RefinementCtx,
|
||||
): void => {
|
||||
checkGraphContent(graph, context);
|
||||
const { graph_id: identifier, ...semantic } = graph;
|
||||
if (
|
||||
identifier !==
|
||||
|
|
@ -411,6 +417,9 @@ const checkGraphInvariants = (
|
|||
export const javascriptApplicationGraphSchema =
|
||||
javascriptApplicationGraphRecordSchema.superRefine(checkGraphInvariants);
|
||||
|
||||
const javascriptApplicationGraphContentSchema =
|
||||
javascriptApplicationGraphInputSchema.superRefine(checkGraphContent);
|
||||
|
||||
/** Fully validated JavaScript Application Graph. */
|
||||
export type JavaScriptApplicationGraph = z.infer<
|
||||
typeof javascriptApplicationGraphSchema
|
||||
|
|
@ -482,10 +491,11 @@ export const createJavaScriptApplicationGraph = (
|
|||
},
|
||||
limitations: uniqueSorted(parsed.limitations),
|
||||
};
|
||||
return javascriptApplicationGraphSchema.parse({
|
||||
...semantic,
|
||||
graph_id: `jag_${digestCanonicalValue(semantic, "JavaScript Application Graph")}`,
|
||||
});
|
||||
const content = javascriptApplicationGraphContentSchema.parse(semantic);
|
||||
return {
|
||||
...content,
|
||||
graph_id: `jag_${digestCanonicalValue(content, "JavaScript Application Graph")}`,
|
||||
};
|
||||
};
|
||||
|
||||
const validatedImmutableApplicationGraphs = new WeakSet<object>();
|
||||
|
|
|
|||
Loading…
Reference in New Issue