Skip to content

Commit

Permalink
Correctly resolve imports ending with "." and ".." (#47850)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewbranch authored Feb 11, 2022
1 parent 73506f3 commit 7f022c5
Show file tree
Hide file tree
Showing 22 changed files with 136 additions and 55 deletions.
18 changes: 16 additions & 2 deletions src/compiler/moduleNameResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ namespace ts {
result = searchResult && searchResult.value;
}
else {
const { path: candidate } = normalizePathAndParts(combinePaths(initialLocationForSecondaryLookup, typeReferenceDirectiveName));
const { path: candidate } = normalizePathForCJSResolution(initialLocationForSecondaryLookup, typeReferenceDirectiveName);
result = nodeLoadModuleByRelativeName(Extensions.DtsOnly, candidate, /*onlyRecordFailures*/ false, moduleResolutionState, /*considerPackageJson*/ true);
}
return resolvedTypeScriptOnly(result);
Expand Down Expand Up @@ -1329,12 +1329,26 @@ namespace ts {
return { value: resolvedValue && { resolved: resolvedValue, isExternalLibraryImport: true } };
}
else {
const { path: candidate, parts } = normalizePathAndParts(combinePaths(containingDirectory, moduleName));
const { path: candidate, parts } = normalizePathForCJSResolution(containingDirectory, moduleName);
const resolved = nodeLoadModuleByRelativeName(extensions, candidate, /*onlyRecordFailures*/ false, state, /*considerPackageJson*/ true);
// Treat explicit "node_modules" import as an external library import.
return resolved && toSearchResult({ resolved, isExternalLibraryImport: contains(parts, "node_modules") });
}
}

}

// If you import from "." inside a containing directory "/foo", the result of `normalizePath`
// would be "/foo", but this loses the information that `foo` is a directory and we intended
// to look inside of it. The Node CommonJS resolution algorithm doesn't call this out
// (https://nodejs.org/api/modules.html#all-together), but it seems that module paths ending
// in `.` are actually normalized to `./` before proceeding with the resolution algorithm.
function normalizePathForCJSResolution(containingDirectory: string, moduleName: string) {
const combined = combinePaths(containingDirectory, moduleName);
const parts = getPathComponents(combined);
const lastPart = lastOrUndefined(parts);
const path = lastPart === "." || lastPart === ".." ? ensureTrailingDirectorySeparator(normalizePath(combined)) : normalizePath(combined);
return { path, parts };
}

