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