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