next.js/turbopack/crates/turbopack-core/src/chunk/evaluate.rs
evaluate.rs84 lines2.4 KB
use anyhow::Result;
use turbo_tasks::{ResolvedVc, Upcast, Vc, turbobail};

use super::ChunkableModule;
use crate::{
    context::AssetContext,
    module::Module,
    reference_type::{EntryReferenceSubType, ReferenceType},
    source::Source,
};

/// Marker trait for the chunking context to accept evaluated entries.
///
/// The chunking context implementation will resolve the dynamic entry to a
/// well-known value or trait object.
#[turbo_tasks::value_trait]
pub trait EvaluatableAsset: Module + ChunkableModule {}

pub trait EvaluatableAssetExt {
    fn to_evaluatable(
        self: Vc<Self>,
        asset_context: Vc<Box<dyn AssetContext>>,
    ) -> Vc<Box<dyn EvaluatableAsset>>;
}

impl<T> EvaluatableAssetExt for T
where
    T: Upcast<Box<dyn Source>>,
{
    fn to_evaluatable(
        self: Vc<Self>,
        asset_context: Vc<Box<dyn AssetContext>>,
    ) -> Vc<Box<dyn EvaluatableAsset>> {
        to_evaluatable(Vc::upcast_non_strict(self), asset_context)
    }
}

#[turbo_tasks::function]
async fn to_evaluatable(
    asset: Vc<Box<dyn Source>>,
    asset_context: Vc<Box<dyn AssetContext>>,
) -> Result<Vc<Box<dyn EvaluatableAsset>>> {
    let module = asset_context
        .process(asset, ReferenceType::Entry(EntryReferenceSubType::Runtime))
        .module();
    let Some(entry) =
        ResolvedVc::try_downcast::<Box<dyn EvaluatableAsset>>(module.to_resolved().await?)
    else {
        turbobail!("{} is not a valid evaluated entry", module.ident());
    };
    Ok(*entry)
}

#[turbo_tasks::value(transparent)]
pub struct EvaluatableAssets(Vec<ResolvedVc<Box<dyn EvaluatableAsset>>>);

#[turbo_tasks::value_impl]
impl EvaluatableAssets {
    #[turbo_tasks::function]
    pub fn empty() -> Vc<EvaluatableAssets> {
        EvaluatableAssets(vec![]).cell()
    }

    #[turbo_tasks::function]
    pub fn one(entry: ResolvedVc<Box<dyn EvaluatableAsset>>) -> Vc<EvaluatableAssets> {
        EvaluatableAssets(vec![entry]).cell()
    }

    #[turbo_tasks::function]
    pub fn many(assets: Vec<ResolvedVc<Box<dyn EvaluatableAsset>>>) -> Vc<EvaluatableAssets> {
        EvaluatableAssets(assets).cell()
    }

    #[turbo_tasks::function]
    pub async fn with_entry(
        self: Vc<Self>,
        entry: ResolvedVc<Box<dyn EvaluatableAsset>>,
    ) -> Result<Vc<EvaluatableAssets>> {
        let mut entries = self.owned().await?;
        entries.push(entry);
        Ok(EvaluatableAssets(entries).cell())
    }
}
Quest for Codev2.0.0
/
SIGN IN