@@ -42,10 +42,12 @@ use crate::{
4242 raw_module:: RawModule ,
4343 reference_type:: ReferenceType ,
4444 resolve:: {
45+ alias_map:: AliasKey ,
4546 node:: { node_cjs_resolve_options, node_esm_resolve_options} ,
4647 parse:: stringify_data_uri,
4748 pattern:: { PatternMatch , read_matches} ,
4849 plugin:: AfterResolvePlugin ,
50+ remap:: ReplacedSubpathValueResult ,
4951 } ,
5052 source:: { OptionSource , Source , Sources } ,
5153} ;
@@ -790,7 +792,7 @@ impl ResolveResult {
790792 }
791793 }
792794
793- pub fn add_conditions < ' a > ( & mut self , conditions : impl IntoIterator < Item = ( & ' a str , bool ) > ) {
795+ pub fn add_conditions ( & mut self , conditions : impl IntoIterator < Item = ( RcStr , bool ) > ) {
794796 let mut primary = std:: mem:: take ( & mut self . primary ) ;
795797 for ( k, v) in conditions {
796798 for ( key, _) in primary. iter_mut ( ) {
@@ -2694,6 +2696,8 @@ async fn resolve_into_package(
26942696 let is_root_match = path. is_match ( "" ) || path. is_match ( "/" ) ;
26952697 let could_match_others = path. could_match_others ( "" ) ;
26962698
2699+ let mut export_path_request = path. clone ( ) ;
2700+ export_path_request. push_front ( rcstr ! ( "." ) . into ( ) ) ;
26972701 for resolve_into_package in options_value. into_package . iter ( ) {
26982702 match resolve_into_package {
26992703 // handled by the `resolve_into_folder` call below
@@ -2709,23 +2713,13 @@ async fn resolve_into_package(
27092713 continue ;
27102714 } ;
27112715
2712- let Some ( path) = path. as_constant_string ( ) else {
2713- bail ! ( "pattern into an exports field is not implemented yet" ) ;
2714- } ;
2715-
2716- let path = if path == "/" {
2717- rcstr ! ( "." )
2718- } else {
2719- format ! ( ".{path}" ) . into ( )
2720- } ;
2721-
27222716 results. push (
27232717 handle_exports_imports_field (
27242718 package_path. clone ( ) ,
27252719 package_json_path,
27262720 * options,
27272721 exports_field,
2728- & path ,
2722+ export_path_request . clone ( ) ,
27292723 conditions,
27302724 unspecified_conditions,
27312725 query,
@@ -2931,55 +2925,94 @@ async fn handle_exports_imports_field(
29312925 package_json_path : FileSystemPath ,
29322926 options : Vc < ResolveOptions > ,
29332927 exports_imports_field : & AliasMap < SubpathValue > ,
2934- path : & str ,
2928+ mut path : Pattern ,
29352929 conditions : & BTreeMap < RcStr , ConditionValue > ,
29362930 unspecified_conditions : & ConditionValue ,
29372931 query : RcStr ,
29382932) -> Result < Vc < ResolveResult > > {
29392933 let mut results = Vec :: new ( ) ;
29402934 let mut conditions_state = FxHashMap :: default ( ) ;
29412935
2942- let req = Pattern :: Constant ( format ! ( "{path}{query}" ) . into ( ) ) ;
2943-
2944- let values = exports_imports_field
2945- . lookup ( & req)
2946- . map ( AliasMatch :: try_into_self)
2947- . collect :: < Result < Vec < _ > > > ( ) ?;
2936+ if !query. is_empty ( ) {
2937+ path. push ( query. into ( ) ) ;
2938+ }
2939+ let req = path;
29482940
2949- for value in values. iter ( ) {
2950- if value. add_results (
2941+ let values = exports_imports_field. lookup ( & req) ;
2942+ for value in values {
2943+ let value = value?;
2944+ if value. output . add_results (
2945+ value. prefix ,
2946+ value. key ,
29512947 conditions,
29522948 unspecified_conditions,
29532949 & mut conditions_state,
29542950 & mut results,
29552951 ) {
2952+ // Match found, stop (leveraging the lazy `lookup` iterator).
29562953 break ;
29572954 }
29582955 }
29592956
29602957 let mut resolved_results = Vec :: new ( ) ;
2961- for ( result_path, conditions) in results {
2958+ for ReplacedSubpathValueResult {
2959+ result_path,
2960+ conditions,
2961+ map_prefix,
2962+ map_key,
2963+ } in results
2964+ {
29622965 if let Some ( result_path) = result_path. with_normalized_path ( ) {
29632966 let request = Request :: parse ( Pattern :: Concatenation ( vec ! [
29642967 Pattern :: Constant ( rcstr!( "./" ) ) ,
2965- result_path,
2968+ result_path. clone ( ) ,
29662969 ] ) )
2967- . to_resolved ( )
2970+ . resolve ( )
29682971 . await ?;
29692972
29702973 let resolve_result = Box :: pin ( resolve_internal_inline (
29712974 package_path. clone ( ) ,
2972- * request,
2975+ request,
29732976 options,
29742977 ) )
29752978 . await ?;
2976- if conditions. is_empty ( ) {
2977- resolved_results. push ( resolve_result. with_request ( path. into ( ) ) ) ;
2979+
2980+ let resolve_result = if let Some ( req) = req. as_constant_string ( ) {
2981+ resolve_result. with_request ( req. clone ( ) )
29782982 } else {
2979- let mut resolve_result = resolve_result. await ?. with_request_ref ( path. into ( ) ) ;
2983+ match map_key {
2984+ AliasKey :: Exact => resolve_result. with_request ( map_prefix. clone ( ) . into ( ) ) ,
2985+ AliasKey :: Wildcard { .. } => {
2986+ // - `req` is the user's request (key of the export map)
2987+ // - `result_path` is the final request (value of the export map), so
2988+ // effectively `'{foo}*{bar}'`
2989+
2990+ // Because of the assertion in AliasMapLookupIterator, `req` is of the
2991+ // form:
2992+ // - "prefix...<dynamic>" or
2993+ // - "prefix...<dynamic>...suffix"
2994+
2995+ let mut old_request_key = result_path;
2996+ // Remove the Pattern::Constant(rcstr!("./")), from above again
2997+ old_request_key. push_front ( rcstr ! ( "./" ) . into ( ) ) ;
2998+ let new_request_key = req. clone ( ) ;
2999+
3000+ resolve_result. with_replaced_request_key_pattern (
3001+ Pattern :: new ( old_request_key) ,
3002+ Pattern :: new ( new_request_key) ,
3003+ )
3004+ }
3005+ }
3006+ } ;
3007+
3008+ let resolve_result = if !conditions. is_empty ( ) {
3009+ let mut resolve_result = resolve_result. owned ( ) . await ?;
29803010 resolve_result. add_conditions ( conditions) ;
2981- resolved_results. push ( resolve_result. cell ( ) ) ;
2982- }
3011+ resolve_result. cell ( )
3012+ } else {
3013+ resolve_result
3014+ } ;
3015+ resolved_results. push ( resolve_result) ;
29833016 }
29843017 }
29853018
@@ -3034,7 +3067,7 @@ async fn resolve_package_internal_with_imports_field(
30343067 package_json_path. clone ( ) ,
30353068 resolve_options,
30363069 imports,
3037- specifier,
3070+ Pattern :: Constant ( specifier. clone ( ) ) ,
30383071 conditions,
30393072 unspecified_conditions,
30403073 RcStr :: default ( ) ,
0 commit comments