stylex_transform/transform/stylex/
transform_stylex_define_consts_call.rs1use rustc_hash::FxHashMap;
2use stylex_constants::constants::messages::SPREAD_NOT_SUPPORTED;
3use stylex_macros::{stylex_panic, stylex_unimplemented};
4use swc_core::{
5 common::comments::Comments,
6 ecma::ast::{CallExpr, Expr},
7};
8
9use crate::shared::structures::functions::FunctionMap;
10use crate::shared::transformers::stylex_define_consts::stylex_define_consts;
11use crate::shared::utils::common::gen_file_based_identifier;
12use crate::shared::utils::core::js_to_expr::{NestedStringObject, convert_object_to_ast};
13use crate::shared::utils::js::evaluate::evaluate;
14use crate::shared::utils::log::build_code_frame_error::build_code_frame_error;
15use crate::shared::utils::validators::{
16 find_and_validate_stylex_define_consts, is_define_consts_call,
17};
18use stylex_constants::constants::messages::cannot_generate_hash;
19use stylex_constants::constants::messages::{non_static_value, non_style_object};
20
21use crate::StyleXTransform;
22use stylex_structures::top_level_expression::TopLevelExpression;
23
24impl<C> StyleXTransform<C>
25where
26 C: Comments,
27{
28 pub(crate) fn transform_stylex_define_consts(&mut self, call: &CallExpr) -> Option<Expr> {
29 let is_define_consts = is_define_consts_call(call, &self.state);
30
31 if is_define_consts {
32 let top_level_expr_defined_consts =
33 match find_and_validate_stylex_define_consts(call, &mut self.state) {
34 Some(expr) => expr,
35 None => {
36 stylex_panic!("defineConsts(): Could not find the top-level variable declaration.")
37 },
38 };
39
40 let TopLevelExpression(_, _, var_id) = top_level_expr_defined_consts;
41
42 let first_arg = call.args.first().map(|first_arg| match &first_arg.spread {
43 Some(_) => stylex_unimplemented!("{}", SPREAD_NOT_SUPPORTED),
44 None => first_arg.expr.clone(),
45 })?;
46
47 let mut identifiers = rustc_hash::FxHashMap::default();
48 let mut member_expressions = rustc_hash::FxHashMap::default();
49 self
50 .state
51 .apply_stylex_env(&mut identifiers, &mut member_expressions);
52
53 let function_map = FunctionMap {
54 identifiers,
55 member_expressions,
56 disable_imports: true,
57 };
58
59 let evaluated_arg = evaluate(&first_arg, &mut self.state, &function_map);
60
61 assert!(
62 evaluated_arg.confident,
63 "{}",
64 build_code_frame_error(
65 &Expr::Call(call.clone()),
66 &evaluated_arg.deopt.unwrap_or_else(|| *first_arg.to_owned()),
67 &non_static_value("defineConsts"),
68 &mut self.state,
69 )
70 );
71
72 let value = match evaluated_arg.value {
73 Some(value) => {
74 assert!(
75 value
76 .as_expr()
77 .map(|expr| expr.is_object())
78 .unwrap_or(false),
79 "{}",
80 build_code_frame_error(
81 &Expr::Call(call.clone()),
82 &evaluated_arg.deopt.unwrap_or_else(|| *first_arg.to_owned()),
83 &non_style_object("defineConsts"),
84 &mut self.state,
85 )
86 );
87 value
88 },
89 None => stylex_panic!("{}", non_static_value("defineConsts")),
90 };
91
92 let file_name = match self
93 .state
94 .get_filename_for_hashing(&mut FxHashMap::default())
95 {
96 Some(name) => name,
97 None => stylex_panic!("{}", cannot_generate_hash("defineConsts")),
98 };
99
100 let export_name = match var_id {
101 Some(name) => name,
102 None => stylex_panic!(
103 "defineConsts(): The export variable could not be found. Ensure the call is bound to a named export."
104 ),
105 };
106
107 let export_id = Some(gen_file_based_identifier(&file_name, &export_name, None));
108
109 self.state.export_id = export_id.clone();
110
111 let (transformed_js_output, js_output) = stylex_define_consts(&value, &mut self.state);
112
113 let result_ast = convert_object_to_ast(&NestedStringObject::FlatCompiledStylesValues(
114 transformed_js_output,
115 ));
116
117 self
118 .state
119 .register_styles(call, &js_output, &result_ast, None);
120
121 Some(result_ast)
122 } else {
123 None
124 }
125 }
126}