fix(javascript): preserve empty ESM import names in provenance (#2797)

Co-authored-by: LouisChen <3361008+chqcjq@users.noreply.github.com>
This commit is contained in:
LouisChen
2026-10-14 03:12:04 +08:00
committed by GitHub
parent 20b802f165
commit ed24604ee1
3 changed files with 110 additions and 2 deletions
@@ -10,6 +10,45 @@ import {
origin,
} from "./javascriptSemanticAnalysis.fixture.js";
describe("JavaScript semantic analysis: ESM import origins", () => {
it.each(["", "a", "0"])(
"preserves exact ESM import name %j in binding origins",
(name) => {
const ir = analyzeJavaScriptSemantics(
"import { " +
JSON.stringify(name) +
' as selected } from "./module.mjs"; const alias = selected; export { alias };',
);
for (const binding of ["selected", "alias"])
expect(origin(topLevelBinding(ir, binding))).toEqual({
specifier: "./module.mjs",
importedPath: [name],
});
expect(ir.moduleLinks).toContainEqual(
expect.objectContaining({
kind: "import",
importedName: name,
localName: "selected",
}),
);
},
);
it("keeps default and namespace import origins distinct from an empty named import", () => {
const ir = analyzeJavaScriptSemantics(
'import value from "./module.mjs"; import * as namespace from "./module.mjs";',
);
expect(origin(topLevelBinding(ir, "value"))).toEqual({
specifier: "./module.mjs",
importedPath: ["default"],
});
expect(origin(topLevelBinding(ir, "namespace"))).toEqual({
specifier: "./module.mjs",
importedPath: [],
});
});
});
describe("JavaScript semantic analysis: structure 1", () => {
it("resolves imports, require destructuring, aliases, assignments, and shadowing", () => {
const ir = analyzeJavaScriptSemantics(`