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