Files
rea/src/javascript/analysis/JavaScriptAnalysisWorkerSchemas.test.ts
T
morlutoandHemang Varshney 018ab2c5d9 fix(javascript): retain unresolved network targets with provenance
Resolve stable lexical and URL targets using shared effects, and preserve unresolved request expressions as partial facts. Carry their uncertainty through workers, artifact graphs, and the CLI. Scope partial endpoint identity to the source site.

Refs: #3451, #3534

Co-authored-by: Hemang Varshney <[email protected]>
2026-10-16 08:14:52 +08:00

119 lines
4.0 KiB
TypeScript

import { expect, it } from "vitest";
import { analyzeJavaScriptStaticSource } from "../../domain/javascript/javascriptStaticAnalysis.js";
import {
javaScriptWorkerModuleHeaderSchema,
javaScriptWorkerModuleRecordSchema,
javaScriptWorkerStaticAnalysisSchema,
} from "./JavaScriptAnalysisWorkerSchemas.js";
import { analyzeJavaScriptSemantics } from "../../domain/javascript/javascriptSemanticAnalysis.js";
import { getterExpansionSource } from "../../../tests/fixtures/javascriptGetterExpansion.js";
it("transfers getter expansion limits and unknown bindings across the worker boundary", () => {
const ir = analyzeJavaScriptSemantics(getterExpansionSource());
const header = { coverage: ir.coverage, limitations: ir.limitations };
expect(
javaScriptWorkerModuleHeaderSchema.parse(
JSON.parse(JSON.stringify(header)) as unknown,
),
).toEqual(header);
for (const value of ir.bindings) {
const record = { kind: "binding", value };
expect(
javaScriptWorkerModuleRecordSchema.parse(
JSON.parse(JSON.stringify(record)) as unknown,
),
).toEqual(record);
}
expect(ir.coverage.resourceLimits).toEqual(["getter-expansion"]);
});
it("retains candidate endpoint interpretation across the worker boundary", () => {
const facts = analyzeJavaScriptStaticSource(`
client.get("settingKey");
fetch("/api");
`);
expect(facts.endpoints).toEqual([
expect.objectContaining({
value: "settingKey",
interpretation: "candidate",
}),
expect.objectContaining({ value: "/api" }),
]);
expect(facts.endpoints[1]).not.toHaveProperty("interpretation");
const serialized = JSON.parse(JSON.stringify(facts)) as unknown;
expect(javaScriptWorkerStaticAnalysisSchema.parse(serialized)).toEqual(facts);
expect(
javaScriptWorkerStaticAnalysisSchema.safeParse({
...facts,
endpoints: facts.endpoints.map((endpoint) => ({
...endpoint,
interpretation: "confirmed",
})),
}).success,
).toBe(false);
});
it.each(["babel-ast-v1", "babel-ast-v2"])(
"versions fingerprints through the worker schema and rejects %s",
(oldAlgorithm) => {
const facts =
analyzeJavaScriptStaticSource(`globalThis.webpackChunkApp.push([[1], {
17(module, exports) { const key = selectKey(); exports.read = value[key]; }
}]);`);
expect(facts.bundler_registrations[0]?.modules[0]).toMatchObject({
structural_fingerprint_algorithm: "babel-ast-v3",
structural_fingerprint_sha256: expect.stringMatching(/^[a-f0-9]{64}$/u),
});
expect(
javaScriptWorkerStaticAnalysisSchema.safeParse(
JSON.parse(JSON.stringify(facts)) as unknown,
).success,
).toBe(true);
const old = {
...facts,
bundler_registrations: facts.bundler_registrations.map(
(registration) => ({
...registration,
modules: registration.modules.map((module) => ({
...module,
structural_fingerprint_algorithm: oldAlgorithm,
})),
}),
),
};
expect(javaScriptWorkerStaticAnalysisSchema.safeParse(old).success).toBe(
false,
);
},
);
it("accepts candidate endpoint interpretations from static analysis", () => {
const facts = analyzeJavaScriptStaticSource(`http.request("POST", target);`);
expect(facts.endpoints).toContainEqual(
expect.objectContaining({
kind: "network",
value: "POST",
interpretation: "candidate",
}),
);
expect(
javaScriptWorkerStaticAnalysisSchema.safeParse(
JSON.parse(JSON.stringify(facts)) as unknown,
).success,
).toBe(true);
});
it("preserves partial request targets through the strict worker schema", () => {
const facts = analyzeJavaScriptStaticSource("fetch(endpointUrl);");
expect(facts.endpoints).toContainEqual(
expect.objectContaining({
kind: "network",
value: "endpointUrl",
resolution: "partial",
}),
);
const serialized = JSON.parse(JSON.stringify(facts)) as unknown;
expect(javaScriptWorkerStaticAnalysisSchema.parse(serialized)).toEqual(facts);
});