@@ -227,70 +227,53 @@ impl<Fs: FileSystem> Cache<Fs> {
227227 ///
228228 /// <https://github.com/parcel-bundler/parcel/blob/4d27ec8b8bd1792f536811fef86e74a31fa0e704/crates/parcel-resolver/src/cache.rs#L232>
229229 pub ( crate ) fn canonicalize_impl ( & self , path : & CachedPath ) -> Result < CachedPath , ResolveError > {
230- let mut result: Option < _ > = None ;
231- while result. is_none ( ) {
232- result = {
233- // Check if this thread is already canonicalizing. If so, we have found a circular symlink.
234- // If a different thread is canonicalizing, OnceLock will queue this thread to wait for the result.
235- let tid = THREAD_ID . with ( |t| * t) ;
236- if path. canonicalizing . load ( Ordering :: Acquire ) == tid {
237- return Err ( io:: Error :: new ( io:: ErrorKind :: NotFound , "Circular symlink" ) . into ( ) ) ;
238- }
239-
240- #[ expect( clippy:: collection_is_never_read) ]
241- let mut _temp = None ;
230+ // Check if this thread is already canonicalizing. If so, we have found a circular symlink.
231+ // If a different thread is canonicalizing, OnceLock will queue this thread to wait for the result.
232+ let tid = THREAD_ID . with ( |t| * t) ;
233+ if path. canonicalizing . load ( Ordering :: Acquire ) == tid {
234+ return Err ( io:: Error :: new ( io:: ErrorKind :: NotFound , "Circular symlink" ) . into ( ) ) ;
235+ }
242236
243- path. canonicalized
244- . get_or_init ( || {
245- path. canonicalizing . store ( tid, Ordering :: Release ) ;
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+ }
246242
247- let res = path. parent ( ) . map_or_else (
248- || Ok ( path. normalize_root ( self ) ) ,
249- |parent| {
250- self . canonicalize_impl ( & parent) . and_then ( |parent_canonical| {
251- let normalized = parent_canonical. normalize_with (
252- path. path ( ) . strip_prefix ( parent. path ( ) ) . unwrap ( ) ,
253- self ,
254- ) ;
243+ path. canonicalizing . store ( tid, Ordering :: Release ) ;
255244
256- if self
257- . fs
258- . symlink_metadata ( path. path ( ) )
259- . is_ok_and ( |m| m. is_symlink )
260- {
261- let link = self . fs . read_link ( normalized. path ( ) ) ?;
262- if link. is_absolute ( ) {
263- return self
264- . canonicalize_impl ( & self . value ( & link. normalize ( ) ) ) ;
265- } else if let Some ( dir) = normalized. parent ( ) {
266- // Symlink is relative `../../foo.js`, use the path directory
267- // to resolve this symlink.
268- return self . canonicalize_impl (
269- & dir. normalize_with ( & link, self ) ,
270- ) ;
271- }
272- debug_assert ! (
273- false ,
274- "Failed to get path parent for {}." ,
275- normalized. path( ) . display( )
276- ) ;
277- }
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 ) ;
278251
279- Ok ( normalized)
280- } )
281- } ,
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( )
282265 ) ;
266+ }
283267
284- path. canonicalizing . store ( 0 , Ordering :: Release ) ;
285- _temp = res. as_ref ( ) . ok ( ) . map ( |cp| Arc :: clone ( & cp. 0 ) ) ;
286- res. map ( |cp| Arc :: downgrade ( & cp. 0 ) )
287- } )
288- . as_ref ( )
289- . map_err ( Clone :: clone)
290- . map ( |weak| weak. upgrade ( ) . map ( CachedPath ) )
291- . transpose ( )
292- } ;
293- }
294- result. unwrap ( )
268+ Ok ( normalized)
269+ } )
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
295278 }
296279}
0 commit comments