Skip to content

Commit 9bdd6a3

Browse files
author
Andy
authored
Support loading "index.d.ts" using "typesVersions" without "types", "typings", or "main" (microsoft#27514)
* Support loading "index.d.ts" using "typesVersions" without "types", "typings", or "main" * Update baseline
1 parent 81f8b47 commit 9bdd6a3

8 files changed

+112
-29
lines changed

src/compiler/moduleNameResolver.ts

+15-29
Original file line numberDiff line numberDiff line change
@@ -1043,15 +1043,6 @@ namespace ts {
10431043
return withPackageId(packageId, loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageJsonContent, versionPaths));
10441044
}
10451045

1046-
function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState, packageJsonContent: PackageJsonPathFields | undefined, versionPaths: VersionPaths | undefined): PathAndExtension | undefined {
1047-
const fromPackageJson = packageJsonContent && loadModuleFromPackageJson(packageJsonContent, versionPaths, extensions, candidate, state);
1048-
if (fromPackageJson) {
1049-
return fromPackageJson;
1050-
}
1051-
const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host);
1052-
return loadModuleFromFile(extensions, combinePaths(candidate, "index"), !directoryExists, state);
1053-
}
1054-
10551046
interface PackageJsonInfo {
10561047
packageJsonContent: PackageJsonPathFields | undefined;
10571048
packageId: PackageId | undefined;
@@ -1111,22 +1102,12 @@ namespace ts {
11111102
}
11121103
}
11131104

1114-
function loadModuleFromPackageJson(jsonContent: PackageJsonPathFields, versionPaths: VersionPaths | undefined, extensions: Extensions, candidate: string, state: ModuleResolutionState): PathAndExtension | undefined {
1115-
let file = extensions !== Extensions.JavaScript && extensions !== Extensions.Json
1116-
? readPackageJsonTypesFields(jsonContent, candidate, state)
1117-
: readPackageJsonMainField(jsonContent, candidate, state);
1118-
if (!file) {
1119-
if (extensions === Extensions.TypeScript) {
1105+
function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState, jsonContent: PackageJsonPathFields | undefined, versionPaths: VersionPaths | undefined): PathAndExtension | undefined {
1106+
const packageFile = jsonContent && (extensions !== Extensions.JavaScript && extensions !== Extensions.Json
1107+
? readPackageJsonTypesFields(jsonContent, candidate, state) ||
11201108
// When resolving typescript modules, try resolving using main field as well
1121-
file = readPackageJsonMainField(jsonContent, candidate, state);
1122-
if (!file) {
1123-
return undefined;
1124-
}
1125-
}
1126-
else {
1127-
return undefined;
1128-
}
1129-
}
1109+
(extensions === Extensions.TypeScript ? readPackageJsonMainField(jsonContent, candidate, state) : undefined)
1110+
: readPackageJsonMainField(jsonContent, candidate, state));
11301111

11311112
const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => {
11321113
const fromFile = tryFile(candidate, onlyRecordFailures, state);
@@ -1146,21 +1127,26 @@ namespace ts {
11461127
return nodeLoadModuleByRelativeName(nextExtensions, candidate, onlyRecordFailures, state, /*considerPackageJson*/ false);
11471128
};
11481129

1149-
const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(file), state.host);
1130+
const onlyRecordFailuresForPackageFile = packageFile ? !directoryProbablyExists(getDirectoryPath(packageFile), state.host) : undefined;
1131+
const onlyRecordFailuresForIndex = onlyRecordFailures || !directoryProbablyExists(candidate, state.host);
1132+
const indexPath = combinePaths(candidate, "index");
11501133

1151-
if (versionPaths && containsPath(candidate, file)) {
1152-
const moduleName = getRelativePathFromDirectory(candidate, file, /*ignoreCase*/ false);
1134+
if (versionPaths && (!packageFile || containsPath(candidate, packageFile))) {
1135+
const moduleName = getRelativePathFromDirectory(candidate, packageFile || indexPath, /*ignoreCase*/ false);
11531136
if (state.traceEnabled) {
11541137
trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, versionPaths.version, version, moduleName);
11551138
}
1156-
const result = tryLoadModuleUsingPaths(extensions, moduleName, candidate, versionPaths.paths, loader, onlyRecordFailures, state);
1139+
const result = tryLoadModuleUsingPaths(extensions, moduleName, candidate, versionPaths.paths, loader, onlyRecordFailuresForPackageFile || onlyRecordFailuresForIndex, state);
11571140
if (result) {
11581141
return removeIgnoredPackageId(result.value);
11591142
}
11601143
}
11611144

11621145
// It won't have a `packageId` set, because we disabled `considerPackageJson`.
1163-
return removeIgnoredPackageId(loader(extensions, file, onlyRecordFailures, state));
1146+
const packageFileResult = packageFile && removeIgnoredPackageId(loader(extensions, packageFile, onlyRecordFailuresForPackageFile!, state));
1147+
if (packageFileResult) return packageFileResult;
1148+
1149+
return loadModuleFromFile(extensions, indexPath, onlyRecordFailuresForIndex, state);
11641150
}
11651151

11661152
/** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */

tests/baselines/reference/typesVersions.ambientModules.trace.json

