@@ -406,7 +406,7 @@ impl RscRenderer {
406406
407407 for dep in & dependencies {
408408 let dep_owned = dep. clone ( ) ;
409- if let Err ( e) = Box :: pin ( self . register_dependency_if_needed ( dep_owned. clone ( ) ) ) . await {
409+ if let Err ( e) = self . register_dependency_if_needed ( dep_owned) . await {
410410 error ! (
411411 "[RSC] Warning: Failed to register dependency '{dep}' for component '{component_id}': {e}"
412412 ) ;
@@ -524,93 +524,97 @@ impl RscRenderer {
524524 }
525525
526526 async fn register_dependency_if_needed ( & mut self , dep : String ) -> Result < ( ) , RariError > {
527- if !dep. starts_with ( "./" ) && !dep. starts_with ( "../" ) {
528- return Ok ( ( ) ) ;
529- }
527+ let mut stack: Vec < String > = vec ! [ dep] ;
528+ let mut visited: FxHashSet < String > = FxHashSet :: default ( ) ;
530529
531530 let base_path = std:: env:: current_dir ( ) . unwrap_or_default ( ) ;
532531 let src_dir = base_path. join ( "src" ) ;
532+ let extensions = [ ".ts" , ".tsx" , ".js" , ".jsx" ] ;
533533
534- let mut resolved_path_candidates = Vec :: new ( ) ;
535-
536- let clean_dep = dep. trim_start_matches ( "./" ) . trim_start_matches ( "../" ) ;
537-
538- if dep. starts_with ( "../" ) {
539- let up_count = dep. matches ( "../" ) . count ( ) ;
540- let remaining_path = dep. replacen ( "../" , "" , up_count) ;
534+ while let Some ( current) = stack. pop ( ) {
535+ if !visited. insert ( current. clone ( ) ) {
536+ continue ;
537+ }
541538
542- if up_count == 1 {
543- resolved_path_candidates. push ( src_dir. join ( & remaining_path) ) ;
544- } else if up_count == 2 {
545- resolved_path_candidates. push ( base_path. join ( & remaining_path) ) ;
539+ if !current. starts_with ( "./" ) && !current. starts_with ( "../" ) {
540+ continue ;
546541 }
547- } else if dep. starts_with ( "./" ) {
548- resolved_path_candidates. push ( src_dir. join ( "components" ) . join ( clean_dep) ) ;
549- resolved_path_candidates. push ( src_dir. join ( clean_dep) ) ;
550- }
551542
552- let extensions = [ ".ts" , ".tsx" , ".js" , ".jsx" ] ;
553- let mut potential_paths = Vec :: new ( ) ;
543+ let clean_dep = current. trim_start_matches ( "./" ) . trim_start_matches ( "../" ) ;
554544
555- for base_path_candidate in & resolved_path_candidates {
556- for ext in & extensions {
557- potential_paths. push ( base_path_candidate. with_extension ( & ext[ 1 ..] ) ) ;
545+ let mut resolved_path_candidates: Vec < std:: path:: PathBuf > = Vec :: new ( ) ;
546+ if current. starts_with ( "../" ) {
547+ let up_count = current. matches ( "../" ) . count ( ) ;
548+ let remaining_path = current. replacen ( "../" , "" , up_count) ;
549+ if up_count == 1 {
550+ resolved_path_candidates. push ( src_dir. join ( & remaining_path) ) ;
551+ } else if up_count == 2 {
552+ resolved_path_candidates. push ( base_path. join ( & remaining_path) ) ;
553+ }
554+ } else if current. starts_with ( "./" ) {
555+ resolved_path_candidates. push ( src_dir. join ( "components" ) . join ( clean_dep) ) ;
556+ resolved_path_candidates. push ( src_dir. join ( clean_dep) ) ;
558557 }
559558
560- for ext in & extensions {
561- potential_paths. push ( base_path_candidate. join ( format ! ( "index{ext}" ) ) ) ;
559+ let mut potential_paths: Vec < std:: path:: PathBuf > = Vec :: new ( ) ;
560+ for base_path_candidate in & resolved_path_candidates {
561+ for ext in & extensions {
562+ potential_paths. push ( base_path_candidate. with_extension ( & ext[ 1 ..] ) ) ;
563+ }
564+ for ext in & extensions {
565+ potential_paths. push ( base_path_candidate. join ( format ! ( "index{ext}" ) ) ) ;
566+ }
562567 }
563- }
564-
565- for potential_path in & potential_paths {
566- if potential_path. exists ( ) {
567- if let Ok ( content) = std:: fs:: read_to_string ( potential_path) {
568- let dep_component_id = potential_path
569- . file_stem ( )
570- . unwrap_or_default ( )
571- . to_string_lossy ( )
572- . to_string ( ) ;
573-
574- let path_components: Vec < & str > = potential_path
575- . strip_prefix ( base_path. join ( "src" ) )
576- . unwrap_or ( potential_path)
577- . components ( )
578- . filter_map ( |c| c. as_os_str ( ) . to_str ( ) )
579- . collect ( ) ;
580-
581- let unique_dep_id = if path_components. len ( ) > 1 {
582- format ! (
583- "{}_{}" ,
584- path_components[ 0 ..path_components. len( ) - 1 ] . join( "_" ) ,
585- dep_component_id
586- )
587- } else {
588- dep_component_id. clone ( )
589- } ;
590-
591- let already_registered = {
592- let registry = self . component_registry . lock ( ) ;
593- registry. is_component_registered ( & unique_dep_id)
594- } ;
595-
596- if !already_registered {
597- if Self :: is_react_component_file ( & content) {
598- let sub_dependencies = extract_dependencies ( & content) ;
599- for sub_dep in sub_dependencies {
600- let _ = Box :: pin ( self . register_dependency_if_needed ( sub_dep) ) . await ;
601- }
602568
603- self . register_component_without_loading ( & unique_dep_id, & content)
604- . await ?;
569+ for potential_path in & potential_paths {
570+ if potential_path. exists ( ) {
571+ if let Ok ( content) = std:: fs:: read_to_string ( potential_path) {
572+ let dep_component_id = potential_path
573+ . file_stem ( )
574+ . unwrap_or_default ( )
575+ . to_string_lossy ( )
576+ . to_string ( ) ;
577+
578+ let path_components: Vec < & str > = potential_path
579+ . strip_prefix ( base_path. join ( "src" ) )
580+ . unwrap_or ( potential_path)
581+ . components ( )
582+ . filter_map ( |c| c. as_os_str ( ) . to_str ( ) )
583+ . collect ( ) ;
584+
585+ let unique_dep_id = if path_components. len ( ) > 1 {
586+ format ! (
587+ "{}_{}" ,
588+ path_components[ 0 ..path_components. len( ) - 1 ] . join( "_" ) ,
589+ dep_component_id
590+ )
605591 } else {
606- debug ! (
607- "Skipping registration of '{}' as it's not a React component" ,
608- unique_dep_id
609- ) ;
592+ dep_component_id. clone ( )
593+ } ;
594+
595+ let already_registered = {
596+ let registry = self . component_registry . lock ( ) ;
597+ registry. is_component_registered ( & unique_dep_id)
598+ } ;
599+
600+ if !already_registered {
601+ if Self :: is_react_component_file ( & content) {
602+ let sub_dependencies = extract_dependencies ( & content) ;
603+ for sub_dep in sub_dependencies {
604+ stack. push ( sub_dep) ;
605+ }
606+ self . register_component_without_loading ( & unique_dep_id, & content)
607+ . await ?;
608+ } else {
609+ debug ! (
610+ "Skipping registration of '{}' as it's not a React component" ,
611+ unique_dep_id
612+ ) ;
613+ }
610614 }
611615 }
616+ break ;
612617 }
613- break ;
614618 }
615619 }
616620
0 commit comments