@@ -36,9 +36,9 @@ import {
36
36
getBaseFileName ,
37
37
GetCanonicalFileName ,
38
38
getConditions ,
39
+ getDefaultResolutionModeForFileWorker ,
39
40
getDirectoryPath ,
40
41
getEmitModuleResolutionKind ,
41
- getModeForResolutionAtIndex ,
42
42
getModuleNameStringLiteralAt ,
43
43
getModuleSpecifierEndingPreference ,
44
44
getNodeModulePathParts ,
@@ -136,12 +136,13 @@ export interface ModuleSpecifierPreferences {
136
136
/**
137
137
* @param syntaxImpliedNodeFormat Used when the import syntax implies ESM or CJS irrespective of the mode of the file.
138
138
*/
139
- getAllowedEndingsInPreferredOrder ( syntaxImpliedNodeFormat ?: SourceFile [ "impliedNodeFormat" ] ) : ModuleSpecifierEnding [ ] ;
139
+ getAllowedEndingsInPreferredOrder ( syntaxImpliedNodeFormat ?: ResolutionMode ) : ModuleSpecifierEnding [ ] ;
140
140
}
141
141
142
142
/** @internal */
143
143
export function getModuleSpecifierPreferences (
144
144
{ importModuleSpecifierPreference, importModuleSpecifierEnding } : UserPreferences ,
145
+ host : Pick < ModuleSpecifierResolutionHost , "getDefaultResolutionModeForFile" > ,
145
146
compilerOptions : CompilerOptions ,
146
147
importingSourceFile : Pick < SourceFile , "fileName" | "impliedNodeFormat" > ,
147
148
oldImportSpecifier ?: string ,
@@ -156,8 +157,10 @@ export function getModuleSpecifierPreferences(
156
157
importModuleSpecifierPreference === "project-relative" ? RelativePreference . ExternalNonRelative :
157
158
RelativePreference . Shortest ,
158
159
getAllowedEndingsInPreferredOrder : syntaxImpliedNodeFormat => {
159
- const preferredEnding = syntaxImpliedNodeFormat !== importingSourceFile . impliedNodeFormat ? getPreferredEnding ( syntaxImpliedNodeFormat ) : filePreferredEnding ;
160
- if ( ( syntaxImpliedNodeFormat ?? importingSourceFile . impliedNodeFormat ) === ModuleKind . ESNext ) {
160
+ const impliedNodeFormat = getDefaultResolutionModeForFile ( importingSourceFile , host , compilerOptions ) ;
161
+ const preferredEnding = syntaxImpliedNodeFormat !== impliedNodeFormat ? getPreferredEnding ( syntaxImpliedNodeFormat ) : filePreferredEnding ;
162
+ const moduleResolution = getEmitModuleResolutionKind ( compilerOptions ) ;
163
+ if ( ( syntaxImpliedNodeFormat ?? impliedNodeFormat ) === ModuleKind . ESNext && ModuleResolutionKind . Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind . NodeNext ) {
161
164
if ( shouldAllowImportingTsExtension ( compilerOptions , importingSourceFile . fileName ) ) {
162
165
return [ ModuleSpecifierEnding . TsExtension , ModuleSpecifierEnding . JsExtension ] ;
163
166
}
@@ -197,7 +200,7 @@ export function getModuleSpecifierPreferences(
197
200
}
198
201
return getModuleSpecifierEndingPreference (
199
202
importModuleSpecifierEnding ,
200
- resolutionMode ?? importingSourceFile . impliedNodeFormat ,
203
+ resolutionMode ?? getDefaultResolutionModeForFile ( importingSourceFile , host , compilerOptions ) ,
201
204
compilerOptions ,
202
205
isFullSourceFile ( importingSourceFile ) ? importingSourceFile : undefined ,
203
206
) ;
@@ -218,7 +221,7 @@ export function updateModuleSpecifier(
218
221
oldImportSpecifier : string ,
219
222
options : ModuleSpecifierOptions = { } ,
220
223
) : string | undefined {
221
- const res = getModuleSpecifierWorker ( compilerOptions , importingSourceFile , importingSourceFileName , toFileName , host , getModuleSpecifierPreferences ( { } , compilerOptions , importingSourceFile , oldImportSpecifier ) , { } , options ) ;
224
+ const res = getModuleSpecifierWorker ( compilerOptions , importingSourceFile , importingSourceFileName , toFileName , host , getModuleSpecifierPreferences ( { } , host , compilerOptions , importingSourceFile , oldImportSpecifier ) , { } , options ) ;
222
225
if ( res === oldImportSpecifier ) return undefined ;
223
226
return res ;
224
227
}
@@ -238,7 +241,7 @@ export function getModuleSpecifier(
238
241
host : ModuleSpecifierResolutionHost ,
239
242
options : ModuleSpecifierOptions = { } ,
240
243
) : string {
241
- return getModuleSpecifierWorker ( compilerOptions , importingSourceFile , importingSourceFileName , toFileName , host , getModuleSpecifierPreferences ( { } , compilerOptions , importingSourceFile ) , { } , options ) ;
244
+ return getModuleSpecifierWorker ( compilerOptions , importingSourceFile , importingSourceFileName , toFileName , host , getModuleSpecifierPreferences ( { } , host , compilerOptions , importingSourceFile ) , { } , options ) ;
242
245
}
243
246
244
247
/** @internal */
@@ -268,7 +271,7 @@ function getModuleSpecifierWorker(
268
271
const info = getInfo ( importingSourceFileName , host ) ;
269
272
const modulePaths = getAllModulePaths ( info , toFileName , host , userPreferences , options ) ;
270
273
return firstDefined ( modulePaths , modulePath => tryGetModuleNameAsNodeModule ( modulePath , info , importingSourceFile , host , compilerOptions , userPreferences , /*packageNameOnly*/ undefined , options . overrideImportMode ) ) ||
271
- getLocalModuleSpecifier ( toFileName , info , compilerOptions , host , options . overrideImportMode || importingSourceFile . impliedNodeFormat , preferences ) ;
274
+ getLocalModuleSpecifier ( toFileName , info , compilerOptions , host , options . overrideImportMode || getDefaultResolutionModeForFile ( importingSourceFile , host , compilerOptions ) , preferences ) ;
272
275
}
273
276
274
277
/** @internal */
@@ -388,7 +391,7 @@ export function getLocalModuleSpecifierBetweenFileNames(
388
391
compilerOptions ,
389
392
host ,
390
393
importMode ,
391
- getModuleSpecifierPreferences ( { } , compilerOptions , importingFile ) ,
394
+ getModuleSpecifierPreferences ( { } , host , compilerOptions , importingFile ) ,
392
395
) ;
393
396
}
394
397
@@ -402,15 +405,19 @@ function computeModuleSpecifiers(
402
405
forAutoImport : boolean ,
403
406
) : readonly string [ ] {
404
407
const info = getInfo ( importingSourceFile . fileName , host ) ;
405
- const preferences = getModuleSpecifierPreferences ( userPreferences , compilerOptions , importingSourceFile ) ;
408
+ const preferences = getModuleSpecifierPreferences ( userPreferences , host , compilerOptions , importingSourceFile ) ;
406
409
const existingSpecifier = isFullSourceFile ( importingSourceFile ) && forEach ( modulePaths , modulePath =>
407
410
forEach (
408
411
host . getFileIncludeReasons ( ) . get ( toPath ( modulePath . path , host . getCurrentDirectory ( ) , info . getCanonicalFileName ) ) ,
409
412
reason => {
410
413
if ( reason . kind !== FileIncludeKind . Import || reason . file !== importingSourceFile . path ) return undefined ;
411
414
// If the candidate import mode doesn't match the mode we're generating for, don't consider it
412
415
// TODO: maybe useful to keep around as an alternative option for certain contexts where the mode is overridable
413
- if ( importingSourceFile . impliedNodeFormat && importingSourceFile . impliedNodeFormat !== getModeForResolutionAtIndex ( importingSourceFile , reason . index , compilerOptions ) ) return undefined ;
416
+ const existingMode = host . getModeForResolutionAtIndex ( importingSourceFile , reason . index ) ;
417
+ const targetMode = options . overrideImportMode ?? host . getDefaultResolutionModeForFile ( importingSourceFile ) ;
418
+ if ( existingMode !== targetMode && existingMode !== undefined && targetMode !== undefined ) {
419
+ return undefined ;
420
+ }
414
421
const specifier = getModuleNameStringLiteralAt ( importingSourceFile , reason . index ) . text ;
415
422
// If the preference is for non relative and the module specifier is relative, ignore it
416
423
return preferences . relativePreference !== RelativePreference . NonRelative || ! pathIsRelative ( specifier ) ?
@@ -1047,7 +1054,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan
1047
1054
1048
1055
// Simplify the full file path to something that can be resolved by Node.
1049
1056
1050
- const preferences = getModuleSpecifierPreferences ( userPreferences , options , importingSourceFile ) ;
1057
+ const preferences = getModuleSpecifierPreferences ( userPreferences , host , options , importingSourceFile ) ;
1051
1058
const allowedEndings = preferences . getAllowedEndingsInPreferredOrder ( ) ;
1052
1059
let moduleSpecifier = path ;
1053
1060
let isPackageRootPath = false ;
@@ -1107,7 +1114,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan
1107
1114
const cachedPackageJson = host . getPackageJsonInfoCache ?.( ) ?. getPackageJsonInfo ( packageJsonPath ) ;
1108
1115
if ( isPackageJsonInfo ( cachedPackageJson ) || cachedPackageJson === undefined && host . fileExists ( packageJsonPath ) ) {
1109
1116
const packageJsonContent : Record < string , any > | undefined = cachedPackageJson ?. contents . packageJsonContent || tryParseJson ( host . readFile ! ( packageJsonPath ) ! ) ;
1110
- const importMode = overrideMode || importingSourceFile . impliedNodeFormat ;
1117
+ const importMode = overrideMode || getDefaultResolutionModeForFile ( importingSourceFile , host , options ) ;
1111
1118
if ( getResolvePackageJsonExports ( options ) ) {
1112
1119
// The package name that we found in node_modules could be different from the package
1113
1120
// name in the package.json content via url/filepath dependency specifiers. We need to
@@ -1302,3 +1309,7 @@ function getRelativePathIfInSameVolume(path: string, directoryPath: string, getC
1302
1309
function isPathRelativeToParent ( path : string ) : boolean {
1303
1310
return startsWith ( path , ".." ) ;
1304
1311
}
1312
+
1313
+ function getDefaultResolutionModeForFile ( file : Pick < SourceFile , "fileName" | "impliedNodeFormat" | "packageJsonScope" > , host : Pick < ModuleSpecifierResolutionHost , "getDefaultResolutionModeForFile" > , compilerOptions : CompilerOptions ) {
1314
+ return isFullSourceFile ( file ) ? host . getDefaultResolutionModeForFile ( file ) : getDefaultResolutionModeForFileWorker ( file , compilerOptions ) ;
1315
+ }
0 commit comments