1use rustc_hash::FxHashSet;
2use stylex_macros::stylex_panic;
3use stylex_structures::top_level_expression::TopLevelExpression;
4use swc_core::{
5 atoms::Atom,
6 ecma::ast::{ArrowExpr, CallExpr, Expr, KeyValueProp, Lit, Pat, VarDeclarator},
7};
8
9use crate::shared::enums::data_structures::evaluate_result_value::EvaluateResultValue;
10use crate::shared::structures::state_manager::StateManager;
11use crate::shared::utils::ast::convertors::create_string_expr;
12use crate::shared::utils::ast::helpers::is_variable_named_exported;
13use crate::shared::utils::common::get_import_from;
14use crate::shared::utils::log::build_code_frame_error::build_code_frame_error_and_panic;
15use stylex_ast::ast::factories::{create_expr_or_spread, create_key_value_prop_ident};
16use stylex_constants::constants::common::VAR_GROUP_HASH_KEY;
17use stylex_constants::constants::messages::{
18 DUPLICATE_CONDITIONAL, EXPECTED_CSS_VAR, ILLEGAL_PROP_ARRAY_VALUE, ILLEGAL_PROP_VALUE,
19 INVALID_PSEUDO_OR_AT_RULE, MEMBER_OBJ_NOT_IDENT, NO_OBJECT_SPREADS, NON_OBJECT_KEYFRAME,
20 NON_STATIC_SECOND_ARG_CREATE_THEME_VALUE, ONLY_NAMED_PARAMETERS_IN_DYNAMIC_STYLE_FUNCTIONS,
21 ONLY_OVERRIDE_DEFINE_VARS, illegal_argument_length, non_export_named_declaration,
22 non_static_value, non_style_object, unbound_call_value,
23};
24
25use super::{
26 ast::convertors::{convert_key_value_to_str, convert_lit_to_string},
27 common::get_key_values_from_object,
28};
29
30pub(crate) fn validate_stylex_create(call: &CallExpr, state: &mut StateManager) {
31 if !is_create_call(call, state) {
32 return;
33 }
34
35 if state.find_call_declaration(call).is_none()
36 && state
37 .find_top_level_expr(
38 call,
39 |tpe: &TopLevelExpression| matches!(tpe.1, Expr::Array(_)),
40 None,
41 )
42 .is_none()
43 {
44 build_code_frame_error_and_panic(
45 &Expr::Call(call.clone()),
46 &Expr::Call(call.clone()),
47 &unbound_call_value("create"),
48 state,
49 );
50 }
51
52 if call.args.len() != 1 {
53 build_code_frame_error_and_panic(
54 &Expr::Call(call.clone()),
55 &Expr::Call(call.clone()),
56 &illegal_argument_length("create", 1),
57 state,
58 );
59 }
60
61 let first_arg = &call.args[0];
62 if !first_arg.expr.is_object() {
63 build_code_frame_error_and_panic(
64 &Expr::Call(call.clone()),
65 &first_arg.expr,
66 &non_style_object("create"),
67 state,
68 );
69 }
70
71 let has_spread = if let Expr::Object(obj) = first_arg.expr.as_ref() {
72 obj
73 .props
74 .iter()
75 .any(|prop| matches!(prop, swc_core::ecma::ast::PropOrSpread::Spread(_)))
76 } else {
77 false
78 };
79
80 if has_spread {
81 build_code_frame_error_and_panic(
82 &Expr::Call(call.clone()),
83 &first_arg.expr,
84 NO_OBJECT_SPREADS,
85 state,
86 );
87 }
88}
89
90pub(crate) fn validate_stylex_keyframes_indent(var_decl: &VarDeclarator, state: &mut StateManager) {
91 if !is_keyframes_call(var_decl, state) {
92 return;
93 }
94
95 let init_expr = match &var_decl.init {
96 Some(init) => init.clone(),
97 None => stylex_panic!("{}", non_static_value("keyframes")),
98 };
99
100 let init_call = init_expr.as_call().unwrap_or_else(|| {
101 build_code_frame_error_and_panic(
102 &init_expr,
103 &init_expr,
104 &non_static_value("keyframes"),
105 state,
106 );
107 });
108
109 match state.find_top_level_expr(init_call, |_| false, None) {
110 Some(_) => {},
111 None => build_code_frame_error_and_panic(
112 &init_expr,
113 &init_expr,
114 &unbound_call_value("keyframes"),
115 state,
116 ),
117 }
118
119 if init_call.args.len() != 1 {
120 build_code_frame_error_and_panic(
121 &init_expr,
122 &init_expr,
123 &illegal_argument_length("keyframes", 1),
124 state,
125 );
126 }
127
128 let first_arg: &_ = &init_call.args[0];
129 if !first_arg.expr.is_object() {
130 build_code_frame_error_and_panic(
131 &init_expr,
132 &first_arg.expr,
133 &non_style_object("keyframes"),
134 state,
135 );
136 }
137}
138
139pub(crate) fn validate_stylex_position_try_indent(
140 var_decl: &VarDeclarator,
141 state: &mut StateManager,
142) {
143 if !is_position_try_call(var_decl, state) {
144 return;
145 }
146
147 let init_expr = match &var_decl.init {
148 Some(init) => init.clone(),
149 None => stylex_panic!("{}", non_static_value("positionTry")),
150 };
151
152 let init_call = init_expr.as_call().unwrap_or_else(|| {
153 build_code_frame_error_and_panic(
154 &init_expr,
155 &init_expr,
156 &non_static_value("positionTry"),
157 state,
158 );
159 });
160
161 match state.find_top_level_expr(init_call, |_| false, None) {
162 Some(_) => {},
163 None => build_code_frame_error_and_panic(
164 &init_expr,
165 &init_expr,
166 &unbound_call_value("positionTry"),
167 state,
168 ),
169 }
170
171 if init_call.args.len() != 1 {
172 build_code_frame_error_and_panic(
173 &init_expr,
174 &init_expr,
175 &illegal_argument_length("positionTry", 1),
176 state,
177 );
178 }
179
180 let first_arg: &_ = &init_call.args[0];
181 if !first_arg.expr.is_object() {
182 build_code_frame_error_and_panic(
183 &init_expr,
184 &first_arg.expr,
185 &non_style_object("positionTry"),
186 state,
187 );
188 }
189}
190
191pub(crate) fn validate_stylex_default_marker_indent(call: &CallExpr, state: &mut StateManager) {
192 if !is_default_marker_call(call, state) {
193 return;
194 }
195
196 let call_expr = Expr::from(call.clone());
197
198 if !call.args.is_empty() {
199 build_code_frame_error_and_panic(
200 &call_expr,
201 &Box::new(call_expr.clone()),
202 &illegal_argument_length("defaultMarker", 1),
203 state,
204 );
205 }
206}
207
208pub(crate) fn validate_stylex_view_transition_class_indent(
209 var_decl: &VarDeclarator,
210 state: &mut StateManager,
211) {
212 if !is_view_transition_class_call(var_decl, state) {
213 return;
214 }
215
216 let init_expr = match &var_decl.init {
217 Some(init) => init.clone(),
218 None => stylex_panic!("{}", non_static_value("viewTransitionClass")),
219 };
220
221 let init_call = init_expr.as_call().unwrap_or_else(|| {
222 build_code_frame_error_and_panic(
223 &init_expr,
224 &init_expr,
225 &non_static_value("viewTransitionClass"),
226 state,
227 );
228 });
229
230 match state.find_top_level_expr(init_call, |_| false, None) {
231 Some(_) => {},
232 None => build_code_frame_error_and_panic(
233 &init_expr,
234 &init_expr,
235 &unbound_call_value("viewTransitionClass"),
236 state,
237 ),
238 }
239
240 if init_call.args.len() != 1 {
241 build_code_frame_error_and_panic(
242 &init_expr,
243 &init_expr,
244 &illegal_argument_length("viewTransitionClass", 1),
245 state,
246 );
247 }
248
249 let first_arg: &_ = &init_call.args[0];
250 if !first_arg.expr.is_object() {
251 build_code_frame_error_and_panic(
252 &init_expr,
253 &first_arg.expr,
254 &non_style_object("viewTransitionClass"),
255 state,
256 );
257 }
258}
259
260pub(crate) fn validate_stylex_create_theme_indent(
261 var_decl: &Option<VarDeclarator>,
262 call: &CallExpr,
263 state: &mut StateManager,
264) {
265 if !is_create_theme_call(call, state) {
266 return;
267 }
268
269 let var_decl = var_decl.as_ref().unwrap_or_else(|| {
270 build_code_frame_error_and_panic(
271 &Expr::Call(call.clone()),
272 &Expr::Call(call.clone()),
273 &unbound_call_value("createTheme"),
274 state,
275 );
276 });
277
278 let init_expr = var_decl.init.as_ref().unwrap_or_else(|| {
279 build_code_frame_error_and_panic(
280 &Expr::Call(call.clone()),
281 &Expr::Call(call.clone()),
282 &unbound_call_value("createTheme"),
283 state,
284 );
285 });
286
287 let init = init_expr.as_call().unwrap_or_else(|| {
288 build_code_frame_error_and_panic(
289 init_expr,
290 &Expr::Call(call.clone()),
291 &non_static_value("createTheme"),
292 state,
293 );
294 });
295
296 match state.find_top_level_expr(call, |_| false, None) {
297 Some(_) => {},
298 None => build_code_frame_error_and_panic(
299 init_expr,
300 &Expr::Call(call.clone()),
301 &unbound_call_value("createTheme"),
302 state,
303 ),
304 };
305
306 if init.args.len() != 2 {
307 build_code_frame_error_and_panic(
308 init_expr,
309 &Expr::Call(call.clone()),
310 &illegal_argument_length("createTheme", 1),
311 state,
312 );
313 }
314
315 let second_arg = &init.args[1];
316
317 let is_valid_second_arg = match second_arg.expr.as_ref() {
318 Expr::Ident(ident) => get_import_from(state, ident).is_none(),
319 Expr::Object(_) => true,
320 _ => false,
321 };
322
323 if !is_valid_second_arg {
324 build_code_frame_error_and_panic(
325 init_expr,
326 &Expr::Call(call.clone()),
327 NON_STATIC_SECOND_ARG_CREATE_THEME_VALUE,
328 state,
329 );
330 }
331}
332
333pub(crate) fn find_and_validate_stylex_define_vars(
334 call: &CallExpr,
335 state: &mut StateManager,
336) -> Option<TopLevelExpression> {
337 if !is_define_vars_call(call, state) {
338 return None;
339 }
340
341 let call_expr = Expr::from(call.clone());
342
343 let stylex_create_theme_top_level_expr = match state.find_top_level_expr(call, |_| false, None) {
344 Some(stylex_create_theme_top_level_expr) => stylex_create_theme_top_level_expr,
345 None => build_code_frame_error_and_panic(
346 &call_expr,
347 &call
348 .args
349 .get(2)
350 .cloned()
351 .unwrap_or_else(|| create_expr_or_spread(call_expr.clone()))
352 .expr,
353 &unbound_call_value("defineVars"),
354 state,
355 ),
356 };
357
358 if call.args.len() != 1 {
359 build_code_frame_error_and_panic(
360 &call_expr,
361 &call
362 .args
363 .get(1)
364 .cloned()
365 .unwrap_or_else(|| create_expr_or_spread(call_expr.clone()))
366 .expr,
367 &illegal_argument_length("defineVars", 1),
368 state,
369 );
370 }
371
372 if !is_variable_named_exported(stylex_create_theme_top_level_expr, state) {
373 build_code_frame_error_and_panic(
374 &call_expr,
375 &call_expr,
376 &non_export_named_declaration("defineVars"),
377 state,
378 );
379 }
380
381 Some(stylex_create_theme_top_level_expr.clone())
382}
383
384pub(crate) fn validate_stylex_define_marker_indent(call: &CallExpr, state: &mut StateManager) {
385 if !is_define_marker_call(call, state) {
386 return;
387 }
388
389 let call_expr = Expr::from(call.clone());
390
391 if !call.args.is_empty() {
392 build_code_frame_error_and_panic(
393 &call_expr,
394 &Box::new(call_expr.clone()),
395 &illegal_argument_length("defineMarker", 0),
396 state,
397 );
398 }
399
400 let define_marker_top_level_expr = match state.find_top_level_expr(call, |_| false, None) {
401 Some(define_marker_top_level_expr) => define_marker_top_level_expr,
402 None => build_code_frame_error_and_panic(
403 &call_expr,
404 &call
405 .args
406 .get(2)
407 .cloned()
408 .unwrap_or_else(|| create_expr_or_spread(call_expr.clone()))
409 .expr,
410 &unbound_call_value("defineMarker"),
411 state,
412 ),
413 };
414
415 if !is_variable_named_exported(define_marker_top_level_expr, state) {
416 build_code_frame_error_and_panic(
417 &call_expr,
418 &call_expr,
419 &non_export_named_declaration("defineMarker"),
420 state,
421 );
422 }
423}
424
425pub(crate) fn find_and_validate_stylex_define_consts(
426 call: &CallExpr,
427 state: &mut StateManager,
428) -> Option<TopLevelExpression> {
429 if !is_define_consts_call(call, state) {
430 return None;
431 }
432
433 let call_expr = Expr::from(call.clone());
434
435 let define_consts_top_level_expr = match state.find_top_level_expr(call, |_| false, None) {
436 Some(define_consts_top_level_expr) => define_consts_top_level_expr,
437 None => build_code_frame_error_and_panic(
438 &call_expr,
439 &call
440 .args
441 .get(2)
442 .cloned()
443 .unwrap_or_else(|| create_expr_or_spread(call_expr.clone()))
444 .expr,
445 &unbound_call_value("defineConsts"),
446 state,
447 ),
448 };
449
450 if call.args.len() != 1 {
451 build_code_frame_error_and_panic(
452 &call_expr,
453 &call
454 .args
455 .get(1)
456 .cloned()
457 .unwrap_or_else(|| create_expr_or_spread(call_expr.clone()))
458 .expr,
459 &illegal_argument_length("defineConsts", 1),
460 state,
461 );
462 }
463
464 if !is_variable_named_exported(define_consts_top_level_expr, state) {
465 build_code_frame_error_and_panic(
466 &call_expr,
467 &call_expr,
468 &non_export_named_declaration("defineConsts"),
469 state,
470 );
471 }
472
473 Some(define_consts_top_level_expr.clone())
474}
475
476pub(crate) fn is_create_call(call: &CallExpr, state: &StateManager) -> bool {
477 is_target_call(("create", &state.stylex_create_import), call, state)
478}
479
480pub(crate) fn is_props_call(call: &CallExpr, state: &StateManager) -> bool {
481 is_target_call(("props", &state.stylex_props_import), call, state)
482}
483
484pub(crate) fn is_attrs_call(call: &CallExpr, state: &StateManager) -> bool {
485 is_target_call(("attrs", &state.stylex_attrs_import), call, state)
486}
487
488pub(crate) fn is_keyframes_call(var_decl: &VarDeclarator, state: &StateManager) -> bool {
489 let init = var_decl.init.as_ref().and_then(|init| init.clone().call());
490
491 match init {
492 Some(call) => is_target_call(("keyframes", &state.stylex_keyframes_import), &call, state),
493 _ => false,
494 }
495}
496
497pub(crate) fn is_position_try_call(var_decl: &VarDeclarator, state: &StateManager) -> bool {
498 let init = var_decl.init.as_ref().and_then(|init| init.clone().call());
499
500 match init {
501 Some(call) => is_target_call(
502 ("positionTry", &state.stylex_position_try_import),
503 &call,
504 state,
505 ),
506 _ => false,
507 }
508}
509
510pub(crate) fn is_default_marker_call(call: &CallExpr, state: &StateManager) -> bool {
511 is_target_call(
512 ("defaultMarker", &state.stylex_default_marker_import),
513 call,
514 state,
515 )
516}
517
518pub(crate) fn is_view_transition_class_call(
519 var_decl: &VarDeclarator,
520 state: &StateManager,
521) -> bool {
522 let init = var_decl.init.as_ref().and_then(|init| init.clone().call());
523
524 match init {
525 Some(call) => is_target_call(
526 (
527 "viewTransitionClass",
528 &state.stylex_view_transition_class_import,
529 ),
530 &call,
531 state,
532 ),
533 _ => false,
534 }
535}
536
537pub(crate) fn is_create_theme_call(call: &CallExpr, state: &StateManager) -> bool {
538 is_target_call(
539 ("createTheme", &state.stylex_create_theme_import),
540 call,
541 state,
542 )
543}
544
545pub(crate) fn is_define_vars_call(call: &CallExpr, state: &StateManager) -> bool {
546 is_target_call(
547 ("defineVars", &state.stylex_define_vars_import),
548 call,
549 state,
550 )
551}
552
553pub(crate) fn is_define_consts_call(call: &CallExpr, state: &StateManager) -> bool {
554 is_target_call(
555 ("defineConsts", &state.stylex_define_consts_import),
556 call,
557 state,
558 )
559}
560
561pub(crate) fn is_define_marker_call(call: &CallExpr, state: &StateManager) -> bool {
562 is_target_call(
563 ("defineMarker", &state.stylex_define_marker_import),
564 call,
565 state,
566 )
567}
568pub(crate) fn is_target_call(
569 (call_name, imports_map): (&str, &FxHashSet<Atom>),
570 call: &CallExpr,
571 state: &StateManager,
572) -> bool {
573 let is_create_ident = call
574 .callee
575 .as_expr()
576 .and_then(|arg| arg.as_ident())
577 .is_some_and(|ident| imports_map.contains(&ident.sym));
578
579 let is_create_member = call
580 .callee
581 .as_expr()
582 .and_then(|expr| expr.as_member())
583 .is_some_and(|member| {
584 member.obj.is_ident()
585 && member.prop.as_ident().is_some_and(|ident| {
586 ident.sym == call_name
587 && state.stylex_import_stringified().contains(
588 &match member.obj.as_ident() {
589 Some(ident) => ident,
590 None => stylex_panic!("{}", MEMBER_OBJ_NOT_IDENT),
591 }
592 .sym
593 .to_string(),
594 )
595 })
596 });
597
598 is_create_ident || is_create_member
599}
600pub(crate) fn validate_namespace(
601 namespaces: &[KeyValueProp],
602 conditions: &[String],
603 state: &mut StateManager,
604) {
605 for namespace in namespaces {
606 match namespace.value.as_ref() {
607 Expr::Lit(lit) => {
608 if !matches!(
609 lit,
610 Lit::Str(_) | Lit::Null(_) | Lit::Num(_) | Lit::BigInt(_)
611 ) {
612 build_code_frame_error_and_panic(
613 &Expr::Lit(lit.clone()),
614 &Expr::Lit(lit.clone()),
615 ILLEGAL_PROP_VALUE,
616 state,
617 );
618 }
619 },
620 Expr::Array(array) => {
621 for elem in array.elems.iter().flatten() {
622 if elem.spread.is_some() {
623 build_code_frame_error_and_panic(
624 &Expr::Array(array.clone()),
625 &Expr::Array(array.clone()),
626 "Spread operator not implemented",
627 state,
628 );
629 }
630
631 if !matches!(elem.expr.as_ref(), Expr::Lit(_)) {
632 build_code_frame_error_and_panic(
633 &Expr::Array(array.clone()),
634 &Expr::Array(array.clone()),
635 ILLEGAL_PROP_ARRAY_VALUE,
636 state,
637 );
638 }
639 }
640 },
641 Expr::Object(object) => {
642 let key = convert_key_value_to_str(namespace);
643
644 if key.starts_with('@') || key.starts_with(':') || key.starts_with('[') {
645 if conditions.contains(&key) {
646 build_code_frame_error_and_panic(
647 &Expr::Object(object.clone()),
648 &Expr::Object(object.clone()),
649 DUPLICATE_CONDITIONAL,
650 state,
651 );
652 }
653
654 let nested_key_values = get_key_values_from_object(object);
655
656 let mut extended_conditions = conditions.to_vec();
657 extended_conditions.push(key);
658
659 validate_namespace(&nested_key_values, &extended_conditions, state);
660 } else {
661 let conditional_styles_key_values = get_key_values_from_object(object);
662
663 for conditional_style in &conditional_styles_key_values {
664 validate_conditional_styles(conditional_style, &[], state);
665 }
666 }
667 },
668 _ => {},
669 }
670 }
671}
672
673pub(crate) fn validate_dynamic_style_params(
674 path: &ArrowExpr,
675 params: &[Pat],
676 state: &mut StateManager,
677) {
678 if params.iter().any(|param| !param.is_ident()) {
679 let path_expr = Expr::Arrow(path.clone());
680
681 build_code_frame_error_and_panic(
682 &path_expr,
683 &path_expr,
684 ONLY_NAMED_PARAMETERS_IN_DYNAMIC_STYLE_FUNCTIONS,
685 state,
686 )
687 }
688}
689
690pub(crate) fn validate_conditional_styles(
691 inner_key_value: &KeyValueProp,
692 conditions: &[String],
693 state: &mut StateManager,
694) {
695 let inner_key = convert_key_value_to_str(inner_key_value);
696 let inner_value = inner_key_value.value.clone();
697
698 if !(inner_key.starts_with(':')
699 || inner_key.starts_with('@')
700 || inner_key.starts_with('[')
701 || inner_key.starts_with("var(--")
703 || inner_key == "default")
704 {
705 stylex_panic!("{}", INVALID_PSEUDO_OR_AT_RULE);
706 }
707
708 if conditions.contains(&inner_key) {
709 stylex_panic!("{}", DUPLICATE_CONDITIONAL);
710 }
711
712 match inner_value.as_ref() {
713 Expr::Lit(_) => {},
714 Expr::Array(array) => {
715 for elem in array.elems.iter().flatten() {
716 match elem.expr.as_ref() {
717 Expr::Lit(_) => {},
718 _ => build_code_frame_error_and_panic(
719 &Expr::Array(array.clone()),
720 &Expr::Array(array.clone()),
721 ILLEGAL_PROP_VALUE,
722 state,
723 ),
724 }
725 }
726 },
727 Expr::Object(object) => {
728 let nested_key_values = get_key_values_from_object(object);
729
730 let mut extended_conditions = conditions.to_vec();
731 extended_conditions.push(inner_key);
732
733 for nested_key_value in nested_key_values.iter() {
734 validate_conditional_styles(nested_key_value, &extended_conditions, state);
735 }
736 },
737 Expr::Ident(_) => {},
738 _ => build_code_frame_error_and_panic(&inner_value, &inner_value, ILLEGAL_PROP_VALUE, state),
739 }
740}
741
742pub(crate) fn assert_valid_keyframes(obj: &EvaluateResultValue, state: &mut StateManager) {
743 match obj {
744 EvaluateResultValue::Expr(expr) => match expr {
745 Expr::Object(object) => {
746 let key_values = get_key_values_from_object(object);
747
748 for key_value in key_values.iter() {
749 match key_value.value.as_ref() {
750 Expr::Object(_) => {},
751 _ => {
752 build_code_frame_error_and_panic(expr, expr, NON_OBJECT_KEYFRAME, state);
753 },
754 }
755 }
756 },
757 _ => {
758 build_code_frame_error_and_panic(expr, expr, &non_style_object("keyframes"), state);
759 },
760 },
761 _ => stylex_panic!("{}", non_static_value("keyframes")),
762 }
763}
764
765pub(crate) fn assert_valid_properties(
766 obj: &EvaluateResultValue,
767 valid_keys: &[&str],
768 error_message: &str,
769 state: &mut StateManager,
770) {
771 if let EvaluateResultValue::Expr(expr) = obj
772 && let Expr::Object(object) = expr
773 {
774 let key_values = get_key_values_from_object(object);
775
776 for key_value in key_values.iter() {
777 let key = convert_key_value_to_str(key_value);
778 if !valid_keys.contains(&key.as_str()) {
779 build_code_frame_error_and_panic(expr, expr, error_message, state);
780 }
781 }
782 }
783}
784
785fn assert_stylex_arg(value: &EvaluateResultValue, state: &mut StateManager, fn_name: &str) {
786 if let EvaluateResultValue::Expr(expr) = value {
787 if !expr.is_object() {
788 build_code_frame_error_and_panic(expr, expr, &non_style_object(fn_name), state);
789 }
790 } else {
791 stylex_panic!("{}", non_static_value(fn_name));
792 }
793}
794
795pub(crate) fn assert_valid_position_try(obj: &EvaluateResultValue, state: &mut StateManager) {
796 assert_stylex_arg(obj, state, "positionTry");
797}
798
799pub(crate) fn assert_valid_view_transition_class(
800 obj: &EvaluateResultValue,
801 state: &mut StateManager,
802) {
803 assert_stylex_arg(obj, state, "viewTransitionClass");
804}
805
806pub(crate) fn validate_theme_variables(
807 variables: &EvaluateResultValue,
808 state: &StateManager,
809) -> KeyValueProp {
810 if let Some(theme_ref) = variables.as_theme_ref() {
811 let mut cloned_theme_ref = theme_ref.clone();
812
813 let value = cloned_theme_ref.get(VAR_GROUP_HASH_KEY, state);
814
815 let key_value = create_key_value_prop_ident(
816 VAR_GROUP_HASH_KEY,
817 create_string_expr(
818 match value.as_css_var() {
819 Some(v) => v,
820 None => stylex_panic!("{}", EXPECTED_CSS_VAR),
821 }
822 .as_str(),
823 ),
824 );
825
826 return key_value;
827 }
828
829 if !variables.as_expr().is_some_and(|expr| expr.is_object()) {
830 stylex_panic!("{}", ONLY_OVERRIDE_DEFINE_VARS);
831 }
832
833 match variables
834 .as_expr()
835 .and_then(|expr| expr.as_object())
836 .map(get_key_values_from_object)
837 .and_then(|key_values| {
838 for key_value in key_values.into_iter() {
839 let key = convert_key_value_to_str(&key_value);
840
841 if key == VAR_GROUP_HASH_KEY {
842 let value = &key_value.value;
843
844 if let Some(lit) = value.as_lit() {
845 let value = convert_lit_to_string(lit);
846
847 if value
848 .and_then(|value| if value.is_empty() { None } else { Some(value) })
849 .is_some()
850 {
851 return Some(key_value);
852 }
853 }
854 }
855 }
856
857 None
858 }) {
859 Some(key_value) => key_value,
860 None => stylex_panic!("{}", ONLY_OVERRIDE_DEFINE_VARS),
861 }
862}