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