fix(javascript): centralize module syntax and separate erased type dependencies

This commit is contained in:
morluto committed 2026-10-13 14:39:06 +08:00
1 parent e1cd292aa6
commit 1b953021ea
18 files changed
+513 -134

No files matched your search

@@ -22,6 +22,11 @@ describe("TypeScript import-equals links", () => {
localName: "dependency",
exportedName: null,
}),
expect.objectContaining({
kind: "type-import",
specifier: "./types",
localName: "types",
}),
]);
});
@@ -51,6 +56,57 @@ describe("TypeScript import-equals links", () => {
});
});
describe("TypeScript type-only module links", () => {
it("retains declarations without runtime bindings or callable claims", () => {
const ir = analyzeJavaScriptSemantics(`
import type { Whole } from "./whole";
import { type Inline } from "./inline";
import { type Erased, value } from "./mixed";
export type { Reexported } from "./reexported";
export { type InlineExport } from "./inline-export";
export type LocalType = string;
export interface LocalInterface { value: string }
function hiddenFunction() { return 1; }
export type { hiddenFunction };
`);
const externalLinks = ir.moduleLinks
.filter(({ specifier }) => specifier !== null)
.map(
({ kind, specifier, importedName, exportedName }) =>
[kind, specifier, importedName, exportedName] as const,
);
expect(externalLinks).toEqual([
["type-import", "./whole", "Whole", null],
["type-import", "./inline", "Inline", null],
["type-import", "./mixed", "Erased", null],
["import", "./mixed", "value", null],
["type-import", "./reexported", "Reexported", "Reexported"],
["type-import", "./inline-export", "InlineExport", "InlineExport"],
]);
const typeLinks = ir.moduleLinks
.filter(({ kind }) => kind === "type-import")
.map(
({ specifier, localName, exportedName, callableId }) =>
[specifier, localName, exportedName, callableId] as const,
);
expect(typeLinks).toEqual([
["./whole", "Whole", null, null],
["./inline", "Inline", null, null],
["./mixed", "Erased", null, null],
["./reexported", null, "Reexported", null],
["./inline-export", null, "InlineExport", null],
[null, "LocalType", "LocalType", null],
[null, "LocalInterface", "LocalInterface", null],
[null, "hiddenFunction", "hiddenFunction", null],
]);
expect(ir.limitations).toContain(
"Compiler options are unavailable; inline type-only imports or re-exports may preserve a module side-effect dependency.",
);
});
});
describe("CommonJS dependency links", () => {
it("retains an import-equals binding and its module origin", () => {
const ir = analyzeJavaScriptSemantics(`
@@ -76,6 +132,12 @@ describe("CommonJS dependency links", () => {
importedName: null,
localName: "typed",
}),
expect.objectContaining({
kind: "type-import",
specifier: "type-only",
importedName: null,
localName: "TypeOnly",
}),
]);
expect(ir.references.filter(({ name }) => name === "typed")).toHaveLength(
1,