1use std::{
2 borrow::Cow,
3 hash::Hash,
4 sync::{
5 Arc,
6 atomic::{AtomicUsize, Ordering},
7 },
8};
9
10use derive_more::Debug;
11use rspack_cacheable::{
12 cacheable, cacheable_dyn,
13 with::{As, AsInner, AsOption, AsPreset},
14};
15use rspack_collections::{Identifiable, IdentifierMap, IdentifierSet};
16use rspack_error::{Diagnosable, Diagnostic, Result, error};
17use rspack_fs::ReadableFileSystem;
18use rspack_hash::{RspackHash, RspackHashDigest};
19use rspack_hook::define_hook;
20use rspack_loader_runner::{AdditionalData, Content, LoaderContext, ResourceData, run_loaders};
21use rspack_sources::{
22 BoxSource, CachedSource, OriginalSource, RawBufferSource, RawStringSource, SourceExt, SourceMap,
23 SourceMapSource, WithoutOriginalOptions,
24};
25use rspack_util::{
26 ext::DynHash,
27 source_map::{ModuleSourceMapConfig, SourceMapKind},
28};
29use serde_json::json;
30use tracing::{Instrument, info_span};
31
32use crate::{
33 AsyncDependenciesBlockIdentifier, BoxDependencyTemplate, BoxLoader, BoxModule,
34 BoxModuleDependency, BuildContext, BuildInfo, BuildMeta, BuildResult, ChunkGraph,
35 CodeGenerationResult, Compilation, ConnectionState, Context, DependenciesBlock, DependencyId,
36 FactoryMeta, GenerateContext, GeneratorOptions, ImportPhase, LibIdentOptions, Module,
37 ModuleCodeGenerationContext, ModuleGraph, ModuleGraphCacheArtifact, ModuleIdentifier,
38 ModuleLayer, ModuleType, OptimizationBailoutItem, OutputOptions, ParseContext, ParseResult,
39 ParserAndGenerator, ParserOptions, Resolve, ResolvedModuleOptions, RspackLoaderRunnerPlugin,
40 RunnerContext, RuntimeGlobals, RuntimeSpec, SideEffectsStateArtifact, SourceType, contextify,
41 diagnostics::ModuleBuildError,
42 get_context, module_analyzed_side_effect_free, module_declared_side_effect_free,
43 module_update_hash,
44 utils::{SourceSizeCache, SourceSizeCacheSerde},
45};
46
47#[cacheable]
48#[derive(Debug, Clone)]
49pub enum ModuleIssuer {
50 Unset,
51 None,
52 Some(ModuleIdentifier),
53}
54
55impl ModuleIssuer {
56 pub fn from_identifier(identifier: Option<ModuleIdentifier>) -> Self {
57 match identifier {
58 Some(id) => Self::Some(id),
59 None => Self::None,
60 }
61 }
62
63 pub fn identifier(&self) -> Option<&ModuleIdentifier> {
64 match self {
65 ModuleIssuer::Some(id) => Some(id),
66 _ => None,
67 }
68 }
69
70 pub fn get_module<'a>(&self, module_graph: &'a ModuleGraph) -> Option<&'a BoxModule> {
71 if let Some(id) = self.identifier()
72 && let Some(module) = module_graph.module_by_identifier(id)
73 {
74 Some(module)
75 } else {
76 None
77 }
78 }
79}
80
81define_hook!(NormalModuleReadResource: SeriesBail(resource_data: &ResourceData, fs: &Arc<dyn ReadableFileSystem>) -> Content,tracing=false);
82define_hook!(NormalModuleLoader: Series(loader_context: &mut LoaderContext<RunnerContext>),tracing=false);
83define_hook!(NormalModuleLoaderShouldYield: SeriesBail(loader_context: &LoaderContext<RunnerContext>) -> bool,tracing=false);
84define_hook!(NormalModuleLoaderStartYielding: Series(loader_context: &mut LoaderContext<RunnerContext>),tracing=false);
85define_hook!(NormalModuleBeforeLoaders: Series(module: &mut NormalModule),tracing=false);
86define_hook!(NormalModuleAdditionalData: Series(additional_data: &mut Option<&mut AdditionalData>),tracing=false);
87
88#[derive(Debug, Default)]
89pub struct NormalModuleHooks {
90 pub read_resource: NormalModuleReadResourceHook,
91 pub loader: NormalModuleLoaderHook,
92 pub loader_should_yield: NormalModuleLoaderShouldYieldHook,
93 pub loader_yield: NormalModuleLoaderStartYieldingHook,
94 pub before_loaders: NormalModuleBeforeLoadersHook,
95 pub additional_data: NormalModuleAdditionalDataHook,
96}
97
98#[cacheable]
99#[derive(Debug)]
100pub struct NormalModule {
101 blocks: Vec<AsyncDependenciesBlockIdentifier>,
102 dependencies: Vec<DependencyId>,
103
104 id: ModuleIdentifier,
105 context: Box<Context>,
107 request: String,
109 user_request: String,
111 raw_request: String,
113 module_type: ModuleType,
115 layer: Option<ModuleLayer>,
117 parser_and_generator: Box<dyn ParserAndGenerator>,
119 match_resource: Option<ResourceData>,
121 resource_data: Arc<ResourceData>,
123 #[debug(skip)]
125 loaders: Vec<BoxLoader>,
126
127 #[cacheable(with=AsOption<AsPreset>)]
129 source: Option<BoxSource>,
130
131 resolve_options: Option<Arc<Resolve>>,
133 #[cacheable(with=AsInner)]
135 parser_and_generator_options: Arc<ResolvedModuleOptions>,
136 extract_source_map: Option<bool>,
138
139 #[allow(unused)]
140 debug_id: usize,
141 #[cacheable(with=As<SourceSizeCacheSerde>)]
142 cached_source_sizes: SourceSizeCache,
143 diagnostics: Vec<Diagnostic>,
144
145 code_generation_dependencies: Option<Vec<BoxModuleDependency>>,
146 presentational_dependencies: Option<Vec<BoxDependencyTemplate>>,
147
148 factory_meta: Option<FactoryMeta>,
149 build_info: BuildInfo,
150 build_meta: BuildMeta,
151 parsed: bool,
152
153 source_map_kind: SourceMapKind,
154}
155
156static DEBUG_ID: AtomicUsize = AtomicUsize::new(1);
157
158impl NormalModule {
159 fn create_id<'request>(
160 module_type: &ModuleType,
161 layer: Option<&ModuleLayer>,
162 request: &'request str,
163 phase: ImportPhase,
164 ) -> Cow<'request, str> {
165 if matches!(module_type, ModuleType::WasmAsync) {
166 let mut id = format!("{module_type}|{request}|{}", phase.as_str());
167 if let Some(layer) = layer {
168 id.push('|');
169 id.push_str(layer);
170 }
171 id.into()
172 } else if let Some(layer) = layer {
173 format!("{module_type}|{request}|{layer}").into()
174 } else if *module_type == ModuleType::JsAuto {
175 request.into()
176 } else {
177 format!("{module_type}|{request}").into()
178 }
179 }
180
181 #[allow(clippy::too_many_arguments)]
182 pub fn new(
183 request: String,
184 user_request: String,
185 raw_request: String,
186 module_type: impl Into<ModuleType>,
187 layer: Option<ModuleLayer>,
188 parser_and_generator: Box<dyn ParserAndGenerator>,
189 parser_and_generator_options: Arc<ResolvedModuleOptions>,
190 match_resource: Option<ResourceData>,
191 resource_data: Arc<ResourceData>,
192 resolve_options: Option<Arc<Resolve>>,
193 loaders: Vec<BoxLoader>,
194 context: Option<Context>,
195 extract_source_map: Option<bool>,
196 import_phase: ImportPhase,
197 ) -> Self {
198 let module_type = module_type.into();
199 let id = Self::create_id(&module_type, layer.as_ref(), &request, import_phase);
200 let build_info = BuildInfo {
201 import_phase,
202 ..Default::default()
203 };
204 Self {
205 blocks: Vec::new(),
206 dependencies: Vec::new(),
207 id: ModuleIdentifier::from(id.as_ref()),
208 context: Box::new(context.unwrap_or_else(|| get_context(&resource_data))),
209 request,
210 user_request,
211 raw_request,
212 module_type,
213 layer,
214 parser_and_generator,
215 parser_and_generator_options,
216 match_resource,
217 resource_data,
218 resolve_options,
219 loaders,
220 source: None,
221 debug_id: DEBUG_ID.fetch_add(1, Ordering::Relaxed),
222 extract_source_map,
223
224 cached_source_sizes: SourceSizeCache::default(),
225 diagnostics: Default::default(),
226 code_generation_dependencies: None,
227 presentational_dependencies: None,
228 factory_meta: None,
229 build_info,
230 build_meta: Default::default(),
231 parsed: false,
232 source_map_kind: SourceMapKind::empty(),
233 }
234 }
235
236 pub fn id(&self) -> ModuleIdentifier {
237 self.id
238 }
239
240 pub fn match_resource(&self) -> Option<&ResourceData> {
241 self.match_resource.as_ref()
242 }
243
244 pub fn match_resource_mut(&mut self) -> &mut Option<ResourceData> {
245 &mut self.match_resource
246 }
247
248 pub fn resource_resolved_data(&self) -> &Arc<ResourceData> {
249 &self.resource_data
250 }
251
252 pub fn request(&self) -> &str {
253 &self.request
254 }
255
256 pub fn user_request(&self) -> &str {
257 &self.user_request
258 }
259
260 pub fn user_request_mut(&mut self) -> &mut String {
261 &mut self.user_request
262 }
263
264 pub fn raw_request(&self) -> &str {
265 &self.raw_request
266 }
267
268 pub fn loaders(&self) -> &[BoxLoader] {
269 &self.loaders
270 }
271
272 pub fn parser_and_generator(&self) -> &dyn ParserAndGenerator {
273 &*self.parser_and_generator
274 }
275
276 pub fn parser_and_generator_mut(&mut self) -> &mut dyn ParserAndGenerator {
277 &mut *self.parser_and_generator
278 }
279
280 pub fn code_generation_dependencies(&self) -> &Option<Vec<BoxModuleDependency>> {
281 &self.code_generation_dependencies
282 }
283
284 pub fn presentational_dependencies(&self) -> &Option<Vec<BoxDependencyTemplate>> {
285 &self.presentational_dependencies
286 }
287
288 #[tracing::instrument(
289 "NormalModule:build_hash", skip_all,fields(
290 resource = self.resource_data.resource()
291 )
292 )]
293 fn init_build_hash(
294 &self,
295 output_options: &OutputOptions,
296 build_meta: &BuildMeta,
297 ) -> RspackHashDigest {
298 let mut hasher = RspackHash::from(output_options);
299 "source".hash(&mut hasher);
300 if let Some(error) = self.first_error() {
301 error.message.hash(&mut hasher);
302 } else if let Some(s) = &self.source {
303 s.hash(&mut hasher);
304 }
305 "meta".hash(&mut hasher);
306 build_meta.hash(&mut hasher);
307 hasher.digest(&output_options.hash_digest)
308 }
309
310 pub fn get_parser_options(&self) -> Option<&ParserOptions> {
311 self.parser_and_generator_options.parser_options()
312 }
313
314 pub fn get_generator_options(&self) -> Option<&GeneratorOptions> {
315 self.parser_and_generator_options.generator_options()
316 }
317}
318
319impl Identifiable for NormalModule {
320 #[inline]
321 fn identifier(&self) -> ModuleIdentifier {
322 self.id
323 }
324}
325
326impl DependenciesBlock for NormalModule {
327 fn add_block_id(&mut self, block: AsyncDependenciesBlockIdentifier) {
328 self.blocks.push(block)
329 }
330
331 fn get_blocks(&self) -> &[AsyncDependenciesBlockIdentifier] {
332 &self.blocks
333 }
334
335 fn add_dependency_id(&mut self, dependency: DependencyId) {
336 self.dependencies.push(dependency)
337 }
338
339 fn remove_dependency_id(&mut self, dependency: DependencyId) {
340 self.dependencies.retain(|d| d != &dependency)
341 }
342
343 fn get_dependencies(&self) -> &[DependencyId] {
344 &self.dependencies
345 }
346}
347
348#[cacheable_dyn]
349#[async_trait::async_trait]
350impl Module for NormalModule {
351 fn module_type(&self) -> &ModuleType {
352 &self.module_type
353 }
354
355 fn source_types(&self, module_graph: &ModuleGraph) -> &[SourceType] {
356 self.parser_and_generator.source_types(self, module_graph)
357 }
358
359 fn source(&self) -> Option<&BoxSource> {
360 self.source.as_ref()
361 }
362
363 fn readable_identifier(&self, context: &Context) -> Cow<'_, str> {
364 Cow::Owned(context.shorten(&self.user_request))
365 }
366
367 fn size(&self, source_type: Option<&SourceType>, _compilation: Option<&Compilation>) -> f64 {
368 if let Some(source_type) = source_type {
369 if let Some(size) = self.cached_source_sizes.get(source_type) {
371 return size;
372 }
373
374 let size = f64::max(1.0, self.parser_and_generator.size(self, Some(source_type)));
375 self.cached_source_sizes.get_or_insert(source_type, size)
376 } else {
377 f64::max(1.0, self.parser_and_generator.size(self, source_type))
378 }
379 }
380
381 #[tracing::instrument("NormalModule:build", skip_all, fields(
382 perfetto.track_name = format!("Module Build"),
383 perfetto.process_name = format!("Rspack Build Detail"),
384 module.resource = self.resource_resolved_data().resource(),
385 module.identifier = self.identifier().as_str(),
386 module.loaders = ?self.loaders.iter().map(|l| l.identifier().as_str()).collect::<Vec<_>>())
387 )]
388 async fn build(
389 mut self: Box<Self>,
390 build_context: BuildContext,
391 _compilation: Option<&Compilation>,
392 ) -> Result<BuildResult> {
393 self.parsed = true;
395
396 let no_parse = if let Some(no_parse) = build_context.compiler_options.module.no_parse.as_ref() {
397 no_parse.try_match(self.request.as_str()).await?
398 } else {
399 false
400 };
401
402 build_context
403 .plugin_driver
404 .normal_module_hooks
405 .before_loaders
406 .call(self.as_mut())
407 .await?;
408
409 let plugin = Arc::new(RspackLoaderRunnerPlugin {
410 plugin_driver: build_context.plugin_driver.clone(),
411 extract_source_map: self.extract_source_map,
412 });
413
414 let compiler_id = build_context.compiler_id;
415 let compilation_id = build_context.compilation_id;
416 let compiler_options = build_context.compiler_options.clone();
417 let resolver_factory = build_context.resolver_factory.clone();
418 let fs = build_context.fs.clone();
419 let (mut loader_result, err) = run_loaders(
420 self.loaders.clone(),
421 self.resource_data.clone(),
422 Some(plugin.clone()),
423 RunnerContext {
424 compiler_id,
425 compilation_id,
426 options: compiler_options,
427 resolver_factory,
428 source_map_kind: self.source_map_kind,
429 module: self,
430 },
431 fs,
432 )
433 .instrument(info_span!("NormalModule:run_loaders",))
434 .await;
435 self = loader_result.context.module;
436
437 if let Some(err) = err {
438 self.build_info.cacheable = loader_result.cacheable;
439 self.build_info.file_dependencies = loader_result
440 .file_dependencies
441 .into_iter()
442 .map(Into::into)
443 .collect();
444 self.build_info.context_dependencies = loader_result
445 .context_dependencies
446 .into_iter()
447 .map(Into::into)
448 .collect();
449 self.build_info.missing_dependencies = loader_result
450 .missing_dependencies
451 .into_iter()
452 .map(Into::into)
453 .collect();
454 self.build_info.build_dependencies = loader_result
455 .build_dependencies
456 .into_iter()
457 .map(Into::into)
458 .collect();
459
460 self.source = None;
461
462 let current_loader = loader_result.current_loader.map(|current_loader| {
463 contextify(
464 build_context.compiler_options.context.as_path(),
465 current_loader.as_str(),
466 )
467 });
468 let diagnostic = Diagnostic::from(rspack_error::Error::from(ModuleBuildError::new(
469 err,
470 current_loader,
471 )));
472 self.diagnostics.push(diagnostic);
473
474 self.build_info.hash =
475 Some(self.init_build_hash(&build_context.compiler_options.output, &self.build_meta));
476 return Ok(BuildResult {
477 module: BoxModule::new(self),
478 dependencies: Vec::new(),
479 blocks: Vec::new(),
480 optimization_bailouts: vec![],
481 });
482 };
483
484 build_context
485 .plugin_driver
486 .normal_module_hooks
487 .additional_data
488 .call(&mut loader_result.additional_data.as_mut())
489 .await?;
490 self.add_diagnostics(loader_result.diagnostics);
491
492 let is_binary = self
493 .get_generator_options()
494 .and_then(|g| match g {
495 GeneratorOptions::Asset(g) => g.binary,
496 GeneratorOptions::AssetInline(g) => g.binary,
497 GeneratorOptions::AssetResource(g) => g.binary,
498 _ => None,
499 })
500 .unwrap_or_else(|| self.module_type.is_binary());
501
502 let content = if is_binary {
503 Content::Buffer(loader_result.content.into_bytes())
504 } else {
505 Content::String(loader_result.content.into_string_lossy())
506 };
507 let source = self.create_source(content, loader_result.source_map)?;
508
509 self.build_info.cacheable = loader_result.cacheable;
510 self.build_info.file_dependencies = loader_result
511 .file_dependencies
512 .into_iter()
513 .map(Into::into)
514 .collect();
515 self.build_info.context_dependencies = loader_result
516 .context_dependencies
517 .into_iter()
518 .map(Into::into)
519 .collect();
520 self.build_info.missing_dependencies = loader_result
521 .missing_dependencies
522 .into_iter()
523 .map(Into::into)
524 .collect();
525 self.build_info.build_dependencies = loader_result
526 .build_dependencies
527 .into_iter()
528 .map(Into::into)
529 .collect();
530
531 if no_parse {
532 self.parsed = false;
533 self.source = Some(source);
534 self.code_generation_dependencies = Some(Vec::new());
535 self.presentational_dependencies = Some(Vec::new());
536
537 self.build_info.hash =
538 Some(self.init_build_hash(&build_context.compiler_options.output, &self.build_meta));
539
540 return Ok(BuildResult {
541 module: BoxModule::new(self),
542 dependencies: vec![],
543 blocks: vec![],
544 optimization_bailouts: vec![],
545 });
546 }
547
548 let (
549 ParseResult {
550 source,
551 dependencies,
552 blocks,
553 presentational_dependencies,
554 code_generation_dependencies,
555 side_effects_bailout,
556 },
557 diagnostics,
558 ) = self
559 .parser_and_generator
560 .parse(ParseContext {
561 source: source.clone(),
562 module_context: &self.context,
563 module_identifier: self.id,
564 module_parser_options: self.parser_and_generator_options.parser_options(),
565 module_generator_options: self.parser_and_generator_options.generator_options(),
566 module_type: &self.module_type,
567 module_layer: self.layer.as_ref(),
568 module_user_request: &self.user_request,
569 module_match_resource: self.match_resource.as_ref(),
570 module_source_map_kind: self.source_map_kind,
571 loaders: &self.loaders,
572 resource_data: &self.resource_data,
573 compiler_options: &build_context.compiler_options,
574 additional_data: loader_result.additional_data,
575 factory_meta: self.factory_meta.as_ref(),
576 build_info: &mut self.build_info,
577 build_meta: &mut self.build_meta,
578 parse_meta: loader_result.parse_meta,
579 runtime_template: &build_context.runtime_template,
580 })
581 .await?
582 .split_into_parts();
583 if diagnostics.iter().any(|d| d.is_error()) {
584 self.build_meta = Default::default();
585 }
586 if !diagnostics.is_empty() {
587 self.add_diagnostics(diagnostics);
588 }
589 let optimization_bailouts = if let Some(side_effects_bailout) = side_effects_bailout {
590 let short_id = self.readable_identifier(&build_context.compiler_options.context);
591 vec![OptimizationBailoutItem::SideEffects {
592 node_type: side_effects_bailout.ty,
593 loc: side_effects_bailout.msg,
594 short_id: short_id.to_string(),
595 }]
596 } else {
597 vec![]
598 };
599 self.source = Some(source);
602 self.code_generation_dependencies = Some(code_generation_dependencies);
603 self.presentational_dependencies = Some(presentational_dependencies);
604
605 self.build_info.hash =
606 Some(self.init_build_hash(&build_context.compiler_options.output, &self.build_meta));
607
608 Ok(BuildResult {
609 module: BoxModule::new(self),
610 dependencies,
611 blocks,
612 optimization_bailouts,
613 })
614 }
615
616 async fn code_generation(
618 &self,
619 code_generation_context: &mut ModuleCodeGenerationContext,
620 ) -> Result<CodeGenerationResult> {
621 let ModuleCodeGenerationContext {
622 compilation,
623 runtime,
624 concatenation_scope,
625 runtime_template,
626 } = code_generation_context;
627
628 if let Some(error) = self.first_error() {
629 let mut code_generation_result = CodeGenerationResult::default();
630 let module_graph = compilation.get_module_graph();
631
632 if self
635 .source_types(module_graph)
636 .contains(&SourceType::JavaScript)
637 {
638 let error = error.render_report(compilation.options.stats.colors)?;
639 code_generation_result.add(
640 SourceType::JavaScript,
641 RawStringSource::from(format!("throw new Error({});\n", json!(error))).boxed(),
642 );
643 code_generation_result.concatenation_scope = std::mem::take(concatenation_scope);
644 }
645 return Ok(code_generation_result);
646 }
647 let Some(source) = &self.source else {
648 return Err(error!(
649 "Failed to generate code because ast or source is not set for module {}",
650 self.request
651 ));
652 };
653
654 let mut code_generation_result = CodeGenerationResult::default();
655 if !self.parsed {
656 runtime_template
657 .runtime_requirements_mut()
658 .insert(RuntimeGlobals::MODULE | RuntimeGlobals::EXPORTS | RuntimeGlobals::THIS_AS_EXPORTS);
659 }
660
661 let module_graph = compilation.get_module_graph();
662 for source_type in self.source_types(module_graph) {
663 let generation_result = self
664 .parser_and_generator
665 .generate(
666 source,
667 self,
668 &mut GenerateContext {
669 compilation,
670 runtime_template,
671 data: &mut code_generation_result.data,
672 requested_source_type: *source_type,
673 module_parser_options: self.parser_and_generator_options.parser_options(),
674 module_generator_options: self.parser_and_generator_options.generator_options(),
675 runtime: *runtime,
676 concatenation_scope: concatenation_scope.as_mut(),
677 },
678 )
679 .await?;
680 code_generation_result.add(*source_type, CachedSource::new(generation_result).boxed());
681 }
682 code_generation_result.concatenation_scope = std::mem::take(concatenation_scope);
683 Ok(code_generation_result)
684 }
685
686 async fn get_runtime_hash(
687 &self,
688 compilation: &Compilation,
689 runtime: Option<&RuntimeSpec>,
690 ) -> Result<RspackHashDigest> {
691 let mut hasher = RspackHash::from(&compilation.options.output);
692 self.build_info.hash.dyn_hash(&mut hasher);
693 if self.source.is_some() {
695 self
696 .parser_and_generator
697 .get_runtime_hash(self, compilation, runtime)
698 .await?
699 .dyn_hash(&mut hasher);
700 }
701 module_update_hash(self, &mut hasher, compilation, runtime);
702 Ok(hasher.digest(&compilation.options.output.hash_digest))
703 }
704
705 fn name_for_condition(&self) -> Option<Box<str>> {
706 let resource = self
708 .match_resource()
709 .unwrap_or_else(|| &self.resource_data)
710 .resource();
711 let idx = resource.find('?');
712 if let Some(idx) = idx {
713 Some(resource[..idx].into())
714 } else {
715 Some(resource.into())
716 }
717 }
718
719 fn lib_ident(&self, options: LibIdentOptions) -> Option<Cow<'_, str>> {
720 let mut ident = String::new();
721 if let Some(layer) = &self.layer {
722 ident += "(";
723 ident += layer;
724 ident += ")/";
725 }
726 ident += &contextify(options.context, self.user_request());
727 Some(Cow::Owned(ident))
728 }
729
730 fn get_resolve_options(&self) -> Option<Arc<Resolve>> {
731 self.resolve_options.clone()
732 }
733
734 fn get_code_generation_dependencies(&self) -> Option<&[BoxModuleDependency]> {
735 if let Some(deps) = self.code_generation_dependencies.as_deref()
736 && !deps.is_empty()
737 {
738 Some(deps)
739 } else {
740 None
741 }
742 }
743
744 fn get_presentational_dependencies(&self) -> Option<&[BoxDependencyTemplate]> {
745 if let Some(deps) = self.presentational_dependencies.as_deref()
746 && !deps.is_empty()
747 {
748 Some(deps)
749 } else {
750 None
751 }
752 }
753
754 fn get_context(&self) -> Option<Box<Context>> {
755 Some(self.context.clone())
756 }
757
758 fn get_layer(&self) -> Option<&ModuleLayer> {
759 self.layer.as_ref()
760 }
761
762 fn get_side_effects_connection_state(
764 &self,
765 module_graph: &ModuleGraph,
766 module_graph_cache: &ModuleGraphCacheArtifact,
767 side_effects_state_artifact: &SideEffectsStateArtifact,
768 module_chain: &mut IdentifierSet,
769 connection_state_cache: &mut IdentifierMap<ConnectionState>,
770 ) -> ConnectionState {
771 module_graph_cache.cached_get_side_effects_connection_state(self.id(), || {
772 if let Some(state) = connection_state_cache.get(&self.id) {
773 return *state;
774 }
775
776 if let Some(side_effect_free) = module_declared_side_effect_free(self) {
777 return ConnectionState::Active(!side_effect_free);
778 }
779
780 if module_analyzed_side_effect_free(self, side_effects_state_artifact) == Some(true) {
781 if module_chain.contains(&self.identifier()) {
783 return ConnectionState::CircularConnection;
784 }
785 module_chain.insert(self.identifier());
786 let mut current = ConnectionState::Active(false);
787 for dependency_id in self.get_dependencies().iter() {
788 let dependency = module_graph.dependency_by_id(dependency_id);
789 let state = dependency.get_module_evaluation_side_effects_state(
790 module_graph,
791 module_graph_cache,
792 side_effects_state_artifact,
793 module_chain,
794 connection_state_cache,
795 );
796 if matches!(state, ConnectionState::Active(true)) {
797 module_chain.remove(&self.identifier());
799 connection_state_cache.insert(self.id, ConnectionState::Active(true));
800 return ConnectionState::Active(true);
801 } else if !matches!(state, ConnectionState::CircularConnection) {
802 current = current + state;
803 }
804 }
805 module_chain.remove(&self.identifier());
806 connection_state_cache.insert(self.id, current);
807 return current;
808 }
809 ConnectionState::Active(true)
810 })
811 }
812
813 fn get_concatenation_bailout_reason(
814 &self,
815 mg: &ModuleGraph,
816 cg: &ChunkGraph,
817 ) -> Option<Cow<'static, str>> {
818 self
819 .parser_and_generator
820 .get_concatenation_bailout_reason(self, mg, cg)
821 }
822
823 fn factory_meta(&self) -> Option<&FactoryMeta> {
824 self.factory_meta.as_ref()
825 }
826
827 fn set_factory_meta(&mut self, factory_meta: FactoryMeta) {
828 self.factory_meta = Some(factory_meta);
829 }
830
831 fn build_info(&self) -> &BuildInfo {
832 &self.build_info
833 }
834
835 fn build_info_mut(&mut self) -> &mut BuildInfo {
836 &mut self.build_info
837 }
838
839 fn build_meta(&self) -> &BuildMeta {
840 &self.build_meta
841 }
842
843 fn build_meta_mut(&mut self) -> &mut BuildMeta {
844 &mut self.build_meta
845 }
846}
847
848impl ModuleSourceMapConfig for NormalModule {
849 fn get_source_map_kind(&self) -> &SourceMapKind {
850 &self.source_map_kind
851 }
852
853 fn set_source_map_kind(&mut self, source_map_kind: SourceMapKind) {
854 self.source_map_kind = source_map_kind;
855 }
856}
857
858impl Diagnosable for NormalModule {
859 fn add_diagnostic(&mut self, diagnostic: Diagnostic) {
860 self.diagnostics.push(diagnostic);
861 }
862
863 fn add_diagnostics(&mut self, mut diagnostics: Vec<Diagnostic>) {
864 self.diagnostics.append(&mut diagnostics);
865 }
866
867 fn diagnostics(&self) -> Cow<'_, [Diagnostic]> {
868 Cow::Borrowed(&self.diagnostics)
869 }
870}
871
872impl NormalModule {
873 fn create_source(&self, content: Content, source_map: Option<SourceMap>) -> Result<BoxSource> {
874 if content.is_buffer() {
875 return Ok(RawBufferSource::from(content.into_bytes()).boxed());
876 }
877 let source_map_kind = self.get_source_map_kind();
878 if source_map_kind.enabled()
879 && let Some(source_map) = source_map
880 {
881 let content = content.into_string_lossy();
882 return Ok(
883 SourceMapSource::new(WithoutOriginalOptions {
884 value: content,
885 name: self.request(),
886 source_map,
887 })
888 .boxed(),
889 );
890 }
891 if source_map_kind.enabled()
892 && let Content::String(content) = content
893 {
894 return Ok(OriginalSource::new(content, self.request()).boxed());
895 }
896 Ok(RawStringSource::from(content.into_string_lossy()).boxed())
897 }
898}