Skip to main content

turbopack_core/chunk/
evaluate.rs

1use anyhow::Result;
2use turbo_tasks::{ResolvedVc, Upcast, Vc, turbobail};
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) =
47        ResolvedVc::try_downcast::<Box<dyn EvaluatableAsset>>(module.to_resolved().await?)
48    else {
49        turbobail!("{} is not a valid evaluated entry", module.ident());
50    };
51    Ok(*entry)
52}
53
54#[turbo_tasks::value(transparent)]
55pub struct EvaluatableAssets(Vec<ResolvedVc<Box<dyn EvaluatableAsset>>>);
56
57#[turbo_tasks::value_impl]
58impl EvaluatableAssets {
59    #[turbo_tasks::function]
60    pub fn empty() -> Vc<EvaluatableAssets> {
61        EvaluatableAssets(vec![]).cell()
62    }
63
64    #[turbo_tasks::function]
65    pub fn one(entry: ResolvedVc<Box<dyn EvaluatableAsset>>) -> Vc<EvaluatableAssets> {
66        EvaluatableAssets(vec![entry]).cell()
67    }
68
69    #[turbo_tasks::function]
70    pub fn many(assets: Vec<ResolvedVc<Box<dyn EvaluatableAsset>>>) -> Vc<EvaluatableAssets> {
71        EvaluatableAssets(assets).cell()
72    }
73
74    #[turbo_tasks::function]
75    pub async fn with_entry(
76        self: Vc<Self>,
77        entry: ResolvedVc<Box<dyn EvaluatableAsset>>,
78    ) -> Result<Vc<EvaluatableAssets>> {
79        let mut entries = self.owned().await?;
80        entries.push(entry);
81        Ok(EvaluatableAssets(entries).cell())
82    }
83}