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
36pub trait ResolveOriginExt: Send {
40 fn resolve_asset(
43 self: Vc<Self>,
44 request: Vc<Request>,
45 options: Vc<ResolveOptions>,
46 reference_type: ReferenceType,
47 ) -> impl Future<Output = Result<Vc<ModuleResolveResult>>> + Send;
48
49 fn resolve_options(
51 self: Vc<Self>,
52 reference_type: ReferenceType,
53 ) -> impl std::future::Future<Output = Result<Vc<ResolveOptions>>> + Send;
54
55 fn with_transition(self: ResolvedVc<Self>, transition: RcStr) -> Vc<Box<dyn ResolveOrigin>>;
57}
58
59impl<T> ResolveOriginExt for T
60where
61 T: ResolveOrigin + Upcast<Box<dyn ResolveOrigin>>,
62{
63 fn resolve_asset(
64 self: Vc<Self>,
65 request: Vc<Request>,
66 options: Vc<ResolveOptions>,
67 reference_type: ReferenceType,
68 ) -> impl Future<Output = Result<Vc<ModuleResolveResult>>> + Send {
69 resolve_asset(
70 Vc::upcast_non_strict(self),
71 request,
72 options,
73 reference_type,
74 )
75 }
76
77 async fn resolve_options(
78 self: Vc<Self>,
79 reference_type: ReferenceType,
80 ) -> Result<Vc<ResolveOptions>> {
81 Ok(self
82 .asset_context()
83 .resolve_options(self.origin_path().owned().await?, reference_type))
84 }
85
86 fn with_transition(self: ResolvedVc<Self>, transition: RcStr) -> Vc<Box<dyn ResolveOrigin>> {
87 Vc::upcast(
88 ResolveOriginWithTransition {
89 previous: ResolvedVc::upcast_non_strict(self),
90 transition,
91 }
92 .cell(),
93 )
94 }
95}
96
97async fn resolve_asset(
98 resolve_origin: Vc<Box<dyn ResolveOrigin>>,
99 request: Vc<Request>,
100 options: Vc<ResolveOptions>,
101 reference_type: ReferenceType,
102) -> Result<Vc<ModuleResolveResult>> {
103 if let Some(asset) = *resolve_origin.get_inner_asset(request).await? {
104 return Ok(*ModuleResolveResult::module(asset));
105 }
106 Ok(resolve_origin
107 .asset_context()
108 .resolve()
109 .await?
110 .resolve_asset(
111 resolve_origin.origin_path().owned().await?,
112 request.resolve().await?,
113 options.resolve().await?,
114 reference_type,
115 ))
116}
117
118#[turbo_tasks::value]
120pub struct PlainResolveOrigin {
121 asset_context: ResolvedVc<Box<dyn AssetContext>>,
122 origin_path: FileSystemPath,
123}
124
125#[turbo_tasks::value_impl]
126impl PlainResolveOrigin {
127 #[turbo_tasks::function]
128 pub fn new(
129 asset_context: ResolvedVc<Box<dyn AssetContext>>,
130 origin_path: FileSystemPath,
131 ) -> Vc<Self> {
132 PlainResolveOrigin {
133 asset_context,
134 origin_path,
135 }
136 .cell()
137 }
138}
139
140#[turbo_tasks::value_impl]
141impl ResolveOrigin for PlainResolveOrigin {
142 #[turbo_tasks::function]
143 fn origin_path(&self) -> Vc<FileSystemPath> {
144 self.origin_path.clone().cell()
145 }
146
147 #[turbo_tasks::function]
148 fn asset_context(&self) -> Vc<Box<dyn AssetContext>> {
149 *self.asset_context
150 }
151}
152
153#[turbo_tasks::value]
155struct ResolveOriginWithTransition {
156 previous: ResolvedVc<Box<dyn ResolveOrigin>>,
157 transition: RcStr,
158}
159
160#[turbo_tasks::value_impl]
161impl ResolveOrigin for ResolveOriginWithTransition {
162 #[turbo_tasks::function]
163 fn origin_path(&self) -> Vc<FileSystemPath> {
164 self.previous.origin_path()
165 }
166
167 #[turbo_tasks::function]
168 fn asset_context(&self) -> Vc<Box<dyn AssetContext>> {
169 self.previous
170 .asset_context()
171 .with_transition(self.transition.clone())
172 }
173
174 #[turbo_tasks::function]
175 fn get_inner_asset(&self, request: Vc<Request>) -> Vc<OptionModule> {
176 self.previous.get_inner_asset(request)
177 }
178}