turbopack_core/chunk/
evaluate.rs

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