turbopack_core/reference/
source_map.rs

1use anyhow::Result;
2use turbo_rcstr::RcStr;
3use turbo_tasks::{ResolvedVc, ValueToString, Vc};
4use turbo_tasks_fs::{File, FileContent, FileSystemEntryType, FileSystemPath};
5
6use super::ModuleReference;
7use crate::{
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]
15pub struct SourceMapReference {
16    from: FileSystemPath,
17    file: FileSystemPath,
18}
19
20#[turbo_tasks::value_impl]
21impl SourceMapReference {
22    #[turbo_tasks::function]
23    pub fn new(from: FileSystemPath, file: FileSystemPath) -> Vc<Self> {
24        Self::cell(SourceMapReference { from, file })
25    }
26}
27
28impl SourceMapReference {
29    async fn get_file(&self) -> Option<FileSystemPath> {
30        let file_type = self.file.get_type().await;
31        if let Ok(file_type_result) = file_type.as_ref()
32            && let FileSystemEntryType::File = &**file_type_result
33        {
34            return Some(self.file.clone());
35        }
36        None
37    }
38}
39
40#[turbo_tasks::value_impl]
41impl ModuleReference for SourceMapReference {
42    #[turbo_tasks::function]
43    async fn resolve_reference(&self) -> Result<Vc<ModuleResolveResult>> {
44        if let Some(file) = self.get_file().await {
45            return Ok(*ModuleResolveResult::module(ResolvedVc::upcast(
46                RawModule::new(Vc::upcast(FileSource::new(file)))
47                    .to_resolved()
48                    .await?,
49            )));
50        }
51        Ok(*ModuleResolveResult::unresolvable())
52    }
53}
54
55#[turbo_tasks::value_impl]
56impl GenerateSourceMap for SourceMapReference {
57    #[turbo_tasks::function]
58    async fn generate_source_map(&self) -> Result<Vc<FileContent>> {
59        let Some(file) = self.get_file().await else {
60            return Ok(FileContent::NotFound.cell());
61        };
62
63        let content = file.read().await?;
64        let content = content.as_content().map(|file| file.content());
65        if let Some(source_map) = resolve_source_map_sources(content, &self.from).await? {
66            Ok(FileContent::Content(File::from(source_map)).cell())
67        } else {
68            Ok(FileContent::NotFound.cell())
69        }
70    }
71}
72
73#[turbo_tasks::value_impl]
74impl ValueToString for SourceMapReference {
75    #[turbo_tasks::function]
76    async fn to_string(&self) -> Result<Vc<RcStr>> {
77        Ok(Vc::cell(
78            format!(
79                "source map file is referenced by {}",
80                self.from.value_to_string().await?
81            )
82            .into(),
83        ))
84    }
85}