@@ -37,9 +37,9 @@ import {
37
37
getBaseFileName ,
38
38
GetCanonicalFileName ,
39
39
getConditions ,
40
+ getDefaultResolutionModeForFileWorker ,
40
41
getDirectoryPath ,
41
42
getEmitModuleResolutionKind ,
42
- getModeForResolutionAtIndex ,
43
43
getModuleNameStringLiteralAt ,
44
44
getModuleSpecifierEndingPreference ,
45
45
getNodeModulePathParts ,
@@ -143,12 +143,13 @@ export interface ModuleSpecifierPreferences {
143
143
/**
144
144
* @param syntaxImpliedNodeFormat Used when the import syntax implies ESM or CJS irrespective of the mode of the file.
145
145
*/
146
- getAllowedEndingsInPreferredOrder ( syntaxImpliedNodeFormat ?: SourceFile [ "impliedNodeFormat" ] ) : ModuleSpecifierEnding [ ] ;
146
+ getAllowedEndingsInPreferredOrder ( syntaxImpliedNodeFormat ?: ResolutionMode ) : ModuleSpecifierEnding [ ] ;
147
147
}
148
148
149
149
/** @internal */
150
150
export function getModuleSpecifierPreferences (
151
151
{ importModuleSpecifierPreference, importModuleSpecifierEnding } : UserPreferences ,
152
+ host : Pick < ModuleSpecifierResolutionHost , "getDefaultResolutionModeForFile" > ,
152
153
compilerOptions : CompilerOptions ,
153
154
importingSourceFile : Pick < SourceFile , "fileName" | "impliedNodeFormat" > ,
154
155
oldImportSpecifier ?: string ,
@@ -163,8 +164,10 @@ export function getModuleSpecifierPreferences(
163
164
importModuleSpecifierPreference === "project-relative" ? RelativePreference . ExternalNonRelative :
164
165
RelativePreference . Shortest ,
165
166
getAllowedEndingsInPreferredOrder : syntaxImpliedNodeFormat => {
166
- const preferredEnding = syntaxImpliedNodeFormat !== importingSourceFile . impliedNodeFormat ? getPreferredEnding ( syntaxImpliedNodeFormat ) : filePreferredEnding ;
167
- if ( ( syntaxImpliedNodeFormat ?? importingSourceFile . impliedNodeFormat ) === ModuleKind . ESNext ) {
167
+ const impliedNodeFormat = getDefaultResolutionModeForFile ( importingSourceFile , host , compilerOptions ) ;
168
+ const preferredEnding = syntaxImpliedNodeFormat !== impliedNodeFormat ? getPreferredEnding ( syntaxImpliedNodeFormat ) : filePreferredEnding ;
169
+ const moduleResolution = getEmitModuleResolutionKind ( compilerOptions ) ;
170
+ if ( ( syntaxImpliedNodeFormat ?? impliedNodeFormat ) === ModuleKind . ESNext && ModuleResolutionKind . Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind . NodeNext ) {
168
171
if ( shouldAllowImportingTsExtension ( compilerOptions , importingSourceFile . fileName ) ) {
169
172
return [ ModuleSpecifierEnding . TsExtension , ModuleSpecifierEnding . JsExtension ] ;
170
173
}
@@ -204,7 +207,7 @@ export function getModuleSpecifierPreferences(
204
207
}
205
208
return getModuleSpecifierEndingPreference (
206
209
importModuleSpecifierEnding ,
207
- resolutionMode ?? importingSourceFile . impliedNodeFormat ,
210
+ resolutionMode ?? getDefaultResolutionModeForFile ( importingSourceFile , host , compilerOptions ) ,
208
211
compilerOptions ,
209
212
isFullSourceFile ( importingSourceFile ) ? importingSourceFile : undefined ,
210
213
) ;
@@ -225,7 +228,7 @@ export function updateModuleSpecifier(
225
228
oldImportSpecifier : string ,
226
229
options : ModuleSpecifierOptions = { } ,
227
230
) : string | undefined {
228
- const res = getModuleSpecifierWorker ( compilerOptions , importingSourceFile , importingSourceFileName , toFileName , host , getModuleSpecifierPreferences ( { } , compilerOptions , importingSourceFile , oldImportSpecifier ) , { } , options ) ;
231
+ const res = getModuleSpecifierWorker ( compilerOptions , importingSourceFile , importingSourceFileName , toFileName , host , getModuleSpecifierPreferences ( { } , host , compilerOptions , importingSourceFile , oldImportSpecifier ) , { } , options ) ;
229
232
if ( res === oldImportSpecifier ) return undefined ;
230
233
return res ;
231
234
}
@@ -245,7 +248,7 @@ export function getModuleSpecifier(
245
248
host : ModuleSpecifierResolutionHost ,
246
249
options : ModuleSpecifierOptions = { } ,
247
250
) : string {
248
- return getModuleSpecifierWorker ( compilerOptions , importingSourceFile , importingSourceFileName , toFileName , host , getModuleSpecifierPreferences ( { } , compilerOptions , importingSourceFile ) , { } , options ) ;
251
+ return getModuleSpecifierWorker ( compilerOptions , importingSourceFile , importingSourceFileName , toFileName , host , getModuleSpecifierPreferences ( { } , host , compilerOptions , importingSourceFile ) , { } , options ) ;
249
252
}
250
253
251
254
/** @internal */
@@ -275,7 +278,7 @@ function getModuleSpecifierWorker(
275
278
const info = getInfo ( importingSourceFileName , host ) ;
276
279
const modulePaths = getAllModulePaths ( info , toFileName , host , userPreferences , compilerOptions , options ) ;
277
280
return firstDefined ( modulePaths , modulePath => tryGetModuleNameAsNodeModule ( modulePath , info , importingSourceFile , host , compilerOptions , userPreferences , /*packageNameOnly*/ undefined , options . overrideImportMode ) ) ||
278
- getLocalModuleSpecifier ( toFileName , info , compilerOptions , host , options . overrideImportMode || importingSourceFile . impliedNodeFormat , preferences ) ;
281
+ getLocalModuleSpecifier ( toFileName , info , compilerOptions , host , options . overrideImportMode || getDefaultResolutionModeForFile ( importingSourceFile , host , compilerOptions ) , preferences ) ;
279
282
}
280
283
281
284
/** @internal */
@@ -403,7 +406,7 @@ export function getLocalModuleSpecifierBetweenFileNames(
403
406
compilerOptions ,
404
407
host ,
405
408
importMode ,
406
- getModuleSpecifierPreferences ( { } , compilerOptions , importingFile ) ,
409
+ getModuleSpecifierPreferences ( { } , host , compilerOptions , importingFile ) ,
407
410
) ;
408
411
}
409
412
@@ -417,15 +420,19 @@ function computeModuleSpecifiers(
417
420
forAutoImport : boolean ,
418
421
) : ModuleSpecifierResult {
419
422
const info = getInfo ( importingSourceFile . fileName , host ) ;
420
- const preferences = getModuleSpecifierPreferences ( userPreferences , compilerOptions , importingSourceFile ) ;
423
+ const preferences = getModuleSpecifierPreferences ( userPreferences , host , compilerOptions , importingSourceFile ) ;
421
424
const existingSpecifier = isFullSourceFile ( importingSourceFile ) && forEach ( modulePaths , modulePath =>
422
425
forEach (
423
426
host . getFileIncludeReasons ( ) . get ( toPath ( modulePath . path , host . getCurrentDirectory ( ) , info . getCanonicalFileName ) ) ,
424
427
reason => {
425
428
if ( reason . kind !== FileIncludeKind . Import || reason . file !== importingSourceFile . path ) return undefined ;
426
429
// If the candidate import mode doesn't match the mode we're generating for, don't consider it
427
430
// TODO: maybe useful to keep around as an alternative option for certain contexts where the mode is overridable
428
- if ( importingSourceFile . impliedNodeFormat && importingSourceFile . impliedNodeFormat !== getModeForResolutionAtIndex ( importingSourceFile , reason . index , compilerOptions ) ) return undefined ;
431
+ const existingMode = host . getModeForResolutionAtIndex ( importingSourceFile , reason . index ) ;
432
+ const targetMode = options . overrideImportMode ?? host . getDefaultResolutionModeForFile ( importingSourceFile ) ;
433
+ if ( existingMode !== targetMode && existingMode !== undefined && targetMode !== undefined ) {
434
+ return undefined ;
435
+ }
429
436
const specifier = getModuleNameStringLiteralAt ( importingSourceFile , reason . index ) . text ;
430
437
// If the preference is for non relative and the module specifier is relative, ignore it
431
438
return preferences . relativePreference !== RelativePreference . NonRelative || ! pathIsRelative ( specifier ) ?
@@ -1093,7 +1100,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan
1093
1100
1094
1101
// Simplify the full file path to something that can be resolved by Node.
1095
1102
1096
- const preferences = getModuleSpecifierPreferences ( userPreferences , options , importingSourceFile ) ;
1103
+ const preferences = getModuleSpecifierPreferences ( userPreferences , host , options , importingSourceFile ) ;
1097
1104
const allowedEndings = preferences . getAllowedEndingsInPreferredOrder ( ) ;
1098
1105
let moduleSpecifier = path ;
1099
1106
let isPackageRootPath = false ;
@@ -1153,7 +1160,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan
1153
1160
const cachedPackageJson = host . getPackageJsonInfoCache ?.( ) ?. getPackageJsonInfo ( packageJsonPath ) ;
1154
1161
if ( isPackageJsonInfo ( cachedPackageJson ) || cachedPackageJson === undefined && host . fileExists ( packageJsonPath ) ) {
1155
1162
const packageJsonContent : Record < string , any > | undefined = cachedPackageJson ?. contents . packageJsonContent || tryParseJson ( host . readFile ! ( packageJsonPath ) ! ) ;
1156
- const importMode = overrideMode || importingSourceFile . impliedNodeFormat ;
1163
+ const importMode = overrideMode || getDefaultResolutionModeForFile ( importingSourceFile , host , options ) ;
1157
1164
if ( getResolvePackageJsonExports ( options ) ) {
1158
1165
// The package name that we found in node_modules could be different from the package
1159
1166
// name in the package.json content via url/filepath dependency specifiers. We need to
@@ -1348,3 +1355,7 @@ function getRelativePathIfInSameVolume(path: string, directoryPath: string, getC
1348
1355
function isPathRelativeToParent ( path : string ) : boolean {
1349
1356
return startsWith ( path , ".." ) ;
1350
1357
}
1358
+
1359
+ function getDefaultResolutionModeForFile ( file : Pick < SourceFile , "fileName" | "impliedNodeFormat" | "packageJsonScope" > , host : Pick < ModuleSpecifierResolutionHost , "getDefaultResolutionModeForFile" > , compilerOptions : CompilerOptions ) {
1360
+ return isFullSourceFile ( file ) ? host . getDefaultResolutionModeForFile ( file ) : getDefaultResolutionModeForFileWorker ( file , compilerOptions ) ;
1361
+ }
0 commit comments