@@ -53,13 +53,13 @@ namespace ts {
53
53
if ( getRootLength ( moduleName ) !== 0 || nameStartsWithDotSlashOrDotDotSlash ( moduleName ) ) {
54
54
const failedLookupLocations : string [ ] = [ ] ;
55
55
const candidate = normalizePath ( combinePaths ( containingDirectory , moduleName ) ) ;
56
- let resolvedFileName = loadNodeModuleFromFile ( supportedExtensions , candidate , failedLookupLocations , host ) ;
56
+ let resolvedFileName = loadNodeModuleFromFile ( supportedExtensions , candidate , failedLookupLocations , /*onlyRecordFailures*/ false , host ) ;
57
57
58
58
if ( resolvedFileName ) {
59
59
return { resolvedModule : { resolvedFileName } , failedLookupLocations } ;
60
60
}
61
61
62
- resolvedFileName = loadNodeModuleFromDirectory ( supportedExtensions , candidate , failedLookupLocations , host ) ;
62
+ resolvedFileName = loadNodeModuleFromDirectory ( supportedExtensions , candidate , failedLookupLocations , /*onlyRecordFailures*/ false , host ) ;
63
63
return resolvedFileName
64
64
? { resolvedModule : { resolvedFileName } , failedLookupLocations }
65
65
: { resolvedModule : undefined , failedLookupLocations } ;
@@ -69,12 +69,22 @@ namespace ts {
69
69
}
70
70
}
71
71
72
- function loadNodeModuleFromFile ( extensions : string [ ] , candidate : string , failedLookupLocation : string [ ] , host : ModuleResolutionHost ) : string {
72
+ /* @internal */
73
+ export function directoryProbablyExists ( directoryName : string , host : { directoryExists ?: ( directoryName : string ) => boolean } ) : boolean {
74
+ // if host does not support 'directoryExists' assume that directory will exist
75
+ return ! host . directoryExists || host . directoryExists ( directoryName ) ;
76
+ }
77
+
78
+ /**
79
+ * @param {boolean } onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary
80
+ * in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations.
81
+ */
82
+ function loadNodeModuleFromFile ( extensions : string [ ] , candidate : string , failedLookupLocation : string [ ] , onlyRecordFailures : boolean , host : ModuleResolutionHost ) : string {
73
83
return forEach ( extensions , tryLoad ) ;
74
84
75
85
function tryLoad ( ext : string ) : string {
76
86
const fileName = fileExtensionIs ( candidate , ext ) ? candidate : candidate + ext ;
77
- if ( host . fileExists ( fileName ) ) {
87
+ if ( ! onlyRecordFailures && host . fileExists ( fileName ) ) {
78
88
return fileName ;
79
89
}
80
90
else {
@@ -84,9 +94,10 @@ namespace ts {
84
94
}
85
95
}
86
96
87
- function loadNodeModuleFromDirectory ( extensions : string [ ] , candidate : string , failedLookupLocation : string [ ] , host : ModuleResolutionHost ) : string {
97
+ function loadNodeModuleFromDirectory ( extensions : string [ ] , candidate : string , failedLookupLocation : string [ ] , onlyRecordFailures : boolean , host : ModuleResolutionHost ) : string {
88
98
const packageJsonPath = combinePaths ( candidate , "package.json" ) ;
89
- if ( host . fileExists ( packageJsonPath ) ) {
99
+ const directoryExists = ! onlyRecordFailures && directoryProbablyExists ( candidate , host ) ;
100
+ if ( directoryExists && host . fileExists ( packageJsonPath ) ) {
90
101
91
102
let jsonContent : { typings ?: string } ;
92
103
@@ -100,7 +111,8 @@ namespace ts {
100
111
}
101
112
102
113
if ( typeof jsonContent . typings === "string" ) {
103
- const result = loadNodeModuleFromFile ( extensions , normalizePath ( combinePaths ( candidate , jsonContent . typings ) ) , failedLookupLocation , host ) ;
114
+ const path = normalizePath ( combinePaths ( candidate , jsonContent . typings ) ) ;
115
+ const result = loadNodeModuleFromFile ( extensions , path , failedLookupLocation , ! directoryProbablyExists ( getDirectoryPath ( path ) , host ) , host ) ;
104
116
if ( result ) {
105
117
return result ;
106
118
}
@@ -111,7 +123,7 @@ namespace ts {
111
123
failedLookupLocation . push ( packageJsonPath ) ;
112
124
}
113
125
114
- return loadNodeModuleFromFile ( extensions , combinePaths ( candidate , "index" ) , failedLookupLocation , host ) ;
126
+ return loadNodeModuleFromFile ( extensions , combinePaths ( candidate , "index" ) , failedLookupLocation , ! directoryExists , host ) ;
115
127
}
116
128
117
129
function loadModuleFromNodeModules ( moduleName : string , directory : string , host : ModuleResolutionHost ) : ResolvedModuleWithFailedLookupLocations {
@@ -121,14 +133,15 @@ namespace ts {
121
133
const baseName = getBaseFileName ( directory ) ;
122
134
if ( baseName !== "node_modules" ) {
123
135
const nodeModulesFolder = combinePaths ( directory , "node_modules" ) ;
136
+ const nodeModulesFolderExists = directoryProbablyExists ( nodeModulesFolder , host ) ;
124
137
const candidate = normalizePath ( combinePaths ( nodeModulesFolder , moduleName ) ) ;
125
138
// Load only typescript files irrespective of allowJs option if loading from node modules
126
- let result = loadNodeModuleFromFile ( supportedTypeScriptExtensions , candidate , failedLookupLocations , host ) ;
139
+ let result = loadNodeModuleFromFile ( supportedTypeScriptExtensions , candidate , failedLookupLocations , ! nodeModulesFolderExists , host ) ;
127
140
if ( result ) {
128
141
return { resolvedModule : { resolvedFileName : result , isExternalLibraryImport : true } , failedLookupLocations } ;
129
142
}
130
143
131
- result = loadNodeModuleFromDirectory ( supportedTypeScriptExtensions , candidate , failedLookupLocations , host ) ;
144
+ result = loadNodeModuleFromDirectory ( supportedTypeScriptExtensions , candidate , failedLookupLocations , ! nodeModulesFolderExists , host ) ;
132
145
if ( result ) {
133
146
return { resolvedModule : { resolvedFileName : result , isExternalLibraryImport : true } , failedLookupLocations } ;
134
147
}
@@ -281,7 +294,8 @@ namespace ts {
281
294
getCanonicalFileName,
282
295
getNewLine : ( ) => newLine ,
283
296
fileExists : fileName => sys . fileExists ( fileName ) ,
284
- readFile : fileName => sys . readFile ( fileName )
297
+ readFile : fileName => sys . readFile ( fileName ) ,
298
+ directoryExists : directoryName => sys . directoryExists ( directoryName )
285
299
} ;
286
300
}
287
301
0 commit comments