use std::sync::{Arc, Weak};
use arcstr::ArcStr;
use dashmap::DashMap;
use oxc_index::IndexVec;
use rolldown_common::{
ModuleIdx, PluginIdx, SharedFileEmitter, SharedModuleInfoDashMap, SharedNormalizedBundlerOptions,
};
use rolldown_resolver::Resolver;
use rolldown_utils::dashmap::FxDashSet;
use crate::{
__inner::SharedPluginable,
PluginContext,
plugin_context::{NativePluginContextImpl, PluginContextMeta},
plugin_driver::{ContextLoadCompletionManager, hook_orders::PluginHookOrders},
type_aliases::{IndexPluginContext, IndexPluginable},
types::build_timings::BuildTimings,
};
pub struct PluginDriverFactory {
plugins: Vec<SharedPluginable>,
resolver: Arc<Resolver>,
}
impl PluginDriverFactory {
pub fn new(plugins: Vec<SharedPluginable>, resolver: &Arc<Resolver>) -> Self {
Self { plugins, resolver: Arc::clone(resolver) }
}
pub fn create_plugin_driver(
&self,
file_emitter: &SharedFileEmitter,
options: &SharedNormalizedBundlerOptions,
session: &rolldown_devtools::Session,
initial_bundle_span: &tracing::Span,
module_infos: SharedModuleInfoDashMap,
transform_dependencies: Arc<DashMap<ModuleIdx, Arc<FxDashSet<ArcStr>>>>,
) -> Arc<crate::plugin_driver::PluginDriver> {
let watch_files = Arc::new(FxDashSet::default());
let meta = Arc::new(PluginContextMeta::default());
let tx = Arc::new(std::sync::Mutex::new(None));
let mut plugin_usage_vec = IndexVec::new();
let bundle_span = initial_bundle_span.clone();
let manual_resolve_span = tracing::debug_span!(
parent: &bundle_span,
"plugin_context_resolve",
CONTEXT_hook_resolve_id_trigger = "manual"
);
let should_skip_user_plugins_for_lazy_proxy_modules =
options.experimental.dev_mode.as_ref().and_then(|dev_mode| dev_mode.lazy) == Some(true);
Arc::new_cyclic(|plugin_driver| {
let mut index_plugins = IndexPluginable::with_capacity(self.plugins.len());
let mut index_contexts = IndexPluginContext::with_capacity(self.plugins.len());
let mut lazy_compilation_plugin_idx: Option<PluginIdx> = None;
self.plugins.iter().for_each(|plugin| {
let plugin_idx = index_plugins.push(Arc::clone(plugin));
plugin_usage_vec.push(plugin.call_hook_usage());
let plugin_name = plugin.call_name();
if lazy_compilation_plugin_idx.is_none() && plugin_name == "lazy-compilation" {
lazy_compilation_plugin_idx = Some(plugin_idx);
}
index_contexts.push(PluginContext::Native(Arc::new(NativePluginContextImpl {
plugin_name,
skipped_resolve_calls: vec![],
plugin_idx,
plugin_driver: Weak::clone(plugin_driver),
meta: Arc::clone(&meta),
resolver: Arc::clone(&self.resolver),
file_emitter: Arc::clone(file_emitter),
module_infos: Arc::clone(&module_infos),
options: Arc::clone(options),
watch_files: Arc::clone(&watch_files),
tx: Arc::clone(&tx),
session: session.clone(),
bundle_span: bundle_span.clone(),
manual_resolve_span: manual_resolve_span.clone(),
})));
});
crate::plugin_driver::PluginDriver {
hook_orders: PluginHookOrders::new(&index_plugins, &plugin_usage_vec),
plugins: index_plugins,
contexts: index_contexts,
should_skip_user_plugins_for_lazy_proxy_modules,
lazy_compilation_plugin_idx,
file_emitter: Arc::clone(file_emitter),
watch_files,
module_infos,
transform_dependencies,
context_load_completion_manager: ContextLoadCompletionManager::default(),
tx,
build_timings: BuildTimings::new(options.plugin_timings.is_some()),
}
})
}
}