@@ -53,13 +53,13 @@ namespace ts {
5353 if ( getRootLength ( moduleName ) !== 0 || nameStartsWithDotSlashOrDotDotSlash ( moduleName ) ) {
5454 const failedLookupLocations : string [ ] = [ ] ;
5555 const candidate = normalizePath ( combinePaths ( containingDirectory , moduleName ) ) ;
56- let resolvedFileName = loadNodeModuleFromFile ( supportedExtensions , candidate , failedLookupLocations , host ) ;
56+ let resolvedFileName = loadNodeModuleFromFile ( supportedExtensions , candidate , failedLookupLocations , /*onlyRecordFailures*/ false , host ) ;
5757
5858 if ( resolvedFileName ) {
5959 return { resolvedModule : { resolvedFileName } , failedLookupLocations } ;
6060 }
6161
62- resolvedFileName = loadNodeModuleFromDirectory ( supportedExtensions , candidate , failedLookupLocations , host ) ;
62+ resolvedFileName = loadNodeModuleFromDirectory ( supportedExtensions , candidate , failedLookupLocations , /*onlyRecordFailures*/ false , host ) ;
6363 return resolvedFileName
6464 ? { resolvedModule : { resolvedFileName } , failedLookupLocations }
6565 : { resolvedModule : undefined , failedLookupLocations } ;
@@ -69,12 +69,22 @@ namespace ts {
6969 }
7070 }
7171
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 {
7383 return forEach ( extensions , tryLoad ) ;
7484
7585 function tryLoad ( ext : string ) : string {
7686 const fileName = fileExtensionIs ( candidate , ext ) ? candidate : candidate + ext ;
77- if ( host . fileExists ( fileName ) ) {
87+ if ( ! onlyRecordFailures && host . fileExists ( fileName ) ) {
7888 return fileName ;
7989 }
8090 else {
@@ -84,9 +94,10 @@ namespace ts {
8494 }
8595 }
8696
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 {
8898 const packageJsonPath = combinePaths ( candidate , "package.json" ) ;
89- if ( host . fileExists ( packageJsonPath ) ) {
99+ const directoryExists = ! onlyRecordFailures && directoryProbablyExists ( candidate , host ) ;
100+ if ( directoryExists && host . fileExists ( packageJsonPath ) ) {
90101
91102 let jsonContent : { typings ?: string } ;
92103
@@ -100,7 +111,8 @@ namespace ts {
100111 }
101112
102113 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 ) ;
104116 if ( result ) {
105117 return result ;
106118 }
@@ -111,7 +123,7 @@ namespace ts {
111123 failedLookupLocation . push ( packageJsonPath ) ;
112124 }
113125
114- return loadNodeModuleFromFile ( extensions , combinePaths ( candidate , "index" ) , failedLookupLocation , host ) ;
126+ return loadNodeModuleFromFile ( extensions , combinePaths ( candidate , "index" ) , failedLookupLocation , ! directoryExists , host ) ;
115127 }
116128
117129 function loadModuleFromNodeModules ( moduleName : string , directory : string , host : ModuleResolutionHost ) : ResolvedModuleWithFailedLookupLocations {
@@ -121,14 +133,15 @@ namespace ts {
121133 const baseName = getBaseFileName ( directory ) ;
122134 if ( baseName !== "node_modules" ) {
123135 const nodeModulesFolder = combinePaths ( directory , "node_modules" ) ;
136+ const nodeModulesFolderExists = directoryProbablyExists ( nodeModulesFolder , host ) ;
124137 const candidate = normalizePath ( combinePaths ( nodeModulesFolder , moduleName ) ) ;
125138 // 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 ) ;
127140 if ( result ) {
128141 return { resolvedModule : { resolvedFileName : result , isExternalLibraryImport : true } , failedLookupLocations } ;
129142 }
130143
131- result = loadNodeModuleFromDirectory ( supportedTypeScriptExtensions , candidate , failedLookupLocations , host ) ;
144+ result = loadNodeModuleFromDirectory ( supportedTypeScriptExtensions , candidate , failedLookupLocations , ! nodeModulesFolderExists , host ) ;
132145 if ( result ) {
133146 return { resolvedModule : { resolvedFileName : result , isExternalLibraryImport : true } , failedLookupLocations } ;
134147 }
@@ -281,7 +294,8 @@ namespace ts {
281294 getCanonicalFileName,
282295 getNewLine : ( ) => newLine ,
283296 fileExists : fileName => sys . fileExists ( fileName ) ,
284- readFile : fileName => sys . readFile ( fileName )
297+ readFile : fileName => sys . readFile ( fileName ) ,
298+ directoryExists : directoryName => sys . directoryExists ( directoryName )
285299 } ;
286300 }
287301
0 commit comments