Skip to main content

stylex_transform/transform/stylex/
transform_stylex_define_consts_call.rs

1use 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}