@@ -59,44 +59,55 @@ namespace ts.moduleSpecifiers {
59
59
} ;
60
60
}
61
61
62
+ // `importingSourceFile` and `importingSourceFileName`? Why not just use `importingSourceFile.path`?
63
+ // Because when this is called by the file renamer, `importingSourceFile` is the file being renamed,
64
+ // while `importingSourceFileName` its *new* name. We need a source file just to get its
65
+ // `impliedNodeFormat` and to detect certain preferences from existing import module specifiers.
62
66
export function updateModuleSpecifier (
63
67
compilerOptions : CompilerOptions ,
68
+ importingSourceFile : SourceFile ,
64
69
importingSourceFileName : Path ,
65
70
toFileName : string ,
66
71
host : ModuleSpecifierResolutionHost ,
67
72
oldImportSpecifier : string ,
68
73
) : string | undefined {
69
- const res = getModuleSpecifierWorker ( compilerOptions , importingSourceFileName , toFileName , host , getPreferencesForUpdate ( compilerOptions , oldImportSpecifier , importingSourceFileName , host ) , { } ) ;
74
+ const res = getModuleSpecifierWorker ( compilerOptions , importingSourceFile , importingSourceFile . path , toFileName , host , getPreferencesForUpdate ( compilerOptions , oldImportSpecifier , importingSourceFileName , host ) , { } ) ;
70
75
if ( res === oldImportSpecifier ) return undefined ;
71
76
return res ;
72
77
}
73
78
74
- // Note: importingSourceFile is just for usesJsExtensionOnImports
79
+ // `importingSourceFile` and `importingSourceFileName`? Why not just use `importingSourceFile.path`?
80
+ // Because when this is called by the declaration emitter, `importingSourceFile` is the implementation
81
+ // file, but `importingSourceFileName` and `toFileName` refer to declaration files (the former to the
82
+ // one currently being produced; the latter to the one being imported). We need an implementation file
83
+ // just to get its `impliedNodeFormat` and to detect certain preferences from existing import module
84
+ // specifiers.
75
85
export function getModuleSpecifier (
76
86
compilerOptions : CompilerOptions ,
77
87
importingSourceFile : SourceFile ,
78
88
importingSourceFileName : Path ,
79
89
toFileName : string ,
80
90
host : ModuleSpecifierResolutionHost ,
81
91
) : string {
82
- return getModuleSpecifierWorker ( compilerOptions , importingSourceFileName , toFileName , host , getPreferences ( host , { } , compilerOptions , importingSourceFile ) , { } ) ;
92
+ return getModuleSpecifierWorker ( compilerOptions , importingSourceFile , importingSourceFileName , toFileName , host , getPreferences ( host , { } , compilerOptions , importingSourceFile ) , { } ) ;
83
93
}
84
94
85
95
export function getNodeModulesPackageName (
86
96
compilerOptions : CompilerOptions ,
87
- importingSourceFileName : Path ,
97
+ importingSourceFile : SourceFile ,
88
98
nodeModulesFileName : string ,
89
99
host : ModuleSpecifierResolutionHost ,
90
100
preferences : UserPreferences ,
91
101
) : string | undefined {
92
- const info = getInfo ( importingSourceFileName , host ) ;
93
- const modulePaths = getAllModulePaths ( importingSourceFileName , nodeModulesFileName , host , preferences ) ;
102
+ const info = getInfo ( importingSourceFile . path , host ) ;
103
+ const modulePaths = getAllModulePaths ( importingSourceFile . path , nodeModulesFileName , host , preferences ) ;
94
104
return firstDefined ( modulePaths ,
95
- modulePath => tryGetModuleNameAsNodeModule ( modulePath , info , host , compilerOptions , /*packageNameOnly*/ true ) ) ;
105
+ modulePath => tryGetModuleNameAsNodeModule ( modulePath , info , importingSourceFile , host , compilerOptions , /*packageNameOnly*/ true ) ) ;
96
106
}
97
107
98
108
function getModuleSpecifierWorker (
99
109
compilerOptions : CompilerOptions ,
110
+ importingSourceFile : SourceFile ,
100
111
importingSourceFileName : Path ,
101
112
toFileName : string ,
102
113
host : ModuleSpecifierResolutionHost ,
@@ -105,7 +116,7 @@ namespace ts.moduleSpecifiers {
105
116
) : string {
106
117
const info = getInfo ( importingSourceFileName , host ) ;
107
118
const modulePaths = getAllModulePaths ( importingSourceFileName , toFileName , host , userPreferences ) ;
108
- return firstDefined ( modulePaths , modulePath => tryGetModuleNameAsNodeModule ( modulePath , info , host , compilerOptions ) ) ||
119
+ return firstDefined ( modulePaths , modulePath => tryGetModuleNameAsNodeModule ( modulePath , info , importingSourceFile , host , compilerOptions ) ) ||
109
120
getLocalModuleSpecifier ( toFileName , info , compilerOptions , host , preferences ) ;
110
121
}
111
122
@@ -222,7 +233,7 @@ namespace ts.moduleSpecifiers {
222
233
let pathsSpecifiers : string [ ] | undefined ;
223
234
let relativeSpecifiers : string [ ] | undefined ;
224
235
for ( const modulePath of modulePaths ) {
225
- const specifier = tryGetModuleNameAsNodeModule ( modulePath , info , host , compilerOptions ) ;
236
+ const specifier = tryGetModuleNameAsNodeModule ( modulePath , info , importingSourceFile , host , compilerOptions ) ;
226
237
nodeModulesSpecifiers = append ( nodeModulesSpecifiers , specifier ) ;
227
238
if ( specifier && modulePath . isRedirect ) {
228
239
// If we got a specifier for a redirect, it was a bare package specifier (e.g. "@foo/bar",
@@ -639,7 +650,7 @@ namespace ts.moduleSpecifiers {
639
650
: removeFileExtension ( relativePath ) ;
640
651
}
641
652
642
- function tryGetModuleNameAsNodeModule ( { path, isRedirect } : ModulePath , { getCanonicalFileName, sourceDirectory } : Info , host : ModuleSpecifierResolutionHost , options : CompilerOptions , packageNameOnly ?: boolean ) : string | undefined {
653
+ function tryGetModuleNameAsNodeModule ( { path, isRedirect } : ModulePath , { getCanonicalFileName, sourceDirectory } : Info , importingSourceFile : SourceFile , host : ModuleSpecifierResolutionHost , options : CompilerOptions , packageNameOnly ?: boolean ) : string | undefined {
643
654
if ( ! host . fileExists || ! host . readFile ) {
644
655
return undefined ;
645
656
}
@@ -706,10 +717,14 @@ namespace ts.moduleSpecifiers {
706
717
let moduleFileToTry = path ;
707
718
if ( host . fileExists ( packageJsonPath ) ) {
708
719
const packageJsonContent = JSON . parse ( host . readFile ! ( packageJsonPath ) ! ) ;
709
- // TODO: Inject `require` or `import` condition based on the intended import mode
710
720
if ( getEmitModuleResolutionKind ( options ) === ModuleResolutionKind . Node12 || getEmitModuleResolutionKind ( options ) === ModuleResolutionKind . NodeNext ) {
721
+ // `conditions` *could* be made to go against `importingSourceFile.impliedNodeFormat` if something wanted to generate
722
+ // an ImportEqualsDeclaration in an ESM-implied file or an ImportCall in a CJS-implied file. But since this function is
723
+ // usually called to conjure an import out of thin air, we don't have an existing usage to call `getModeForUsageAtIndex`
724
+ // with, so for now we just stick with the mode of the file.
725
+ const conditions = [ "node" , importingSourceFile . impliedNodeFormat === ModuleKind . ESNext ? "import" : "require" , "types" ] ;
711
726
const fromExports = packageJsonContent . exports && typeof packageJsonContent . name === "string"
712
- ? tryGetModuleNameFromExports ( options , path , packageRootPath , getPackageNameFromTypesPackageName ( packageJsonContent . name ) , packageJsonContent . exports , [ "node" , "types" ] )
727
+ ? tryGetModuleNameFromExports ( options , path , packageRootPath , getPackageNameFromTypesPackageName ( packageJsonContent . name ) , packageJsonContent . exports , conditions )
713
728
: undefined ;
714
729
if ( fromExports ) {
715
730
const withJsExtension = ! hasTSFileExtension ( fromExports . moduleFileToTry )
0 commit comments