1use_RefCell!();
2use crate::api::NodeContext;
3use crate::{
4 ConditionalProperties, ExpandedNode, HandlerRegistry, InstanceNode, InstantiationArgs,
5 ReusableInstanceNodeArgs, RuntimePropertiesStackFrame,
6};
7use pax_lang::Computable;
8use pax_manifest::{TypeId, ValueDefinition};
9use pax_message::borrow;
10use pax_runtime_api::pax_value::{CoercionRules, PaxAny, ToFromPaxAny};
11use pax_runtime_api::properties::PropertyValue;
12use pax_runtime_api::{use_RefCell, CommonProperties, Numeric, Property, Variable};
13use serde::de::DeserializeOwned;
14use std::borrow::Borrow;
15use std::collections::{BTreeMap, HashMap};
16use std::rc::Rc;
17
18pub trait PaxCartridge {}
19pub trait DefinitionToInstanceTraverser {
20 fn new(manifest: pax_manifest::PaxManifest) -> Self
21 where
22 Self: Sized;
23
24 fn get_manifest(&self) -> std::cell::Ref<pax_manifest::PaxManifest>;
25
26 #[cfg(any(feature = "designer", feature = "designtime"))]
27 fn get_designtime_manager(
28 &self,
29 project_query: String,
30 ) -> std::option::Option<std::rc::Rc<RefCell<pax_designtime::DesigntimeManager>>>;
31
32 fn get_main_component(&self, id: &str) -> std::rc::Rc<crate::ComponentInstance> {
33 let main_component_type_id = {
34 let manifest = self.get_manifest();
35 manifest.main_component_type_id.clone()
36 };
37
38 let wrapper_type_id = TypeId::build_singleton(id, Some("RootComponent"));
39
40 let mut args = self.build_component_args(&main_component_type_id);
41 args.template_node_identifier = Some(pax_manifest::UniqueTemplateNodeIdentifier::build(
42 wrapper_type_id,
43 pax_manifest::TemplateNodeId::build(0),
44 ));
45 let main_component = crate::ComponentInstance::instantiate(args);
46 main_component
47 }
48
49 fn get_component(
50 &mut self,
51 type_id: &pax_manifest::TypeId,
52 ) -> std::rc::Rc<dyn crate::rendering::InstanceNode> {
53 let factory = self
54 .get_component_factory(type_id)
55 .expect("Failed to get component factory");
56 let args = self.build_component_args(type_id);
57 factory.build_component(args)
58 }
59
60 fn get_component_factory(
61 &self,
62 type_id: &pax_manifest::TypeId,
63 ) -> Option<Box<dyn crate::ComponentFactory>>;
64
65 fn build_component_args(
66 &self,
67 type_id: &pax_manifest::TypeId,
68 ) -> crate::rendering::InstantiationArgs {
69 let manifest: std::cell::Ref<pax_manifest::PaxManifest> = self.get_manifest();
70 if let None = manifest.components.get(type_id) {
71 panic!("Components with type_id {} not found in manifest", type_id);
72 }
73 let component = manifest.components.get(type_id).unwrap();
74 let factory = self
75 .get_component_factory(&type_id)
76 .expect(&format!("No component factory for type: {}", type_id));
77 let prototypical_common_properties_factory = factory.build_default_common_properties();
78 let prototypical_properties_factory = factory.build_default_properties();
79
80 let handlers = manifest.get_component_handlers(type_id);
82 let handler_registry = Some(factory.build_component_handlers(handlers));
83
84 let mut component_template = None;
85 if let Some(template) = &component.template {
86 let root = template.get_root();
87 let mut instances = Vec::new();
88 for node_id in root {
89 let node = template.get_node(&node_id).unwrap();
90 match node.type_id.get_pax_type() {
91 pax_manifest::PaxType::If
92 | pax_manifest::PaxType::Slot
93 | pax_manifest::PaxType::Repeat => {
94 instances.push(self.build_control_flow(type_id, &node_id, None));
95 }
96 pax_manifest::PaxType::Comment => continue,
97 _ => {
98 instances.push(self.build_template_node(type_id, &node_id, None));
99 }
100 }
101 }
102 component_template = Some(RefCell::new(instances));
103 }
104
105 crate::rendering::InstantiationArgs {
106 prototypical_common_properties_factory,
107 prototypical_properties_factory,
108 handler_registry,
109 component_template,
110 children: None,
111 template_node_identifier: None,
112 properties_scope_factory: Some(factory.get_properties_scope_factory()),
113 }
114 }
115
116 fn build_control_flow(
117 &self,
118 containing_component_type_id: &pax_manifest::TypeId,
119 node_id: &pax_manifest::TemplateNodeId,
120 prior_node: Option<ReusableInstanceNodeArgs>,
121 ) -> std::rc::Rc<dyn crate::rendering::InstanceNode> {
122 let manifest = self.get_manifest();
123 let prototypical_common_properties_factory =
124 Box::new(|_, _| Some(std::rc::Rc::new(RefCell::new(CommonProperties::default()))));
125
126 let containing_component = manifest
127 .components
128 .get(containing_component_type_id)
129 .unwrap();
130 let containing_template = containing_component.template.as_ref().unwrap();
131 let tnd = containing_template.get_node(node_id).unwrap();
132 let unique_identifier = pax_manifest::UniqueTemplateNodeIdentifier::build(
133 containing_component_type_id.clone(),
134 node_id.clone(),
135 );
136
137 let children: RefCell<Vec<Rc<dyn InstanceNode>>> = if let Some(prior_node) = prior_node {
138 prior_node.children
139 } else {
140 RefCell::new(self.build_children(containing_component_type_id, &node_id))
141 };
142 match tnd.type_id.get_pax_type() {
143 pax_manifest::PaxType::If => {
144 let expr_info = tnd
145 .control_flow_settings
146 .as_ref()
147 .unwrap()
148 .condition_expression
149 .as_ref()
150 .unwrap()
151 .clone();
152 let prototypical_properties_factory: Box<
153 dyn Fn(
154 std::rc::Rc<crate::RuntimePropertiesStackFrame>,
155 Option<std::rc::Rc<ExpandedNode>>,
156 )
157 -> Option<std::rc::Rc<RefCell<pax_runtime_api::pax_value::PaxAny>>>,
158 > = Box::new(move |stack_frame, expanded_node| {
159 let cloned_stack = stack_frame.clone();
160 let expr_ast = expr_info.expression.clone();
161
162 let mut dependencies = Vec::new();
163 for dependency in &expr_info.dependencies {
164 if let Some(p) = stack_frame.resolve_symbol_as_erased_property(dependency) {
165 dependencies.push(p);
166 } else {
167 log::warn!("Failed to resolve symbol {}", dependency);
168 }
169 }
170
171 if let Some(expanded_node) = &expanded_node {
172 let expanded_node = borrow!(**expanded_node);
173 let outer_ref = expanded_node.properties.borrow();
174 let rc = Rc::clone(&outer_ref);
175 let mut inner_ref = (*rc).borrow_mut();
176 let cp = ConditionalProperties::mut_from_pax_any(&mut inner_ref).unwrap();
177 cp.boolean_expression
178 .replace_with(Property::computed_with_name(
179 move || {
180 let new_value = expr_ast
181 .compute(cloned_stack.clone())
182 .unwrap_or_else(|err| {
183 log::warn!("Failed to compute expression: {:?}", err);
184 Default::default()
185 });
186 let coerced =
187 bool::try_coerce(new_value).unwrap_or_else(|_e| {
188 log::warn!(
189 "Failed to parse boolean expression: {}",
190 expr_ast
191 );
192 Default::default()
193 });
194 coerced
195 },
196 &dependencies,
197 "conditional (if) expr",
198 ));
199 return None;
200 }
201
202 Some(std::rc::Rc::new(RefCell::new({
203 let mut properties = crate::ConditionalProperties::default();
204 properties.boolean_expression = Property::computed_with_name(
205 move || {
206 let new_value = expr_ast.compute(cloned_stack.clone()).unwrap();
207 let coerced = bool::try_coerce(new_value).unwrap_or_else(|_e| {
208 log::warn!("Failed to parse boolean expression: {}", expr_ast);
209 Default::default()
210 });
211 coerced
212 },
213 &dependencies,
214 "conditional (if) expr",
215 );
216 properties.to_pax_any()
217 })))
218 });
219 crate::ConditionalInstance::instantiate(crate::rendering::InstantiationArgs {
220 prototypical_common_properties_factory,
221 prototypical_properties_factory,
222 handler_registry: None,
223 component_template: None,
224 children: Some(children),
225 template_node_identifier: Some(unique_identifier),
226 properties_scope_factory: None,
227 })
228 }
229 pax_manifest::PaxType::Slot => {
230 let expr_info = tnd
231 .control_flow_settings
232 .as_ref()
233 .unwrap()
234 .slot_index_expression
235 .as_ref()
236 .unwrap()
237 .clone();
238
239 let prototypical_properties_factory: Box<
240 dyn Fn(
241 std::rc::Rc<crate::RuntimePropertiesStackFrame>,
242 Option<std::rc::Rc<ExpandedNode>>,
243 )
244 -> Option<std::rc::Rc<RefCell<pax_runtime_api::pax_value::PaxAny>>>,
245 > = Box::new(move |stack_frame, expanded_node| {
246 let cloned_stack = stack_frame.clone();
247 let expr_ast = expr_info.expression.clone();
248
249 let mut dependencies = Vec::new();
250 for dependency in &expr_info.dependencies {
251 if let Some(p) = stack_frame.resolve_symbol_as_erased_property(dependency) {
252 dependencies.push(p);
253 } else {
254 log::warn!("Failed to resolve symbol {}", dependency);
255 }
256 }
257
258 if let Some(expanded_node) = &expanded_node {
259 let expanded_node = borrow!(**expanded_node);
260 let outer_ref = expanded_node.properties.borrow();
261 let rc = Rc::clone(&outer_ref);
262 let mut inner_ref = (*rc).borrow_mut();
263 let slot_properties =
264 crate::Slot::mut_from_pax_any(&mut inner_ref).unwrap();
265 slot_properties
266 .index
267 .replace_with(Property::computed_with_name(
268 move || {
269 let new_value = expr_ast
270 .compute(cloned_stack.clone())
271 .unwrap_or_else(|op_err| {
272 log::warn!(
273 "Failed to compute expression: {:?}",
274 op_err
275 );
276 Default::default()
277 });
278 let coerced: Numeric = Numeric::try_coerce(new_value)
279 .unwrap_or_else(|_| {
280 log::warn!(
281 "Failed to parse slot index expression: {}",
282 expr_ast
283 );
284 Default::default()
285 });
286 coerced
287 },
288 &dependencies,
289 "slot index",
290 ));
291 return None;
292 }
293
294 Some(std::rc::Rc::new(RefCell::new({
295 let mut properties = crate::Slot::default();
296
297 properties.index = Property::computed_with_name(
298 move || {
299 let new_value = expr_ast
300 .compute(cloned_stack.clone())
301 .unwrap_or_else(|op_err| {
302 log::warn!("Failed to compute expression: {:?}", op_err);
303 Default::default()
304 });
305 let coerced: Numeric = Numeric::try_coerce(new_value)
306 .unwrap_or_else(|_| {
307 log::warn!(
308 "Failed to parse slot index expression: {}",
309 expr_ast
310 );
311 Default::default()
312 });
313 coerced
314 },
315 &dependencies,
316 "slot index",
317 );
318 properties.to_pax_any()
319 })))
320 });
321 crate::SlotInstance::instantiate(crate::rendering::InstantiationArgs {
322 prototypical_common_properties_factory,
323 prototypical_properties_factory,
324 handler_registry: None,
325 component_template: None,
326 children: Some(children),
327 template_node_identifier: Some(unique_identifier),
328 properties_scope_factory: None,
329 })
330 }
331 pax_manifest::PaxType::Repeat => {
332 let source_expression_info = tnd
333 .control_flow_settings
334 .as_ref()
335 .unwrap()
336 .repeat_source_expression
337 .clone()
338 .unwrap();
339 let predictate_definition = tnd
340 .control_flow_settings
341 .as_ref()
342 .unwrap()
343 .repeat_predicate_definition
344 .clone()
345 .unwrap();
346 let prototypical_properties_factory: Box<
347 dyn Fn(
348 std::rc::Rc<crate::RuntimePropertiesStackFrame>,
349 Option<std::rc::Rc<ExpandedNode>>,
350 )
351 -> Option<std::rc::Rc<RefCell<pax_runtime_api::pax_value::PaxAny>>>,
352 > = Box::new(move |stack_frame, expanded_node| {
353 let cloned_stack = stack_frame.clone();
354 let expr = source_expression_info.expression.clone();
355 let deps = source_expression_info.dependencies.clone();
356
357 let mut dependencies = Vec::new();
358 for dependency in &deps {
359 if let Some(p) = stack_frame.resolve_symbol_as_erased_property(dependency) {
360 dependencies.push(p);
361 } else {
362 log::warn!("Failed to resolve symbol {}", dependency);
363 }
364 }
365
366 let (elem, index) = match &predictate_definition {
367 pax_manifest::ControlFlowRepeatPredicateDefinition::ElemId(id) => {
368 (Some(id.clone()), None)
369 }
370 pax_manifest::ControlFlowRepeatPredicateDefinition::ElemIdIndexId(
371 t1,
372 t2,
373 ) => (Some(t1.clone()), Some(t2.clone())),
374 };
375
376 if let Some(expanded_node) = &expanded_node {
377 let expanded_node = borrow!(**expanded_node);
378 let outer_ref = expanded_node.properties.borrow();
379 let rc = Rc::clone(&outer_ref);
380 let mut inner_ref = (*rc).borrow_mut();
381 let repeat =
382 crate::RepeatProperties::mut_from_pax_any(&mut inner_ref).unwrap();
383 repeat
384 .source_expression
385 .replace_with(Property::computed_with_name(
386 move || {
387 expr.compute(cloned_stack.clone()).unwrap_or_else(|op_err| {
388 log::warn!("Failed to compute expression: {:?}", op_err);
389 Default::default()
390 })
391 },
392 &dependencies,
393 "repeat source vec",
394 ));
395 repeat.iterator_i_symbol.replace_with(Property::new(index));
396 repeat
397 .iterator_elem_symbol
398 .replace_with(Property::new(elem));
399 return None;
400 }
401
402 Some(std::rc::Rc::new(RefCell::new({
403 let mut properties = crate::RepeatProperties::default();
404
405 properties.source_expression = Property::computed_with_name(
406 move || {
407 expr.compute(cloned_stack.clone()).unwrap_or_else(|op_err| {
408 log::warn!("Failed to compute expression: {:?}", op_err);
409 Default::default()
410 })
411 },
412 &dependencies,
413 "repeat source vec",
414 );
415
416 properties
417 .iterator_i_symbol
418 .replace_with(Property::new(index));
419 properties
420 .iterator_elem_symbol
421 .replace_with(Property::new(elem));
422 properties.to_pax_any()
423 })))
424 });
425 crate::RepeatInstance::instantiate(crate::rendering::InstantiationArgs {
426 prototypical_common_properties_factory,
427 prototypical_properties_factory,
428 handler_registry: None,
429 component_template: None,
430 children: Some(children),
431 template_node_identifier: Some(unique_identifier),
432 properties_scope_factory: None,
433 })
434 }
435 _ => {
436 unreachable!("Unexpected control flow type {}", tnd.type_id)
437 }
438 }
439 }
440
441 fn build_children(
442 &self,
443 containing_component_type_id: &pax_manifest::TypeId,
444 node_id: &pax_manifest::TemplateNodeId,
445 ) -> Vec<std::rc::Rc<dyn crate::rendering::InstanceNode>> {
446 let manifest = self.get_manifest();
447 let containing_component = manifest
448 .components
449 .get(containing_component_type_id)
450 .unwrap();
451 let containing_template = containing_component.template.as_ref().unwrap();
452 let children = containing_template.get_children(node_id);
453
454 let mut children_instances = Vec::new();
455 for child_id in &children.unwrap_or_default() {
456 let child = containing_template.get_node(&child_id).unwrap();
457 match child.type_id.get_pax_type() {
458 pax_manifest::PaxType::If
459 | pax_manifest::PaxType::Slot
460 | pax_manifest::PaxType::Repeat => {
461 children_instances.push(self.build_control_flow(
462 containing_component_type_id,
463 &child_id,
464 None,
465 ));
466 }
467 pax_manifest::PaxType::Comment => continue,
468 _ => {
469 children_instances.push(self.build_template_node(
470 containing_component_type_id,
471 child_id,
472 None,
473 ));
474 }
475 }
476 }
477 children_instances
478 }
479
480 fn build_template_node(
481 &self,
482 containing_component_type_id: &pax_manifest::TypeId,
483 node_id: &pax_manifest::TemplateNodeId,
484 prior_node: Option<ReusableInstanceNodeArgs>,
485 ) -> std::rc::Rc<dyn crate::rendering::InstanceNode> {
486 let manifest = self.get_manifest();
487
488 let containing_component = manifest
489 .components
490 .get(containing_component_type_id)
491 .unwrap();
492 let containing_template = containing_component.template.as_ref().unwrap();
493 let node = containing_template.get_node(node_id).unwrap();
494 let containing_component_factory = self
495 .get_component_factory(containing_component_type_id)
496 .unwrap();
497
498 let mut args = self.build_component_args(&node.type_id);
499 let node_component_factory = self.get_component_factory(&node.type_id).unwrap();
500
501 if let Some(prior_node) = prior_node {
502 args.handler_registry = prior_node.handler_registry;
503 args.children = Some(prior_node.children);
504 args.template_node_identifier = prior_node.template_node_identifier;
505 } else {
506 let handlers_from_tnd = manifest.get_inline_event_handlers(node);
507 let updated_registry = if let Some(registry) = args.handler_registry {
508 containing_component_factory.add_inline_handlers(handlers_from_tnd, registry)
509 } else {
510 containing_component_factory.add_inline_handlers(
511 handlers_from_tnd,
512 std::rc::Rc::new(RefCell::new(crate::HandlerRegistry::default())),
513 )
514 };
515 args.handler_registry = Some(updated_registry);
517
518 args.children = Some(RefCell::new(
520 self.build_children(containing_component_type_id, node_id),
521 ));
522
523 args.template_node_identifier =
525 Some(pax_manifest::UniqueTemplateNodeIdentifier::build(
526 containing_component_type_id.clone(),
527 node_id.clone(),
528 ));
529 }
530
531 let inline_properties = manifest.get_inline_properties(containing_component_type_id, node);
533 let updated_properties =
534 node_component_factory.build_inline_properties(inline_properties.clone());
535 args.prototypical_properties_factory = updated_properties;
536
537 let updated_common_properties =
539 node_component_factory.build_inline_common_properties(inline_properties);
540 args.prototypical_common_properties_factory = updated_common_properties;
541
542 node_component_factory.build_component(args)
543 }
544
545 fn get_template_node_by_id(
546 &self,
547 id: &str,
548 ) -> Option<std::rc::Rc<dyn crate::rendering::InstanceNode>> {
549 let manifest = self.get_manifest();
550 let main_component_type_id = manifest.main_component_type_id.clone();
551 let main_component = manifest.components.get(&main_component_type_id).unwrap();
552 let template = main_component.template.as_ref().unwrap();
553 for node_id in template.get_ids() {
554 if let Some(found) =
555 self.recurse_get_template_node_by_id(id, &main_component_type_id, node_id)
556 {
557 return Some(self.build_template_node(&found.0, &found.1, None));
558 }
559 }
560 None
561 }
562
563 fn check_for_id_in_template_node(
564 &self,
565 id: &str,
566 tnd: &pax_manifest::TemplateNodeDefinition,
567 ) -> bool {
568 if let Some(settings) = &tnd.settings {
569 for setting in settings {
570 if let pax_manifest::SettingElement::Setting(token, value) = setting {
571 if &token.token_value == "id" {
572 if let pax_manifest::ValueDefinition::Identifier(ident) = value {
573 if ident.name == id {
574 return true;
575 }
576 }
577 }
578 }
579 }
580 }
581 false
582 }
583
584 fn recurse_get_template_node_by_id<'a>(
585 &'a self,
586 id: &str,
587 containing_component_type_id: &'a pax_manifest::TypeId,
588 node_id: &'a pax_manifest::TemplateNodeId,
589 ) -> Option<(pax_manifest::TypeId, pax_manifest::TemplateNodeId)> {
590 let manifest = self.get_manifest();
591 let containing_component = manifest
592 .components
593 .get(containing_component_type_id)
594 .unwrap();
595 let containing_template = containing_component.template.as_ref().unwrap();
596 let tnd = containing_template.get_node(node_id).unwrap();
597
598 if self.check_for_id_in_template_node(id, tnd) {
599 return Some((containing_component_type_id.clone(), node_id.clone()));
600 }
601
602 if let Some(component) = &manifest.components.get(&tnd.type_id) {
603 if let Some(template) = &component.template {
604 for node_id in template.get_ids() {
605 if let Some(found) =
606 self.recurse_get_template_node_by_id(id, &tnd.type_id, node_id)
607 {
608 return Some(found.clone());
609 }
610 }
611 }
612 }
613 None
614 }
615}
616
617fn resolve_property<T: CoercionRules + PropertyValue + DeserializeOwned>(
618 name: &str,
619 defined_properties: &BTreeMap<String, ValueDefinition>,
620 stack: &Rc<RuntimePropertiesStackFrame>,
621) -> Property<Option<T>> {
622 let Some(value_def) = defined_properties.get(name) else {
623 return Property::default();
624 };
625 let cloned_stack = stack.clone();
626 let resolved_property: Property<Option<T>> = match value_def.clone() {
627 pax_manifest::ValueDefinition::LiteralValue(lv) => {
628 let val = T::try_coerce(lv).unwrap_or_else(|err| {
629 log::warn!("Failed to coerce new value for property. Error: {:?}", err);
630 Default::default()
631 });
632 Property::new_with_name(Some(val), name)
633 }
634 pax_manifest::ValueDefinition::DoubleBinding(identifier) => {
635 let untyped_property =
636 if let Some(p) = stack.resolve_symbol_as_erased_property(&identifier.name) {
637 p
638 } else {
639 log::warn!("Failed to resolve symbol {}", identifier.name);
640 return Default::default();
641 };
642 Property::new_from_untyped(untyped_property.clone())
643 }
644 pax_manifest::ValueDefinition::Expression(info) => {
645 let mut dependents = vec![];
646 for dependency in &info.dependencies {
647 if let Some(p) = stack.resolve_symbol_as_erased_property(dependency) {
648 dependents.push(p);
649 } else {
650 log::warn!("Failed to resolve symbol {}", dependency);
651 }
652 }
653 let name = &info.expression.to_string();
654 Property::computed_with_name(
655 move || {
656 let new_value = info
657 .expression
658 .compute(cloned_stack.clone())
659 .unwrap_or_else(|err| {
660 log::warn!("Failed to compute expression: {:?}", err);
661 Default::default()
662 });
663 let coerced = T::try_coerce(new_value.clone()).unwrap_or_else(|err| {
664 log::warn!("Failed to coerce new value for property. Error: {:?}", err);
665 Default::default()
666 });
667 Some(coerced)
668 },
669 &dependents,
670 name,
671 )
672 }
673 pax_manifest::ValueDefinition::Identifier(ident) => {
674 let property = if let Some(p) = stack.resolve_symbol_as_erased_property(&ident.name) {
675 Property::new_from_untyped(p.clone())
676 } else {
677 log::warn!("Failed to resolve symbol {}", ident.name);
678 return Default::default();
679 };
680 let untyped = property.untyped();
681 Property::computed_with_name(
682 move || {
683 let new_value = property.get();
684 Some(new_value)
685 },
686 &[untyped],
687 &ident.name,
688 )
689 }
690 _ => unreachable!("Invalid value definition for {}", stringify!($prop_name)),
691 };
692 resolved_property
693}
694
695pub trait ComponentFactory {
696 fn build_default_common_properties(
698 &self,
699 ) -> Box<
700 dyn Fn(
701 Rc<RuntimePropertiesStackFrame>,
702 Option<Rc<ExpandedNode>>,
703 ) -> Option<Rc<RefCell<CommonProperties>>>,
704 > {
705 Box::new(|_, _| Some(Rc::new(RefCell::new(CommonProperties::default()))))
706 }
707
708 fn build_default_properties(
710 &self,
711 ) -> Box<
712 dyn Fn(
713 Rc<RuntimePropertiesStackFrame>,
714 Option<Rc<ExpandedNode>>,
715 ) -> Option<Rc<RefCell<PaxAny>>>,
716 >;
717
718 fn build_inline_common_properties(
719 &self,
720 defined_properties: BTreeMap<String, pax_manifest::ValueDefinition>,
721 ) -> Box<
722 dyn Fn(
723 Rc<RuntimePropertiesStackFrame>,
724 Option<Rc<ExpandedNode>>,
725 ) -> Option<Rc<RefCell<CommonProperties>>>,
726 > {
727 Box::new(move |stack_frame, expanded_node| {
728 if let Some(expanded_node) = &expanded_node {
729 update_existing_common_properties(expanded_node, &defined_properties, &stack_frame);
730 None
731 } else {
732 Some(create_new_common_properties(
733 &defined_properties,
734 &stack_frame,
735 ))
736 }
737 })
738 }
739
740 fn build_inline_properties(
742 &self,
743 defined_properties: BTreeMap<String, ValueDefinition>,
744 ) -> Box<
745 dyn Fn(
746 Rc<RuntimePropertiesStackFrame>,
747 Option<Rc<ExpandedNode>>,
748 ) -> Option<Rc<RefCell<PaxAny>>>,
749 >;
750
751 fn build_handler(&self, fn_name: &str)
754 -> fn(Rc<RefCell<PaxAny>>, &NodeContext, Option<PaxAny>);
755
756 fn build_component_handlers(
758 &self,
759 handlers: Vec<(String, Vec<String>)>,
760 ) -> Rc<RefCell<HandlerRegistry>>;
761
762 fn add_inline_handlers(
764 &self,
765 handlers: Vec<(String, String)>,
766 registry: Rc<RefCell<HandlerRegistry>>,
767 ) -> Rc<RefCell<HandlerRegistry>>;
768
769 fn build_component(&self, args: InstantiationArgs) -> Rc<dyn InstanceNode>;
771
772 fn get_properties_scope_factory(
774 &self,
775 ) -> Box<dyn Fn(Rc<RefCell<PaxAny>>) -> HashMap<String, Variable>> {
776 Box::new(|_| HashMap::new())
777 }
778}
779
780fn update_existing_common_properties(
781 expanded_node: &Rc<ExpandedNode>,
782 defined_properties: &BTreeMap<String, pax_manifest::ValueDefinition>,
783 stack_frame: &Rc<RuntimePropertiesStackFrame>,
784) {
785 let expanded_node = borrow!(**expanded_node);
786 let outer_ref = expanded_node.common_properties.borrow();
787 let rc = Rc::clone(&outer_ref);
788 let inner_ref = (*rc).borrow_mut();
789 let mut cp = inner_ref;
790
791 update_common_properties(&mut cp, defined_properties, stack_frame);
792}
793
794fn create_id_property(
795 defined_properties: &BTreeMap<String, pax_manifest::ValueDefinition>,
796) -> Property<Option<String>> {
797 let id = defined_properties.get("id");
798 Property::new(
799 if let Some(pax_manifest::ValueDefinition::Identifier(pax_identifier)) = id {
800 Some(pax_identifier.name.clone())
801 } else {
802 None
803 },
804 )
805}
806
807fn create_new_common_properties(
808 defined_properties: &BTreeMap<String, pax_manifest::ValueDefinition>,
809 stack_frame: &Rc<RuntimePropertiesStackFrame>,
810) -> Rc<RefCell<CommonProperties>> {
811 Rc::new(RefCell::new(CommonProperties {
812 id: create_id_property(defined_properties),
813 x: resolve_property("x", defined_properties, stack_frame),
814 y: resolve_property("y", defined_properties, stack_frame),
815 width: resolve_property("width", defined_properties, stack_frame),
816 height: resolve_property("height", defined_properties, stack_frame),
817 scale_x: resolve_property("scale_x", defined_properties, stack_frame),
818 scale_y: resolve_property("scale_y", defined_properties, stack_frame),
819 skew_x: resolve_property("skew_x", defined_properties, stack_frame),
820 skew_y: resolve_property("skew_y", defined_properties, stack_frame),
821 rotate: resolve_property("rotate", defined_properties, stack_frame),
822 transform: resolve_property("transform", defined_properties, stack_frame),
823 anchor_x: resolve_property("anchor_x", defined_properties, stack_frame),
824 anchor_y: resolve_property("anchor_y", defined_properties, stack_frame),
825 unclippable: resolve_property("unclippable", defined_properties, stack_frame),
826 _raycastable: resolve_property("_raycastable", defined_properties, stack_frame),
827 _suspended: resolve_property("_suspended", defined_properties, stack_frame),
828 }))
829}
830
831fn update_common_properties(
832 cp: &mut CommonProperties,
833 defined_properties: &BTreeMap<String, pax_manifest::ValueDefinition>,
834 stack_frame: &Rc<RuntimePropertiesStackFrame>,
835) {
836 cp.id.replace_with(create_id_property(defined_properties));
837 cp.x.replace_with(resolve_property("x", defined_properties, stack_frame));
838 cp.y.replace_with(resolve_property("y", defined_properties, stack_frame));
839 cp.width
840 .replace_with(resolve_property("width", defined_properties, stack_frame));
841 cp.height
842 .replace_with(resolve_property("height", defined_properties, stack_frame));
843 cp.scale_x
844 .replace_with(resolve_property("scale_x", defined_properties, stack_frame));
845 cp.scale_y
846 .replace_with(resolve_property("scale_y", defined_properties, stack_frame));
847 cp.skew_x
848 .replace_with(resolve_property("skew_x", defined_properties, stack_frame));
849 cp.skew_y
850 .replace_with(resolve_property("skew_y", defined_properties, stack_frame));
851 cp.rotate
852 .replace_with(resolve_property("rotate", defined_properties, stack_frame));
853 cp.transform.replace_with(resolve_property(
854 "transform",
855 defined_properties,
856 stack_frame,
857 ));
858 cp.anchor_x.replace_with(resolve_property(
859 "anchor_x",
860 defined_properties,
861 stack_frame,
862 ));
863 cp.anchor_y.replace_with(resolve_property(
864 "anchor_y",
865 defined_properties,
866 stack_frame,
867 ));
868 cp.unclippable.replace_with(resolve_property(
869 "unclippable",
870 defined_properties,
871 stack_frame,
872 ));
873 cp._raycastable.replace_with(resolve_property(
874 "_raycastable",
875 defined_properties,
876 stack_frame,
877 ));
878 cp._suspended.replace_with(resolve_property(
879 "_suspended",
880 defined_properties,
881 stack_frame,
882 ));
883}