Skip to content

Commit f0981df

Browse files
committed
fix bare specifier resolution order for paths without baseUrl
1 parent 2af4a12 commit f0981df

File tree

6 files changed

+38
-4
lines changed

6 files changed

+38
-4
lines changed

src/transpilation/resolve.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,27 @@ class ResolutionContext {
209209
if (resolvedNodeModulesFile) return resolvedNodeModulesFile;
210210
}
211211

212+
const isRelativeDependency = ts.isExternalModuleNameRelative(dependencyPath);
213+
214+
if (!isRelativeDependency && this.options.paths) {
215+
// Bare specifiers: check paths mappings first, matching TypeScript's resolution order.
216+
// When baseUrl is not set, resolve paths relative to the tsconfig directory (TS 6.0+ behavior)
217+
const pathsBase =
218+
this.options.baseUrl ??
219+
(this.options.configFilePath ? path.dirname(this.options.configFilePath) : undefined);
220+
if (pathsBase) {
221+
const fileFromPaths = this.tryGetModuleNameFromPaths(dependencyPath, this.options.paths, pathsBase);
222+
if (fileFromPaths) return fileFromPaths;
223+
}
224+
}
225+
212226
// Check if file is a file in the project
213227
const resolvedPath = this.formatPathToFile(dependencyPath, requiringFile);
214228
const fileFromPath = this.getFileFromPath(resolvedPath);
215229
if (fileFromPath) return fileFromPath;
216230

217-
if (this.options.paths) {
218-
// If no file found yet and paths are present, try to find project file via paths mappings
219-
// When baseUrl is not set, resolve paths relative to the tsconfig directory (TS 6.0+ behavior)
231+
if (isRelativeDependency && this.options.paths) {
232+
// Relative imports are still file-relative first; fall back to paths afterwards.
220233
const pathsBase =
221234
this.options.baseUrl ??
222235
(this.options.configFilePath ? path.dirname(this.options.configFilePath) : undefined);

test/transpile/module-resolution/paths-simple/myprogram/tsconfig.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
{
22
"compilerOptions": {
3+
"baseUrl": ".",
4+
"ignoreDeprecations": "6.0",
35
"rootDir": "..",
46
"outDir": "dist",
57
"paths": {

test/unit/language-extensions/multi.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ test("Destructuring assignment of LuaMultiReturn returning nil", () => {
4141
const [a, ...b] = multiReturn();
4242
export {a, b};
4343
`
44-
.ignoreDiagnostics([2322, 2461])
44+
.ignoreDiagnostics([2322, 2461]) // TS2322: bare return not assignable to LuaMultiReturn; TS2461: not iterable
4545
.withLanguageExtensions()
4646
.expectToEqual({ a: undefined, b: [] });
4747
});

test/unit/modules/resolution.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,20 @@ test("import = require", () => {
174174
.setOptions({ module: ts.ModuleKind.CommonJS })
175175
.tap(expectToRequire("foo.bar"));
176176
});
177+
178+
test("paths without baseUrl resolves bare imports before sibling files", () => {
179+
util.testModule`
180+
import * as pkg from "pkg";
181+
pkg;
182+
`
183+
.setMainFileName("/virtual/app/main.ts")
184+
.addExtraFile("/virtual/app/pkg.ts", "export const sibling = true;")
185+
.addExtraFile("/virtual/shared/pkg.ts", "export const mapped = true;")
186+
.setOptions({
187+
baseUrl: undefined,
188+
configFilePath: "/virtual/tsconfig.json",
189+
paths: { pkg: ["./shared/pkg"] },
190+
rootDir: "/virtual",
191+
})
192+
.tap(expectToRequire("shared.pkg"));
193+
});

test/unit/precedingStatements.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ describe("execution order", () => {
108108
);
109109
return result;
110110
`
111+
// TS2783: duplicate property in spread — intentional, testing execution order
111112
.ignoreDiagnostics([2783])
112113
.expectToMatchJsResult();
113114
});

test/unit/spread.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ describe("in object literal", () => {
116116
"{ ...{ x: false }, x: true }",
117117
"{ ...{ x: false }, x: false, ...{ x: true } }",
118118
])("of object literal (%p)", expression => {
119+
// TS2783: duplicate property in spread — intentional, testing spread override behavior
119120
util.testExpression(expression).ignoreDiagnostics([2783]).expectToMatchJsResult();
120121
});
121122

0 commit comments

Comments
 (0)