Skip to main content

rspack_core/
raw_module.rs

1use std::{borrow::Cow, hash::Hash};
2
3use rspack_cacheable::{
4  cacheable, cacheable_dyn,
5  with::{AsOption, AsPreset},
6};
7use rspack_collections::{Identifiable, IdentifierMap, IdentifierSet};
8use rspack_error::{Result, impl_empty_diagnosable_trait};
9use rspack_hash::{RspackHash, RspackHashDigest};
10use rspack_macros::impl_source_map_config;
11use rspack_sources::{BoxSource, OriginalSource, RawStringSource, SourceExt};
12use rspack_util::source_map::{ModuleSourceMapConfig, SourceMapKind};
13
14use crate::{
15  BoxModule, BuildContext, BuildInfo, BuildMeta, BuildResult, CodeGenerationResult, Compilation,
16  ConnectionState, Context, DependenciesBlock, DependencyId, FactoryMeta, Module,
17  ModuleCodeGenerationContext, ModuleGraph, ModuleGraphCacheArtifact, ModuleIdentifier, ModuleType,
18  RuntimeGlobals, RuntimeSpec, SideEffectsStateArtifact, SourceType,
19  dependencies_block::AsyncDependenciesBlockIdentifier, impl_module_meta_info,
20  module_declared_side_effect_free, module_update_hash,
21};
22
23#[impl_source_map_config]
24#[cacheable]
25#[derive(Debug)]
26pub struct RawModule {
27  blocks: Vec<AsyncDependenciesBlockIdentifier>,
28  dependencies: Vec<DependencyId>,
29  source_str: String,
30  #[cacheable(with=AsOption<AsPreset>)]
31  source: Option<BoxSource>,
32  identifier: ModuleIdentifier,
33  readable_identifier: String,
34  runtime_requirements: RuntimeGlobals,
35  factory_meta: Option<FactoryMeta>,
36  build_info: BuildInfo,
37  build_meta: BuildMeta,
38}
39
40static RAW_MODULE_SOURCE_TYPES: &[SourceType] = &[SourceType::JavaScript];
41
42impl RawModule {
43  pub fn new(
44    source_str: String,
45    identifier: ModuleIdentifier,
46    readable_identifier: String,
47    runtime_requirements: RuntimeGlobals,
48  ) -> Self {
49    Self {
50      blocks: Default::default(),
51      dependencies: Default::default(),
52      source_str,
53      source: None,
54      identifier,
55      readable_identifier,
56      runtime_requirements,
57      factory_meta: None,
58      build_info: BuildInfo {
59        cacheable: true,
60        strict: true,
61        ..Default::default()
62      },
63      build_meta: Default::default(),
64      source_map_kind: SourceMapKind::empty(),
65    }
66  }
67}
68
69impl Identifiable for RawModule {
70  fn identifier(&self) -> ModuleIdentifier {
71    self.identifier
72  }
73}
74
75impl DependenciesBlock for RawModule {
76  fn add_block_id(&mut self, block: AsyncDependenciesBlockIdentifier) {
77    self.blocks.push(block)
78  }
79
80  fn get_blocks(&self) -> &[AsyncDependenciesBlockIdentifier] {
81    &self.blocks
82  }
83
84  fn add_dependency_id(&mut self, dependency: DependencyId) {
85    self.dependencies.push(dependency)
86  }
87
88  fn remove_dependency_id(&mut self, dependency: DependencyId) {
89    self.dependencies.retain(|d| d != &dependency)
90  }
91
92  fn get_dependencies(&self) -> &[DependencyId] {
93    &self.dependencies
94  }
95}
96
97#[cacheable_dyn]
98#[async_trait::async_trait]
99impl Module for RawModule {
100  impl_module_meta_info!();
101
102  fn module_type(&self) -> &ModuleType {
103    &ModuleType::JsAuto
104  }
105
106  fn source_types(&self, _module_graph: &ModuleGraph) -> &[SourceType] {
107    RAW_MODULE_SOURCE_TYPES
108  }
109
110  fn source(&self) -> Option<&BoxSource> {
111    self.source.as_ref()
112  }
113
114  fn readable_identifier(&self, _context: &Context) -> Cow<'_, str> {
115    Cow::Borrowed(&self.readable_identifier)
116  }
117
118  fn size(&self, _source_type: Option<&SourceType>, _compilation: Option<&Compilation>) -> f64 {
119    f64::max(1.0, self.source_str.len() as f64)
120  }
121
122  // #[tracing::instrument("RawModule::code_generation", skip_all, fields(identifier = ?self.identifier()))]
123  async fn code_generation(
124    &self,
125    code_generation_context: &mut ModuleCodeGenerationContext,
126  ) -> Result<CodeGenerationResult> {
127    let mut cgr = CodeGenerationResult::default();
128    code_generation_context
129      .runtime_template
130      .runtime_requirements_mut()
131      .insert(self.runtime_requirements);
132    if self.get_source_map_kind().enabled() {
133      cgr.add(
134        SourceType::JavaScript,
135        OriginalSource::new(self.source_str.clone(), self.identifier.to_string()).boxed(),
136      );
137    } else {
138      cgr.add(
139        SourceType::JavaScript,
140        RawStringSource::from(self.source_str.clone()).boxed(),
141      );
142    };
143    Ok(cgr)
144  }
145
146  async fn get_runtime_hash(
147    &self,
148    compilation: &Compilation,
149    runtime: Option<&RuntimeSpec>,
150  ) -> Result<RspackHashDigest> {
151    let mut hasher = RspackHash::from(&compilation.options.output);
152    self.source_str.hash(&mut hasher);
153    module_update_hash(self, &mut hasher, compilation, runtime);
154    Ok(hasher.digest(&compilation.options.output.hash_digest))
155  }
156
157  fn get_side_effects_connection_state(
158    &self,
159    _module_graph: &ModuleGraph,
160    _module_graph_cache: &ModuleGraphCacheArtifact,
161    _side_effects_state_artifact: &SideEffectsStateArtifact,
162    _module_chain: &mut IdentifierSet,
163    _connection_state_cache: &mut IdentifierMap<ConnectionState>,
164  ) -> ConnectionState {
165    if let Some(side_effect_free) = module_declared_side_effect_free(self) {
166      return ConnectionState::Active(!side_effect_free);
167    }
168    ConnectionState::Active(true)
169  }
170
171  async fn build(
172    self: Box<Self>,
173    _build_context: BuildContext,
174    _compilation: Option<&Compilation>,
175  ) -> Result<BuildResult> {
176    Ok(BuildResult {
177      module: BoxModule::new(self),
178      dependencies: vec![],
179      blocks: vec![],
180      optimization_bailouts: vec![],
181    })
182  }
183}
184
185impl_empty_diagnosable_trait!(RawModule);