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 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}