Skip to main content

turbopack_core/reference/
source_map.rs

1use 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}