next_core/next_client/
runtime_entry.rs1use 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}