turbopack_core/chunk/
evaluate.rs

1use anyhow::{Result, bail};
2use turbo_tasks::{ResolvedVc, Upcast, ValueToString, Vc};
3
4use super::ChunkableModule;
5use crate::{
6    context::AssetContext,
7    module::Module,
8    reference_type::{EntryReferenceSubType, ReferenceType},
9    source::Source,
10};
11
12/// Marker trait for the chunking context to accept evaluated entries.
13///
14/// The chunking context implementation will resolve the dynamic entry to a
15/// well-known value or trait object.
16#[turbo_tasks::value_trait]
17pub trait EvaluatableAsset: Module + ChunkableModule {}
18
19pub trait EvaluatableAssetExt {
20    fn to_evaluatable(
21        self: Vc<Self>,
22        asset_context: Vc<Box<dyn AssetContext>>,
23    ) -> Vc<Box<dyn EvaluatableAsset>>;
24}
25
26impl<T> EvaluatableAssetExt for T
27where
28    T: Upcast<Box<dyn Source>>,
29{
30    fn to_evaluatable(
31        self: Vc<Self>,
32        asset_context: Vc<Box<dyn AssetContext>>,
33    ) -> Vc<Box<dyn EvaluatableAsset>> {
34        to_evaluatable(Vc::upcast_non_strict(self), asset_context)
35    }
36}
37
38#[turbo_tasks::function]
39async fn to_evaluatable(
40    asset: Vc<Box<dyn Source>>,
41    asset_context: Vc<Box<dyn AssetContext>>,
42) -> Result<Vc<Box<dyn EvaluatableAsset>>> {
43    let module = asset_context
44        .process(asset, ReferenceType::Entry(EntryReferenceSubType::Runtime))
45        .module();
46    let Some(entry) = Vc::try_resolve_downcast::<Box<dyn EvaluatableAsset>>(module).await? else {
47        bail!(
48            "{} is not a valid evaluated entry",
49            module.ident().to_string().await?
50        )
51    };
52    Ok(entry)
53}
54
55#[turbo_tasks::value(transparent)]
56pub struct EvaluatableAssets(Vec<ResolvedVc<Box<dyn EvaluatableAsset>>>);
57
58#[turbo_tasks::value_impl]
59impl EvaluatableAssets {
60    #[turbo_tasks::function]
61    pub fn empty() -> Vc<EvaluatableAssets> {
62        EvaluatableAssets(vec![]).cell()
63    }
64
65    #[turbo_tasks::function]
66    pub fn one(entry: ResolvedVc<Box<dyn EvaluatableAsset>>) -> Vc<EvaluatableAssets> {
67        EvaluatableAssets(vec![entry]).cell()
68    }
69
70    #[turbo_tasks::function]
71    pub fn many(assets: Vec<ResolvedVc<Box<dyn EvaluatableAsset>>>) -> Vc<EvaluatableAssets> {
72        EvaluatableAssets(assets).cell()
73    }
74
75    #[turbo_tasks::function]
76    pub async fn with_entry(
77        self: Vc<Self>,
78        entry: ResolvedVc<Box<dyn EvaluatableAsset>>,
79    ) -> Result<Vc<EvaluatableAssets>> {
80        let mut entries = self.owned().await?;
81        entries.push(entry);
82        Ok(EvaluatableAssets(entries).cell())
83    }
84}