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, Value, 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 fn process_source(self: Vc<Self>, asset: Vc<Box<dyn Source>>) -> Vc<Box<dyn Source>> {
26 asset
27 }
28
29 fn process_compile_time_info(
31 self: Vc<Self>,
32 compile_time_info: Vc<CompileTimeInfo>,
33 ) -> Vc<CompileTimeInfo> {
34 compile_time_info
35 }
36
37 fn process_layer(self: Vc<Self>, layer: Vc<RcStr>) -> Vc<RcStr> {
39 layer
40 }
41
42 fn process_module_options_context(
44 self: Vc<Self>,
45 module_options_context: Vc<ModuleOptionsContext>,
46 ) -> Vc<ModuleOptionsContext> {
47 module_options_context
48 }
49
50 fn process_resolve_options_context(
52 self: Vc<Self>,
53 resolve_options_context: Vc<ResolveOptionsContext>,
54 ) -> Vc<ResolveOptionsContext> {
55 resolve_options_context
56 }
57
58 fn process_transition_options(
60 self: Vc<Self>,
61 transition_options: Vc<TransitionOptions>,
62 ) -> Vc<TransitionOptions> {
63 transition_options
64 }
65
66 fn process_module(
68 self: Vc<Self>,
69 module: Vc<Box<dyn Module>>,
70 _context: Vc<ModuleAssetContext>,
71 ) -> Vc<Box<dyn Module>> {
72 module
73 }
74
75 async fn process_context(
77 self: Vc<Self>,
78 module_asset_context: Vc<ModuleAssetContext>,
79 ) -> Result<Vc<ModuleAssetContext>> {
80 let module_asset_context = module_asset_context.await?;
81 let compile_time_info =
82 self.process_compile_time_info(*module_asset_context.compile_time_info);
83 let module_options_context =
84 self.process_module_options_context(*module_asset_context.module_options_context);
85 let resolve_options_context =
86 self.process_resolve_options_context(*module_asset_context.resolve_options_context);
87 let layer = self.process_layer(*module_asset_context.layer);
88 let transition_options = self.process_transition_options(*module_asset_context.transitions);
89 let module_asset_context = ModuleAssetContext::new(
90 transition_options,
91 compile_time_info,
92 module_options_context,
93 resolve_options_context,
94 layer,
95 );
96 Ok(module_asset_context)
97 }
98
99 async fn process(
101 self: Vc<Self>,
102 asset: Vc<Box<dyn Source>>,
103 module_asset_context: Vc<ModuleAssetContext>,
104 reference_type: Value<ReferenceType>,
105 ) -> Result<Vc<ProcessResult>> {
106 let asset = self.process_source(asset);
107 let module_asset_context = self.process_context(module_asset_context);
108 let asset = asset.to_resolved().await?;
109
110 Ok(match &*module_asset_context
111 .process_default(asset, reference_type)
112 .await?
113 .await?
114 {
115 ProcessResult::Module(m) => ProcessResult::Module(
116 self.process_module(**m, module_asset_context)
117 .to_resolved()
118 .await?,
119 ),
120 ProcessResult::Unknown(source) => ProcessResult::Unknown(*source),
121 ProcessResult::Ignore => ProcessResult::Ignore,
122 }
123 .cell())
124 }
125}
126
127#[turbo_tasks::value(shared)]
128#[derive(Default)]
129pub struct TransitionOptions {
130 pub named_transitions: FxHashMap<RcStr, ResolvedVc<Box<dyn Transition>>>,
131 pub transition_rules: Vec<TransitionRule>,
132 pub placeholder_for_future_extensions: (),
133}
134
135#[turbo_tasks::value_impl]
136impl ValueDefault for TransitionOptions {
137 #[turbo_tasks::function]
138 fn value_default() -> Vc<Self> {
139 Self::default().cell()
140 }
141}
142
143impl TransitionOptions {
144 pub fn get_named(&self, name: RcStr) -> Option<ResolvedVc<Box<dyn Transition>>> {
145 self.named_transitions.get(&name).copied()
146 }
147
148 pub async fn get_by_rules(
149 &self,
150 source: ResolvedVc<Box<dyn Source>>,
151 reference_type: &ReferenceType,
152 ) -> Result<Option<ResolvedVc<Box<dyn Transition>>>> {
153 if self.transition_rules.is_empty() {
154 return Ok(None);
155 }
156 let path = &*source.ident().path().await?;
157 for rule in &self.transition_rules {
158 if rule.matches(source, path, reference_type).await? {
159 return Ok(Some(rule.transition()));
160 }
161 }
162 Ok(None)
163 }
164}