@@ -661,51 +661,52 @@ namespace ts {
661661 * @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
662662 * 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.
663663 */
664- function loadModuleFromFile ( candidate : string , extensions : string [ ] , failedLookupLocation : string [ ] , onlyRecordFailures : boolean , state : ModuleResolutionState ) : string {
665- // First try to keep/add an extension: importing "./ foo.ts" can be matched by a file "./ foo.ts", and "./ foo" by "./ foo.d .ts"
666- const resolvedByAddingOrKeepingExtension = loadModuleFromFileWorker ( candidate , extensions , failedLookupLocation , onlyRecordFailures , state ) ;
667- if ( resolvedByAddingOrKeepingExtension ) {
668- return resolvedByAddingOrKeepingExtension ;
664+ function loadModuleFromFile ( candidate : string , extensions : string [ ] , failedLookupLocation : string [ ] , onlyRecordFailures : boolean , state : ModuleResolutionState ) : string | undefined {
665+ // First, try adding an extension. An import of " foo" could be matched by a file "foo.ts", or " foo.js " by "foo.js .ts"
666+ const resolvedByAddingExtension = tryAddingExtensions ( candidate , extensions , failedLookupLocation , onlyRecordFailures , state ) ;
667+ if ( resolvedByAddingExtension ) {
668+ return resolvedByAddingExtension ;
669669 }
670- // Then try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one, e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts"
670+
671+ // If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one;
672+ // e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts"
671673 if ( hasJavaScriptFileExtension ( candidate ) ) {
672674 const extensionless = removeFileExtension ( candidate ) ;
673675 if ( state . traceEnabled ) {
674676 const extension = candidate . substring ( extensionless . length ) ;
675677 trace ( state . host , Diagnostics . File_name_0_has_a_1_extension_stripping_it , candidate , extension ) ;
676678 }
677- return loadModuleFromFileWorker ( extensionless , extensions , failedLookupLocation , onlyRecordFailures , state ) ;
679+ return tryAddingExtensions ( extensionless , extensions , failedLookupLocation , onlyRecordFailures , state ) ;
678680 }
679681 }
680682
681- function loadModuleFromFileWorker ( candidate : string , extensions : string [ ] , failedLookupLocation : string [ ] , onlyRecordFailures : boolean , state : ModuleResolutionState ) : string {
683+ /** Try to return an existing file that adds one of the `extensions` to `candidate`. */
684+ function tryAddingExtensions ( candidate : string , extensions : string [ ] , failedLookupLocation : string [ ] , onlyRecordFailures : boolean , state : ModuleResolutionState ) : string | undefined {
682685 if ( ! onlyRecordFailures ) {
683686 // check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing
684687 const directory = getDirectoryPath ( candidate ) ;
685688 if ( directory ) {
686689 onlyRecordFailures = ! directoryProbablyExists ( directory , state . host ) ;
687690 }
688691 }
689- return forEach ( extensions , tryLoad ) ;
692+ return forEach ( extensions , ext =>
693+ ! ( state . skipTsx && isJsxOrTsxExtension ( ext ) ) && tryFile ( candidate + ext , failedLookupLocation , onlyRecordFailures , state ) ) ;
694+ }
690695
691- function tryLoad ( ext : string ) : string {
692- if ( state . skipTsx && isJsxOrTsxExtension ( ext ) ) {
693- return undefined ;
694- }
695- const fileName = fileExtensionIs ( candidate , ext ) ? candidate : candidate + ext ;
696- if ( ! onlyRecordFailures && state . host . fileExists ( fileName ) ) {
697- if ( state . traceEnabled ) {
698- trace ( state . host , Diagnostics . File_0_exist_use_it_as_a_name_resolution_result , fileName ) ;
699- }
700- return fileName ;
696+ /** Return the file if it exists. */
697+ function tryFile ( fileName : string , failedLookupLocation : string [ ] , onlyRecordFailures : boolean , state : ModuleResolutionState ) : string | undefined {
698+ if ( ! onlyRecordFailures && state . host . fileExists ( fileName ) ) {
699+ if ( state . traceEnabled ) {
700+ trace ( state . host , Diagnostics . File_0_exist_use_it_as_a_name_resolution_result , fileName ) ;
701701 }
702- else {
703- if ( state . traceEnabled ) {
704- trace ( state . host , Diagnostics . File_0_does_not_exist , fileName ) ;
705- }
706- failedLookupLocation . push ( fileName ) ;
707- return undefined ;
702+ return fileName ;
703+ }
704+ else {
705+ if ( state . traceEnabled ) {
706+ trace ( state . host , Diagnostics . File_0_does_not_exist , fileName ) ;
708707 }
708+ failedLookupLocation . push ( fileName ) ;
709+ return undefined ;
709710 }
710711 }
711712
@@ -718,7 +719,9 @@ namespace ts {
718719 }
719720 const typesFile = tryReadTypesSection ( packageJsonPath , candidate , state ) ;
720721 if ( typesFile ) {
721- const result = loadModuleFromFile ( typesFile , extensions , failedLookupLocation , ! directoryProbablyExists ( getDirectoryPath ( typesFile ) , state . host ) , state ) ;
722+ const onlyRecordFailures = ! directoryProbablyExists ( getDirectoryPath ( typesFile ) , state . host ) ;
723+ // The package.json "typings" property must specify the file with extension, so just try that exact filename.
724+ const result = tryFile ( typesFile , failedLookupLocation , onlyRecordFailures , state ) ;
722725 if ( result ) {
723726 return result ;
724727 }
0 commit comments