next_core/next_client/
runtime_entry.rs

1use anyhow::{Result, bail};
2use turbo_tasks::{ResolvedVc, ValueToString, Vc};
3use turbo_tasks_fs::FileSystemPath;
4use turbopack_core::{
5    chunk::{EvaluatableAsset, EvaluatableAssetExt, EvaluatableAssets},
6    context::AssetContext,
7    module::Module,
8    reference_type::CommonJsReferenceSubType,
9    resolve::{origin::PlainResolveOrigin, parse::Request},
10    source::Source,
11};
12use turbopack_ecmascript::resolve::cjs_resolve;
13
14#[turbo_tasks::value(shared)]
15pub enum RuntimeEntry {
16    Request(ResolvedVc<Request>, FileSystemPath),
17    Evaluatable(ResolvedVc<Box<dyn EvaluatableAsset>>),
18    Source(ResolvedVc<Box<dyn Source>>),
19}
20
21#[turbo_tasks::value_impl]
22impl RuntimeEntry {
23    #[turbo_tasks::function]
24    pub async fn resolve_entry(
25        self: Vc<Self>,
26        asset_context: Vc<Box<dyn AssetContext>>,
27    ) -> Result<Vc<EvaluatableAssets>> {
28        let (request, path) = match &*self.await? {
29            RuntimeEntry::Evaluatable(e) => return Ok(EvaluatableAssets::one(**e)),
30            RuntimeEntry::Source(source) => {
31                return Ok(EvaluatableAssets::one(source.to_evaluatable(asset_context)));
32            }
33            RuntimeEntry::Request(r, path) => (*r, path.clone()),
34        };
35
36        let modules = cjs_resolve(
37            Vc::upcast(PlainResolveOrigin::new(asset_context, path.clone())),
38            *request,
39            CommonJsReferenceSubType::Undefined,
40            None,
41            false,
42        )
43        .resolve()
44        .await?
45        .primary_modules()
46        .await?;
47
48        let mut runtime_entries = Vec::with_capacity(modules.len());
49        for &module in &modules {
50            if let Some(entry) = ResolvedVc::try_downcast::<Box<dyn EvaluatableAsset>>(module) {
51                runtime_entries.push(entry);
52            } else {
53                bail!(
54                    "runtime reference resolved to an asset ({}) that cannot be evaluated",
55                    module.ident().to_string().await?
56                );
57            }
58        }
59
60        Ok(Vc::cell(runtime_entries))
61    }
62}
63
64#[turbo_tasks::value(transparent)]
65pub struct RuntimeEntries(Vec<ResolvedVc<RuntimeEntry>>);
66
67#[turbo_tasks::value_impl]
68impl RuntimeEntries {
69    #[turbo_tasks::function]
70    pub async fn resolve_entries(
71        &self,
72        asset_context: Vc<Box<dyn AssetContext>>,
73    ) -> Result<Vc<EvaluatableAssets>> {
74        let mut runtime_entries = Vec::new();
75
76        for reference in &self.0 {
77            let resolved_entries = reference.resolve_entry(asset_context).await?;
78            runtime_entries.extend(&resolved_entries);
79        }
80
81        Ok(Vc::cell(runtime_entries))
82    }
83}