mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-16 07:13:43 -05:00
--moduleResolution bundler (formerly known as hybrid) (#51669)
* WIP * Add extension error back unless noEmit is set * Add non-relative tests * Add error for importing from declaration file * Update unit test * Add explicit flag for importing from .ts extensions * Add module specifier resolution changes * Add auto-import tests * Disallow relative imports into node_modules * Ensure auto-imports don’t suggest ./node_modules; * Test a non-portable declaration emit issue * Test auto-importing TSX file * Update path completions * Fix lint due to merge * Remove minimal-specific stuff * Remove minimal tests * Update unit tests * Add options * Add customConditions option * Add first tests * CJS constructs are not allowed * Add another test * Fix extension adding/replacing priority * Update test to reflect the choice not to block on unrecognized extensions * Add auto-imports and string completions tests * Revamp string completions ending preferences * Comment test * Auto-imports of declaration files cannot use .ts extension * Have declaration file auto imports default to extensionless instead * Add test for custom conditions * Fix indentation * Add baseline showing resolvePackageJsonImports/Exports compatibility * Fix test and prevent CJS require from resolving * Update unit test baselines * Fix bad merge conflict resolution * Make resolvedUsingTsExtension optional * Update missed baselines * Revert now-unnecessary API implementation changes * Clean up * Update baselines to es5 emit * Rename to `bundler`
This commit is contained in:
@@ -2,6 +2,7 @@ import {
|
||||
append,
|
||||
appendIfUnique,
|
||||
arrayFrom,
|
||||
arrayIsEqualTo,
|
||||
changeAnyExtension,
|
||||
CharacterCodes,
|
||||
combinePaths,
|
||||
@@ -9,10 +10,12 @@ import {
|
||||
comparePaths,
|
||||
Comparison,
|
||||
CompilerOptions,
|
||||
concatenate,
|
||||
contains,
|
||||
containsPath,
|
||||
createCompilerDiagnostic,
|
||||
Debug,
|
||||
deduplicate,
|
||||
Diagnostic,
|
||||
DiagnosticMessage,
|
||||
DiagnosticReporter,
|
||||
@@ -47,12 +50,14 @@ import {
|
||||
getPathsBasePath,
|
||||
getPossibleOriginalInputExtensionForExtension,
|
||||
getRelativePathFromDirectory,
|
||||
getResolveJsonModule,
|
||||
getRootLength,
|
||||
hasJSFileExtension,
|
||||
hasProperty,
|
||||
hasTrailingDirectorySeparator,
|
||||
hostGetCanonicalFileName,
|
||||
isArray,
|
||||
isDeclarationFileName,
|
||||
isExternalModuleNameRelative,
|
||||
isRootedDiskPath,
|
||||
isString,
|
||||
@@ -94,6 +99,7 @@ import {
|
||||
startsWith,
|
||||
stringContains,
|
||||
supportedDeclarationExtensions,
|
||||
supportedTSExtensionsFlat,
|
||||
supportedTSImplementationExtensions,
|
||||
toPath,
|
||||
tryExtractTSExtension,
|
||||
@@ -128,7 +134,7 @@ function withPackageId(packageInfo: PackageJsonInfo | undefined, r: PathAndExten
|
||||
};
|
||||
}
|
||||
}
|
||||
return r && { path: r.path, extension: r.ext, packageId };
|
||||
return r && { path: r.path, extension: r.ext, packageId, resolvedUsingTsExtension: r.resolvedUsingTsExtension };
|
||||
}
|
||||
|
||||
function noPackageId(r: PathAndExtension | undefined): Resolved | undefined {
|
||||
@@ -138,7 +144,7 @@ function noPackageId(r: PathAndExtension | undefined): Resolved | undefined {
|
||||
function removeIgnoredPackageId(r: Resolved | undefined): PathAndExtension | undefined {
|
||||
if (r) {
|
||||
Debug.assert(r.packageId === undefined);
|
||||
return { path: r.path, ext: r.extension };
|
||||
return { path: r.path, ext: r.extension, resolvedUsingTsExtension: r.resolvedUsingTsExtension };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,6 +163,7 @@ interface Resolved {
|
||||
* Note: This is a file name with preserved original casing, not a normalized `Path`.
|
||||
*/
|
||||
originalPath?: string | true;
|
||||
resolvedUsingTsExtension: boolean | undefined;
|
||||
}
|
||||
|
||||
/** Result of trying to resolve a module at a file. Needs to have 'packageId' added later. */
|
||||
@@ -164,6 +171,7 @@ interface PathAndExtension {
|
||||
path: string;
|
||||
// (Use a different name than `extension` to make sure Resolved isn't assignable to PathAndExtension.)
|
||||
ext: Extension;
|
||||
resolvedUsingTsExtension: boolean | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,7 +223,14 @@ function createResolvedModuleWithFailedLookupLocations(
|
||||
return resultFromCache;
|
||||
}
|
||||
return {
|
||||
resolvedModule: resolved && { resolvedFileName: resolved.path, originalPath: resolved.originalPath === true ? undefined : resolved.originalPath, extension: resolved.extension, isExternalLibraryImport, packageId: resolved.packageId },
|
||||
resolvedModule: resolved && {
|
||||
resolvedFileName: resolved.path,
|
||||
originalPath: resolved.originalPath === true ? undefined : resolved.originalPath,
|
||||
extension: resolved.extension,
|
||||
isExternalLibraryImport,
|
||||
packageId: resolved.packageId,
|
||||
resolvedUsingTsExtension: !!resolved.resolvedUsingTsExtension,
|
||||
},
|
||||
failedLookupLocations: initializeResolutionField(failedLookupLocations),
|
||||
affectingLocations: initializeResolutionField(affectingLocations),
|
||||
resolutionDiagnostics: initializeResolutionField(diagnostics),
|
||||
@@ -488,7 +503,7 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string
|
||||
|
||||
const failedLookupLocations: string[] = [];
|
||||
const affectingLocations: string[] = [];
|
||||
let features = getDefaultNodeResolutionFeatures(options);
|
||||
let features = getNodeResolutionFeatures(options);
|
||||
// Unlike `import` statements, whose mode-calculating APIs are all guaranteed to return `undefined` if we're in an un-mode-ed module resolution
|
||||
// setting, type references will return their target mode regardless of options because of how the parser works, so we guard against the mode being
|
||||
// set in a non-modal module resolution setting here. Do note that our behavior is not particularly well defined when these mode-overriding imports
|
||||
@@ -499,7 +514,7 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string
|
||||
if (resolutionMode === ModuleKind.ESNext && (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext)) {
|
||||
features |= NodeResolutionFeatures.EsmMode;
|
||||
}
|
||||
const conditions = features & NodeResolutionFeatures.Exports ? features & NodeResolutionFeatures.EsmMode ? ["node", "import", "types"] : ["node", "require", "types"] : [];
|
||||
const conditions = features & NodeResolutionFeatures.Exports ? getConditions(options, !!(features & NodeResolutionFeatures.EsmMode)) : [];
|
||||
const diagnostics: Diagnostic[] = [];
|
||||
const moduleResolutionState: ModuleResolutionState = {
|
||||
compilerOptions: options,
|
||||
@@ -614,10 +629,44 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string
|
||||
}
|
||||
}
|
||||
|
||||
function getDefaultNodeResolutionFeatures(options: CompilerOptions) {
|
||||
return getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node16 ? NodeResolutionFeatures.Node16Default :
|
||||
getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext ? NodeResolutionFeatures.NodeNextDefault :
|
||||
NodeResolutionFeatures.None;
|
||||
function getNodeResolutionFeatures(options: CompilerOptions) {
|
||||
let features = NodeResolutionFeatures.None;
|
||||
switch (getEmitModuleResolutionKind(options)) {
|
||||
case ModuleResolutionKind.Node16:
|
||||
features = NodeResolutionFeatures.Node16Default;
|
||||
break;
|
||||
case ModuleResolutionKind.NodeNext:
|
||||
features = NodeResolutionFeatures.NodeNextDefault;
|
||||
break;
|
||||
case ModuleResolutionKind.Bundler:
|
||||
features = NodeResolutionFeatures.BundlerDefault;
|
||||
break;
|
||||
}
|
||||
if (options.resolvePackageJsonExports) {
|
||||
features |= NodeResolutionFeatures.Exports;
|
||||
}
|
||||
else if (options.resolvePackageJsonExports === false) {
|
||||
features &= ~NodeResolutionFeatures.Exports;
|
||||
}
|
||||
if (options.resolvePackageJsonImports) {
|
||||
features |= NodeResolutionFeatures.Imports;
|
||||
}
|
||||
else if (options.resolvePackageJsonImports === false) {
|
||||
features &= ~NodeResolutionFeatures.Imports;
|
||||
}
|
||||
return features;
|
||||
}
|
||||
|
||||
function getConditions(options: CompilerOptions, esmMode?: boolean) {
|
||||
// conditions are only used by the node16/nodenext/bundler resolvers - there's no priority order in the list,
|
||||
// it's essentially a set (priority is determined by object insertion order in the object we look at).
|
||||
const conditions = esmMode || getEmitModuleResolutionKind(options) === ModuleResolutionKind.Bundler
|
||||
? ["node", "import"]
|
||||
: ["node", "require"];
|
||||
if (!options.noDtsResolution) {
|
||||
conditions.push("types");
|
||||
}
|
||||
return concatenate(conditions, options.customConditions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1235,6 +1284,9 @@ export function resolveModuleName(moduleName: string, containingFile: string, co
|
||||
case ModuleResolutionKind.Classic:
|
||||
result = classicNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference);
|
||||
break;
|
||||
case ModuleResolutionKind.Bundler:
|
||||
result = bundlerModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference);
|
||||
break;
|
||||
default:
|
||||
return Debug.fail(`Unexpected moduleResolution: ${moduleResolution}`);
|
||||
}
|
||||
@@ -1489,6 +1541,8 @@ export enum NodeResolutionFeatures {
|
||||
|
||||
NodeNextDefault = AllFeatures,
|
||||
|
||||
BundlerDefault = Imports | SelfName | Exports | ExportsPatternTrailers,
|
||||
|
||||
EsmMode = 1 << 5,
|
||||
}
|
||||
|
||||
@@ -1528,7 +1582,7 @@ function nodeNextModuleNameResolverWorker(features: NodeResolutionFeatures, modu
|
||||
// es module file or cjs-like input file, use a variant of the legacy cjs resolver that supports the selected modern features
|
||||
const esmMode = resolutionMode === ModuleKind.ESNext ? NodeResolutionFeatures.EsmMode : 0;
|
||||
let extensions = compilerOptions.noDtsResolution ? Extensions.ImplementationFiles : Extensions.TypeScript | Extensions.JavaScript | Extensions.Declaration;
|
||||
if (compilerOptions.resolveJsonModule) {
|
||||
if (getResolveJsonModule(compilerOptions)) {
|
||||
extensions |= Extensions.Json;
|
||||
}
|
||||
return nodeModuleNameResolverWorker(features | esmMode, moduleName, containingDirectory, compilerOptions, host, cache, extensions, /*isConfigLookup*/ false, redirectedReference);
|
||||
@@ -1547,6 +1601,15 @@ function tryResolveJSModuleWorker(moduleName: string, initialDir: string, host:
|
||||
/*redirectedReferences*/ undefined);
|
||||
}
|
||||
|
||||
export function bundlerModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations {
|
||||
const containingDirectory = getDirectoryPath(containingFile);
|
||||
let extensions = compilerOptions.noDtsResolution ? Extensions.ImplementationFiles : Extensions.TypeScript | Extensions.JavaScript | Extensions.Declaration;
|
||||
if (getResolveJsonModule(compilerOptions)) {
|
||||
extensions |= Extensions.Json;
|
||||
}
|
||||
return nodeModuleNameResolverWorker(getNodeResolutionFeatures(compilerOptions), moduleName, containingDirectory, compilerOptions, host, cache, extensions, /*isConfigLookup*/ false, redirectedReference);
|
||||
}
|
||||
|
||||
export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations;
|
||||
/** @internal */ export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, lookupConfig?: boolean): ResolvedModuleWithFailedLookupLocations; // eslint-disable-line @typescript-eslint/unified-signatures
|
||||
export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, isConfigLookup?: boolean): ResolvedModuleWithFailedLookupLocations {
|
||||
@@ -1556,10 +1619,10 @@ export function nodeModuleNameResolver(moduleName: string, containingFile: strin
|
||||
}
|
||||
else if (compilerOptions.noDtsResolution) {
|
||||
extensions = Extensions.ImplementationFiles;
|
||||
if (compilerOptions.resolveJsonModule) extensions |= Extensions.Json;
|
||||
if (getResolveJsonModule(compilerOptions)) extensions |= Extensions.Json;
|
||||
}
|
||||
else {
|
||||
extensions = compilerOptions.resolveJsonModule
|
||||
extensions = getResolveJsonModule(compilerOptions)
|
||||
? Extensions.TypeScript | Extensions.JavaScript | Extensions.Declaration | Extensions.Json
|
||||
: Extensions.TypeScript | Extensions.JavaScript | Extensions.Declaration;
|
||||
}
|
||||
@@ -1571,12 +1634,7 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa
|
||||
|
||||
const failedLookupLocations: string[] = [];
|
||||
const affectingLocations: string[] = [];
|
||||
// conditions are only used by the node16/nodenext resolver - there's no priority order in the list,
|
||||
//it's essentially a set (priority is determined by object insertion order in the object we look at).
|
||||
const conditions = features & NodeResolutionFeatures.EsmMode ? ["node", "import", "types"] : ["node", "require", "types"];
|
||||
if (compilerOptions.noDtsResolution) {
|
||||
conditions.pop();
|
||||
}
|
||||
const conditions = getConditions(compilerOptions, !!(features & NodeResolutionFeatures.EsmMode));
|
||||
|
||||
const diagnostics: Diagnostic[] = [];
|
||||
const state: ModuleResolutionState = {
|
||||
@@ -1720,7 +1778,7 @@ function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string,
|
||||
}
|
||||
}
|
||||
// esm mode relative imports shouldn't do any directory lookups (either inside `package.json`
|
||||
// files or implicit `index.js`es). This is a notable depature from cjs norms, where `./foo/pkg`
|
||||
// files or implicit `index.js`es). This is a notable departure from cjs norms, where `./foo/pkg`
|
||||
// could have been redirected by `./foo/pkg/package.json` to an arbitrary location!
|
||||
if (!(state.features & NodeResolutionFeatures.EsmMode)) {
|
||||
return loadNodeModuleFromDirectory(extensions, candidate, onlyRecordFailures, state, considerPackageJson);
|
||||
@@ -1795,7 +1853,12 @@ function loadModuleFromFile(extensions: Extensions, candidate: string, onlyRecor
|
||||
function loadModuleFromFileNoImplicitExtensions(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined {
|
||||
// If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one;
|
||||
// e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts"
|
||||
if (hasJSFileExtension(candidate) || extensions & Extensions.Json && fileExtensionIs(candidate, Extension.Json)) {
|
||||
if (hasJSFileExtension(candidate) ||
|
||||
extensions & Extensions.Json && fileExtensionIs(candidate, Extension.Json) ||
|
||||
extensions & (Extensions.TypeScript | Extensions.Declaration)
|
||||
&& moduleResolutionSupportsResolvingTsExtensions(state.compilerOptions)
|
||||
&& fileExtensionIsOneOf(candidate, supportedTSExtensionsFlat)
|
||||
) {
|
||||
const extensionless = removeFileExtension(candidate);
|
||||
const extension = candidate.substring(extensionless.length);
|
||||
if (state.traceEnabled) {
|
||||
@@ -1810,7 +1873,7 @@ function loadJSOrExactTSFileName(extensions: Extensions, candidate: string, only
|
||||
extensions & Extensions.Declaration && fileExtensionIsOneOf(candidate, supportedDeclarationExtensions)
|
||||
) {
|
||||
const result = tryFile(candidate, onlyRecordFailures, state);
|
||||
return result !== undefined ? { path: candidate, ext: tryExtractTSExtension(candidate) as Extension } : undefined;
|
||||
return result !== undefined ? { path: candidate, ext: tryExtractTSExtension(candidate) as Extension, resolvedUsingTsExtension: undefined } : undefined;
|
||||
}
|
||||
|
||||
return loadModuleFromFileNoImplicitExtensions(extensions, candidate, onlyRecordFailures, state);
|
||||
@@ -1854,6 +1917,13 @@ function tryAddingExtensions(candidate: string, extensions: Extensions, original
|
||||
if (result) return result;
|
||||
}
|
||||
return undefined;
|
||||
case Extension.Ts:
|
||||
case Extension.Tsx:
|
||||
case Extension.Dts:
|
||||
if (moduleResolutionSupportsResolvingTsExtensions(state.compilerOptions) && extensionIsOk(extensions, originalExtension)) {
|
||||
return tryExtension(originalExtension, /*resolvedUsingTsExtension*/ true);
|
||||
}
|
||||
// falls through
|
||||
default:
|
||||
return extensions & Extensions.TypeScript && (tryExtension(Extension.Ts) || tryExtension(Extension.Tsx))
|
||||
|| extensions & Extensions.Declaration && tryExtension(Extension.Dts)
|
||||
@@ -1863,9 +1933,9 @@ function tryAddingExtensions(candidate: string, extensions: Extensions, original
|
||||
|
||||
}
|
||||
|
||||
function tryExtension(ext: Extension): PathAndExtension | undefined {
|
||||
function tryExtension(ext: Extension, resolvedUsingTsExtension?: boolean): PathAndExtension | undefined {
|
||||
const path = tryFile(candidate + ext, onlyRecordFailures, state);
|
||||
return path === undefined ? undefined : { path, ext };
|
||||
return path === undefined ? undefined : { path, ext, resolvedUsingTsExtension };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1921,26 +1991,30 @@ export function getEntrypointsFromPackageJsonInfo(
|
||||
|
||||
let entrypoints: string[] | undefined;
|
||||
const extensions = Extensions.TypeScript | Extensions.Declaration | (resolveJs ? Extensions.JavaScript : 0);
|
||||
const features = getDefaultNodeResolutionFeatures(options);
|
||||
const requireState = getTemporaryModuleResolutionState(cache?.getPackageJsonInfoCache(), host, options);
|
||||
requireState.conditions = ["node", "require", "types"];
|
||||
requireState.requestContainingDirectory = packageJsonInfo.packageDirectory;
|
||||
const requireResolution = loadNodeModuleFromDirectoryWorker(
|
||||
const features = getNodeResolutionFeatures(options);
|
||||
const loadPackageJsonMainState = getTemporaryModuleResolutionState(cache?.getPackageJsonInfoCache(), host, options);
|
||||
loadPackageJsonMainState.conditions = getConditions(options);
|
||||
loadPackageJsonMainState.requestContainingDirectory = packageJsonInfo.packageDirectory;
|
||||
const mainResolution = loadNodeModuleFromDirectoryWorker(
|
||||
extensions,
|
||||
packageJsonInfo.packageDirectory,
|
||||
/*onlyRecordFailures*/ false,
|
||||
requireState,
|
||||
loadPackageJsonMainState,
|
||||
packageJsonInfo.contents.packageJsonContent,
|
||||
getVersionPathsOfPackageJsonInfo(packageJsonInfo, requireState));
|
||||
entrypoints = append(entrypoints, requireResolution?.path);
|
||||
getVersionPathsOfPackageJsonInfo(packageJsonInfo, loadPackageJsonMainState));
|
||||
entrypoints = append(entrypoints, mainResolution?.path);
|
||||
|
||||
if (features & NodeResolutionFeatures.Exports && packageJsonInfo.contents.packageJsonContent.exports) {
|
||||
for (const conditions of [["node", "import", "types"], ["node", "require", "types"]]) {
|
||||
const exportState = { ...requireState, failedLookupLocations: [], conditions };
|
||||
const conditionSets = deduplicate(
|
||||
[getConditions(options, /*esmMode*/ true), getConditions(options, /*esmMode*/ false)],
|
||||
arrayIsEqualTo
|
||||
);
|
||||
for (const conditions of conditionSets) {
|
||||
const loadPackageJsonExportsState = { ...loadPackageJsonMainState, failedLookupLocations: [], conditions };
|
||||
const exportResolutions = loadEntrypointsFromExportMap(
|
||||
packageJsonInfo,
|
||||
packageJsonInfo.contents.packageJsonContent.exports,
|
||||
exportState,
|
||||
loadPackageJsonExportsState,
|
||||
extensions);
|
||||
if (exportResolutions) {
|
||||
for (const resolution of exportResolutions) {
|
||||
@@ -2046,7 +2120,7 @@ export interface PackageJsonInfoContents {
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function getPackageScopeForPath(fileName: string, state: ModuleResolutionState): PackageJsonInfo | undefined {
|
||||
export function getPackageScopeForPath(fileName: string, state: ModuleResolutionState): PackageJsonInfo | undefined {
|
||||
const parts = getPathComponents(fileName);
|
||||
parts.pop();
|
||||
while (parts.length > 0) {
|
||||
@@ -2179,9 +2253,9 @@ function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: st
|
||||
}
|
||||
|
||||
/** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */
|
||||
function resolvedIfExtensionMatches(extensions: Extensions, path: string): PathAndExtension | undefined {
|
||||
function resolvedIfExtensionMatches(extensions: Extensions, path: string, resolvedUsingTsExtension?: boolean): PathAndExtension | undefined {
|
||||
const ext = tryGetExtensionFromPath(path);
|
||||
return ext !== undefined && extensionIsOk(extensions, ext) ? { path, ext } : undefined;
|
||||
return ext !== undefined && extensionIsOk(extensions, ext) ? { path, ext, resolvedUsingTsExtension } : undefined;
|
||||
}
|
||||
|
||||
/** True if `extension` is one of the supported `extensions`. */
|
||||
@@ -2372,7 +2446,13 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo
|
||||
traceIfEnabled(state, Diagnostics.Using_0_subpath_1_with_target_2, "imports", key, combinedLookup);
|
||||
traceIfEnabled(state, Diagnostics.Resolving_module_0_from_1, combinedLookup, scope.packageDirectory + "/");
|
||||
const result = nodeModuleNameResolverWorker(state.features, combinedLookup, scope.packageDirectory + "/", state.compilerOptions, state.host, cache, extensions, /*isConfigLookup*/ false, redirectedReference);
|
||||
return toSearchResult(result.resolvedModule ? { path: result.resolvedModule.resolvedFileName, extension: result.resolvedModule.extension, packageId: result.resolvedModule.packageId, originalPath: result.resolvedModule.originalPath } : undefined);
|
||||
return toSearchResult(result.resolvedModule ? {
|
||||
path: result.resolvedModule.resolvedFileName,
|
||||
extension: result.resolvedModule.extension,
|
||||
packageId: result.resolvedModule.packageId,
|
||||
originalPath: result.resolvedModule.originalPath,
|
||||
resolvedUsingTsExtension: result.resolvedModule.resolvedUsingTsExtension
|
||||
} : undefined);
|
||||
}
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName);
|
||||
@@ -2753,7 +2833,7 @@ function tryLoadModuleUsingPaths(extensions: Extensions, moduleName: string, bas
|
||||
if (extension !== undefined) {
|
||||
const path = tryFile(candidate, onlyRecordFailures, state);
|
||||
if (path !== undefined) {
|
||||
return noPackageId({ path, ext: extension });
|
||||
return noPackageId({ path, ext: extension, resolvedUsingTsExtension: undefined });
|
||||
}
|
||||
}
|
||||
return loader(extensions, candidate, onlyRecordFailures || !directoryProbablyExists(getDirectoryPath(candidate), state.host), state);
|
||||
@@ -2813,7 +2893,15 @@ function tryFindNonRelativeModuleNameInCache(cache: NonRelativeModuleNameResolut
|
||||
trace(state.host, Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, moduleName, containingDirectory);
|
||||
}
|
||||
state.resultFromCache = result;
|
||||
return { value: result.resolvedModule && { path: result.resolvedModule.resolvedFileName, originalPath: result.resolvedModule.originalPath || true, extension: result.resolvedModule.extension, packageId: result.resolvedModule.packageId } };
|
||||
return {
|
||||
value: result.resolvedModule && {
|
||||
path: result.resolvedModule.resolvedFileName,
|
||||
originalPath: result.resolvedModule.originalPath || true,
|
||||
extension: result.resolvedModule.extension,
|
||||
packageId: result.resolvedModule.packageId,
|
||||
resolvedUsingTsExtension: result.resolvedModule.resolvedUsingTsExtension
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2880,6 +2968,18 @@ export function classicNameResolver(moduleName: string, containingFile: string,
|
||||
}
|
||||
}
|
||||
|
||||
export function moduleResolutionSupportsResolvingTsExtensions(compilerOptions: CompilerOptions) {
|
||||
return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Bundler;
|
||||
}
|
||||
|
||||
// Program errors validate that `noEmit` or `emitDeclarationOnly` is also set,
|
||||
// so this function doesn't check them to avoid propagating errors.
|
||||
export function shouldAllowImportingTsExtension(compilerOptions: CompilerOptions, fromFileName?: string) {
|
||||
return moduleResolutionSupportsResolvingTsExtensions(compilerOptions) && (
|
||||
!!compilerOptions.allowImportingTsExtensions ||
|
||||
fromFileName && isDeclarationFileName(fromFileName));
|
||||
}
|
||||
|
||||
/**
|
||||
* A host may load a module from a global cache of typings.
|
||||
* This is the minumum code needed to expose that functionality; the rest is in the host.
|
||||
|
||||
Reference in New Issue
Block a user