rspack_core/loader/
rspack_loader.rs1use std::sync::Arc;
2
3use rspack_error::{Diagnostic, Result};
4use rspack_fs::ReadableFileSystem;
5use rspack_loader_runner::{Content, LoaderContext, LoaderRunnerPlugin, ResourceData};
6use rspack_sources::SourceMap;
7use rustc_hash::FxHashSet as HashSet;
8
9use crate::{RunnerContext, SharedPluginDriver, utils::extract_source_map};
10
11pub struct RspackLoaderRunnerPlugin {
12 pub plugin_driver: SharedPluginDriver,
13 pub extract_source_map: Option<bool>,
14}
15
16#[async_trait::async_trait]
17impl LoaderRunnerPlugin for RspackLoaderRunnerPlugin {
18 type Context = RunnerContext;
19
20 fn name(&self) -> &'static str {
21 "rspack-loader-runner"
22 }
23
24 async fn before_all(&self, context: &mut LoaderContext<Self::Context>) -> Result<()> {
25 self
26 .plugin_driver
27 .normal_module_hooks
28 .loader
29 .call(context)
30 .await
31 }
32
33 async fn process_resource(
34 &self,
35 resource_data: &ResourceData,
36 fs: Arc<dyn ReadableFileSystem>,
37 ) -> Result<Option<(Content, Option<SourceMap>, HashSet<std::path::PathBuf>)>> {
38 let result = self
40 .plugin_driver
41 .normal_module_hooks
42 .read_resource
43 .call(resource_data, &fs)
44 .await?;
45
46 if let Some(content) = result {
47 if let Some(true) = self.extract_source_map {
48 let extract_result = match &content {
50 Content::String(s) => extract_source_map(fs, s, resource_data.resource()).await,
51 Content::Buffer(b) => {
52 extract_source_map(fs, &String::from_utf8_lossy(b), resource_data.resource()).await
53 }
54 };
55
56 match extract_result {
57 Ok(extract_result) => {
58 let file_deps = extract_result
60 .file_dependencies
61 .map(|deps| deps.into_iter().collect::<HashSet<_>>())
62 .unwrap_or_default();
63
64 return Ok(Some((
66 Content::String(extract_result.source),
67 extract_result.source_map,
68 file_deps,
69 )));
70 }
71 Err(e) => {
72 self
75 .plugin_driver
76 .diagnostics
77 .lock()
78 .expect("should get lock")
79 .push(Diagnostic::warn("extractSourceMap".into(), e));
80 return Ok(Some((content, None, HashSet::default())));
81 }
82 }
83 }
84 return Ok(Some((content, None, HashSet::default())));
86 }
87
88 Ok(None)
90 }
91
92 async fn should_yield(&self, context: &LoaderContext<Self::Context>) -> Result<bool> {
93 let res = self
94 .plugin_driver
95 .normal_module_hooks
96 .loader_should_yield
97 .call(context)
98 .await?;
99
100 if let Some(res) = res {
101 return Ok(res);
102 }
103
104 Ok(false)
105 }
106
107 async fn start_yielding(&self, context: &mut LoaderContext<Self::Context>) -> Result<()> {
108 self
109 .plugin_driver
110 .normal_module_hooks
111 .loader_yield
112 .call(context)
113 .await
114 }
115}