fix(javascript): accept retained empty endpoint seeds (#6462)
Application analysis preserves the complete literal request endpoint,
including the empty string, and the event seed already accepts a
retained empty name. The endpoint seed still required a non-empty
value, so trace-javascript-semantics refused to select a retained ""
endpoint with invalid_request.
The endpoint seed now accepts any string and keeps exact matching.
Boundary-field seeds keep their minimum because boundary nodes are only
produced from method names.
Found while fixing #6458; the event half of that report landed in
cf5e4f6fa.
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
193e01abb1
commit
b912ec184c
2 files changed
+64
-1
No files matched your search
@@ -42,9 +42,11 @@ export const javaScriptSemanticQuerySeedSchema = z.discriminatedUnion("kind", [
|
||||
kind: z.literal("property"),
|
||||
name: z.string(),
|
||||
}),
|
||||
// Analysis preserves the complete literal endpoint, including the empty
|
||||
// string, so the seed matches any retained value exactly, as event does.
|
||||
z.strictObject({
|
||||
kind: z.literal("endpoint"),
|
||||
value: z.string().min(1),
|
||||
value: z.string(),
|
||||
}),
|
||||
z.strictObject({
|
||||
kind: z.literal("event"),
|
||||
|
||||
@@ -162,3 +162,64 @@ cliTest(
|
||||
},
|
||||
120_000,
|
||||
);
|
||||
|
||||
cliTest(
|
||||
"traces a retained empty literal endpoint by its preserved value",
|
||||
async ({ cli }) => {
|
||||
const root = await createTestTempDirectory("rea-empty-endpoint-seed-");
|
||||
await writeFile(
|
||||
join(root, "main.js"),
|
||||
'export const load = async () => (await fetch("")).json();\n',
|
||||
);
|
||||
const analyzed = await cli.run({
|
||||
arguments: [
|
||||
"analyze-javascript-application",
|
||||
root,
|
||||
"--artifact-format",
|
||||
"directory",
|
||||
"--json",
|
||||
],
|
||||
timeoutMs: 60_000,
|
||||
});
|
||||
expect(analyzed.exitCode, analyzed.stderr).toBe(0);
|
||||
const application = toolContract(
|
||||
"analyze_javascript_application",
|
||||
).outputSchema.parse(analyzed.json);
|
||||
const graph = javascriptApplicationAnalysisResultSchema.parse(
|
||||
application.normalized_result,
|
||||
).semantic_graph;
|
||||
// Analysis keeps the complete literal endpoint, here the empty string.
|
||||
const retained = new Set(
|
||||
graph.nodes
|
||||
.filter(
|
||||
(node) =>
|
||||
(node.kind === "request" || node.kind === "response") &&
|
||||
node.properties.endpoint === "",
|
||||
)
|
||||
.map((node) => node.node_id),
|
||||
);
|
||||
expect(retained.size).toBeGreaterThan(0);
|
||||
const request = join(root, "endpoint-query.json");
|
||||
await writeFile(
|
||||
request,
|
||||
JSON.stringify({
|
||||
application,
|
||||
query: {
|
||||
seed: { kind: "endpoint", value: "" },
|
||||
direction: "forward-influence",
|
||||
},
|
||||
}),
|
||||
);
|
||||
const traced = await cli.run({
|
||||
arguments: ["trace-javascript-semantics", request, "--json"],
|
||||
timeoutMs: 60_000,
|
||||
});
|
||||
expect(traced.exitCode, traced.stdout).toBe(0);
|
||||
const trace = javaScriptSemanticTraceResultSchema.parse(
|
||||
toolContract("trace_javascript_semantics").outputSchema.parse(traced.json)
|
||||
.normalized_result,
|
||||
);
|
||||
expect(new Set(trace.seed_node_ids)).toEqual(retained);
|
||||
},
|
||||
120_000,
|
||||
);
|
||||
Reference in new issue
Block a user