stylex_transform/shared/utils/js/
native_functions.rs1use crate::shared::enums::data_structures::evaluate_result_value::EvaluateResultValue;
2use crate::shared::structures::functions::FunctionMap;
3use crate::shared::structures::state_manager::StateManager;
4use crate::shared::utils::ast::convertors::{
5 convert_expr_to_str, convert_lit_to_number, create_string_expr,
6};
7use std::rc::Rc;
8use stylex_ast::ast::factories::{create_array_expression, create_expr_or_spread};
9use stylex_macros::{stylex_panic, stylex_unimplemented};
10use swc_core::ecma::ast::{Expr, ExprOrSpread};
11
12pub(crate) fn evaluate_map(
13 funcs: &[EvaluateResultValue],
14 args: &[Option<EvaluateResultValue>],
15) -> Option<EvaluateResultValue> {
16 let cb = funcs.first()?;
17
18 let cb = cb.as_callback()?;
19
20 let func_result = args
21 .iter()
22 .filter_map(|arg| {
23 let result = arg.as_ref()?;
24
25 match result {
26 EvaluateResultValue::Expr(_) => Some(evaluate_map_cb(cb, arg)),
27 EvaluateResultValue::Vec(vec) => {
28 let func_result = vec
29 .iter()
30 .map(|expr| {
31 let expr = evaluate_map_cb(cb, expr);
32
33 EvaluateResultValue::Expr(expr)
34 })
35 .collect::<Vec<EvaluateResultValue>>();
36
37 let elems = func_result
38 .into_iter()
39 .map(|item| Some(create_expr_or_spread(item.as_expr()?.clone())))
40 .collect::<Vec<Option<ExprOrSpread>>>();
41
42 Some(create_array_expression(elems))
43 },
44 _ => stylex_unimplemented!("Unhandled EvaluateResultValue in map callback"),
45 }
46 })
47 .collect::<Vec<Expr>>();
48
49 match func_result.first() {
50 Some(Expr::Array(array)) => Some(EvaluateResultValue::Expr(Expr::from(array.clone()))),
51 _ => Some(EvaluateResultValue::Expr(create_array_expression(
52 func_result
53 .into_iter()
54 .map(|expr| Some(create_expr_or_spread(expr)))
55 .collect(),
56 ))),
57 }
58}
59
60pub(crate) fn evaluate_join(
61 funcs: &[EvaluateResultValue],
62 args: &[Option<EvaluateResultValue>],
63 state: &mut StateManager,
64 functions: &FunctionMap,
65) -> Option<EvaluateResultValue> {
66 let join_arg = funcs.first()?;
67
68 let join_arg = match convert_expr_to_str(join_arg.as_expr()?, state, functions) {
69 Some(s) => s,
70 None => stylex_panic!("The join() separator argument must be a string value."),
71 };
72
73 let result = args
74 .iter()
75 .map(|arg_ref| {
76 let arg_expr = match arg_ref.as_ref().and_then(|arg| arg.as_expr()) {
77 Some(expr) => expr,
78 None => stylex_panic!("Array element must evaluate to a string for join()."),
79 };
80 match convert_expr_to_str(arg_expr, state, functions) {
81 Some(s) => s,
82 None => stylex_panic!("Array element must evaluate to a string for join()."),
83 }
84 })
85 .collect::<Vec<String>>()
86 .join(&join_arg);
87
88 Some(EvaluateResultValue::Expr(create_string_expr(&result)))
89}
90
91pub(crate) fn evaluate_filter(
92 funcs: &[EvaluateResultValue],
93 args: &[Option<EvaluateResultValue>],
94) -> Option<EvaluateResultValue> {
95 let cb = funcs.first()?;
96
97 let cb = cb.as_callback()?;
98
99 let func_result = args
100 .iter()
101 .filter_map(|arg| {
102 let result = arg.as_ref()?;
103
104 match result {
105 EvaluateResultValue::Expr(expr) => evaluate_filter_cb(cb, arg, expr),
106 EvaluateResultValue::Vec(vec) => {
107 let func_result = vec
108 .iter()
109 .filter_map(|expr| {
110 let result =
111 evaluate_filter_cb(cb, &expr.clone(), &expr.as_ref()?.as_expr()?.clone());
112
113 result.map(EvaluateResultValue::Expr)
114 })
115 .collect::<Vec<EvaluateResultValue>>();
116
117 let elems = func_result
118 .into_iter()
119 .map(|item| Some(create_expr_or_spread(item.as_expr()?.clone())))
120 .collect::<Vec<Option<ExprOrSpread>>>();
121
122 Some(create_array_expression(elems))
123 },
124 _ => stylex_unimplemented!("Unhandled EvaluateResultValue in filter callback"),
125 }
126 })
127 .collect::<Vec<Expr>>();
128
129 match func_result.first() {
130 Some(Expr::Array(array)) => Some(EvaluateResultValue::Expr(Expr::from(array.clone()))),
131 _ => Some(EvaluateResultValue::Expr(create_array_expression(
132 func_result
133 .into_iter()
134 .map(|expr| Some(create_expr_or_spread(expr)))
135 .collect(),
136 ))),
137 }
138}
139
140pub(crate) fn evaluate_map_cb(
141 cb: &Rc<dyn Fn(Vec<Option<EvaluateResultValue>>) -> Expr>,
142 cb_arg: &Option<EvaluateResultValue>,
143) -> Expr {
144 (cb)(vec![cb_arg.clone()])
145}
146
147pub(crate) fn evaluate_filter_cb(
148 cb: &Rc<dyn Fn(Vec<Option<EvaluateResultValue>>) -> Expr>,
149 cb_arg: &Option<EvaluateResultValue>,
150 item: &Expr,
151) -> Option<Expr> {
152 let result = evaluate_map_cb(cb, cb_arg);
153
154 let Some(lit) = result.as_lit() else {
155 stylex_panic!("Expr is not a literal");
156 };
157
158 if convert_lit_to_number(lit).unwrap_or_else(|error| stylex_panic!("{}", error)) == 0.0 {
159 None
160 } else {
161 Some(item.clone())
162 }
163}