+8
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
"File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.ts' does not exist.",
3333
"File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.tsx' does not exist.",
3434
"File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.d.ts' does not exist.",
35+
"'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'index'.",
36+
"Module name 'index', matched pattern '*'.",
37+
"Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.",
38+
"Loading module as file / folder, candidate module location 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other/ts3.1/index', target file type 'TypeScript'.",
3539
"Directory 'tests/cases/conformance/moduleResolution/node_modules/@types' does not exist, skipping all lookups in it.",
3640
"Directory 'tests/cases/conformance/node_modules' does not exist, skipping all lookups in it.",
3741
"Directory 'tests/cases/node_modules' does not exist, skipping all lookups in it.",
@@ -46,6 +50,10 @@
4650
"Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.",
4751
"File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.js' does not exist.",
4852
"File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.jsx' does not exist.",
53+
"'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'index'.",
54+
"Module name 'index', matched pattern '*'.",
55+
"Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.",
56+
"Loading module as file / folder, candidate module location 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other/ts3.1/index', target file type 'JavaScript'.",
4957
"Directory 'tests/cases/conformance/node_modules' does not exist, skipping all lookups in it.",
5058
"Directory 'tests/cases/node_modules' does not exist, skipping all lookups in it.",
5159
"Directory 'tests/node_modules' does not exist, skipping all lookups in it.",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//// [tests/cases/conformance/moduleResolution/typesVersions.justIndex.ts] ////
2+
3+
//// [package.json]
4+
{
5+
"typesVersions": {
6+
">=3.1.0-0": { "*" : ["ts3.1/*"] }
7+
}
8+
}
9+
10+
//// [index.d.ts]
11+
export const a = 0;
12+
13+
//// [user.ts]
14+
import { a } from "a";
15+
16+
17+
//// [user.js]
18+
"use strict";
19+
Object.defineProperty(exports, "__esModule", { value: true });
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
=== /a/ts3.1/index.d.ts ===
2+
export const a = 0;
3+
>a : Symbol(a, Decl(index.d.ts, 0, 12))
4+
5+
=== /b/user.ts ===
6+
import { a } from "a";
7+
>a : Symbol(a, Decl(user.ts, 0, 8))
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[
2+
"======== Resolving module 'a' from '/b/user.ts'. ========",
3+
"Module resolution kind is not specified, using 'NodeJs'.",
4+
"'baseUrl' option is set to '/', using this value to resolve non-relative module name 'a'.",
5+
"Resolving module name 'a' relative to base url '/' - '/a'.",
6+
"Loading module as file / folder, candidate module location '/a', target file type 'TypeScript'.",
7+
"File '/a.ts' does not exist.",
8+
"File '/a.tsx' does not exist.",
9+
"File '/a.d.ts' does not exist.",
10+
"'package.json' does not have a 'typings' field.",
11+
"'package.json' does not have a 'types' field.",
12+
"'package.json' does not have a 'main' field.",
13+
"'package.json' has a 'typesVersions' field with version-specific path mappings.",
14+
"Found 'package.json' at '/a/package.json'.",
15+
"'package.json' has a 'typesVersions' field with version-specific path mappings.",
16+
"'package.json' does not have a 'typings' field.",
17+
"'package.json' does not have a 'types' field.",
18+
"'package.json' does not have a 'main' field.",
19+
"'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'index'.",
20+
"Module name 'index', matched pattern '*'.",
21+
"Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.",
22+
"File '/a/ts3.1/index' does not exist.",
23+
"Loading module as file / folder, candidate module location '/a/ts3.1/index', target file type 'TypeScript'.",
24+
"File '/a/ts3.1/index.ts' does not exist.",
25+
"File '/a/ts3.1/index.tsx' does not exist.",
26+
"File '/a/ts3.1/index.d.ts' exist - use it as a name resolution result.",
27+
"======== Module name 'a' was successfully resolved to '/a/ts3.1/index.d.ts'. ========"
28+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
=== /a/ts3.1/index.d.ts ===
2+
export const a = 0;
3+
>a : 0
4+
>0 : 0
5+
6+
=== /b/user.ts ===
7+
import { a } from "a";
8+
>a : 0
9+

tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json

+8
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
"File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.ts' does not exist.",
3333
"File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.tsx' does not exist.",
3434
"File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts' does not exist.",
35+
"'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'index'.",
36+
"Module name 'index', matched pattern '*'.",
37+
"Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.",
38+
"Loading module as file / folder, candidate module location 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other/ts3.1/index', target file type 'TypeScript'.",
3539
"Directory 'tests/cases/conformance/declarationEmit/node_modules/@types' does not exist, skipping all lookups in it.",
3640
"Directory 'tests/cases/conformance/node_modules' does not exist, skipping all lookups in it.",
3741
"Directory 'tests/cases/node_modules' does not exist, skipping all lookups in it.",
@@ -46,6 +50,10 @@
4650
"Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.",
4751
"File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.js' does not exist.",
4852
"File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.jsx' does not exist.",
53+
"'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'index'.",
54+
"Module name 'index', matched pattern '*'.",
55+
"Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.",
56+
"Loading module as file / folder, candidate module location 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other/ts3.1/index', target file type 'JavaScript'.",
4957
"Directory 'tests/cases/conformance/node_modules' does not exist, skipping all lookups in it.",
5058
"Directory 'tests/cases/node_modules' does not exist, skipping all lookups in it.",
5159
"Directory 'tests/node_modules' does not exist, skipping all lookups in it.",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// @baseUrl: /
2+
// @traceResolution: true
3+
// @target: esnext
4+
// @module: commonjs
5+
6+
// @filename: /a/package.json
7+
{
8+
"typesVersions": {
9+
">=3.1.0-0": { "*" : ["ts3.1/*"] }
10+
}
11+
}
12+
13+
// @filename: /a/ts3.1/index.d.ts
14+
export const a = 0;
15+
16+
// @filename: /b/user.ts
17+
import { a } from "a";

0 commit comments

Comments
 (0)