Skip to content

JS/TS: an export default NAME line inside a template literal is taken as the module's default export #2968

Closed

Description

@inth3shadows

The default-export reader takes an export default NAME line inside a template literal as the module's default export when NAME is a node of the file. The real export default statement later in the file is then ignored.

// gen.ts
export function App() { return 1; }
export function Main() { return 2; }
export const template = `
export default App
`;
export default Main;

// use.ts
import X from './gen';
export function use() { return X(); }
edge on main expected
use → App (gen.ts:1, resolvedBy: import) ✗ Main (gen.ts:2)

statedDefaultExport (import-resolver.ts#L210-L244) scans comment-stripped source but deliberately doesn't mask strings. Its docstring explains why: a masker thrown out of step by nested templates blanked real statements. It relies on "a statement must name a node of the file instead — one a template only writes as text names none — and of several statements, one that does wins". That fails when the template's text names a real node, as in code generators, scaffolding scripts and docs/test helpers that build module source in template strings. The loop takes the first statement that names a node and breaks, so the template wins whenever it comes first.

Reproduced on main at 72f398a with CODEGRAPH_KERNEL=0. Linux/WSL2, Node 22.23.2.

Possible direction (not verified). Skip an EXPORT_DEFAULT_HEAD match that sits inside a template or string literal, using the extractor's own export_statement positions (the AST already knows which export default is real) rather than a masker. Or, when several statements name nodes, prefer the one at module scope by AST.

Related: #2432 (introduced the stated-default reading), #2967.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions