test(javascript): consolidate source analysis and export regressions

This commit is contained in:
morluto
2026-10-08 03:57:54 +08:00
parent c93422a898
commit f517a5a1d7
18 changed files with 354 additions and 853 deletions
@@ -20,37 +20,46 @@ const filesFor = (paths: readonly string[]) =>
]),
);
const cases = ["#", "?"].flatMap((punctuation) =>
(["require", "import", undefined] as const).flatMap((moduleKind) =>
(["literal", "stripped", "both"] as const).map((layout) => ({
punctuation,
moduleKind,
layout,
})),
),
);
describe("module specifier punctuation", () => {
it.each(cases)(
"resolves $moduleKind with $punctuation and $layout files",
({ punctuation, moduleKind, layout }) => {
it.each(["#", "?"])(
"keeps CommonJS punctuation and strips URL suffixes for ESM (%s)",
(punctuation) => {
const literal = `app/dep.cjs${punctuation}literal.cjs`;
const stripped = "app/dep.cjs";
const files = filesFor([
...(layout !== "stripped" ? [literal] : []),
...(layout !== "literal" ? [stripped] : []),
]);
const expected = moduleKind === "require" ? literal : stripped;
const result = resolveArtifactPathByContext({
const commonJs = resolveArtifactPathByContext({
declaredPath: `./dep.cjs${punctuation}literal.cjs`,
sourcePath: "app/main.js",
context: "module-specifier",
files,
...(moduleKind === undefined ? {} : { moduleKind }),
files: filesFor([literal, stripped]),
moduleKind: "require",
});
expect(result).toMatchObject({
resolution_status: files.has(expected) ? "resolved" : "not-found",
resolved_path: files.has(expected) ? expected : null,
expect(commonJs).toMatchObject({
resolution_status: "resolved",
resolved_path: literal,
});
const esm = resolveArtifactPathByContext({
declaredPath: `./dep.cjs${punctuation}literal.cjs`,
sourcePath: "app/main.js",
context: "module-specifier",
files: filesFor([literal, stripped]),
moduleKind: "import",
});
expect(esm).toMatchObject({
resolution_status: "resolved",
resolved_path: stripped,
});
const noStrippedTarget = resolveArtifactPathByContext({
declaredPath: `./dep.cjs${punctuation}literal.cjs`,
sourcePath: "app/main.js",
context: "module-specifier",
files: filesFor([literal]),
moduleKind: "import",
});
expect(noStrippedTarget).toMatchObject({
resolution_status: "not-found",
resolved_path: null,
});
},
);
@@ -1,166 +0,0 @@
import { describe, expect, it } from "vitest";
import { analyzeJavaScriptSemantics } from "../../domain/javascript/javascriptSemanticAnalysis.js";
import { completeApplicationCoverage } from "../../domain/javascript/javascriptApplicationEvidenceSchemas.js";
import { projectJavaScriptExportReturnShapes } from "./JavaScriptReturnShapeProjection.js";
const projectReturns = (body: string) => {
const ir = analyzeJavaScriptSemantics(`export function result() { ${body} }`);
const link = ir.moduleLinks.find(
({ exportedName }) => exportedName === "result",
);
if (link === undefined) throw new Error("Expected the result export");
const projected = projectJavaScriptExportReturnShapes({
ir,
link,
modulePath: "fixture.js",
baseCoverage: completeApplicationCoverage(),
});
if (projected === null) throw new Error("Expected exported return shapes");
return projected;
};
const unknownBranchField = {
path: "",
state: "unknown",
value: null,
reason: "Branches have incompatible values.",
};
describe("exported primitive union return shapes", () => {
const conditionalCases = [
"missing",
"unsupported()",
'({ key: "value" })',
'["value"]',
'+"invalid"',
].flatMap((other) => [
`condition ? (choice ? "one" : "two") : ${other}`,
`condition ? ${other} : (choice ? "one" : "two")`,
]);
const logicalCases = [
{ operator: "||", known: '(choice ? "" : "one")' },
{ operator: "&&", known: '(choice ? 0 : "one")' },
{ operator: "??", known: '(choice ? null : "one")' },
].flatMap(({ operator, known }) => [
`${known} ${operator} missing`,
`missing ${operator} ${known}`,
]);
it.each([...conditionalCases, ...logicalCases])(
"projects an unknown field instead of a definite union for %s",
(expression) => {
const projected = projectReturns(`return ${expression};`);
expect(projected.properties.static_return_shapes).toEqual([
{
source_range: expect.any(Object),
value_status: "ambiguous",
fields: [unknownBranchField],
property_coverage: [],
},
]);
// Complete return-site collection does not make its values known.
expect(projected.properties.return_shape_coverage).toEqual({
status: "complete",
retained_return_sites: 1,
omitted_return_sites: 0,
omitted_fields: 0,
omitted_property_coverage: 0,
projection_complete: true,
});
expect(projected.coverage).toEqual(completeApplicationCoverage());
expect(projected.limitations).toContain(
"Return shapes are inferred from inert syntax and do not prove runtime behavior.",
);
},
);
it("keeps an incompatible object field unknown beside a known literal", () => {
const projected = projectReturns(`
return {
kind: "result",
value: condition ? (choice ? "one" : "two") : missing,
};
`);
expect(projected.properties.static_return_shapes).toEqual([
{
source_range: expect.any(Object),
value_status: "object",
fields: [
{ path: "/kind", state: "literal", value: "result", reason: null },
{ ...unknownBranchField, path: "/value" },
],
property_coverage: [{ path: "", status: "complete", omitted: 0 }],
},
]);
});
it("retains valid nested unions, duplicates, and null alternatives", () => {
const projected = projectReturns(`
return condition
? (choice ? "two" : "one")
: (other ? "one" : null);
`);
expect(projected.properties.static_return_shapes).toEqual([
{
source_range: expect.any(Object),
value_status: "union",
fields: [
{
path: "",
state: "union",
value: [null, "one", "two"],
reason: null,
},
],
property_coverage: [],
},
]);
});
it("preserves three independent direct returns without merging their values", () => {
const projected = projectReturns(`
if (condition) return choice ? "one" : "two";
if (other) return missing;
return { kind: "object" };
`);
expect(projected.properties.static_return_shapes).toEqual([
{
source_range: expect.any(Object),
value_status: "union",
fields: [
{ path: "", state: "union", value: ["one", "two"], reason: null },
],
property_coverage: [],
},
{
source_range: expect.any(Object),
value_status: "unknown",
fields: [
{
path: "",
state: "unknown",
value: null,
reason: "Unbound identifier missing.",
},
],
property_coverage: [],
},
{
source_range: expect.any(Object),
value_status: "object",
fields: [
{ path: "/kind", state: "literal", value: "object", reason: null },
],
property_coverage: [{ path: "", status: "complete", omitted: 0 }],
},
]);
expect(projected.properties.return_shape_coverage).toMatchObject({
status: "complete",
retained_return_sites: 3,
omitted_return_sites: 0,
projection_complete: true,
});
});
});