Skip to main content

rspack_core/compilation/finish_modules/
mod.rs

1use rspack_error::Result;
2
3use super::*;
4use crate::logger::Logger;
5
6pub async fn finish_modules_pass(compilation: &mut Compilation) -> Result<()> {
7  let dependencies_diagnostics_artifact = compilation.dependencies_diagnostics_artifact.clone();
8  let async_modules_artifact = compilation.async_modules_artifact.clone();
9  let diagnostics = compilation
10    .collect_build_module_graph_effects(
11      &mut dependencies_diagnostics_artifact.borrow_mut(),
12      &mut async_modules_artifact.borrow_mut(),
13    )
14    .await?;
15  compilation.extend_diagnostics(diagnostics);
16
17  Ok(())
18}
19
20impl Compilation {
21  #[tracing::instrument("Compilation:collect_build_module_graph_effects", skip_all)]
22  pub async fn collect_build_module_graph_effects(
23    &mut self,
24    dependencies_diagnostics_artifact: &mut DependenciesDiagnosticsArtifact,
25    async_modules_artifact: &mut AsyncModulesArtifact,
26  ) -> Result<Vec<Diagnostic>> {
27    let logger = self.get_logger("rspack.Compilation");
28    if let Some(mut mutations) = self.incremental.mutations_write() {
29      mutations.extend(
30        self
31          .build_module_graph_artifact
32          .affected_dependencies
33          .updated()
34          .iter()
35          .map(|&dependency| Mutation::DependencyUpdate { dependency }),
36      );
37      mutations.extend(
38        self
39          .build_module_graph_artifact
40          .affected_modules
41          .removed()
42          .iter()
43          .map(|&module| Mutation::ModuleRemove { module }),
44      );
45      mutations.extend(
46        self
47          .build_module_graph_artifact
48          .affected_modules
49          .updated()
50          .iter()
51          .map(|&module| Mutation::ModuleUpdate { module }),
52      );
53      mutations.extend(
54        self
55          .build_module_graph_artifact
56          .affected_modules
57          .added()
58          .iter()
59          .map(|&module| Mutation::ModuleAdd { module }),
60      );
61      tracing::debug!(target: incremental::TRACING_TARGET, passes = %IncrementalPasses::MAKE, %mutations);
62    }
63
64    let start = logger.time("finish modules");
65    // finish_modules means the module graph (modules, connections, dependencies) are
66    // frozen and start to optimize (provided exports, infer async, etc.) based on the
67    // module graph, so any kind of change that affect these should be done before the
68    // finish_modules
69    self
70      .plugin_driver
71      .clone()
72      .compilation_hooks
73      .finish_modules
74      .call(self, async_modules_artifact)
75      .await?;
76
77    logger.time_end(start);
78
79    // https://github.com/webpack/webpack/blob/19ca74127f7668aaf60d59f4af8fcaee7924541a/lib/Compilation.js#L2988
80    self.module_graph_cache_artifact.freeze();
81    // Collect dependencies diagnostics at here to make sure:
82    // 1. after finish_modules: has provide exports info
83    // 2. before optimize dependencies: side effects free module hasn't been skipped
84    let mut all_diagnostics =
85      self.collect_dependencies_diagnostics(dependencies_diagnostics_artifact);
86    self.module_graph_cache_artifact.unfreeze();
87
88    // take make diagnostics
89    let diagnostics = self.build_module_graph_artifact.diagnostics();
90    all_diagnostics.extend(diagnostics);
91    Ok(all_diagnostics)
92  }
93
94  #[tracing::instrument("Compilation:collect_dependencies_diagnostics", skip_all)]
95  fn collect_dependencies_diagnostics(
96    &self,
97    dependencies_diagnostics_artifact: &mut DependenciesDiagnosticsArtifact,
98  ) -> Vec<Diagnostic> {
99    // Compute modules while holding the lock, then release it
100    let (modules, has_mutations) = {
101      let mutations = self
102        .incremental
103        .mutations_read(IncrementalPasses::DEPENDENCIES_DIAGNOSTICS);
104
105      // TODO move diagnostic collect to make
106      if let Some(mutations) = mutations {
107        if !dependencies_diagnostics_artifact.is_empty() {
108          let revoked_modules = mutations.iter().filter_map(|mutation| match mutation {
109            Mutation::ModuleRemove { module } => Some(*module),
110            _ => None,
111          });
112          for revoked_module in revoked_modules {
113            dependencies_diagnostics_artifact.remove(&revoked_module);
114          }
115          let modules = mutations.get_affected_modules_with_module_graph(self.get_module_graph());
116          let logger = self.get_logger("rspack.incremental.dependenciesDiagnostics");
117          logger.log(format!(
118            "{} modules are affected, {} in total",
119            modules.len(),
120            self.get_module_graph().modules().len()
121          ));
122          (modules, true)
123        } else {
124          (
125            self.get_module_graph().modules().keys().copied().collect(),
126            true,
127          )
128        }
129      } else {
130        (
131          self.get_module_graph().modules().keys().copied().collect(),
132          false,
133        )
134      }
135    };
136
137    let module_graph = self.get_module_graph();
138    let module_graph_cache = &self.module_graph_cache_artifact;
139    let dependencies_diagnostics: DependenciesDiagnosticsArtifact = modules
140      .par_iter()
141      .map(|module_identifier| {
142        let mgm = module_graph
143          .module_graph_module_by_identifier(module_identifier)
144          .expect("should have mgm");
145        let diagnostics = mgm
146          .all_dependencies
147          .iter()
148          .filter_map(|dependency_id| {
149            let dependency = module_graph.dependency_by_id(dependency_id);
150            dependency
151              .get_diagnostics(module_graph, module_graph_cache)
152              .map(|diagnostics| {
153                diagnostics.into_iter().map(|mut diagnostic| {
154                  diagnostic.module_identifier = Some(*module_identifier);
155                  diagnostic.loc = dependency.loc();
156                  diagnostic
157                })
158              })
159          })
160          .flatten()
161          .collect::<Vec<_>>();
162        (*module_identifier, diagnostics)
163      })
164      .collect::<rspack_collections::IdentifierMap<Vec<Diagnostic>>>()
165      .into();
166    let all_modules_diagnostics = if has_mutations {
167      dependencies_diagnostics_artifact.extend(dependencies_diagnostics);
168      dependencies_diagnostics_artifact.clone()
169    } else {
170      dependencies_diagnostics
171    };
172    all_modules_diagnostics.into_values().flatten().collect()
173  }
174}