mirror of
https://github.com/morluto/rea
synced 2026-10-26 14:25:49 -04:00
0323ce0a28
* fix(javascript): keep the request endpoint on a uniquely consumed response collectResponseConsumers always produced response-consumer operations with endpoint null, so a json()/text() consumer that resolved to exactly one request lost the request's literal endpoint in the semantic graph. When the consumer resolves to one request through that request's own result binding, the same condition that already makes it complete, it now carries that request's endpoint. Ambiguous consumers stay null. Fixes #3328 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(javascript): drop the endpoint when another write can replace the response Copy the request's endpoint only when the request is the binding's sole write; any other assignment, update, loop or destructuring target can replace the response before the consumer reads it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
60 lines
1.6 KiB
TypeScript
60 lines
1.6 KiB
TypeScript
import { expect, it } from "vitest";
|
|
|
|
import { analyzeJavaScriptSemantics } from "./javascriptSemanticAnalysis.js";
|
|
|
|
const responses = (source: string) =>
|
|
analyzeJavaScriptSemantics(source)
|
|
.requestOperations.filter(({ kind }) => kind === "response-consumer")
|
|
.map(({ method, endpoint, resolution }) => ({
|
|
method,
|
|
endpoint,
|
|
resolution,
|
|
}));
|
|
|
|
it("keeps the endpoint of a uniquely consumed request response", () => {
|
|
expect(
|
|
responses(`
|
|
async function load() {
|
|
const a = await fetch("https://example.test/a");
|
|
const b = await fetch("https://example.test/b");
|
|
return [await a.json(), await b.text()];
|
|
}
|
|
`),
|
|
).toEqual([
|
|
{
|
|
method: "json",
|
|
endpoint: "https://example.test/a",
|
|
resolution: "complete",
|
|
},
|
|
{
|
|
method: "text",
|
|
endpoint: "https://example.test/b",
|
|
resolution: "complete",
|
|
},
|
|
]);
|
|
});
|
|
|
|
it("leaves an ambiguous response consumer without an endpoint", () => {
|
|
expect(
|
|
responses(`
|
|
async function load(flag) {
|
|
let response = await fetch("https://example.test/a");
|
|
if (flag) response = await fetch("https://example.test/b");
|
|
return response.json();
|
|
}
|
|
`),
|
|
).toEqual([{ method: "json", endpoint: null, resolution: "partial" }]);
|
|
});
|
|
|
|
it("leaves a response replaced by a non-request value without an endpoint", () => {
|
|
expect(
|
|
responses(`
|
|
async function load(cachedResponse) {
|
|
let response = await fetch("https://example.test/a");
|
|
response = cachedResponse;
|
|
return response.json();
|
|
}
|
|
`),
|
|
).toEqual([expect.objectContaining({ method: "json", endpoint: null })]);
|
|
});
|