fix: resolve bare package imports against the "." exports subpath#1276
Merged
fix: resolve bare package imports against the "." exports subpath#1276
Conversation
4 tasks
Contributor
Author
|
That's arguably a lot of tests for such a small fix, but while at it... |
Member
|
Can you rebase? |
`resolveExportPath('')` — the call made for bare package imports like
`import x from 'foo'` — used to blindly prepend './' to the lookup key,
turning '' into './'. That never matched the '.' key stored in the
resolved exports map, so the export lookup silently returned zero paths.
In practice the bug was masked for packages that also declared a `main`
field, because `resolveSourceFile` falls back to `mainPaths` when the
exports lookup returns nothing and `exportPath === ''`. Packages that
only declared `exports` (no `main`) would not resolve their bare entry
point and the parser would fail to walk their dependency graph.
Normalize both '' and '.' to '.' so the lookup matches the canonical
'.' subpath key used by both the string-shorthand `exports: "./foo.js"`
form and the object form `exports: { ".": "./foo.js" }`. Subpath imports
(either bare 'sub' or './sub') continue to work unchanged.
Tests added:
- Plain string exports resolved via bare import
- Object exports with '.' key resolved via bare import
- Single-level conditional exports under '.' resolved via bare import
- Explicit '.' exportPath accepted
- Regression guard for non-bare subpath imports
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bce7993 to
3333725
Compare
Contributor
Author
|
@sorccu Done: trimmed a dupe test along the way |
sorccu
approved these changes
Apr 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Affected Components
Notes for the Reviewer
Follow-up to the investigation in #1274 — this is the incidental bug flagged there, split into its own PR for independent review.
The bug
resolveExportPath('')— the call made for bare package imports likeimport x from 'foo'— used to blindly prepend./to the lookup key, turning''into'./'. That never matched the.key stored in the resolved exports map, so the export lookup silently returned zero paths.In practice the bug was masked for packages that also declared a
mainfield, becauseresolveSourceFilefalls back tomainPathswhen the exports lookup returns nothing andexportPath === ''. Packages that only declaredexports(nomain) would not resolve their bare entry point and the parser would fail to walk their dependency graph.The fix
Normalize both
''and'.'to.before handing off to the resolver, so the lookup matches the canonical.subpath key used by both the string-shorthand (exports: "./foo.js") and the object form (exports: { ".": "./foo.js" }). Subpath imports (either baresubor./sub) continue to work unchanged.Tests
All tests written TDD-first (watched failing, then fix, then watched passing).
exports: "./index.js") via bare import.key via bare import.via bare import (exercises bothimportandrequirecondition paths).as the exportPath (some callers pass.directly instead of'')./suband baresub) still resolve correctly alongside the.entryCheck-parser suite: 51 passed baseline → 56 passed after fix (+5 new, zero regressions). Same 3 pre-existing
execainfrastructure failures as on main, unrelated.Intentionally NOT in scope
The "sugar for main export" variant — where
exportsis an object with no keys starting with.and should be treated as conditions for the.subpath, e.g.exports: { import: "./esm.mjs", require: "./cjs.cjs" }. The current#resolveExportstreatsimport/requireas subpath names in that case. Happy to do a third PR if it's worth fixing; the workaround is to use the more explicit{ ".": { ... } }form.Test plan
npx vitest run src/services/check-parser/package-files/__tests__/package-json-file.spec.ts— all 9 tests greenexports(nomain) and confirm the bare import resolves🤖 Generated with Claude Code