@@ -95,7 +95,7 @@ namespace ts {
95
95
currentDirectory = host . getCurrentDirectory ( ) ;
96
96
}
97
97
98
- return currentDirectory && getDefaultTypeRoots ( currentDirectory , host ) ;
98
+ return currentDirectory !== undefined && getDefaultTypeRoots ( currentDirectory , host ) ;
99
99
}
100
100
101
101
/**
@@ -675,23 +675,33 @@ namespace ts {
675
675
676
676
/* @internal */
677
677
export function loadModuleFromNodeModules ( moduleName : string , directory : string , failedLookupLocations : string [ ] , state : ModuleResolutionState , checkOneLevel : boolean ) : string {
678
+ return loadModuleFromNodeModulesWorker ( moduleName , directory , failedLookupLocations , state , checkOneLevel , /*typesOnly*/ false ) ;
679
+ }
680
+
681
+ function loadModuleFromNodeModulesAtTypes ( moduleName : string , directory : string , failedLookupLocations : string [ ] , state : ModuleResolutionState ) : string {
682
+ return loadModuleFromNodeModulesWorker ( moduleName , directory , failedLookupLocations , state , /*checkOneLevel*/ false , /*typesOnly*/ true ) ;
683
+ }
684
+
685
+ function loadModuleFromNodeModulesWorker ( moduleName : string , directory : string , failedLookupLocations : string [ ] , state : ModuleResolutionState , checkOneLevel : boolean , typesOnly : boolean ) : string {
678
686
directory = normalizeSlashes ( directory ) ;
679
687
while ( true ) {
680
688
const baseName = getBaseFileName ( directory ) ;
681
689
if ( baseName !== "node_modules" ) {
682
- // Try to load source from the package
683
- const packageResult = loadModuleFromNodeModulesFolder ( moduleName , directory , failedLookupLocations , state ) ;
684
- if ( packageResult && hasTypeScriptFileExtension ( packageResult ) ) {
685
- // Always prefer a TypeScript (.ts, .tsx, .d.ts) file shipped with the package
686
- return packageResult ;
687
- }
688
- else {
689
- // Else prefer a types package over non-TypeScript results (e.g. JavaScript files)
690
- const typesResult = loadModuleFromNodeModulesFolder ( combinePaths ( "@types" , moduleName ) , directory , failedLookupLocations , state ) ;
691
- if ( typesResult || packageResult ) {
692
- return typesResult || packageResult ;
690
+ let packageResult : string | undefined ;
691
+ if ( ! typesOnly ) {
692
+ // Try to load source from the package
693
+ packageResult = loadModuleFromNodeModulesFolder ( moduleName , directory , failedLookupLocations , state ) ;
694
+ if ( packageResult && hasTypeScriptFileExtension ( packageResult ) ) {
695
+ // Always prefer a TypeScript (.ts, .tsx, .d.ts) file shipped with the package
696
+ return packageResult ;
693
697
}
694
698
}
699
+
700
+ // Else prefer a types package over non-TypeScript results (e.g. JavaScript files)
701
+ const typesResult = loadModuleFromNodeModulesFolder ( combinePaths ( "@types" , moduleName ) , directory , failedLookupLocations , state ) ;
702
+ if ( typesResult || packageResult ) {
703
+ return typesResult || packageResult ;
704
+ }
695
705
}
696
706
697
707
const parentPath = getDirectoryPath ( directory ) ;
@@ -709,7 +719,7 @@ namespace ts {
709
719
const state = { compilerOptions, host, traceEnabled, skipTsx : ! compilerOptions . jsx } ;
710
720
const failedLookupLocations : string [ ] = [ ] ;
711
721
const supportedExtensions = getSupportedExtensions ( compilerOptions ) ;
712
- let containingDirectory = getDirectoryPath ( containingFile ) ;
722
+ const containingDirectory = getDirectoryPath ( containingFile ) ;
713
723
714
724
const resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings ( moduleName , containingDirectory , loadModuleFromFile , failedLookupLocations , supportedExtensions , state ) ;
715
725
if ( resolvedFileName ) {
@@ -718,18 +728,9 @@ namespace ts {
718
728
719
729
let referencedSourceFile : string ;
720
730
if ( moduleHasNonRelativeName ( moduleName ) ) {
721
- while ( true ) {
722
- const searchName = normalizePath ( combinePaths ( containingDirectory , moduleName ) ) ;
723
- referencedSourceFile = loadModuleFromFile ( searchName , supportedExtensions , failedLookupLocations , /*onlyRecordFailures*/ false , state ) ;
724
- if ( referencedSourceFile ) {
725
- break ;
726
- }
727
- const parentPath = getDirectoryPath ( containingDirectory ) ;
728
- if ( parentPath === containingDirectory ) {
729
- break ;
730
- }
731
- containingDirectory = parentPath ;
732
- }
731
+ referencedSourceFile = referencedSourceFile = loadModuleFromAncestorDirectories ( moduleName , containingDirectory , supportedExtensions , failedLookupLocations , state ) ||
732
+ // If we didn't find the file normally, look it up in @types.
733
+ loadModuleFromNodeModulesAtTypes ( moduleName , containingDirectory , failedLookupLocations , state ) ;
733
734
}
734
735
else {
735
736
const candidate = normalizePath ( combinePaths ( containingDirectory , moduleName ) ) ;
@@ -741,4 +742,20 @@ namespace ts {
741
742
? { resolvedModule : { resolvedFileName : referencedSourceFile } , failedLookupLocations }
742
743
: { resolvedModule : undefined , failedLookupLocations } ;
743
744
}
745
+
746
+ /** Climb up parent directories looking for a module. */
747
+ function loadModuleFromAncestorDirectories ( moduleName : string , containingDirectory : string , supportedExtensions : string [ ] , failedLookupLocations : string [ ] , state : ModuleResolutionState ) : string | undefined {
748
+ while ( true ) {
749
+ const searchName = normalizePath ( combinePaths ( containingDirectory , moduleName ) ) ;
750
+ const referencedSourceFile = loadModuleFromFile ( searchName , supportedExtensions , failedLookupLocations , /*onlyRecordFailures*/ false , state ) ;
751
+ if ( referencedSourceFile ) {
752
+ return referencedSourceFile ;
753
+ }
754
+ const parentPath = getDirectoryPath ( containingDirectory ) ;
755
+ if ( parentPath === containingDirectory ) {
756
+ return undefined ;
757
+ }
758
+ containingDirectory = parentPath ;
759
+ }
760
+ }
744
761
}
0 commit comments