turbopack_core/resolve/
origin.rs1use std::future::Future;
2
3use anyhow::Result;
4use turbo_rcstr::RcStr;
5use turbo_tasks::{ResolvedVc, Upcast, Vc};
6use turbo_tasks_fs::FileSystemPath;
7
8use super::{ModuleResolveResult, options::ResolveOptions, parse::Request};
9use crate::{context::AssetContext, module::OptionModule, reference_type::ReferenceType};
10
11#[turbo_tasks::value_trait]
14pub trait ResolveOrigin {
15 #[turbo_tasks::function]
20 fn origin_path(self: Vc<Self>) -> Vc<FileSystemPath>;
21
22 #[turbo_tasks::function]
25 fn asset_context(self: Vc<Self>) -> Vc<Box<dyn AssetContext>>;
26
27 #[turbo_tasks::function]
30 fn get_inner_asset(self: Vc<Self>, request: Vc<Request>) -> Vc<OptionModule> {
31 let _ = request;
32 Vc::cell(None)
33 }
34
35 #[turbo_tasks::function]
37 async fn resolve_options(self: Vc<Self>) -> Result<Vc<ResolveOptions>> {
38 Ok(self
39 .asset_context()
40 .resolve_options(self.origin_path().owned().await?))
41 }
42}
43
44pub trait ResolveOriginExt: Send {
48 fn resolve_asset(
51 self: Vc<Self>,
52 request: Vc<Request>,
53 options: Vc<ResolveOptions>,
54 reference_type: ReferenceType,
55 ) -> impl Future<Output = Result<Vc<ModuleResolveResult>>> + Send;
56
57 fn with_transition(self: ResolvedVc<Self>, transition: RcStr) -> Vc<Box<dyn ResolveOrigin>>;
59}
60
61impl<T> ResolveOriginExt for T
62where
63 T: ResolveOrigin + Upcast<Box<dyn ResolveOrigin>>,
64{
65 fn resolve_asset(
66 self: Vc<Self>,
67 request: Vc<Request>,
68 options: Vc<ResolveOptions>,
69 reference_type: ReferenceType,
70 ) -> impl Future<Output = Result<Vc<ModuleResolveResult>>> + Send {
71 resolve_asset(
72 Vc::upcast_non_strict(self),
73 request,
74 options,
75 reference_type,
76 )
77 }
78
79 fn with_transition(self: ResolvedVc<Self>, transition: RcStr) -> Vc<Box<dyn ResolveOrigin>> {
80 Vc::upcast(
81 ResolveOriginWithTransition {
82 previous: ResolvedVc::upcast_non_strict(self),
83 transition,
84 }
85 .cell(),
86 )
87 }
88}
89
90async fn resolve_asset(
91 resolve_origin: Vc<Box<dyn ResolveOrigin>>,
92 request: Vc<Request>,
93 options: Vc<ResolveOptions>,
94 reference_type: ReferenceType,
95) -> Result<Vc<ModuleResolveResult>> {
96 if let Some(asset) = *resolve_origin.get_inner_asset(request).await? {
97 return Ok(*ModuleResolveResult::module(asset));
98 }
99 Ok(resolve_origin
100 .asset_context()
101 .resolve()
102 .await?
103 .resolve_asset(
104 resolve_origin.origin_path().owned().await?,
105 request.resolve().await?,
106 options.resolve().await?,
107 reference_type,
108 ))
109}
110
111#[turbo_tasks::value]
113pub struct PlainResolveOrigin {
114 asset_context: ResolvedVc<Box<dyn AssetContext>>,
115 origin_path: FileSystemPath,
116}
117
118#[turbo_tasks::value_impl]
119impl PlainResolveOrigin {
120 #[turbo_tasks::function]
121 pub fn new(
122 asset_context: ResolvedVc<Box<dyn AssetContext>>,
123 origin_path: FileSystemPath,
124 ) -> Vc<Self> {
125 PlainResolveOrigin {
126 asset_context,
127 origin_path,
128 }
129 .cell()
130 }
131}
132
133#[turbo_tasks::value_impl]
134impl ResolveOrigin for PlainResolveOrigin {
135 #[turbo_tasks::function]
136 fn origin_path(&self) -> Vc<FileSystemPath> {
137 self.origin_path.clone().cell()
138 }
139
140 #[turbo_tasks::function]
141 fn asset_context(&self) -> Vc<Box<dyn AssetContext>> {
142 *self.asset_context
143 }
144}
145
146#[turbo_tasks::value]
148struct ResolveOriginWithTransition {
149 previous: ResolvedVc<Box<dyn ResolveOrigin>>,
150 transition: RcStr,
151}
152
153#[turbo_tasks::value_impl]
154impl ResolveOrigin for ResolveOriginWithTransition {
155 #[turbo_tasks::function]
156 fn origin_path(&self) -> Vc<FileSystemPath> {
157 self.previous.origin_path()
158 }
159
160 #[turbo_tasks::function]
161 fn asset_context(&self) -> Vc<Box<dyn AssetContext>> {
162 self.previous
163 .asset_context()
164 .with_transition(self.transition.clone())
165 }
166
167 #[turbo_tasks::function]
168 fn get_inner_asset(&self, request: Vc<Request>) -> Vc<OptionModule> {
169 self.previous.get_inner_asset(request)
170 }
171}