@@ -234,60 +234,46 @@ impl<Fs: FileSystem> Cache<Fs> {
234234 return Err ( io:: Error :: new ( io:: ErrorKind :: NotFound , "Circular symlink" ) . into ( ) ) ;
235235 }
236236
237- path. canonicalized
238- . get_or_init ( || {
239- path. canonicalizing . store ( tid, Ordering :: Release ) ;
240-
241- let res = path. parent ( ) . map_or_else (
242- || Ok ( path. normalize_root ( self ) ) ,
243- |parent| {
244- self . canonicalize_impl ( & parent) . and_then ( |parent_canonical| {
245- let normalized = parent_canonical. normalize_with (
246- path. path ( ) . strip_prefix ( parent. path ( ) ) . unwrap ( ) ,
247- self ,
248- ) ;
237+ let mut canonicalized_guard = path. canonicalized . lock ( ) . unwrap ( ) ;
238+ let canonicalized = canonicalized_guard. clone ( ) ?;
239+ if let Some ( cached_path) = canonicalized. upgrade ( ) {
240+ return Ok ( CachedPath ( cached_path) ) ;
241+ }
249242
250- if self . fs . symlink_metadata ( path. path ( ) ) . is_ok_and ( |m| m. is_symlink ) {
251- let link = self . fs . read_link ( normalized. path ( ) ) ?;
252- if link. is_absolute ( ) {
253- return self . canonicalize_impl ( & self . value ( & link. normalize ( ) ) ) ;
254- } else if let Some ( dir) = normalized. parent ( ) {
255- // Symlink is relative `../../foo.js`, use the path directory
256- // to resolve this symlink.
257- return self
258- . canonicalize_impl ( & dir. normalize_with ( & link, self ) ) ;
259- }
260- debug_assert ! (
261- false ,
262- "Failed to get path parent for {}." ,
263- normalized. path( ) . display( )
264- ) ;
265- }
243+ path. canonicalizing . store ( tid, Ordering :: Release ) ;
266244
267- Ok ( normalized)
268- } )
269- } ,
270- ) ;
245+ let res = path. parent ( ) . map_or_else (
246+ || Ok ( path. normalize_root ( self ) ) ,
247+ |parent| {
248+ self . canonicalize_impl ( & parent) . and_then ( |parent_canonical| {
249+ let normalized = parent_canonical
250+ . normalize_with ( path. path ( ) . strip_prefix ( parent. path ( ) ) . unwrap ( ) , self ) ;
271251
272- path. canonicalizing . store ( 0 , Ordering :: Release ) ;
273- // Store the canonicalized path in the cache before downgrading to weak reference
274- // This ensures there's always at least one strong reference to prevent dropping
275- if let Ok ( ref cp) = res {
276- // Only insert if not already present to avoid unnecessary operations
277- let paths = self . paths . pin ( ) ;
278- if !paths. contains ( cp) {
279- paths. insert ( cp. clone ( ) ) ;
252+ if self . fs . symlink_metadata ( path. path ( ) ) . is_ok_and ( |m| m. is_symlink ) {
253+ let link = self . fs . read_link ( normalized. path ( ) ) ?;
254+ if link. is_absolute ( ) {
255+ return self . canonicalize_impl ( & self . value ( & link. normalize ( ) ) ) ;
256+ } else if let Some ( dir) = normalized. parent ( ) {
257+ // Symlink is relative `../../foo.js`, use the path directory
258+ // to resolve this symlink.
259+ return self . canonicalize_impl ( & dir. normalize_with ( & link, self ) ) ;
260+ }
261+ debug_assert ! (
262+ false ,
263+ "Failed to get path parent for {}." ,
264+ normalized. path( ) . display( )
265+ ) ;
280266 }
281- }
282- // Convert to Weak reference for storage
283- res. map ( |cp| Arc :: downgrade ( & cp. 0 ) )
284- } )
285- . as_ref ( )
286- . map_err ( Clone :: clone)
287- . and_then ( |weak| {
288- weak. upgrade ( ) . map ( CachedPath ) . ok_or_else ( || {
289- ResolveError :: from ( io:: Error :: other ( "Canonicalized path was dropped" ) )
267+
268+ Ok ( normalized)
290269 } )
291- } )
270+ } ,
271+ ) ;
272+
273+ path. canonicalizing . store ( 0 , Ordering :: Release ) ;
274+ // Convert to Weak reference for storage
275+ * canonicalized_guard = res. as_ref ( ) . map_err ( Clone :: clone) . map ( |cp| Arc :: downgrade ( & cp. 0 ) ) ;
276+
277+ res
292278 }
293279}
0 commit comments