@@ -67,40 +67,31 @@ namespace ts {
67
67
}
68
68
69
69
/** Reads from "main" or "types"/"typings" depending on `extensions`. */
70
- function tryReadPackageJsonMainOrTypes ( extensions : Extensions , packageJsonPath : string , baseDirectory : string , state : ModuleResolutionState ) : string {
70
+ function tryReadPackageJsonFields ( readTypes : boolean , packageJsonPath : string , baseDirectory : string , state : ModuleResolutionState ) : string | undefined {
71
71
const jsonContent = readJson ( packageJsonPath , state . host ) ;
72
+ return readTypes ? tryReadFromField ( "typings" ) || tryReadFromField ( "types" ) : tryReadFromField ( "main" ) ;
72
73
73
- switch ( extensions ) {
74
- case Extensions . DtsOnly :
75
- case Extensions . TypeScript :
76
- return tryReadFromField ( "typings" ) || tryReadFromField ( "types" ) ;
77
-
78
- case Extensions . JavaScript :
79
- if ( typeof jsonContent . main === "string" ) {
80
- if ( state . traceEnabled ) {
81
- trace ( state . host , Diagnostics . No_types_specified_in_package_json_so_returning_main_value_of_0 , jsonContent . main ) ;
82
- }
83
- return normalizePath ( combinePaths ( baseDirectory , jsonContent . main ) ) ;
74
+ function tryReadFromField ( fieldName : "typings" | "types" | "main" ) : string | undefined {
75
+ if ( ! hasProperty ( jsonContent , fieldName ) ) {
76
+ if ( state . traceEnabled ) {
77
+ trace ( state . host , Diagnostics . package_json_does_not_have_a_0_field , fieldName ) ;
84
78
}
85
- return undefined ;
86
- }
79
+ return ;
80
+ }
87
81
88
- function tryReadFromField ( fieldName : string ) {
89
- if ( hasProperty ( jsonContent , fieldName ) ) {
90
- const typesFile = ( < any > jsonContent ) [ fieldName ] ;
91
- if ( typeof typesFile === "string" ) {
92
- const typesFilePath = normalizePath ( combinePaths ( baseDirectory , typesFile ) ) ;
93
- if ( state . traceEnabled ) {
94
- trace ( state . host , Diagnostics . package_json_has_0_field_1_that_references_2 , fieldName , typesFile , typesFilePath ) ;
95
- }
96
- return typesFilePath ;
97
- }
98
- else {
99
- if ( state . traceEnabled ) {
100
- trace ( state . host , Diagnostics . Expected_type_of_0_field_in_package_json_to_be_string_got_1 , fieldName , typeof typesFile ) ;
101
- }
82
+ const fileName = jsonContent [ fieldName ] ;
83
+ if ( typeof fileName !== "string" ) {
84
+ if ( state . traceEnabled ) {
85
+ trace ( state . host , Diagnostics . Expected_type_of_0_field_in_package_json_to_be_string_got_1 , fieldName , typeof fileName ) ;
102
86
}
87
+ return ;
103
88
}
89
+
90
+ const path = normalizePath ( combinePaths ( baseDirectory , fileName ) ) ;
91
+ if ( state . traceEnabled ) {
92
+ trace ( state . host , Diagnostics . package_json_has_0_field_1_that_references_2 , fieldName , fileName , path ) ;
93
+ }
94
+ return path ;
104
95
}
105
96
}
106
97
@@ -698,7 +689,8 @@ namespace ts {
698
689
return { resolvedModule : undefined , failedLookupLocations } ;
699
690
700
691
function tryResolve ( extensions : Extensions ) : SearchResult < { resolved : Resolved , isExternalLibraryImport : boolean } > {
701
- const resolved = tryLoadModuleUsingOptionalResolutionSettings ( extensions , moduleName , containingDirectory , nodeLoadModuleByRelativeName , failedLookupLocations , state ) ;
692
+ const loader : ResolutionKindSpecificLoader = ( extensions , candidate , failedLookupLocations , onlyRecordFailures , state ) => nodeLoadModuleByRelativeName ( extensions , candidate , failedLookupLocations , onlyRecordFailures , state , /*considerPackageJson*/ true ) ;
693
+ const resolved = tryLoadModuleUsingOptionalResolutionSettings ( extensions , moduleName , containingDirectory , loader , failedLookupLocations , state ) ;
702
694
if ( resolved ) {
703
695
return toSearchResult ( { resolved, isExternalLibraryImport : false } ) ;
704
696
}
@@ -713,7 +705,7 @@ namespace ts {
713
705
}
714
706
else {
715
707
const candidate = normalizePath ( combinePaths ( containingDirectory , moduleName ) ) ;
716
- const resolved = nodeLoadModuleByRelativeName ( extensions , candidate , failedLookupLocations , /*onlyRecordFailures*/ false , state ) ;
708
+ const resolved = nodeLoadModuleByRelativeName ( extensions , candidate , failedLookupLocations , /*onlyRecordFailures*/ false , state , /*considerPackageJson*/ true ) ;
717
709
return resolved && toSearchResult ( { resolved, isExternalLibraryImport : false } ) ;
718
710
}
719
711
}
@@ -731,7 +723,7 @@ namespace ts {
731
723
return real ;
732
724
}
733
725
734
- function nodeLoadModuleByRelativeName ( extensions : Extensions , candidate : string , failedLookupLocations : Push < string > , onlyRecordFailures : boolean , state : ModuleResolutionState ) : Resolved | undefined {
726
+ function nodeLoadModuleByRelativeName ( extensions : Extensions , candidate : string , failedLookupLocations : Push < string > , onlyRecordFailures : boolean , state : ModuleResolutionState , considerPackageJson : boolean ) : Resolved | undefined {
735
727
if ( state . traceEnabled ) {
736
728
trace ( state . host , Diagnostics . Loading_module_as_file_Slash_folder_candidate_module_location_0_target_file_type_1 , candidate , Extensions [ extensions ] ) ;
737
729
}
@@ -759,7 +751,7 @@ namespace ts {
759
751
onlyRecordFailures = true ;
760
752
}
761
753
}
762
- return loadNodeModuleFromDirectory ( extensions , candidate , failedLookupLocations , onlyRecordFailures , state ) ;
754
+ return loadNodeModuleFromDirectory ( extensions , candidate , failedLookupLocations , onlyRecordFailures , state , considerPackageJson ) ;
763
755
}
764
756
765
757
/* @internal */
@@ -835,48 +827,55 @@ namespace ts {
835
827
return undefined ;
836
828
}
837
829
838
- function loadNodeModuleFromDirectory ( extensions : Extensions , candidate : string , failedLookupLocations : Push < string > , onlyRecordFailures : boolean , state : ModuleResolutionState ) : Resolved | undefined {
839
- const packageJsonPath = pathToPackageJson ( candidate ) ;
830
+ function loadNodeModuleFromDirectory ( extensions : Extensions , candidate : string , failedLookupLocations : Push < string > , onlyRecordFailures : boolean , state : ModuleResolutionState , considerPackageJson = true ) : Resolved | undefined {
840
831
const directoryExists = ! onlyRecordFailures && directoryProbablyExists ( candidate , state . host ) ;
841
832
842
- if ( directoryExists && state . host . fileExists ( packageJsonPath ) ) {
843
- if ( state . traceEnabled ) {
844
- trace ( state . host , Diagnostics . Found_package_json_at_0 , packageJsonPath ) ;
845
- }
846
- const mainOrTypesFile = tryReadPackageJsonMainOrTypes ( extensions , packageJsonPath , candidate , state ) ;
847
- if ( mainOrTypesFile ) {
848
- const onlyRecordFailures = ! directoryProbablyExists ( getDirectoryPath ( mainOrTypesFile ) , state . host ) ;
849
- // A package.json "typings" may specify an exact filename, or may choose to omit an extension.
850
- const fromExactFile = tryFile ( mainOrTypesFile , failedLookupLocations , onlyRecordFailures , state ) ;
851
- if ( fromExactFile ) {
852
- const resolved = fromExactFile && resolvedIfExtensionMatches ( extensions , fromExactFile ) ;
853
- if ( resolved ) {
854
- return resolved ;
855
- }
856
- if ( state . traceEnabled ) {
857
- trace ( state . host , Diagnostics . File_0_has_an_unsupported_extension_so_skipping_it , fromExactFile ) ;
858
- }
859
- }
860
- const resolved = tryAddingExtensions ( mainOrTypesFile , Extensions . TypeScript , failedLookupLocations , onlyRecordFailures , state ) ;
861
- if ( resolved ) {
862
- return resolved ;
833
+ if ( considerPackageJson ) {
834
+ const packageJsonPath = pathToPackageJson ( candidate ) ;
835
+ if ( directoryExists && state . host . fileExists ( packageJsonPath ) ) {
836
+ const fromPackageJson = loadModuleFromPackageJson ( packageJsonPath , extensions , candidate , failedLookupLocations , state ) ;
837
+ if ( fromPackageJson ) {
838
+ return fromPackageJson ;
863
839
}
864
840
}
865
841
else {
866
- if ( state . traceEnabled ) {
867
- trace ( state . host , Diagnostics . package_json_does_not_have_a_types_or_main_field ) ;
842
+ if ( directoryExists && state . traceEnabled ) {
843
+ trace ( state . host , Diagnostics . File_0_does_not_exist , packageJsonPath ) ;
868
844
}
845
+ // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results
846
+ failedLookupLocations . push ( packageJsonPath ) ;
869
847
}
870
848
}
871
- else {
872
- if ( directoryExists && state . traceEnabled ) {
873
- trace ( state . host , Diagnostics . File_0_does_not_exist , packageJsonPath ) ;
849
+
850
+ return loadModuleFromFile ( extensions , combinePaths ( candidate , "index" ) , failedLookupLocations , ! directoryExists , state ) ;
851
+ }
852
+
853
+ function loadModuleFromPackageJson ( packageJsonPath : string , extensions : Extensions , candidate : string , failedLookupLocations : Push < string > , state : ModuleResolutionState ) : Resolved | undefined {
854
+ if ( state . traceEnabled ) {
855
+ trace ( state . host , Diagnostics . Found_package_json_at_0 , packageJsonPath ) ;
856
+ }
857
+
858
+ const file = tryReadPackageJsonFields ( extensions !== Extensions . JavaScript , packageJsonPath , candidate , state ) ;
859
+ if ( ! file ) {
860
+ return undefined ;
861
+ }
862
+
863
+ const onlyRecordFailures = ! directoryProbablyExists ( getDirectoryPath ( file ) , state . host ) ;
864
+ const fromFile = tryFile ( file , failedLookupLocations , onlyRecordFailures , state ) ;
865
+ if ( fromFile ) {
866
+ const resolved = fromFile && resolvedIfExtensionMatches ( extensions , fromFile ) ;
867
+ if ( resolved ) {
868
+ return resolved ;
869
+ }
870
+ if ( state . traceEnabled ) {
871
+ trace ( state . host , Diagnostics . File_0_has_an_unsupported_extension_so_skipping_it , fromFile ) ;
874
872
}
875
- // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results
876
- failedLookupLocations . push ( packageJsonPath ) ;
877
873
}
878
874
879
- return loadModuleFromFile ( extensions , combinePaths ( candidate , "index" ) , failedLookupLocations , ! directoryExists , state ) ;
875
+ // Even if extensions is DtsOnly, we can still look up a .ts file as a result of package.json "types"
876
+ const nextExtensions = extensions === Extensions . DtsOnly ? Extensions . TypeScript : extensions ;
877
+ // Don't do package.json lookup recursively, because Node.js' package lookup doesn't.
878
+ return nodeLoadModuleByRelativeName ( nextExtensions , file , failedLookupLocations , onlyRecordFailures , state , /*considerPackageJson*/ false ) ;
880
879
}
881
880
882
881
/** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */
@@ -1040,7 +1039,6 @@ namespace ts {
1040
1039
return value !== undefined ? { value } : undefined ;
1041
1040
}
1042
1041
1043
-
1044
1042
/** Calls `callback` on `directory` and every ancestor directory it has, returning the first defined result. */
1045
1043
function forEachAncestorDirectory < T > ( directory : string , callback : ( directory : string ) => SearchResult < T > ) : SearchResult < T > {
1046
1044
while ( true ) {
0 commit comments