Skip to main content

turbopack_core/
rebase.rs

1use std::hash::Hash;
2
3use anyhow::Result;
4use turbo_tasks::{ResolvedVc, TryJoinIterExt, Vc, turbobail};
5use turbo_tasks_fs::FileSystemPath;
6
7use crate::{
8    asset::{Asset, AssetContent},
9    module::Module,
10    output::{OutputAsset, OutputAssetsReference, OutputAssetsWithReferenced},
11    reference::referenced_modules_and_affecting_sources,
12};
13
14/// Converts a [Module] graph into an [OutputAsset] graph by placing it into a
15/// different directory.
16#[turbo_tasks::value]
17#[derive(Hash)]
18pub struct RebasedAsset {
19    module: ResolvedVc<Box<dyn Module>>,
20    input_dir: FileSystemPath,
21    output_dir: FileSystemPath,
22}
23
24#[turbo_tasks::value_impl]
25impl RebasedAsset {
26    #[turbo_tasks::function]
27    pub fn new(
28        module: ResolvedVc<Box<dyn Module>>,
29        input_dir: FileSystemPath,
30        output_dir: FileSystemPath,
31    ) -> Vc<Self> {
32        Self::cell(RebasedAsset {
33            module,
34            input_dir,
35            output_dir,
36        })
37    }
38}
39
40#[turbo_tasks::value_impl]
41impl OutputAssetsReference for RebasedAsset {
42    #[turbo_tasks::function]
43    async fn references(&self) -> Result<Vc<OutputAssetsWithReferenced>> {
44        let references = referenced_modules_and_affecting_sources(*self.module, false)
45            .await?
46            .iter()
47            .flat_map(|(_, ref_data)| ref_data.modules.iter())
48            .map(async |module| {
49                Ok(ResolvedVc::upcast(
50                    RebasedAsset::new(**module, self.input_dir.clone(), self.output_dir.clone())
51                        .to_resolved()
52                        .await?,
53                ))
54            })
55            .try_join()
56            .await?;
57        Ok(OutputAssetsWithReferenced::from_assets(Vc::cell(
58            references,
59        )))
60    }
61}
62
63#[turbo_tasks::value_impl]
64impl OutputAsset for RebasedAsset {
65    #[turbo_tasks::function]
66    async fn path(&self) -> Result<Vc<FileSystemPath>> {
67        Ok(FileSystemPath::rebase(
68            self.module.ident().await?.path.clone(),
69            self.input_dir.clone(),
70            self.output_dir.clone(),
71        ))
72    }
73}
74
75#[turbo_tasks::value_impl]
76impl Asset for RebasedAsset {
77    #[turbo_tasks::function]
78    async fn content(&self) -> Result<Vc<AssetContent>> {
79        if let Some(source) = *self.module.source().await? {
80            Ok(source.content())
81        } else {
82            turbobail!("Module {} has no source", self.module.ident());
83        }
84    }
85}