Skip to content

feat: report star re-exports on both import and export sides#215

Open
BridgeAR wants to merge 1 commit into
guybedford:mainfrom
BridgeAR:BridgeAR/2026-06-30-star-export-220
Open

feat: report star re-exports on both import and export sides#215
BridgeAR wants to merge 1 commit into
guybedford:mainfrom
BridgeAR:BridgeAR/2026-06-30-star-export-220

Conversation

@BridgeAR

@BridgeAR BridgeAR commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

export * from 'module' is both a dependency edge and a re-export, but the lexer surfaced only the specifier — typed identically to a side-effect import 'module', so consumers cannot tell the two apart without a regex over the source. This reports the star on both sides:

  1. A new import type StaticReexportStar = 8 marks the specifier of a plain export * from 'x', distinguishing it from a side-effect import 'x' (type 1), which is otherwise the same shape.
  2. The export side reports the name * for a plain export *, its name span pointing at the literal * and its statement range matching the import's, so the two halves correlate. export * as ns from 'x' is unchanged — it already reports ns.

Why

import-in-the-middle currently runs a regex over every re-export statement to recover the star re-exports the lexer dropped. Typing the specifier lets it drop that regex and read imported.t === 8 directly — the information the lexer already had while tokenizing, at no extra scan cost.

Test plan

  • npm run build && npm test (wasm + asm.js builds)
  • New Export star reexport* cases in test/_unit.cjs cover type 8 vs side-effect 1, export name *, comments between tokens, facade + module-syntax detection, and statement-range correlation.

Refs: #76
Refs: nodejs/import-in-the-middle#259

`export * from 'module'` is both a dependency edge and a re-export, but only
the specifier was surfaced, typed identically to a side-effect `import
'module'`. Consumers could not tell the two apart without a regex over the
source.

1. A new import type `StaticReexportStar = 8` marks the specifier of a plain
   `export * from 'x'`, distinguishing it from a side-effect `import 'x'`
   (type `1`), which is otherwise the same shape.
2. The export side reports the name `*` for a plain `export *`, its name span
   pointing at the literal `*` and its statement range matching the import's,
   so the two halves correlate. `export * as ns from 'x'` is unchanged.

import-in-the-middle can drop the per-statement regex it runs to recover star
re-exports and read `imported.t === 8` instead — the information the lexer
already had while tokenizing.

Refs: guybedford#76
Refs: nodejs/import-in-the-middle#259
@BridgeAR
BridgeAR marked this pull request as ready for review July 1, 2026 17:20

@guybedford guybedford left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to land this. Formally speaking though it is a breaking change unless we make it export metadata-based.

If we wanted a non-breaking version, RollupJS used to have an internal convention here (not sure if it still does) of making the export name itself *module. That is, if the export name begins with * then it is a star export from that module.

It's a hack and this approach is better though. Would just be nice to bunch with any other major changes for a 3.x.

@guybedford

Copy link
Copy Markdown
Owner

If we're doing a break for 3.x, making exports return an object would likely be smarter then as well.

@BridgeAR

BridgeAR commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

I think having v3 makes most sense

@guybedford guybedford added this to the 3.0.0 milestone Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants