Skip to content

Commit 121152f

Browse files
authored
fix: resolve node_modules/package/dir/foo.js if node_modules/package/dir/foo/ exists (#896)
fixes #893 closes #894 PR #839 incorrectly assumed the specifier is always a package name, but a specifier can be `package/dir/foo` where both `node_modules/package/dir/foo.js` and `node_modules/package/dir/foo/` exists.
1 parent a1d806b commit 121152f

File tree

10 files changed

+21
-2
lines changed

10 files changed

+21
-2
lines changed

fixtures/enhanced-resolve/test/fixtures/node_modules/@scope/dir-and-file/foo.js

Whitespace-only changes.

fixtures/enhanced-resolve/test/fixtures/node_modules/@scope/dir-and-file/foo/bar.js

Whitespace-only changes.

fixtures/enhanced-resolve/test/fixtures/node_modules/@scope/dir-and-file/foo/index.js

Whitespace-only changes.

fixtures/enhanced-resolve/test/fixtures/node_modules/@scope/dir-and-file/package.json

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fixtures/enhanced-resolve/test/fixtures/node_modules/dir-and-file/foo.js

Whitespace-only changes.

fixtures/enhanced-resolve/test/fixtures/node_modules/dir-and-file/foo/bar.js

Whitespace-only changes.

fixtures/enhanced-resolve/test/fixtures/node_modules/dir-and-file/foo/index.js

Whitespace-only changes.

fixtures/enhanced-resolve/test/fixtures/node_modules/dir-and-file/package.json

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lib.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,15 @@ impl<Fs: FileSystem> ResolverGeneric<Fs> {
932932
return Ok(self.cache.is_dir(&cached_path, ctx).then(|| cached_path.clone()));
933933
}
934934

935-
// Perf: try LOAD_AS_DIRECTORY first. No modern package manager creates `node_modules/X.js`.
935+
// Only load the file if it is targeting a `X/sub/dir`.
936+
if specifier != package_name
937+
&& !specifier.ends_with('/')
938+
&& let Some(path) = self.load_as_file(&cached_path, tsconfig, ctx)?
939+
{
940+
return Ok(Some(path));
941+
}
942+
// Otherwise just load the directory.
943+
// No modern package manager creates `node_modules/X.js`.
936944
if self.cache.is_dir(&cached_path, ctx) {
937945
if let Some(path) =
938946
self.load_browser_field_or_alias(&cached_path, tsconfig, ctx)?
@@ -942,6 +950,7 @@ impl<Fs: FileSystem> ResolverGeneric<Fs> {
942950
if let Some(path) = self.load_as_directory(&cached_path, tsconfig, ctx)? {
943951
return Ok(Some(path));
944952
}
953+
// Still need to try to load the file in case there are path aliases.
945954
} else if let Some(path) = self.load_as_file(&cached_path, tsconfig, ctx)? {
946955
return Ok(Some(path));
947956
}

src/tests/resolve.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ fn resolve() {
4949
("handle fragment edge case (no fragment)", f.clone(), "./no#fragment/#/#", f.join("no#fragment/#/#.js")),
5050
("handle fragment edge case (fragment)", f.clone(), "./no#fragment/#/", f.join("no.js#fragment/#/")),
5151
("handle fragment escaping", f.clone(), "./no\0#fragment/\0#/\0##fragment", f.join("no#fragment/#/#.js#fragment")),
52-
52+
// Test `node_modules/X/foo/` and `node_modules/X/foo.js` precedence.
53+
("file and dir precedence 1", f.clone(), "dir-and-file/foo", f.join("node_modules/dir-and-file/foo.js")),
54+
("file and dir precedence 2", f.clone(), "@scope/dir-and-file/foo", f.join("node_modules/@scope/dir-and-file/foo.js")),
55+
("file and dir precedence 1", f.clone(), "dir-and-file/foo/", f.join("node_modules/dir-and-file/foo/index.js")),
56+
("file and dir precedence 2", f.clone(), "@scope/dir-and-file/foo/", f.join("node_modules/@scope/dir-and-file/foo/index.js")),
5357
];
5458

5559
for (comment, path, request, expected) in pass {

0 commit comments

Comments
 (0)