@@ -37,9 +37,9 @@ import {
3737 getBaseFileName ,
3838 GetCanonicalFileName ,
3939 getConditions ,
40+ getDefaultResolutionModeForFileWorker ,
4041 getDirectoryPath ,
4142 getEmitModuleResolutionKind ,
42- getModeForResolutionAtIndex ,
4343 getModuleNameStringLiteralAt ,
4444 getModuleSpecifierEndingPreference ,
4545 getNodeModulePathParts ,
@@ -143,12 +143,13 @@ export interface ModuleSpecifierPreferences {
143143 /**
144144 * @param syntaxImpliedNodeFormat Used when the import syntax implies ESM or CJS irrespective of the mode of the file.
145145 */
146- getAllowedEndingsInPreferredOrder ( syntaxImpliedNodeFormat ?: SourceFile [ "impliedNodeFormat" ] ) : ModuleSpecifierEnding [ ] ;
146+ getAllowedEndingsInPreferredOrder ( syntaxImpliedNodeFormat ?: ResolutionMode ) : ModuleSpecifierEnding [ ] ;
147147}
148148
149149/** @internal */
150150export function getModuleSpecifierPreferences (
151151 { importModuleSpecifierPreference, importModuleSpecifierEnding } : UserPreferences ,
152+ host : Pick < ModuleSpecifierResolutionHost , "getDefaultResolutionModeForFile" > ,
152153 compilerOptions : CompilerOptions ,
153154 importingSourceFile : Pick < SourceFile , "fileName" | "impliedNodeFormat" > ,
154155 oldImportSpecifier ?: string ,
@@ -163,8 +164,10 @@ export function getModuleSpecifierPreferences(
163164 importModuleSpecifierPreference === "project-relative" ? RelativePreference . ExternalNonRelative :
164165 RelativePreference . Shortest ,
165166 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 ) {
168171 if ( shouldAllowImportingTsExtension ( compilerOptions , importingSourceFile . fileName ) ) {
169172 return [ ModuleSpecifierEnding . TsExtension , ModuleSpecifierEnding . JsExtension ] ;
170173 }
@@ -204,7 +207,7 @@ export function getModuleSpecifierPreferences(
204207 }
205208 return getModuleSpecifierEndingPreference (
206209 importModuleSpecifierEnding ,
207- resolutionMode ?? importingSourceFile . impliedNodeFormat ,
210+ resolutionMode ?? getDefaultResolutionModeForFile ( importingSourceFile , host , compilerOptions ) ,
208211 compilerOptions ,
209212 isFullSourceFile ( importingSourceFile ) ? importingSourceFile : undefined ,
210213 ) ;
@@ -225,7 +228,7 @@ export function updateModuleSpecifier(
225228 oldImportSpecifier : string ,
226229 options : ModuleSpecifierOptions = { } ,
227230) : 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 ) ;
229232 if ( res === oldImportSpecifier ) return undefined ;
230233 return res ;
231234}
@@ -245,7 +248,7 @@ export function getModuleSpecifier(
245248 host : ModuleSpecifierResolutionHost ,
246249 options : ModuleSpecifierOptions = { } ,
247250) : 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 ) ;
249252}
250253
251254/** @internal */
@@ -275,7 +278,7 @@ function getModuleSpecifierWorker(
275278 const info = getInfo ( importingSourceFileName , host ) ;
276279 const modulePaths = getAllModulePaths ( info , toFileName , host , userPreferences , compilerOptions , options ) ;
277280 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 ) ;
279282}
280283
281284/** @internal */
@@ -403,7 +406,7 @@ export function getLocalModuleSpecifierBetweenFileNames(
403406 compilerOptions ,
404407 host ,
405408 importMode ,
406- getModuleSpecifierPreferences ( { } , compilerOptions , importingFile ) ,
409+ getModuleSpecifierPreferences ( { } , host , compilerOptions , importingFile ) ,
407410 ) ;
408411}
409412
@@ -417,15 +420,19 @@ function computeModuleSpecifiers(
417420 forAutoImport : boolean ,
418421) : ModuleSpecifierResult {
419422 const info = getInfo ( importingSourceFile . fileName , host ) ;
420- const preferences = getModuleSpecifierPreferences ( userPreferences , compilerOptions , importingSourceFile ) ;
423+ const preferences = getModuleSpecifierPreferences ( userPreferences , host , compilerOptions , importingSourceFile ) ;
421424 const existingSpecifier = isFullSourceFile ( importingSourceFile ) && forEach ( modulePaths , modulePath =>
422425 forEach (
423426 host . getFileIncludeReasons ( ) . get ( toPath ( modulePath . path , host . getCurrentDirectory ( ) , info . getCanonicalFileName ) ) ,
424427 reason => {
425428 if ( reason . kind !== FileIncludeKind . Import || reason . file !== importingSourceFile . path ) return undefined ;
426429 // If the candidate import mode doesn't match the mode we're generating for, don't consider it
427430 // 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+ }
429436 const specifier = getModuleNameStringLiteralAt ( importingSourceFile , reason . index ) . text ;
430437 // If the preference is for non relative and the module specifier is relative, ignore it
431438 return preferences . relativePreference !== RelativePreference . NonRelative || ! pathIsRelative ( specifier ) ?
@@ -1093,7 +1100,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan
10931100
10941101 // Simplify the full file path to something that can be resolved by Node.
10951102
1096- const preferences = getModuleSpecifierPreferences ( userPreferences , options , importingSourceFile ) ;
1103+ const preferences = getModuleSpecifierPreferences ( userPreferences , host , options , importingSourceFile ) ;
10971104 const allowedEndings = preferences . getAllowedEndingsInPreferredOrder ( ) ;
10981105 let moduleSpecifier = path ;
10991106 let isPackageRootPath = false ;
@@ -1153,7 +1160,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan
11531160 const cachedPackageJson = host . getPackageJsonInfoCache ?.( ) ?. getPackageJsonInfo ( packageJsonPath ) ;
11541161 if ( isPackageJsonInfo ( cachedPackageJson ) || cachedPackageJson === undefined && host . fileExists ( packageJsonPath ) ) {
11551162 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 ) ;
11571164 if ( getResolvePackageJsonExports ( options ) ) {
11581165 // The package name that we found in node_modules could be different from the package
11591166 // 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
13481355function isPathRelativeToParent ( path : string ) : boolean {
13491356 return startsWith ( path , ".." ) ;
13501357}
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