turbopack_core/reference/
source_map.rs1use anyhow::Result;
2use turbo_tasks::{ResolvedVc, ValueToString, Vc};
3use turbo_tasks_fs::{File, FileContent, FileSystemEntryType, FileSystemPath};
4
5use super::ModuleReference;
6use crate::{
7 chunk::{ChunkingType, TracedMode},
8 file_source::FileSource,
9 raw_module::RawModule,
10 resolve::ModuleResolveResult,
11 source_map::{GenerateSourceMap, utils::resolve_source_map_sources},
12};
13
14#[turbo_tasks::value]
15#[derive(ValueToString)]
16#[value_to_string("source map file is referenced by {from}")]
17pub struct SourceMapReference {
18 from: FileSystemPath,
19 file: FileSystemPath,
20}
21
22#[turbo_tasks::value_impl]
23impl SourceMapReference {
24 #[turbo_tasks::function]
25 pub fn new(from: FileSystemPath, file: FileSystemPath) -> Vc<Self> {
26 Self::cell(SourceMapReference { from, file })
27 }
28}
29
30impl SourceMapReference {
31 async fn get_file(&self) -> Option<FileSystemPath> {
32 let file_type = self.file.get_type().await;
33 if let Ok(file_type_result) = file_type.as_ref()
34 && let FileSystemEntryType::File = &**file_type_result
35 {
36 return Some(self.file.clone());
37 }
38 None
39 }
40}
41
42#[turbo_tasks::value_impl]
43impl ModuleReference for SourceMapReference {
44 #[turbo_tasks::function]
45 async fn resolve_reference(&self) -> Result<Vc<ModuleResolveResult>> {
46 if let Some(file) = self.get_file().await {
47 return Ok(*ModuleResolveResult::module(ResolvedVc::upcast(
48 RawModule::new(Vc::upcast(FileSource::new(file)))
49 .to_resolved()
50 .await?,
51 )));
52 }
53 Ok(*ModuleResolveResult::unresolvable())
54 }
55
56 fn chunking_type(&self) -> Option<ChunkingType> {
57 Some(ChunkingType::Traced {
58 mode: TracedMode::Transitive,
59 })
60 }
61}
62
63#[turbo_tasks::value_impl]
64impl GenerateSourceMap for SourceMapReference {
65 #[turbo_tasks::function]
66 async fn generate_source_map(&self) -> Result<Vc<FileContent>> {
67 let Some(file) = self.get_file().await else {
68 return Ok(FileContent::NotFound.cell());
69 };
70
71 let content = file.read().await?;
72 let content = content.as_content().map(|file| file.content());
73 if let Some(source_map) = resolve_source_map_sources(content, &self.from).await? {
74 Ok(FileContent::Content(File::from(source_map)).cell())
75 } else {
76 Ok(FileContent::NotFound.cell())
77 }
78 }
79}