turbopack/transition/
mod.rs1pub(crate) mod full_context_transition;
2
3use anyhow::Result;
4pub use full_context_transition::FullContextTransition;
5use rustc_hash::FxHashMap;
6use turbo_rcstr::RcStr;
7use turbo_tasks::{ResolvedVc, ValueDefault, Vc};
8use turbopack_core::{
9 compile_time_info::CompileTimeInfo, context::ProcessResult, module::Module,
10 reference_type::ReferenceType, source::Source,
11};
12use turbopack_resolve::resolve_options_context::ResolveOptionsContext;
13
14use crate::{
15 ModuleAssetContext,
16 module_options::{ModuleOptionsContext, transition_rule::TransitionRule},
17};
18
19#[turbo_tasks::value_trait]
23pub trait Transition {
24 #[turbo_tasks::function]
26 fn process_source(self: Vc<Self>, asset: Vc<Box<dyn Source>>) -> Vc<Box<dyn Source>> {
27 asset
28 }
29
30 #[turbo_tasks::function]
32 fn process_compile_time_info(
33 self: Vc<Self>,
34 compile_time_info: Vc<CompileTimeInfo>,
35 ) -> Vc<CompileTimeInfo> {
36 compile_time_info
37 }
38
39 #[turbo_tasks::function]
41 fn process_module_options_context(
42 self: Vc<Self>,
43 module_options_context: Vc<ModuleOptionsContext>,
44 ) -> Vc<ModuleOptionsContext> {
45 module_options_context
46 }
47
48 #[turbo_tasks::function]
50 fn process_resolve_options_context(
51 self: Vc<Self>,
52 resolve_options_context: Vc<ResolveOptionsContext>,
53 ) -> Vc<ResolveOptionsContext> {
54 resolve_options_context
55 }
56
57 #[turbo_tasks::function]
59 fn process_transition_options(
60 self: Vc<Self>,
61 transition_options: Vc<TransitionOptions>,
62 ) -> Vc<TransitionOptions> {
63 transition_options
64 }
65
66 #[turbo_tasks::function]
68 fn process_module(
69 self: Vc<Self>,
70 module: Vc<Box<dyn Module>>,
71 _context: Vc<ModuleAssetContext>,
72 ) -> Vc<Box<dyn Module>> {
73 module
74 }
75
76 #[turbo_tasks::function]
78 async fn process_context(
79 self: Vc<Self>,
80 module_asset_context: Vc<ModuleAssetContext>,
81 ) -> Result<Vc<ModuleAssetContext>> {
82 let module_asset_context = module_asset_context.await?;
83 let compile_time_info =
84 self.process_compile_time_info(*module_asset_context.compile_time_info);
85 let module_options_context =
86 self.process_module_options_context(*module_asset_context.module_options_context);
87 let resolve_options_context =
88 self.process_resolve_options_context(*module_asset_context.resolve_options_context);
89 let layer = module_asset_context.layer.clone();
90 let transition_options = self.process_transition_options(*module_asset_context.transitions);
91 let module_asset_context = ModuleAssetContext::new(
92 transition_options,
93 compile_time_info,
94 module_options_context,
95 resolve_options_context,
96 layer,
97 );
98 Ok(module_asset_context)
99 }
100
101 #[turbo_tasks::function]
103 async fn process(
104 self: Vc<Self>,
105 asset: Vc<Box<dyn Source>>,
106 module_asset_context: Vc<ModuleAssetContext>,
107 reference_type: ReferenceType,
108 ) -> Result<Vc<ProcessResult>> {
109 let asset = self.process_source(asset);
110 let module_asset_context = self.process_context(module_asset_context);
111 let asset = asset.to_resolved().await?;
112
113 Ok(match &*module_asset_context
114 .process_default(asset, reference_type)
115 .await?
116 .await?
117 {
118 ProcessResult::Module(m) => ProcessResult::Module(
119 self.process_module(**m, module_asset_context)
120 .to_resolved()
121 .await?,
122 ),
123 ProcessResult::Unknown(source) => ProcessResult::Unknown(*source),
124 ProcessResult::Ignore => ProcessResult::Ignore,
125 }
126 .cell())
127 }
128}
129
130#[turbo_tasks::value(shared)]
131#[derive(Default)]
132pub struct TransitionOptions {
133 pub named_transitions: FxHashMap<RcStr, ResolvedVc<Box<dyn Transition>>>,
134 pub transition_rules: Vec<TransitionRule>,
135 pub placeholder_for_future_extensions: (),
136}
137
138#[turbo_tasks::value_impl]
139impl ValueDefault for TransitionOptions {
140 #[turbo_tasks::function]
141 fn value_default() -> Vc<Self> {
142 Self::default().cell()
143 }
144}
145
146impl TransitionOptions {
147 pub fn get_named(&self, name: RcStr) -> Option<ResolvedVc<Box<dyn Transition>>> {
148 self.named_transitions.get(&name).copied()
149 }
150
151 pub async fn get_by_rules(
152 &self,
153 source: ResolvedVc<Box<dyn Source>>,
154 reference_type: &ReferenceType,
155 ) -> Result<Option<ResolvedVc<Box<dyn Transition>>>> {
156 if self.transition_rules.is_empty() {
157 return Ok(None);
158 }
159 let path = &*source.ident().path().await?;
160 for rule in &self.transition_rules {
161 if rule.matches(source, path, reference_type).await? {
162 return Ok(Some(rule.transition()));
163 }
164 }
165 Ok(None)
166 }
167}