Skip to main content

rspack_core/
runtime_module.rs

1use std::fmt::Debug;
2
3use async_trait::async_trait;
4use rspack_cacheable::cacheable;
5use rspack_collections::Identifier;
6
7use crate::{ChunkUkey, Compilation, Module, RuntimeCodeTemplate, RuntimeGlobals};
8
9pub struct RuntimeModuleGenerateContext<'a> {
10  pub compilation: &'a Compilation,
11  pub runtime_template: &'a RuntimeCodeTemplate<'a>,
12}
13
14#[async_trait]
15pub trait RuntimeModule:
16  Module + CustomSourceRuntimeModule + AttachableRuntimeModule + NamedRuntimeModule
17{
18  fn stage(&self) -> RuntimeModuleStage {
19    RuntimeModuleStage::Normal
20  }
21  fn full_hash(&self) -> bool {
22    false
23  }
24  fn dependent_hash(&self) -> bool {
25    false
26  }
27  // if wrap iife
28  fn should_isolate(&self) -> bool {
29    true
30  }
31  fn template(&self) -> Vec<(String, String)> {
32    vec![]
33  }
34  async fn generate(
35    &self,
36    context: &RuntimeModuleGenerateContext<'_>,
37  ) -> rspack_error::Result<String>;
38  async fn generate_with_custom(&self, compilation: &Compilation) -> rspack_error::Result<String> {
39    if let Some(custom_source) = self.get_custom_source() {
40      Ok(custom_source)
41    } else {
42      let runtime_template = compilation.runtime_template.create_runtime_code_template();
43      let context = RuntimeModuleGenerateContext {
44        compilation,
45        runtime_template: &runtime_template,
46      };
47      self.generate(&context).await
48    }
49  }
50  fn additional_runtime_requirements(&self, _compilation: &Compilation) -> RuntimeGlobals {
51    RuntimeGlobals::default()
52  }
53}
54
55#[async_trait]
56pub trait AttachableRuntimeModule {
57  fn attach(&mut self, chunk: ChunkUkey);
58}
59
60#[async_trait]
61pub trait NamedRuntimeModule {
62  fn name(&self) -> Identifier;
63}
64
65#[async_trait]
66pub trait CustomSourceRuntimeModule {
67  fn set_custom_source(&mut self, source: String);
68  fn get_custom_source(&self) -> Option<String>;
69  fn get_constructor_name(&self) -> String;
70}
71
72pub type BoxRuntimeModule = Box<dyn RuntimeModule>;
73
74#[cacheable]
75#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
76pub enum RuntimeModuleStage {
77  #[default]
78  Normal, // Runtime modules without any dependencies to other runtime modules
79  Basic,   // Runtime modules with simple dependencies on other runtime modules
80  Attach,  // Runtime modules which attach to handlers of other runtime modules
81  Trigger, // Runtime modules which trigger actions on bootstrap
82}
83
84impl From<u32> for RuntimeModuleStage {
85  fn from(stage: u32) -> Self {
86    match stage {
87      0 => RuntimeModuleStage::Normal,
88      5 => RuntimeModuleStage::Basic,
89      10 => RuntimeModuleStage::Attach,
90      20 => RuntimeModuleStage::Trigger,
91      _ => RuntimeModuleStage::Normal,
92    }
93  }
94}
95
96impl From<RuntimeModuleStage> for u32 {
97  fn from(value: RuntimeModuleStage) -> Self {
98    match value {
99      RuntimeModuleStage::Normal => 0,
100      RuntimeModuleStage::Basic => 5,
101      RuntimeModuleStage::Attach => 10,
102      RuntimeModuleStage::Trigger => 20,
103    }
104  }
105}
106
107pub trait RuntimeModuleExt {
108  fn boxed(self) -> Box<dyn RuntimeModule>;
109}
110
111impl<T: RuntimeModule + 'static> RuntimeModuleExt for T {
112  fn boxed(self) -> Box<dyn RuntimeModule> {
113    Box::new(self)
114  }
115}