@@ -63,6 +63,7 @@ mod path;
6363mod resolution;
6464mod specifier;
6565mod tsconfig;
66+ mod tsconfig_context;
6667#[ cfg( feature = "fs_cache" ) ]
6768mod tsconfig_serde;
6869#[ cfg( target_os = "windows" ) ]
@@ -109,7 +110,10 @@ pub use crate::{
109110 resolution:: { ModuleType , Resolution } ,
110111 tsconfig:: { CompilerOptions , CompilerOptionsPathsMap , ProjectReference , TsConfig } ,
111112} ;
112- use crate :: { context:: ResolveContext as Ctx , path:: SLASH_START , specifier:: Specifier } ;
113+ use crate :: {
114+ context:: ResolveContext as Ctx , path:: SLASH_START , specifier:: Specifier ,
115+ tsconfig_context:: TsconfigResolveContext ,
116+ } ;
113117
114118type ResolveResult < Cp > = Result < Option < Cp > , ResolveError > ;
115119
@@ -207,7 +211,12 @@ impl<C: Cache> ResolverGeneric<C> {
207211 /// * See [ResolveError]
208212 pub fn resolve_tsconfig < P : AsRef < Path > > ( & self , path : P ) -> Result < Arc < C :: Tc > , ResolveError > {
209213 let path = path. as_ref ( ) ;
210- self . load_tsconfig ( true , path, & TsconfigReferences :: Auto )
214+ self . load_tsconfig (
215+ true ,
216+ path,
217+ & TsconfigReferences :: Auto ,
218+ & mut TsconfigResolveContext :: default ( ) ,
219+ )
211220 }
212221
213222 /// Resolve `specifier` at absolute `path` with [ResolveContext]
@@ -1224,23 +1233,36 @@ impl<C: Cache> ResolverGeneric<C> {
12241233 root : bool ,
12251234 path : & Path ,
12261235 references : & TsconfigReferences ,
1236+ ctx : & mut TsconfigResolveContext ,
12271237 ) -> Result < Arc < C :: Tc > , ResolveError > {
12281238 self . cache . get_tsconfig ( root, path, |tsconfig| {
12291239 let directory = self . cache . value ( tsconfig. directory ( ) ) ;
12301240 tracing:: trace!( tsconfig = ?tsconfig, "load_tsconfig" ) ;
12311241
1242+ if ctx. is_already_extended ( tsconfig. path ( ) ) {
1243+ return Err ( ResolveError :: TsconfigCircularExtend (
1244+ ctx. get_extended_configs_with ( tsconfig. path ( ) . to_path_buf ( ) ) . into ( ) ,
1245+ ) ) ;
1246+ }
1247+
12321248 // Extend tsconfig
12331249 let extended_tsconfig_paths = tsconfig
12341250 . extends ( )
12351251 . map ( |specifier| self . get_extended_tsconfig_path ( & directory, tsconfig, specifier) )
12361252 . collect :: < Result < Vec < _ > , _ > > ( ) ?;
1237- for extended_tsconfig_path in extended_tsconfig_paths {
1238- let extended_tsconfig = self . load_tsconfig (
1239- /* root */ false ,
1240- & extended_tsconfig_path,
1241- & TsconfigReferences :: Disabled ,
1242- ) ?;
1243- tsconfig. extend_tsconfig ( & extended_tsconfig) ;
1253+ if !extended_tsconfig_paths. is_empty ( ) {
1254+ ctx. with_extended_file ( tsconfig. path ( ) . to_owned ( ) , |ctx| {
1255+ for extended_tsconfig_path in extended_tsconfig_paths {
1256+ let extended_tsconfig = self . load_tsconfig (
1257+ /* root */ false ,
1258+ & extended_tsconfig_path,
1259+ & TsconfigReferences :: Disabled ,
1260+ ctx,
1261+ ) ?;
1262+ tsconfig. extend_tsconfig ( & extended_tsconfig) ;
1263+ }
1264+ Result :: Ok :: < ( ) , ResolveError > ( ( ) )
1265+ } ) ?;
12441266 }
12451267
12461268 if tsconfig. load_references ( references) {
@@ -1280,6 +1302,7 @@ impl<C: Cache> ResolverGeneric<C> {
12801302 /* root */ true ,
12811303 & tsconfig_options. config_file ,
12821304 & tsconfig_options. references ,
1305+ & mut TsconfigResolveContext :: default ( ) ,
12831306 ) ?;
12841307 let paths = tsconfig. resolve ( cached_path. path ( ) , specifier) ;
12851308 for path in paths {
0 commit comments