fix(reference-imports): retain exact dynamic import targets

Use the shared exact-literal reader for dynamic imports, preserving expression-free templates and transparent TypeScript wrappers while leaving computed targets unknown.

Fixes #6654
This commit is contained in:
morluto committed 2026-10-23 19:18:47 +08:00
1 parent 8f9b2ab948
commit 16e64d58ff
2 files changed
+19 -2

No files matched your search

+11 -1
View File
@@ -72,6 +72,16 @@ const safeModuleName = (node: Node | null | undefined): string | undefined => {
return undefined;
};
const exactStringModuleName = (
node: Node | null | undefined,
): string | undefined => {
if (node === null || node === undefined) return undefined;
const literal = readExactJavaScriptLiteral(node);
return literal.found && typeof literal.value === "string"
? literal.value
: undefined;
};
const resolveSpecifier = (
specifier: string,
): ReferenceSourceImportResolution => {
@@ -248,7 +258,7 @@ const extractRequireAndDynamicImports = (
for (const call of expressions) {
if (isImportExpression(call)) {
const specifier = safeModuleName(call.source);
const specifier = exactStringModuleName(call.source);
appendRelationship(relationships, limitations, {
fromPath: from_path,
to: specifier ?? "<dynamic-import>",
@@ -15,6 +15,8 @@ it("resolves dynamic source imports while retaining computed targets as unknown"
'import "./static";',
'require("./common");',
'const lazy = import("./lazy");',
"const templated = import(`./template-lazy.mjs`);",
'const wrapped = import("./wrapped-lazy.mjs" as const);',
'async function load() { return await import("./data.json", { with: { type: "json" } }); }',
'const name = "./not-guessed.js"; import(name);',
"import(`./${name}.js`);",
@@ -24,6 +26,9 @@ it("resolves dynamic source imports while retaining computed targets as unknown"
...["static.ts", "common.js", "lazy.ts"].map((path) =>
writeFile(join(root, path), "export {};\n"),
),
...["template-lazy.mjs", "wrapped-lazy.mjs"].map((path) =>
writeFile(join(root, path), "export {};\n"),
),
writeFile(join(root, "data.json"), '{"value":1}\n'),
]);
@@ -34,11 +39,13 @@ it("resolves dynamic source imports while retaining computed targets as unknown"
});
if (!result.ok) throw result.error;
expect(result.value.parse_failures).toEqual([]);
expect(result.value.relationships).toHaveLength(6);
expect(result.value.relationships).toHaveLength(8);
for (const [to, kind] of [
["static.ts", "imports"],
["common.js", "requires"],
["lazy.ts", "imports"],
["template-lazy.mjs", "imports"],
["wrapped-lazy.mjs", "imports"],
["data.json", "imports"],
])
expect(result.value.relationships).toContainEqual({