From 9bdd6a3b555c353e0a23968dc08a4ce57668d920 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 3 Oct 2018 11:44:16 -0700 Subject: [PATCH] Support loading "index.d.ts" using "typesVersions" without "types", "typings", or "main" (#27514) * Support loading "index.d.ts" using "typesVersions" without "types", "typings", or "main" * Update baseline --- src/compiler/moduleNameResolver.ts | 44 +++++++------------ .../typesVersions.ambientModules.trace.json | 8 ++++ .../reference/typesVersions.justIndex.js | 19 ++++++++ .../reference/typesVersions.justIndex.symbols | 8 ++++ .../typesVersions.justIndex.trace.json | 28 ++++++++++++ .../reference/typesVersions.justIndex.types | 9 ++++ ...VersionsDeclarationEmit.ambient.trace.json | 8 ++++ .../typesVersions.justIndex.ts | 17 +++++++ 8 files changed, 112 insertions(+), 29 deletions(-) create mode 100644 tests/baselines/reference/typesVersions.justIndex.js create mode 100644 tests/baselines/reference/typesVersions.justIndex.symbols create mode 100644 tests/baselines/reference/typesVersions.justIndex.trace.json create mode 100644 tests/baselines/reference/typesVersions.justIndex.types create mode 100644 tests/cases/conformance/moduleResolution/typesVersions.justIndex.ts diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index aaa04e4f4bb..4906abc8f8c 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -1043,15 +1043,6 @@ namespace ts { return withPackageId(packageId, loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageJsonContent, versionPaths)); } - function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState, packageJsonContent: PackageJsonPathFields | undefined, versionPaths: VersionPaths | undefined): PathAndExtension | undefined { - const fromPackageJson = packageJsonContent && loadModuleFromPackageJson(packageJsonContent, versionPaths, extensions, candidate, state); - if (fromPackageJson) { - return fromPackageJson; - } - const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host); - return loadModuleFromFile(extensions, combinePaths(candidate, "index"), !directoryExists, state); - } - interface PackageJsonInfo { packageJsonContent: PackageJsonPathFields | undefined; packageId: PackageId | undefined; @@ -1111,22 +1102,12 @@ namespace ts { } } - function loadModuleFromPackageJson(jsonContent: PackageJsonPathFields, versionPaths: VersionPaths | undefined, extensions: Extensions, candidate: string, state: ModuleResolutionState): PathAndExtension | undefined { - let file = extensions !== Extensions.JavaScript && extensions !== Extensions.Json - ? readPackageJsonTypesFields(jsonContent, candidate, state) - : readPackageJsonMainField(jsonContent, candidate, state); - if (!file) { - if (extensions === Extensions.TypeScript) { + function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState, jsonContent: PackageJsonPathFields | undefined, versionPaths: VersionPaths | undefined): PathAndExtension | undefined { + const packageFile = jsonContent && (extensions !== Extensions.JavaScript && extensions !== Extensions.Json + ? readPackageJsonTypesFields(jsonContent, candidate, state) || // When resolving typescript modules, try resolving using main field as well - file = readPackageJsonMainField(jsonContent, candidate, state); - if (!file) { - return undefined; - } - } - else { - return undefined; - } - } + (extensions === Extensions.TypeScript ? readPackageJsonMainField(jsonContent, candidate, state) : undefined) + : readPackageJsonMainField(jsonContent, candidate, state)); const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => { const fromFile = tryFile(candidate, onlyRecordFailures, state); @@ -1146,21 +1127,26 @@ namespace ts { return nodeLoadModuleByRelativeName(nextExtensions, candidate, onlyRecordFailures, state, /*considerPackageJson*/ false); }; - const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(file), state.host); + const onlyRecordFailuresForPackageFile = packageFile ? !directoryProbablyExists(getDirectoryPath(packageFile), state.host) : undefined; + const onlyRecordFailuresForIndex = onlyRecordFailures || !directoryProbablyExists(candidate, state.host); + const indexPath = combinePaths(candidate, "index"); - if (versionPaths && containsPath(candidate, file)) { - const moduleName = getRelativePathFromDirectory(candidate, file, /*ignoreCase*/ false); + if (versionPaths && (!packageFile || containsPath(candidate, packageFile))) { + const moduleName = getRelativePathFromDirectory(candidate, packageFile || indexPath, /*ignoreCase*/ false); if (state.traceEnabled) { 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); } - const result = tryLoadModuleUsingPaths(extensions, moduleName, candidate, versionPaths.paths, loader, onlyRecordFailures, state); + const result = tryLoadModuleUsingPaths(extensions, moduleName, candidate, versionPaths.paths, loader, onlyRecordFailuresForPackageFile || onlyRecordFailuresForIndex, state); if (result) { return removeIgnoredPackageId(result.value); } } // It won't have a `packageId` set, because we disabled `considerPackageJson`. - return removeIgnoredPackageId(loader(extensions, file, onlyRecordFailures, state)); + const packageFileResult = packageFile && removeIgnoredPackageId(loader(extensions, packageFile, onlyRecordFailuresForPackageFile!, state)); + if (packageFileResult) return packageFileResult; + + return loadModuleFromFile(extensions, indexPath, onlyRecordFailuresForIndex, state); } /** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */ diff --git a/tests/baselines/reference/typesVersions.ambientModules.trace.json b/tests/baselines/reference/typesVersions.ambientModules.trace.json index 8e4d2ecba2d..ad73f88a8ef 100644 --- a/tests/baselines/reference/typesVersions.ambientModules.trace.json +++ b/tests/baselines/reference/typesVersions.ambientModules.trace.json @@ -32,6 +32,10 @@ "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.ts' does not exist.", "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.tsx' does not exist.", "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.d.ts' does not exist.", + "'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'.", + "Module name 'index', matched pattern '*'.", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", + "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'.", "Directory 'tests/cases/conformance/moduleResolution/node_modules/@types' does not exist, skipping all lookups in it.", "Directory 'tests/cases/conformance/node_modules' does not exist, skipping all lookups in it.", "Directory 'tests/cases/node_modules' does not exist, skipping all lookups in it.", @@ -46,6 +50,10 @@ "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.js' does not exist.", "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.jsx' does not exist.", + "'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'.", + "Module name 'index', matched pattern '*'.", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", + "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'.", "Directory 'tests/cases/conformance/node_modules' does not exist, skipping all lookups in it.", "Directory 'tests/cases/node_modules' does not exist, skipping all lookups in it.", "Directory 'tests/node_modules' does not exist, skipping all lookups in it.", diff --git a/tests/baselines/reference/typesVersions.justIndex.js b/tests/baselines/reference/typesVersions.justIndex.js new file mode 100644 index 00000000000..094376c7d0f --- /dev/null +++ b/tests/baselines/reference/typesVersions.justIndex.js @@ -0,0 +1,19 @@ +//// [tests/cases/conformance/moduleResolution/typesVersions.justIndex.ts] //// + +//// [package.json] +{ + "typesVersions": { + ">=3.1.0-0": { "*" : ["ts3.1/*"] } + } +} + +//// [index.d.ts] +export const a = 0; + +//// [user.ts] +import { a } from "a"; + + +//// [user.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/typesVersions.justIndex.symbols b/tests/baselines/reference/typesVersions.justIndex.symbols new file mode 100644 index 00000000000..a4441e407d7 --- /dev/null +++ b/tests/baselines/reference/typesVersions.justIndex.symbols @@ -0,0 +1,8 @@ +=== /a/ts3.1/index.d.ts === +export const a = 0; +>a : Symbol(a, Decl(index.d.ts, 0, 12)) + +=== /b/user.ts === +import { a } from "a"; +>a : Symbol(a, Decl(user.ts, 0, 8)) + diff --git a/tests/baselines/reference/typesVersions.justIndex.trace.json b/tests/baselines/reference/typesVersions.justIndex.trace.json new file mode 100644 index 00000000000..d69aa51f72d --- /dev/null +++ b/tests/baselines/reference/typesVersions.justIndex.trace.json @@ -0,0 +1,28 @@ +[ + "======== Resolving module 'a' from '/b/user.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "'baseUrl' option is set to '/', using this value to resolve non-relative module name 'a'.", + "Resolving module name 'a' relative to base url '/' - '/a'.", + "Loading module as file / folder, candidate module location '/a', target file type 'TypeScript'.", + "File '/a.ts' does not exist.", + "File '/a.tsx' does not exist.", + "File '/a.d.ts' does not exist.", + "'package.json' does not have a 'typings' field.", + "'package.json' does not have a 'types' field.", + "'package.json' does not have a 'main' field.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at '/a/package.json'.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "'package.json' does not have a 'typings' field.", + "'package.json' does not have a 'types' field.", + "'package.json' does not have a 'main' field.", + "'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'.", + "Module name 'index', matched pattern '*'.", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", + "File '/a/ts3.1/index' does not exist.", + "Loading module as file / folder, candidate module location '/a/ts3.1/index', target file type 'TypeScript'.", + "File '/a/ts3.1/index.ts' does not exist.", + "File '/a/ts3.1/index.tsx' does not exist.", + "File '/a/ts3.1/index.d.ts' exist - use it as a name resolution result.", + "======== Module name 'a' was successfully resolved to '/a/ts3.1/index.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/typesVersions.justIndex.types b/tests/baselines/reference/typesVersions.justIndex.types new file mode 100644 index 00000000000..578d4695e1c --- /dev/null +++ b/tests/baselines/reference/typesVersions.justIndex.types @@ -0,0 +1,9 @@ +=== /a/ts3.1/index.d.ts === +export const a = 0; +>a : 0 +>0 : 0 + +=== /b/user.ts === +import { a } from "a"; +>a : 0 + diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json index f1db86cc283..2fcf9d052d4 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json @@ -32,6 +32,10 @@ "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.ts' does not exist.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.tsx' does not exist.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts' does not exist.", + "'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'.", + "Module name 'index', matched pattern '*'.", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", + "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'.", "Directory 'tests/cases/conformance/declarationEmit/node_modules/@types' does not exist, skipping all lookups in it.", "Directory 'tests/cases/conformance/node_modules' does not exist, skipping all lookups in it.", "Directory 'tests/cases/node_modules' does not exist, skipping all lookups in it.", @@ -46,6 +50,10 @@ "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.js' does not exist.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.jsx' does not exist.", + "'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'.", + "Module name 'index', matched pattern '*'.", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", + "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'.", "Directory 'tests/cases/conformance/node_modules' does not exist, skipping all lookups in it.", "Directory 'tests/cases/node_modules' does not exist, skipping all lookups in it.", "Directory 'tests/node_modules' does not exist, skipping all lookups in it.", diff --git a/tests/cases/conformance/moduleResolution/typesVersions.justIndex.ts b/tests/cases/conformance/moduleResolution/typesVersions.justIndex.ts new file mode 100644 index 00000000000..966a0a54153 --- /dev/null +++ b/tests/cases/conformance/moduleResolution/typesVersions.justIndex.ts @@ -0,0 +1,17 @@ +// @baseUrl: / +// @traceResolution: true +// @target: esnext +// @module: commonjs + +// @filename: /a/package.json +{ + "typesVersions": { + ">=3.1.0-0": { "*" : ["ts3.1/*"] } + } +} + +// @filename: /a/ts3.1/index.d.ts +export const a = 0; + +// @filename: /b/user.ts +import { a } from "a";