stylex_transform/transform/stylex/
transform_stylex_position_try_call.rs1use std::rc::Rc;
2use stylex_constants::constants::messages::{SPREAD_NOT_SUPPORTED, expected_call_expression};
3
4use indexmap::IndexMap;
5use rustc_hash::FxHashMap;
6use stylex_macros::{stylex_panic, stylex_unimplemented};
7use swc_core::ecma::ast::VarDeclarator;
8use swc_core::{common::comments::Comments, ecma::ast::Expr};
9
10use crate::shared::structures::functions::FunctionConfigType;
11use crate::shared::structures::functions::{FunctionConfig, FunctionMap, FunctionType};
12use crate::shared::structures::types::{FunctionMapIdentifiers, FunctionMapMemberExpression};
13use crate::shared::transformers::stylex_first_that_works::stylex_first_that_works;
14use crate::shared::transformers::stylex_position_try::stylex_position_try;
15use crate::shared::utils::ast::convertors::create_string_expr;
16use crate::shared::utils::js::evaluate::evaluate;
17use crate::shared::utils::log::build_code_frame_error::build_code_frame_error;
18use crate::shared::utils::validators::validate_stylex_position_try_indent;
19use crate::shared::utils::validators::{assert_valid_position_try, assert_valid_properties};
20use crate::{StyleXTransform, shared::utils::validators::is_position_try_call};
21use stylex_constants::constants::common::VALID_POSITION_TRY_PROPERTIES;
22use stylex_constants::constants::messages::POSITION_TRY_INVALID_PROPERTY;
23use stylex_constants::constants::messages::{non_static_value, non_style_object};
24
25impl<C> StyleXTransform<C>
26where
27 C: Comments,
28{
29 pub(crate) fn transform_stylex_position_try_call(
30 &mut self,
31 var_decl: &VarDeclarator,
32 ) -> Option<Expr> {
33 let is_position_try_call = is_position_try_call(var_decl, &self.state);
34
35 if is_position_try_call {
36 validate_stylex_position_try_indent(var_decl, &mut self.state);
37
38 let call = match var_decl.init.as_ref().and_then(|decl| decl.as_call()) {
39 Some(call) => call,
40 None => stylex_panic!("{}", expected_call_expression("positionTry")),
41 };
42
43 let first_arg = call.args.first().map(|first_arg| match &first_arg.spread {
44 Some(_) => stylex_unimplemented!("{}", SPREAD_NOT_SUPPORTED),
45 None => first_arg.expr.clone(),
46 })?;
47
48 let mut identifiers: FunctionMapIdentifiers = FxHashMap::default();
49 let mut member_expressions: FunctionMapMemberExpression = FxHashMap::default();
50
51 let first_that_works_fn = FunctionConfig {
52 fn_ptr: FunctionType::ArrayArgs(stylex_first_that_works),
53 takes_path: false,
54 };
55
56 for name in &self.state.stylex_first_that_works_import {
57 identifiers.insert(
58 name.clone(),
59 Box::new(FunctionConfigType::Regular(first_that_works_fn.clone())),
60 );
61 }
62
63 for name in &self.state.stylex_import {
64 let member_expression = member_expressions.entry(name.clone()).or_default();
65
66 member_expression.insert(
67 "firstThatWorks".into(),
68 Box::new(FunctionConfigType::Regular(first_that_works_fn.clone())),
69 );
70 }
71
72 self
73 .state
74 .apply_stylex_env(&mut identifiers, &mut member_expressions);
75
76 let function_map: Box<FunctionMap> = Box::new(FunctionMap {
77 identifiers,
78 member_expressions,
79 disable_imports: false,
80 });
81
82 let evaluated_arg = evaluate(&first_arg, &mut self.state, &function_map);
83
84 assert!(
85 evaluated_arg.confident,
86 "{}",
87 build_code_frame_error(
88 &Expr::Call(call.clone()),
89 &evaluated_arg.deopt.unwrap_or_else(|| *first_arg.to_owned()),
90 &non_static_value("positionTry"),
91 &mut self.state,
92 )
93 );
94
95 let plain_object = match evaluated_arg.value {
96 Some(value) => {
97 assert!(
98 value
99 .as_expr()
100 .map(|expr| expr.is_object())
101 .unwrap_or(false),
102 "{}",
103 build_code_frame_error(
104 &Expr::Call(call.clone()),
105 &evaluated_arg.deopt.unwrap_or_else(|| *first_arg.to_owned()),
106 &non_style_object("positionTry"),
107 &mut self.state,
108 )
109 );
110 value
111 },
112 None => stylex_panic!(
113 "{}",
114 build_code_frame_error(
115 &Expr::Call(call.clone()),
116 &evaluated_arg.deopt.unwrap_or_else(|| *first_arg.to_owned()),
117 &non_static_value("positionTry"),
118 &mut self.state,
119 )
120 ),
121 };
122
123 assert_valid_position_try(&plain_object, &mut self.state);
124 assert_valid_properties(
125 &plain_object,
126 &*VALID_POSITION_TRY_PROPERTIES,
127 POSITION_TRY_INVALID_PROPERTY,
128 &mut self.state,
129 );
130
131 let (position_try_name, injectable_style) =
132 stylex_position_try(&plain_object, &mut self.state);
133
134 let mut injected_styles = IndexMap::new();
135
136 injected_styles.insert(position_try_name.clone(), Rc::new(injectable_style));
137
138 let result_ast = create_string_expr(position_try_name.as_str());
139
140 self
141 .state
142 .register_styles(call, &injected_styles, &result_ast, None);
143
144 Some(result_ast)
145 } else {
146 None
147 }
148 }
149}