Skip to content

buildImportArtifactNames drops the barrel-renamed declared name for CJS require() through a renamed barrel #2071

Description

@carlos-alm

Follow-up from a Greptile review comment on PR #1968 (#1968 (comment), src/domain/graph/builder/stages/build-edges.ts:1068-1072).

buildImportArtifactNames's local traceBarrel helper resolves through barrel chains via resolveBarrelExportCached, but only keeps resolved.file, discarding resolved.name (the declared name after a barrel-rename translation, e.g. export { realName as friendlyName } from './underlying'). This is asymmetric with the ESM import path (buildImportedNamesMap's own traceBarrel, same file) and the native equivalent, both of which correctly thread .name through as part of PR #1968's #1823 fix.

Why it doesn't currently cause an observable bug: traced the sole consumer, resolveReceiverEdge (call-resolver.ts:331), called from build-edges.ts:1909 and incremental.ts:765. It only calls importedNames?.has(effectiveReceiver) — a key-presence check — and never reads the map's value. The map's key (the CJS-destructured local binding name, e.g. friendlyName) is set correctly regardless of this bug, so the "is this an import artifact vs. a local definition" classification resolveReceiverEdge performs is unaffected today. There's also no native-engine equivalent of buildImportArtifactNames to diverge from.

Why it's still worth tracking: if importArtifactNames's value ever gains a real consumer (e.g. something that needs the target file and the correct declared name in that file, mirroring how the ESM path already works), the CJS-through-a-renamed-barrel case will silently carry the wrong name with no test coverage catching it, since today's tests only exercise the ESM path's renamed-barrel behavior.

Fix sketch: widen buildImportArtifactNames's return value from Map<string, string> (name → file) to carry {file, name} pairs (mirroring buildImportedNamesMap's importedNames/importedOriginalNames pair), and update resolveReceiverEdge's parameter type accordingly. Deferred rather than done inline on #1968 because it cascades into resolveReceiverEdge's shared parameter type, which is also used by the ESM-only importedNames map (plain file strings) — doing it properly means either a second parallel map or a tuple-typed one shared by both callers, more invasive than a one-line fix for a currently-unread value.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions