turbopack_core/chunk/
evaluate.rs

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