diff --git a/crates/rspack_core/src/context_module.rs b/crates/rspack_core/src/context_module.rs index 68cf9628e759..350a6224564a 100644 --- a/crates/rspack_core/src/context_module.rs +++ b/crates/rspack_core/src/context_module.rs @@ -2,6 +2,7 @@ use std::{borrow::Cow, hash::Hash, sync::Arc}; use cow_utils::CowUtils; use derive_more::Debug; +use futures::future::BoxFuture; use indoc::formatdoc; use itertools::Itertools; use rspack_cacheable::{ @@ -160,8 +161,11 @@ pub enum FakeMapValue { Map(HashMap), } -pub type ResolveContextModuleDependencies = - Arc Result> + Send + Sync>; +pub type ResolveContextModuleDependencies = Arc< + dyn Fn(ContextModuleOptions) -> BoxFuture<'static, Result>> + + Send + + Sync, +>; #[impl_source_map_config] #[cacheable] @@ -958,7 +962,7 @@ impl Module for ContextModule { _: Option<&Compilation>, ) -> Result { let resolve_dependencies = &self.resolve_dependencies; - let context_element_dependencies = resolve_dependencies(self.options.clone())?; + let context_element_dependencies = resolve_dependencies(self.options.clone()).await?; let mut dependencies: Vec = vec![]; let mut blocks = vec![]; diff --git a/crates/rspack_core/src/context_module_factory.rs b/crates/rspack_core/src/context_module_factory.rs index 37dc94d91619..0500e13b1280 100644 --- a/crates/rspack_core/src/context_module_factory.rs +++ b/crates/rspack_core/src/context_module_factory.rs @@ -1,5 +1,6 @@ use std::{borrow::Cow, sync::Arc}; +use async_recursion::async_recursion; use cow_utils::CowUtils; use derive_more::Debug; use rspack_error::{Result, ToStringResultToRspackResultExt, error}; @@ -122,34 +123,36 @@ impl ContextModuleFactory { plugin_driver: SharedPluginDriver, ) -> Self { let resolve_dependencies: ResolveContextModuleDependencies = Arc::new(move |options| { - tracing::trace!("resolving context module path {}", options.resource); + let resolver_factory = resolver_factory.clone(); + Box::pin(async move { + tracing::trace!("resolving context module path {}", options.resource); + let resolver = &resolver_factory.get(ResolveOptionsWithDependencyType { + resolve_options: options + .resolve_options + .clone() + .map(|r| Box::new(Arc::unwrap_or_clone(r))), + resolve_to_context: false, + dependency_category: options.context_options.category, + }); + let mut context_element_dependencies = vec![]; + visit_dirs( + options.resource.as_str(), + &options.resource, + &mut context_element_dependencies, + &options, + &resolver.options(), + resolver.inner_fs(), + ) + .await?; + context_element_dependencies.sort_by_cached_key(|d| d.user_request.clone()); - let resolver = &resolver_factory.get(ResolveOptionsWithDependencyType { - resolve_options: options - .resolve_options - .clone() - .map(|r| Box::new(Arc::unwrap_or_clone(r))), - resolve_to_context: false, - dependency_category: options.context_options.category, - }); - - let mut context_element_dependencies = vec![]; - visit_dirs( - options.resource.as_str(), - &options.resource, - &mut context_element_dependencies, - &options, - &resolver.options(), - resolver.inner_fs(), - )?; - context_element_dependencies.sort_by_cached_key(|d| d.user_request.clone()); - - tracing::trace!( - "resolving dependencies for {:?}", - context_element_dependencies - ); + tracing::trace!( + "resolving dependencies for {:?}", + context_element_dependencies + ); - Ok(context_element_dependencies) + Ok(context_element_dependencies) + }) }); Self { @@ -400,7 +403,8 @@ impl ContextModuleFactory { } } -fn visit_dirs( +#[async_recursion] +async fn visit_dirs( ctx: &str, dir: &Utf8Path, dependencies: &mut Vec, @@ -409,7 +413,8 @@ fn visit_dirs( fs: Arc, ) -> Result<()> { if !fs - .metadata_sync(dir) + .metadata(dir) + .await .map(|m| m.is_directory) .unwrap_or(false) { @@ -417,7 +422,7 @@ fn visit_dirs( } let include = &options.context_options.include; let exclude = &options.context_options.exclude; - for filename in fs.read_dir_sync(dir)? { + for filename in fs.read_dir(dir).await? { let path = dir.join(&filename); let path_str = path.as_str(); @@ -429,7 +434,8 @@ fn visit_dirs( } if fs - .metadata_sync(&path) + .metadata(&path) + .await .map(|m| m.is_directory) .unwrap_or(false) { @@ -441,7 +447,8 @@ fn visit_dirs( options, resolve_options, fs.clone(), - )?; + ) + .await?; } } else if filename.starts_with('.') { // ignore hidden files diff --git a/crates/rspack_plugin_module_replacement/src/context_replacement.rs b/crates/rspack_plugin_module_replacement/src/context_replacement.rs index 754903f6f6a0..f4816416c76b 100644 --- a/crates/rspack_plugin_module_replacement/src/context_replacement.rs +++ b/crates/rspack_plugin_module_replacement/src/context_replacement.rs @@ -2,8 +2,8 @@ use std::sync::Arc; use rspack_core::{ AfterResolveResult, BeforeResolveResult, ContextElementDependency, - ContextModuleFactoryAfterResolve, ContextModuleFactoryBeforeResolve, DependencyId, - DependencyType, Plugin, + ContextModuleFactoryAfterResolve, ContextModuleFactoryBeforeResolve, ContextModuleOptions, + DependencyId, DependencyType, Plugin, }; use rspack_error::Result; use rspack_hook::{plugin, plugin_hook}; @@ -88,40 +88,43 @@ async fn cmf_after_resolve(&self, mut result: AfterResolveResult) -> Result>(); - Ok(deps) + let resource_identifier = ContextElementDependency::create_resource_identifier( + options.resource.as_str(), + &request, + options.context_options.attributes.as_ref(), + ); + ContextElementDependency { + id: DependencyId::new(), + request, + user_request: key.to_string(), + category: options.context_options.category, + context: options.resource.clone().into(), + layer: options.layer.clone(), + options: options.context_options.clone(), + resource_identifier, + attributes: options.context_options.attributes.clone(), + referenced_exports: options.context_options.referenced_exports.clone(), + dependency_type: DependencyType::ContextElement(options.type_prefix), + factorize_info: Default::default(), + } + }) + .collect::>(); + Ok(deps) + }) }); } // if let Some(new_content_callback) = &self.new_content_callback {