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