@@ -68,6 +68,37 @@ fn rsc_module_type_priority(module_type: &str) -> u8 {
6868 }
6969}
7070
71+ fn resolve_manifest_shared_option < ' a > (
72+ shared_options : & ' a [ ManifestSharedOption ] ,
73+ concrete_share_key : & str ,
74+ ) -> ( String , Option < & ' a ManifestSharedOption > ) {
75+ if let Some ( shared) = shared_options
76+ . iter ( )
77+ . find ( |shared| shared. share_key == concrete_share_key)
78+ {
79+ return ( shared. name . clone ( ) , Some ( shared) ) ;
80+ }
81+
82+ let prefix_match = shared_options
83+ . iter ( )
84+ . filter ( |shared| {
85+ shared. share_key . ends_with ( '/' ) && concrete_share_key. starts_with ( & shared. share_key )
86+ } )
87+ . max_by_key ( |shared| shared. share_key . len ( ) ) ;
88+
89+ if let Some ( shared) = prefix_match {
90+ let remainder = & concrete_share_key[ shared. share_key . len ( ) ..] ;
91+ let manifest_name = if shared. name . ends_with ( '/' ) {
92+ format ! ( "{}{}" , shared. name, remainder)
93+ } else {
94+ shared. name . clone ( )
95+ } ;
96+ return ( manifest_name, Some ( shared) ) ;
97+ }
98+
99+ ( concrete_share_key. to_string ( ) , None )
100+ }
101+
71102fn collect_rsc_candidates_for_module (
72103 compilation : & Compilation ,
73104 module_identifier : & ModuleIdentifier ,
@@ -318,6 +349,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
318349 . map ( |shared| StatsShared {
319350 id : compose_id_with_separator ( & container_name, & shared. name ) ,
320351 name : shared. name . clone ( ) ,
352+ share_key : shared. share_key . clone ( ) ,
321353 version : shared. version . clone ( ) . unwrap_or_default ( ) ,
322354 requiredVersion : shared. required_version . clone ( ) ,
323355 // default singleton to true when not provided by user
@@ -461,12 +493,15 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
461493
462494 if matches ! ( module_type, ModuleType :: ProvideShared ) {
463495 if let Some ( ( pkg, ver) ) = parse_provide_shared_identifier ( & identifier) {
464- let entry = ensure_shared_entry ( & mut shared_map, & container_name, & pkg) ;
496+ let ( manifest_name, matched_shared) =
497+ resolve_manifest_shared_option ( & self . options . shared , & pkg) ;
498+ let entry = ensure_shared_entry ( & mut shared_map, & container_name, & manifest_name, & pkg) ;
465499 if entry. version . is_empty ( ) {
466500 entry. version = ver;
467501 }
502+ entry. share_key = pkg. clone ( ) ;
468503 // overlay user-configured shared options (singleton/requiredVersion/version)
469- if let Some ( opt) = self . options . shared . iter ( ) . find ( |s| s . name == pkg ) {
504+ if let Some ( opt) = matched_shared {
470505 if let Some ( singleton) = opt. singleton {
471506 entry. singleton = Some ( singleton) ;
472507 }
@@ -477,7 +512,9 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
477512 entry. version = cfg_ver;
478513 }
479514 }
480- let targets = shared_module_targets. entry ( pkg. clone ( ) ) . or_default ( ) ;
515+ let targets = shared_module_targets
516+ . entry ( manifest_name. clone ( ) )
517+ . or_default ( ) ;
481518 for connection in module_graph. get_outgoing_connections ( & module_identifier) {
482519 let referenced = * connection. module_identifier ( ) ;
483520 if should_collect_module ( & referenced) {
@@ -507,10 +544,12 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
507544 else {
508545 continue ;
509546 } ;
510- let pkg = consume_shared_module. share_key ( ) . to_string ( ) ;
511- if pkg . is_empty ( ) {
547+ let share_key = consume_shared_module. share_key ( ) . to_string ( ) ;
548+ if share_key . is_empty ( ) {
512549 continue ;
513550 }
551+ let ( pkg, matched_shared) =
552+ resolve_manifest_shared_option ( & self . options . shared , & share_key) ;
514553 let required = consume_shared_module
515554 . required_version ( )
516555 . map ( ToString :: to_string) ;
@@ -529,12 +568,13 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
529568 . entry ( pkg. clone ( ) )
530569 . or_default ( )
531570 . extend ( target_ids. into_iter ( ) ) ;
532- let entry = ensure_shared_entry ( & mut shared_map, & container_name, & pkg) ;
571+ let entry = ensure_shared_entry ( & mut shared_map, & container_name, & pkg, & share_key) ;
572+ entry. share_key = share_key. clone ( ) ;
533573 if entry. requiredVersion . is_none ( ) && required. is_some ( ) {
534574 entry. requiredVersion = required;
535575 }
536576 // overlay user-configured shared options
537- if let Some ( opt) = self . options . shared . iter ( ) . find ( |s| s . name == pkg ) {
577+ if let Some ( opt) = matched_shared {
538578 if let Some ( singleton) = opt. singleton {
539579 entry. singleton = Some ( singleton) ;
540580 }
@@ -630,8 +670,13 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
630670 let Some ( module_ids) = shared_module_targets. get ( pkg) else {
631671 continue ;
632672 } ;
673+ let lookup = if shared_entry. share_key . is_empty ( ) {
674+ pkg. clone ( )
675+ } else {
676+ shared_entry. share_key . clone ( )
677+ } ;
633678 shared_entry. rsc =
634- build_rsc_reference_meta_from_modules ( compilation, pkg . clone ( ) , module_ids. iter ( ) . copied ( ) ) ;
679+ build_rsc_reference_meta_from_modules ( compilation, lookup , module_ids. iter ( ) . copied ( ) ) ;
635680 }
636681
637682 for ( expose_file_key, expose) in exposes_map. iter_mut ( ) {
@@ -842,6 +887,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
842887 . map ( |s| ManifestShared {
843888 id : s. id ,
844889 name : s. name ,
890+ share_key : s. share_key ,
845891 version : s. version ,
846892 requiredVersion : s. requiredVersion ,
847893 singleton : s. singleton ,
0 commit comments