mirror of
https://github.com/oven-sh/bun
synced 2026-02-11 03:18:53 +00:00
Fix module resolution: '.' in subdirectory resolves to index.ts
Previously, importing '.' or './' from within a subdirectory would
incorrectly resolve to a file with the same name in the parent
directory, rather than the index file in the current directory.
For example, importing from 'lib/run.ts':
```ts
import { foo } from ".";
```
Would incorrectly resolve to the root 'lib.ts' instead of 'lib/index.ts'.
This fix adds a check in loadAsFile() to detect when the path being
resolved is actually a directory. If the basename has no extension
(indicating it's likely a directory reference), we check if it exists
as a directory before attempting file resolution. This ensures directory
imports correctly fall through to index file resolution.
Fixes #24449
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3779,6 +3779,18 @@ pub const Resolver = struct {
|
||||
}
|
||||
}
|
||||
|
||||
// If the path itself is an existing directory, don't try to load it as a file.
|
||||
// This prevents "import '.' from 'lib/foo.ts'" incorrectly resolving to a file
|
||||
// named "lib.ts" in the parent directory instead of "lib/index.ts".
|
||||
if (r.dirInfoCached(path) catch null) |_| {
|
||||
if (r.debug_logs) |*debug| {
|
||||
debug.addNoteFmt("\"{s}\" is a directory, not a file", .{path});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const base = std.fs.path.basename(path);
|
||||
|
||||
const dir_path = bun.strings.withoutTrailingSlashWindowsPath(Dirname.dirname(path));
|
||||
|
||||
const dir_entry: *Fs.FileSystem.RealFS.EntriesOption = rfs.readDirectory(
|
||||
@@ -3811,8 +3823,6 @@ pub const Resolver = struct {
|
||||
|
||||
const entries = dir_entry.entries;
|
||||
|
||||
const base = std.fs.path.basename(path);
|
||||
|
||||
// Try the plain path without any extensions
|
||||
if (r.debug_logs) |*debug| {
|
||||
debug.addNoteFmt("Checking for file \"{s}\" ", .{base});
|
||||
|
||||
54
test/regression/issue/24449.test.ts
Normal file
54
test/regression/issue/24449.test.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { bunEnv, bunExe, normalizeBunSnapshot, tempDir } from "harness";
|
||||
|
||||
test("issue #24449 - '.' in subdirectory should resolve to index.ts, not root file with same name", async () => {
|
||||
// Create temp directory with test files
|
||||
using dir = tempDir("test-issue-24449", {
|
||||
"lib.ts": `export const eulerNumber = 2.71828;`,
|
||||
"lib/index.ts": `export const piNumber = 3.14159;`,
|
||||
"lib/run.ts": `
|
||||
import { piNumber } from ".";
|
||||
console.log("piNumber:", piNumber);
|
||||
`,
|
||||
});
|
||||
|
||||
// Spawn Bun process
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "lib/run.ts"],
|
||||
env: bunEnv,
|
||||
cwd: String(dir),
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
// Should import from lib/index.ts, not lib.ts
|
||||
expect(normalizeBunSnapshot(stdout, dir)).toMatchInlineSnapshot(`"piNumber: 3.14159"`);
|
||||
expect(exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test("issue #24449 - './' in subdirectory should resolve to index.ts, not root file with same name", async () => {
|
||||
// Create temp directory with test files
|
||||
using dir = tempDir("test-issue-24449-slash", {
|
||||
"lib.ts": `export const eulerNumber = 2.71828;`,
|
||||
"lib/index.ts": `export const piNumber = 3.14159;`,
|
||||
"lib/run.ts": `
|
||||
import { piNumber } from "./";
|
||||
console.log("piNumber:", piNumber);
|
||||
`,
|
||||
});
|
||||
|
||||
// Spawn Bun process
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "lib/run.ts"],
|
||||
env: bunEnv,
|
||||
cwd: String(dir),
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
// Should import from lib/index.ts, not lib.ts
|
||||
expect(normalizeBunSnapshot(stdout, dir)).toMatchInlineSnapshot(`"piNumber: 3.14159"`);
|
||||
expect(exitCode).toBe(0);
|
||||
});
|
||||
Reference in New Issue
Block a user