pub mod internal;
pub mod rollback;
use std::hash::BuildHasherDefault;
use internal::try_get_module_graph_module_mut_by_identifier;
use rayon::prelude::*;
use rspack_collections::{IdentifierHasher, IdentifierMap};
use rspack_error::Result;
use rspack_hash::RspackHashDigest;
use rustc_hash::{FxHashMap as HashMap, FxHasher};
use swc_core::ecma::atoms::Atom;
use crate::{
AsyncDependenciesBlock, AsyncDependenciesBlockIdentifier, AsyncDependenciesBlockIdentifierMap,
AsyncModulesArtifact, Compilation, DependenciesBlock, Dependency, ExportInfo,
ImportedByDeferModulesArtifact, ModuleGraphCacheArtifact, RuntimeSpec, SideEffectsStateArtifact,
UsedNameItem,
};
mod module;
pub use module::*;
mod connection;
pub use connection::*;
use crate::{
BoxDependency, BoxModule, DependencyCondition, DependencyId, ExportsInfoArtifact,
ModuleIdentifier,
};
pub type ImportVarMap = HashMap<(Option<ModuleIdentifier>, bool), String >;
pub type BuildDependency = (
DependencyId,
Option<ModuleIdentifier>,
);
#[derive(Debug, Clone)]
pub struct DependencyExtraMeta {
pub ids: Vec<Atom>,
pub explanation: Option<&'static str>,
}
#[derive(Debug, Default, Clone)]
pub struct DependencyParents {
pub block: Option<AsyncDependenciesBlockIdentifier>,
pub module: ModuleIdentifier,
pub index_in_block: usize,
}
#[derive(Debug, Default)]
pub struct IncomingConnectionsByOriginModule<'a> {
non_modules: Vec<&'a ModuleGraphConnection>,
modules: IdentifierMap<Vec<&'a ModuleGraphConnection>>,
}
impl<'a> IncomingConnectionsByOriginModule<'a> {
fn with_capacity(capacity: usize) -> Self {
Self {
non_modules: Vec::new(),
modules: IdentifierMap::with_capacity_and_hasher(capacity, Default::default()),
}
}
fn push(
&mut self,
origin_module: Option<ModuleIdentifier>,
connection: &'a ModuleGraphConnection,
) {
if let Some(origin_module) = origin_module {
self
.modules
.entry(origin_module)
.or_default()
.push(connection);
} else {
self.non_modules.push(connection);
}
}
pub fn non_modules(&self) -> &[&'a ModuleGraphConnection] {
&self.non_modules
}
pub fn modules(&self) -> &IdentifierMap<Vec<&'a ModuleGraphConnection>> {
&self.modules
}
pub fn into_parts(
self,
) -> (
Vec<&'a ModuleGraphConnection>,
IdentifierMap<Vec<&'a ModuleGraphConnection>>,
) {
(self.non_modules, self.modules)
}
}
#[derive(Debug, Default)]
pub(crate) struct ModuleGraphData {
pub(crate) modules:
rollback::RollbackMap<ModuleIdentifier, BoxModule, BuildHasherDefault<IdentifierHasher>>,
dependencies: HashMap<DependencyId, BoxDependency>,
blocks: AsyncDependenciesBlockIdentifierMap<Box<AsyncDependenciesBlock>>,
dependency_id_to_parents: HashMap<DependencyId, DependencyParents>,
connection_to_condition: HashMap<DependencyId, DependencyCondition>,
module_graph_modules:
rollback::OverlayMap<ModuleIdentifier, ModuleGraphModule, BuildHasherDefault<IdentifierHasher>>,
connections:
rollback::OverlayMap<DependencyId, ModuleGraphConnection, BuildHasherDefault<FxHasher>>,
dep_meta_map: HashMap<DependencyId, DependencyExtraMeta>,
}
impl ModuleGraphData {
fn checkpoint(&mut self) {
self.modules.checkpoint();
self.module_graph_modules.checkpoint();
self.connections.checkpoint();
}
fn recover(&mut self) {
self.modules.reset();
self.module_graph_modules.reset();
self.connections.reset();
self.dep_meta_map.clear();
}
}
#[derive(Debug, Default)]
pub struct ModuleGraph {
pub(super) inner: ModuleGraphData,
}
impl ModuleGraph {
pub fn checkpoint(&mut self) {
self.inner.checkpoint()
}
pub fn reset(&mut self) {
self.inner.recover()
}
}
impl ModuleGraph {
#[inline]
pub fn modules_len(&self) -> usize {
self.inner.modules.len()
}
#[inline]
pub fn modules(&self) -> impl Iterator<Item = (&ModuleIdentifier, &BoxModule)> {
self.inner.modules.iter()
}
#[inline]
pub fn modules_par(
&self,
) -> impl rayon::prelude::ParallelIterator<Item = (&ModuleIdentifier, &BoxModule)> {
self.inner.modules.par_iter()
}
#[inline]
pub fn modules_keys(&self) -> impl Iterator<Item = &ModuleIdentifier> {
self.inner.modules.iter().map(|(k, _)| k)
}
#[inline]
pub fn module_graph_modules(
&self,
) -> impl Iterator<Item = (&ModuleIdentifier, &ModuleGraphModule)> {
self.inner.module_graph_modules.iter()
}
pub fn get_outcoming_connections_by_module(
&self,
module_id: &ModuleIdentifier,
) -> IdentifierMap<Vec<&ModuleGraphConnection>> {
let connections = self
.module_graph_module_by_identifier(module_id)
.expect("should have mgm")
.outgoing_connections();
let mut map: IdentifierMap<Vec<&ModuleGraphConnection>> =
IdentifierMap::with_capacity_and_hasher(connections.len(), Default::default());
for dep_id in connections {
let con = self
.connection_by_dependency_id(dep_id)
.expect("should have connection");
map.entry(*con.module_identifier()).or_default().push(con);
}
map
}
pub fn get_active_outcoming_connections_by_module(
&self,
module_id: &ModuleIdentifier,
runtime: Option<&RuntimeSpec>,
module_graph: &ModuleGraph,
module_graph_cache: &ModuleGraphCacheArtifact,
side_effects_state_artifact: &SideEffectsStateArtifact,
exports_info_artifact: &ExportsInfoArtifact,
) -> IdentifierMap<Vec<&ModuleGraphConnection>> {
let connections = self
.module_graph_module_by_identifier(module_id)
.expect("should have mgm")
.outgoing_connections();
let mut map: IdentifierMap<Vec<&ModuleGraphConnection>> =
IdentifierMap::with_capacity_and_hasher(connections.len(), Default::default());
for dep_id in connections {
let con = self
.connection_by_dependency_id(dep_id)
.expect("should have connection");
if !con.is_active(
module_graph,
runtime,
module_graph_cache,
side_effects_state_artifact,
exports_info_artifact,
) {
continue;
}
map.entry(*con.module_identifier()).or_default().push(con);
}
map
}
pub fn get_incoming_connections_by_origin_module(
&self,
module_id: &ModuleIdentifier,
) -> IncomingConnectionsByOriginModule<'_> {
let connections = self
.module_graph_module_by_identifier(module_id)
.expect("should have mgm")
.incoming_connections();
let mut map = IncomingConnectionsByOriginModule::with_capacity(connections.len());
for dep_id in connections {
let con = self
.connection_by_dependency_id(dep_id)
.expect("should have connection");
map.push(con.original_module_identifier, con);
}
map
}
pub fn revoke_dependency(
&mut self,
dep_id: &DependencyId,
force: bool,
) -> Option<BuildDependency> {
let original_module_identifier = self.get_parent_module(dep_id).copied();
let module_identifier = self.module_identifier_by_dependency_id(dep_id).copied();
let parent_block = self.get_parent_block(dep_id).copied();
if module_identifier.is_some() {
self.inner.connections.remove(dep_id);
}
if force {
self.inner.dependencies.remove(dep_id);
self.inner.dependency_id_to_parents.remove(dep_id);
self.inner.connection_to_condition.remove(dep_id);
if let Some(m_id) = original_module_identifier
&& let Some(module) = self.inner.modules.get_mut(&m_id)
{
module.remove_dependency_id(*dep_id);
}
if let Some(b_id) = parent_block
&& let Some(block) = self.inner.blocks.get_mut(&b_id)
{
block.remove_dependency_id(*dep_id);
}
}
if let Some(original_module_identifier) = &original_module_identifier
&& let Some(mgm) =
try_get_module_graph_module_mut_by_identifier(self, original_module_identifier)
{
mgm.remove_outgoing_connection(dep_id);
if force {
mgm.all_dependencies_mut().retain(|id| id != dep_id);
}
}
if let Some(module_identifier) = &module_identifier
&& let Some(mgm) = try_get_module_graph_module_mut_by_identifier(self, module_identifier)
{
mgm.remove_incoming_connection(dep_id);
}
Some((*dep_id, original_module_identifier))
}
pub fn revoke_module(&mut self, module_id: &ModuleIdentifier) -> Vec<BuildDependency> {
let blocks = self
.module_by_identifier(module_id)
.map(|m| Vec::from(m.get_blocks()))
.unwrap_or_default();
let (incoming_connections, all_dependencies) = self
.module_graph_module_by_identifier(module_id)
.map(|mgm| {
(
mgm.incoming_connections().clone(),
mgm.all_dependencies().to_vec(),
)
})
.unwrap_or_default();
self.inner.modules.remove(module_id);
self.inner.module_graph_modules.remove(module_id);
for block in blocks {
self.inner.blocks.remove(&block);
}
for dep_id in all_dependencies {
self.revoke_dependency(&dep_id, true);
}
incoming_connections
.iter()
.filter_map(|dep_id| self.revoke_dependency(dep_id, false))
.collect()
}
pub fn add_module_graph_module(&mut self, module_graph_module: ModuleGraphModule) {
self
.inner
.module_graph_modules
.insert(module_graph_module.module_identifier, module_graph_module);
}
pub fn clone_module_attributes(
compilation: &mut Compilation,
source_module: &ModuleIdentifier,
target_module: &ModuleIdentifier,
) {
let module_graph = compilation.get_module_graph_mut();
let old_mgm = module_graph
.module_graph_module_by_identifier(source_module)
.expect("should have mgm");
let assign_tuple = (
old_mgm.post_order_index,
old_mgm.pre_order_index,
old_mgm.depth,
);
let new_mgm = module_graph.module_graph_module_by_identifier_mut(target_module);
new_mgm.post_order_index = assign_tuple.0;
new_mgm.pre_order_index = assign_tuple.1;
new_mgm.depth = assign_tuple.2;
let exports_info = compilation
.exports_info_artifact
.get_exports_info(source_module);
compilation
.exports_info_artifact
.set_exports_info(*target_module, exports_info);
let is_async = ModuleGraph::is_async(&compilation.async_modules_artifact, source_module);
ModuleGraph::set_async(
&mut compilation.async_modules_artifact,
*target_module,
is_async,
);
}
pub fn move_module_connections(
&mut self,
old_module: &ModuleIdentifier,
new_module: &ModuleIdentifier,
filter_connection: impl Fn(&ModuleGraphConnection, &Box<dyn Dependency>) -> bool,
) {
if old_module == new_module {
return;
}
let outgoing_connections = self
.module_graph_module_by_identifier(old_module)
.expect("should have mgm")
.outgoing_connections()
.clone();
let mut affected_outgoing_connection = vec![];
for dep_id in outgoing_connections {
let connection = self
.connection_by_dependency_id(&dep_id)
.expect("should have connection");
let dependency = self.dependency_by_id(&dep_id);
if filter_connection(connection, dependency) {
let connection = self
.connection_by_dependency_id_mut(&dep_id)
.expect("should have connection");
connection.original_module_identifier = Some(*new_module);
affected_outgoing_connection.push(dep_id);
}
}
let old_mgm = self.module_graph_module_by_identifier_mut(old_module);
for dep_id in &affected_outgoing_connection {
old_mgm.remove_outgoing_connection(dep_id);
}
let new_mgm = self.module_graph_module_by_identifier_mut(new_module);
for dep_id in affected_outgoing_connection {
new_mgm.add_outgoing_connection(dep_id);
}
let incoming_connections = self
.module_graph_module_by_identifier(old_module)
.expect("should have mgm")
.incoming_connections()
.clone();
let mut affected_incoming_connection = vec![];
for dep_id in incoming_connections {
let connection = self
.connection_by_dependency_id(&dep_id)
.expect("should have connection");
let dependency = self.dependency_by_id(&dep_id);
if filter_connection(connection, dependency) {
let connection = self
.connection_by_dependency_id_mut(&dep_id)
.expect("should have connection");
connection.set_module_identifier(*new_module);
affected_incoming_connection.push(dep_id);
}
}
let old_mgm = self.module_graph_module_by_identifier_mut(old_module);
for dep_id in &affected_incoming_connection {
old_mgm.remove_incoming_connection(dep_id);
}
let new_mgm = self.module_graph_module_by_identifier_mut(new_module);
for dep_id in affected_incoming_connection {
new_mgm.add_incoming_connection(dep_id);
}
}
pub fn copy_outgoing_module_connections<F>(
&mut self,
old_module: &ModuleIdentifier,
new_module: &ModuleIdentifier,
filter_connection: F,
) where
F: Fn(&ModuleGraphConnection, &BoxDependency) -> bool,
{
if old_module == new_module {
return;
}
let old_mgm_connections = self
.module_graph_module_by_identifier(old_module)
.expect("should have mgm")
.outgoing_connections()
.clone();
let mut affected_outgoing_connections = vec![];
for dep_id in old_mgm_connections {
let connection = self
.connection_by_dependency_id(&dep_id)
.expect("should have connection");
let dep = self.dependency_by_id(&dep_id);
if filter_connection(connection, dep) {
let con = self
.connection_by_dependency_id_mut(&dep_id)
.expect("should have connection");
con.original_module_identifier = Some(*new_module);
affected_outgoing_connections.push(dep_id);
}
}
let new_mgm = self.module_graph_module_by_identifier_mut(new_module);
for dep_id in affected_outgoing_connections {
new_mgm.add_outgoing_connection(dep_id);
}
}
pub fn get_depth(&self, module_id: &ModuleIdentifier) -> Option<usize> {
self
.module_graph_module_by_identifier(module_id)
.and_then(|mgm| mgm.depth)
}
pub fn set_depth_if_lower(&mut self, module_id: &ModuleIdentifier, depth: usize) -> bool {
let mgm = self.module_graph_module_by_identifier_mut(module_id);
match mgm.depth {
Some(cur_depth) if cur_depth <= depth => false,
_ => {
mgm.depth = Some(depth);
true
}
}
}
pub fn add_module(&mut self, module: BoxModule) {
self.inner.modules.insert(module.identifier(), module);
}
pub fn add_block(&mut self, block: Box<AsyncDependenciesBlock>) {
self.inner.blocks.insert(block.identifier(), block);
}
pub fn set_parents(&mut self, dependency_id: DependencyId, parents: DependencyParents) {
self
.inner
.dependency_id_to_parents
.insert(dependency_id, parents);
}
pub fn get_parent_module(&self, dependency_id: &DependencyId) -> Option<&ModuleIdentifier> {
self
.inner
.dependency_id_to_parents
.get(dependency_id)
.map(|p| &p.module)
}
pub fn get_parent_block(
&self,
dependency_id: &DependencyId,
) -> Option<&AsyncDependenciesBlockIdentifier> {
self
.inner
.dependency_id_to_parents
.get(dependency_id)
.and_then(|p| p.block.as_ref())
}
pub fn get_parent_block_index(&self, dependency_id: &DependencyId) -> Option<usize> {
self
.inner
.dependency_id_to_parents
.get(dependency_id)
.map(|p| p.index_in_block)
}
pub fn block_by_id(
&self,
block_id: &AsyncDependenciesBlockIdentifier,
) -> Option<&AsyncDependenciesBlock> {
self.inner.blocks.get(block_id).map(AsRef::as_ref)
}
pub fn block_by_id_expect(
&self,
block_id: &AsyncDependenciesBlockIdentifier,
) -> &AsyncDependenciesBlock {
self
.inner
.blocks
.get(block_id)
.expect("should insert block before get it")
}
pub fn blocks(&self) -> &AsyncDependenciesBlockIdentifierMap<Box<AsyncDependenciesBlock>> {
&self.inner.blocks
}
pub fn dependencies(&self) -> impl Iterator<Item = (&DependencyId, &BoxDependency)> {
self.inner.dependencies.iter()
}
pub fn add_dependency(&mut self, dependency: BoxDependency) {
self.inner.dependencies.insert(*dependency.id(), dependency);
}
pub fn dependency_by_id(&self, dependency_id: &DependencyId) -> &BoxDependency {
self
.inner
.dependencies
.get(dependency_id)
.unwrap_or_else(|| panic!("Dependency with ID {dependency_id:?} not found"))
}
pub fn dependency_by_id_mut(&mut self, dependency_id: &DependencyId) -> &mut BoxDependency {
self
.inner
.dependencies
.get_mut(dependency_id)
.unwrap_or_else(|| panic!("Dependency with ID {dependency_id:?} not found"))
}
pub fn module_graph_module_by_dependency_id(
&self,
id: &DependencyId,
) -> Option<&ModuleGraphModule> {
self
.module_identifier_by_dependency_id(id)
.and_then(|module_identifier| self.module_graph_module_by_identifier(module_identifier))
}
pub fn module_identifier_by_dependency_id(
&self,
dep_id: &DependencyId,
) -> Option<&ModuleIdentifier> {
self
.inner
.connections
.get(dep_id)
.map(|con| con.module_identifier())
}
pub fn get_module_by_dependency_id(&self, dep_id: &DependencyId) -> Option<&BoxModule> {
self
.module_identifier_by_dependency_id(dep_id)
.and_then(|module_id| self.inner.modules.get(module_id))
}
fn add_connection(
&mut self,
connection: ModuleGraphConnection,
condition: Option<DependencyCondition>,
) {
if self
.connection_by_dependency_id(&connection.dependency_id)
.is_some()
{
return;
}
if let Some(condition) = condition {
self
.inner
.connection_to_condition
.insert(connection.dependency_id, condition);
}
let module_id = *connection.module_identifier();
let origin_module_id = connection.original_module_identifier;
let dependency_id = connection.dependency_id;
self
.inner
.connections
.insert(connection.dependency_id, connection);
{
let mgm = self.module_graph_module_by_identifier_mut(&module_id);
mgm.add_incoming_connection(dependency_id);
}
if let Some(identifier) = origin_module_id {
let original_mgm = self.module_graph_module_by_identifier_mut(&identifier);
original_mgm.add_outgoing_connection(dependency_id);
};
}
pub fn set_resolved_module(
&mut self,
original_module_identifier: Option<ModuleIdentifier>,
dependency_id: DependencyId,
module_identifier: ModuleIdentifier,
) -> Result<()> {
let dependency = self.dependency_by_id(&dependency_id);
let is_module_dependency =
dependency.as_module_dependency().is_some() || dependency.as_context_dependency().is_some();
let condition = dependency
.as_module_dependency()
.and_then(|dep| dep.get_condition());
if !is_module_dependency {
return Ok(());
}
let conditional = condition.is_some();
let new_connection = ModuleGraphConnection::new(
dependency_id,
original_module_identifier,
module_identifier,
conditional,
);
self.add_connection(new_connection, condition);
Ok(())
}
pub fn module_by_identifier(&self, identifier: &ModuleIdentifier) -> Option<&BoxModule> {
self.inner.modules.get(identifier)
}
pub fn module_by_identifier_mut(
&mut self,
identifier: &ModuleIdentifier,
) -> Option<&mut BoxModule> {
self.inner.modules.get_mut(identifier)
}
pub fn module_graph_module_by_identifier(
&self,
identifier: &ModuleIdentifier,
) -> Option<&ModuleGraphModule> {
self.inner.module_graph_modules.get(identifier)
}
pub fn module_graph_module_by_identifier_mut(
&mut self,
identifier: &ModuleIdentifier,
) -> &mut ModuleGraphModule {
self
.inner
.module_graph_modules
.get_mut(identifier)
.unwrap_or_else(|| panic!("ModuleGraphModule with identifier {identifier:?} not found"))
}
pub fn get_ordered_outgoing_connections(
&self,
module_identifier: &ModuleIdentifier,
) -> impl Iterator<Item = &ModuleGraphConnection> {
self
.module_graph_module_by_identifier(module_identifier)
.map(|m| {
m.all_dependencies()
.iter()
.filter_map(|dep_id| self.connection_by_dependency_id(dep_id))
})
.into_iter()
.flatten()
}
pub fn get_outgoing_deps_in_order(
&self,
module_identifier: &ModuleIdentifier,
) -> impl Iterator<Item = &DependencyId> {
self
.module_graph_module_by_identifier(module_identifier)
.map(|m| {
m.all_dependencies()
.iter()
.filter(|dep_id| self.connection_by_dependency_id(dep_id).is_some())
})
.into_iter()
.flatten()
}
pub fn connection_by_dependency_id(
&self,
dependency_id: &DependencyId,
) -> Option<&ModuleGraphConnection> {
self.inner.connections.get(dependency_id)
}
pub fn get_resolved_module(&self, dependency_id: &DependencyId) -> Option<&ModuleIdentifier> {
match self.connection_by_dependency_id(dependency_id) {
Some(connection) => Some(&connection.resolved_module),
None => None,
}
}
pub fn connection_by_dependency_id_mut(
&mut self,
dependency_id: &DependencyId,
) -> Option<&mut ModuleGraphConnection> {
self.inner.connections.get_mut(dependency_id)
}
pub fn get_pre_order_index(&self, module_id: &ModuleIdentifier) -> Option<u32> {
self
.module_graph_module_by_identifier(module_id)
.and_then(|mgm| mgm.pre_order_index)
}
pub fn get_post_order_index(&self, module_id: &ModuleIdentifier) -> Option<u32> {
self
.module_graph_module_by_identifier(module_id)
.and_then(|mgm| mgm.post_order_index)
}
pub fn get_issuer(&self, module_id: &ModuleIdentifier) -> Option<&BoxModule> {
self
.module_graph_module_by_identifier(module_id)
.and_then(|mgm| mgm.issuer().get_module(self))
}
pub fn is_optional(
&self,
module_id: &ModuleIdentifier,
module_graph_cache: &ModuleGraphCacheArtifact,
side_effects_state_artifact: &SideEffectsStateArtifact,
exports_info_artifact: &ExportsInfoArtifact,
) -> bool {
let mut has_connections = false;
for connection in self.get_incoming_connections(module_id) {
let dependency = self.dependency_by_id(&connection.dependency_id);
let Some(module_dependency) = dependency.as_module_dependency() else {
return false;
};
if !module_dependency.get_optional()
|| !connection.is_target_active(
self,
None,
module_graph_cache,
side_effects_state_artifact,
exports_info_artifact,
)
{
return false;
}
has_connections = true;
}
has_connections
}
pub fn is_async(
async_modules_artifact: &AsyncModulesArtifact,
module_id: &ModuleIdentifier,
) -> bool {
async_modules_artifact.contains(module_id)
}
pub fn is_deferred(
&self,
imported_by_defer_modules_artifact: &ImportedByDeferModulesArtifact,
module_id: &ModuleIdentifier,
) -> bool {
let imported_by_defer = imported_by_defer_modules_artifact.contains(module_id);
if !imported_by_defer {
return false;
}
let module = self
.module_by_identifier(module_id)
.expect("should have module");
!module.build_meta().has_top_level_await
}
pub fn set_async(
async_modules_artifact: &mut AsyncModulesArtifact,
module_id: ModuleIdentifier,
is_async: bool,
) -> bool {
let original = Self::is_async(async_modules_artifact, &module_id);
if original == is_async {
return false;
}
if original {
async_modules_artifact.remove(&module_id)
} else {
async_modules_artifact.insert(module_id)
}
}
pub fn get_outgoing_connections(
&self,
module_id: &ModuleIdentifier,
) -> impl Iterator<Item = &ModuleGraphConnection> + Clone {
self
.module_graph_module_by_identifier(module_id)
.map(|mgm| {
mgm
.outgoing_connections()
.iter()
.filter_map(|id| self.connection_by_dependency_id(id))
})
.into_iter()
.flatten()
}
pub fn get_incoming_connections(
&self,
module_id: &ModuleIdentifier,
) -> impl Iterator<Item = &ModuleGraphConnection> + Clone {
self
.module_graph_module_by_identifier(module_id)
.map(|mgm| {
mgm
.incoming_connections()
.iter()
.filter_map(|id| self.connection_by_dependency_id(id))
})
.into_iter()
.flatten()
}
pub fn get_module_hash(&self, module_id: &ModuleIdentifier) -> Option<&RspackHashDigest> {
self
.module_by_identifier(module_id)
.and_then(|m| m.build_info().hash.as_ref())
}
pub fn get_dep_meta_if_existing(&self, id: &DependencyId) -> Option<&DependencyExtraMeta> {
self.inner.dep_meta_map.get(id)
}
pub fn set_dependency_extra_meta(&mut self, dep_id: DependencyId, extra: DependencyExtraMeta) {
self.inner.dep_meta_map.insert(dep_id, extra);
}
pub fn can_update_module(&self, dep_id: &DependencyId, module_id: &ModuleIdentifier) -> bool {
let connection = self
.connection_by_dependency_id(dep_id)
.expect("should have connection");
connection.module_identifier() != module_id
}
pub fn do_update_module(&mut self, dep_id: &DependencyId, module_id: &ModuleIdentifier) {
let connection = self
.connection_by_dependency_id_mut(dep_id)
.unwrap_or_else(|| panic!("{dep_id:?}"));
let old_module_identifier = *connection.module_identifier();
connection.set_module_identifier(*module_id);
let old_mgm = self.module_graph_module_by_identifier_mut(&old_module_identifier);
old_mgm.remove_incoming_connection(dep_id);
let new_mgm = self.module_graph_module_by_identifier_mut(module_id);
new_mgm.add_incoming_connection(*dep_id);
}
pub fn get_optimization_bailout_mut(
&mut self,
id: &ModuleIdentifier,
) -> &mut Vec<OptimizationBailoutItem> {
let mgm = self.module_graph_module_by_identifier_mut(id);
mgm.optimization_bailout_mut()
}
pub fn get_optimization_bailout(&self, id: &ModuleIdentifier) -> &Vec<OptimizationBailoutItem> {
let mgm = self
.module_graph_module_by_identifier(id)
.expect("should have module graph module");
&mgm.optimization_bailout
}
pub fn get_condition_state(
&self,
connection: &ModuleGraphConnection,
runtime: Option<&RuntimeSpec>,
module_graph_cache: &ModuleGraphCacheArtifact,
side_effects_state_artifact: &SideEffectsStateArtifact,
exports_info_artifact: &ExportsInfoArtifact,
) -> ConnectionState {
let condition = self
.inner
.connection_to_condition
.get(&connection.dependency_id)
.expect("should have condition");
condition.get_connection_state(
connection,
runtime,
self,
module_graph_cache,
side_effects_state_artifact,
exports_info_artifact,
)
}
pub fn is_connection_active(
&self,
connection: &ModuleGraphConnection,
runtime: Option<&RuntimeSpec>,
module_graph_cache: &ModuleGraphCacheArtifact,
side_effects_state_artifact: &SideEffectsStateArtifact,
exports_info_artifact: &ExportsInfoArtifact,
) -> bool {
let condition = self
.inner
.connection_to_condition
.get(&connection.dependency_id)
.expect("should have condition");
condition.is_connection_active(
connection,
runtime,
self,
module_graph_cache,
side_effects_state_artifact,
exports_info_artifact,
)
}
pub fn cache_recovery_connection(&mut self, connection: ModuleGraphConnection) {
let condition = self
.dependency_by_id(&connection.dependency_id)
.as_module_dependency()
.and_then(|dep| dep.get_condition());
if let Some(condition) = condition {
self
.inner
.connection_to_condition
.insert(connection.dependency_id, condition);
}
self
.inner
.connections
.insert(connection.dependency_id, connection);
}
pub fn batch_set_connections_original_module(
&mut self,
tasks: Vec<(DependencyId, ModuleIdentifier)>,
) {
let changed = tasks
.into_par_iter()
.map(|(dep_id, original_module_identifier)| {
let mut con = self
.connection_by_dependency_id(&dep_id)
.expect("should have connection")
.clone();
con.original_module_identifier = Some(original_module_identifier);
(dep_id, con)
})
.collect::<Vec<_>>();
for (dep_id, con) in changed {
self.inner.connections.insert(dep_id, con);
}
}
pub fn batch_set_connections_module(&mut self, tasks: Vec<(DependencyId, ModuleIdentifier)>) {
let changed = tasks
.into_par_iter()
.map(|(dep_id, module_identifier)| {
let mut con = self
.connection_by_dependency_id(&dep_id)
.expect("should have connection")
.clone();
con.set_module_identifier(module_identifier);
(dep_id, con)
})
.collect::<Vec<_>>();
for (dep_id, con) in changed {
self.inner.connections.insert(dep_id, con);
}
}
pub fn batch_add_connections(
&mut self,
tasks: Vec<(ModuleIdentifier, Vec<DependencyId>, Vec<DependencyId>)>,
) {
let changed = tasks
.into_par_iter()
.map(|(mid, outgoings, incomings)| {
let mut mgm = self
.module_graph_module_by_identifier(&mid)
.expect("should have mgm")
.clone();
for outgoing in outgoings {
mgm.add_outgoing_connection(outgoing);
}
for incoming in incomings {
mgm.add_incoming_connection(incoming);
}
(mid, mgm)
})
.collect::<Vec<_>>();
for (mid, mgm) in changed {
self.inner.module_graph_modules.insert(mid, mgm);
}
}
pub fn batch_remove_connections(
&mut self,
tasks: Vec<(ModuleIdentifier, Vec<DependencyId>, Vec<DependencyId>)>,
) {
let changed = tasks
.into_par_iter()
.map(|(mid, outgoings, incomings)| {
let mut mgm = self
.module_graph_module_by_identifier(&mid)
.expect("should have mgm")
.clone();
for outgoing in outgoings.iter() {
mgm.remove_outgoing_connection(outgoing);
}
for incoming in incomings.iter() {
mgm.remove_incoming_connection(incoming);
}
(mid, mgm)
})
.collect::<Vec<_>>();
for (mid, mgm) in changed {
self.inner.module_graph_modules.insert(mid, mgm);
}
}
pub fn batch_set_export_info_used_name(
&mut self,
exports_info_artifact: &mut ExportsInfoArtifact,
tasks: Vec<(ExportInfo, UsedNameItem)>,
) {
for (export_info, used_name) in tasks {
export_info
.as_data_mut(exports_info_artifact)
.set_used_name(used_name);
}
}
}