function realPath(path: string, host: ModuleResolutionHost, traceEnabled: boolean): string {
Expand Down
12 changes: 0 additions & 12 deletions src/compiler/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -585,18 +585,6 @@ namespace ts {
return getCanonicalFileName(nonCanonicalizedPath) as Path;
}

export function normalizePathAndParts(path: string): { path: string, parts: string[] } {
path = normalizeSlashes(path);
const [root, ...parts] = reducePathComponents(getPathComponents(path));
if (parts.length) {
const joinedParts = root + parts.join(directorySeparator);
return { path: hasTrailingDirectorySeparator(path) ? ensureTrailingDirectorySeparator(joinedParts) : joinedParts, parts };
}
else {
return { path: root, parts };
}
}

//// Path Mutation

/**
Expand Down
14 changes: 14 additions & 0 deletions tests/baselines/reference/importFromDot.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
tests/cases/conformance/moduleResolution/a/b.ts(1,20): error TS2305: Module '"."' has no exported member 'rootA'.


==== tests/cases/conformance/moduleResolution/a.ts (0 errors) ====
export const rootA = 0;

==== tests/cases/conformance/moduleResolution/a/index.ts (0 errors) ====
export const indexInA = 0;

==== tests/cases/conformance/moduleResolution/a/b.ts (1 errors) ====
import { indexInA, rootA } from ".";
~~~~~
!!! error TS2305: Module '"."' has no exported member 'rootA'.

25 changes: 25 additions & 0 deletions tests/baselines/reference/importFromDot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//// [tests/cases/conformance/moduleResolution/importFromDot.ts] ////

//// [a.ts]
export const rootA = 0;

//// [index.ts]
export const indexInA = 0;

//// [b.ts]
import { indexInA, rootA } from ".";


//// [a.js]
"use strict";
exports.__esModule = true;
exports.rootA = void 0;
exports.rootA = 0;
//// [index.js]
"use strict";
exports.__esModule = true;
exports.indexInA = void 0;
exports.indexInA = 0;
//// [b.js]
"use strict";
exports.__esModule = true;
13 changes: 13 additions & 0 deletions tests/baselines/reference/importFromDot.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
=== tests/cases/conformance/moduleResolution/a.ts ===
export const rootA = 0;
>rootA : Symbol(rootA, Decl(a.ts, 0, 12))

=== tests/cases/conformance/moduleResolution/a/index.ts ===
export const indexInA = 0;
>indexInA : Symbol(indexInA, Decl(index.ts, 0, 12))

=== tests/cases/conformance/moduleResolution/a/b.ts ===
import { indexInA, rootA } from ".";
>indexInA : Symbol(indexInA, Decl(b.ts, 0, 8))
>rootA : Symbol(rootA, Decl(b.ts, 0, 18))

15 changes: 15 additions & 0 deletions tests/baselines/reference/importFromDot.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
=== tests/cases/conformance/moduleResolution/a.ts ===
export const rootA = 0;
>rootA : 0
>0 : 0

=== tests/cases/conformance/moduleResolution/a/index.ts ===
export const indexInA = 0;
>indexInA : 0
>0 : 0

=== tests/cases/conformance/moduleResolution/a/b.ts ===
import { indexInA, rootA } from ".";
>indexInA : 0
>rootA : any

26 changes: 26 additions & 0 deletions tests/baselines/reference/importWithTrailingSlash.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/a/b/test.ts(3,3): error TS2339: Property 'a' does not exist on type '{ aIndex: number; }'.
/a/test.ts(3,3): error TS2339: Property 'a' does not exist on type '{ aIndex: number; }'.


==== /a.ts (0 errors) ====
export default { a: 0 };

==== /a/index.ts (0 errors) ====
export default { aIndex: 0 };

==== /a/test.ts (1 errors) ====
import a from ".";
import aIndex from "./";
a.a;
~
!!! error TS2339: Property 'a' does not exist on type '{ aIndex: number; }'.
aIndex.aIndex;

==== /a/b/test.ts (1 errors) ====
import a from "..";
import aIndex from "../";
a.a;
~
!!! error TS2339: Property 'a' does not exist on type '{ aIndex: number; }'.
aIndex.aIndex;

4 changes: 0 additions & 4 deletions tests/baselines/reference/importWithTrailingSlash.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ import aIndex from "./";
>aIndex : Symbol(aIndex, Decl(test.ts, 1, 6))

a.a;
>a.a : Symbol(a, Decl(a.ts, 0, 16))
>a : Symbol(a, Decl(test.ts, 0, 6))
>a : Symbol(a, Decl(a.ts, 0, 16))

aIndex.aIndex;
>aIndex.aIndex : Symbol(aIndex, Decl(index.ts, 0, 16))
Expand All @@ -31,9 +29,7 @@ import aIndex from "../";
>aIndex : Symbol(aIndex, Decl(test.ts, 1, 6))

a.a;
>a.a : Symbol(a, Decl(a.ts, 0, 16))
>a : Symbol(a, Decl(test.ts, 0, 6))
>a : Symbol(a, Decl(a.ts, 0, 16))

aIndex.aIndex;
>aIndex.aIndex : Symbol(aIndex, Decl(index.ts, 0, 16))
Expand Down
16 changes: 9 additions & 7 deletions tests/baselines/reference/importWithTrailingSlash.trace.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
[
"======== Resolving module '.' from '/a/test.ts'. ========",
"Explicitly specified module resolution kind: 'NodeJs'.",
"Loading module as file / folder, candidate module location '/a', target file type 'TypeScript'.",
"File '/a.ts' exist - use it as a name resolution result.",
"======== Module name '.' was successfully resolved to '/a.ts'. ========",
"Loading module as file / folder, candidate module location '/a/', target file type 'TypeScript'.",
"File '/a/package.json' does not exist.",
"File '/a/index.ts' exist - use it as a name resolution result.",
"======== Module name '.' was successfully resolved to '/a/index.ts'. ========",
"======== Resolving module './' from '/a/test.ts'. ========",
"Explicitly specified module resolution kind: 'NodeJs'.",
"Loading module as file / folder, candidate module location '/a/', target file type 'TypeScript'.",
"File '/a/package.json' does not exist.",
"File '/a/package.json' does not exist according to earlier cached lookups.",
"File '/a/index.ts' exist - use it as a name resolution result.",
"======== Module name './' was successfully resolved to '/a/index.ts'. ========",
"======== Resolving module '..' from '/a/b/test.ts'. ========",
"Explicitly specified module resolution kind: 'NodeJs'.",
"Loading module as file / folder, candidate module location '/a', target file type 'TypeScript'.",
"File '/a.ts' exist - use it as a name resolution result.",
"======== Module name '..' was successfully resolved to '/a.ts'. ========",
"Loading module as file / folder, candidate module location '/a/', target file type 'TypeScript'.",
"File '/a/package.json' does not exist according to earlier cached lookups.",
"File '/a/index.ts' exist - use it as a name resolution result.",
"======== Module name '..' was successfully resolved to '/a/index.ts'. ========",
"======== Resolving module '../' from '/a/b/test.ts'. ========",
"Explicitly specified module resolution kind: 'NodeJs'.",
"Loading module as file / folder, candidate module location '/a/', target file type 'TypeScript'.",
Expand Down
16 changes: 8 additions & 8 deletions tests/baselines/reference/importWithTrailingSlash.types
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ export default { aIndex: 0 };

=== /a/test.ts ===
import a from ".";
>a : { a: number; }
>a : { aIndex: number; }

import aIndex from "./";
>aIndex : { aIndex: number; }

a.a;
>a.a : number
>a : { a: number; }
>a : number
>a.a : any
>a : { aIndex: number; }
>a : any

aIndex.aIndex;
>aIndex.aIndex : number
Expand All @@ -29,15 +29,15 @@ aIndex.aIndex;

=== /a/b/test.ts ===
import a from "..";
>a : { a: number; }
>a : { aIndex: number; }

import aIndex from "../";
>aIndex : { aIndex: number; }

a.a;
>a.a : number
>a : { a: number; }
>a : number
>a.a : any
>a : { aIndex: number; }
>a : any

aIndex.aIndex;
>aIndex.aIndex : number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ Creating configuration project /user/username/projects/myproject/b/tsconfig.json
Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/index.ts 500 undefined WatchType: Closed Script info
Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ Creating configuration project /user/username/projects/myproject/b/tsconfig.json
Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/index.ts 500 undefined WatchType: Closed Script info
Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ For info: /user/username/projects/myproject/b/helper.ts :: Config file name: /us
Creating configuration project /user/username/projects/myproject/b/tsconfig.json
Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded
Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ For info: /user/username/projects/myproject/b/helper.ts :: Config file name: /us
Creating configuration project /user/username/projects/myproject/b/tsconfig.json
Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded
Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ Creating configuration project /user/username/projects/myproject/b/tsconfig.json
Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/index.ts 500 undefined WatchType: Closed Script info
Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ Creating configuration project /user/username/projects/myproject/b/tsconfig.json
Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded
FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/index.ts 500 undefined WatchType: Closed Script info
Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ For info: /user/username/projects/myproject/b/helper.ts :: Config file name: /us
Creating configuration project /user/username/projects/myproject/b/tsconfig.json
Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded
Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ For info: /user/username/projects/myproject/b/helper.ts :: Config file name: /us
Creating configuration project /user/username/projects/myproject/b/tsconfig.json
Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded
Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations
FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file
Expand Down
Loading

0 comments on commit 7f022c5

Please sign in to comment.