1use std::collections::HashMap;
12use std::sync::LazyLock;
13
14use crate::Effect;
15use crate::Type;
16use crate::object_shape::*;
17use crate::type_config::AliasingEffectConfig;
18use crate::type_config::AliasingSignatureConfig;
19use crate::type_config::ApplyArgConfig;
20use crate::type_config::ApplyArgHoleKind;
21use crate::type_config::BuiltInTypeRef;
22use crate::type_config::TypeConfig;
23use crate::type_config::TypeReferenceConfig;
24use crate::type_config::ValueKind;
25use crate::type_config::ValueReason;
26
27pub type Global = Type;
30
31pub struct GlobalRegistry {
40 base: Option<&'static HashMap<String, Global>>,
41 entries: HashMap<String, Global>,
42}
43
44impl GlobalRegistry {
45 pub fn new() -> Self {
47 Self {
48 base: None,
49 entries: HashMap::new(),
50 }
51 }
52
53 pub fn with_base(base: &'static HashMap<String, Global>) -> Self {
55 Self {
56 base: Some(base),
57 entries: HashMap::new(),
58 }
59 }
60
61 pub fn get(&self, key: &str) -> Option<&Global> {
62 self.entries
63 .get(key)
64 .or_else(|| self.base.and_then(|b| b.get(key)))
65 }
66
67 pub fn insert(&mut self, key: String, value: Global) {
68 self.entries.insert(key, value);
69 }
70
71 pub fn contains_key(&self, key: &str) -> bool {
72 self.entries.contains_key(key) || self.base.map_or(false, |b| b.contains_key(key))
73 }
74
75 pub fn keys(&self) -> impl Iterator<Item = &String> {
78 let base_keys = self
79 .base
80 .into_iter()
81 .flat_map(|b| b.keys())
82 .filter(|k| !self.entries.contains_key(k.as_str()));
83 self.entries.keys().chain(base_keys)
84 }
85
86 pub fn into_inner(self) -> HashMap<String, Global> {
89 debug_assert!(
90 self.base.is_none(),
91 "into_inner() called on overlay-mode GlobalRegistry"
92 );
93 self.entries
94 }
95}
96
97impl Clone for GlobalRegistry {
98 fn clone(&self) -> Self {
99 Self {
100 base: self.base,
101 entries: self.entries.clone(),
102 }
103 }
104}
105
106struct BaseRegistries {
111 shapes: HashMap<String, ObjectShape>,
112 globals: HashMap<String, Global>,
113}
114
115static BASE: LazyLock<BaseRegistries> = LazyLock::new(|| {
116 let mut shapes = build_builtin_shapes();
117 let globals = build_default_globals(&mut shapes);
118 BaseRegistries {
119 shapes: shapes.into_inner(),
120 globals: globals.into_inner(),
121 }
122});
123
124pub fn base_shapes() -> &'static HashMap<String, ObjectShape> {
126 &BASE.shapes
127}
128
129pub fn base_globals() -> &'static HashMap<String, Global> {
131 &BASE.globals
132}
133
134pub fn install_type_config(
143 _globals: &mut GlobalRegistry,
144 shapes: &mut ShapeRegistry,
145 type_config: &TypeConfig,
146 module_name: &str,
147 _loc: (),
148) -> Global {
149 install_type_config_inner(_globals, shapes, type_config, module_name, _loc, &mut None)
150}
151
152pub fn install_type_config_with_errors(
154 _globals: &mut GlobalRegistry,
155 shapes: &mut ShapeRegistry,
156 type_config: &TypeConfig,
157 module_name: &str,
158 _loc: (),
159 errors: &mut Vec<String>,
160) -> Global {
161 install_type_config_inner(
162 _globals,
163 shapes,
164 type_config,
165 module_name,
166 _loc,
167 &mut Some(errors),
168 )
169}
170
171fn install_type_config_inner(
172 _globals: &mut GlobalRegistry,
173 shapes: &mut ShapeRegistry,
174 type_config: &TypeConfig,
175 module_name: &str,
176 _loc: (),
177 errors: &mut Option<&mut Vec<String>>,
178) -> Global {
179 match type_config {
180 TypeConfig::TypeReference(TypeReferenceConfig { name }) => match name {
181 BuiltInTypeRef::Array => Type::Object {
182 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
183 },
184 BuiltInTypeRef::MixedReadonly => Type::Object {
185 shape_id: Some(BUILT_IN_MIXED_READONLY_ID.to_string()),
186 },
187 BuiltInTypeRef::Primitive => Type::Primitive,
188 BuiltInTypeRef::Ref => Type::Object {
189 shape_id: Some(BUILT_IN_USE_REF_ID.to_string()),
190 },
191 BuiltInTypeRef::Any => Type::Poly,
192 },
193 TypeConfig::Function(func_config) => {
194 let return_type = install_type_config_inner(
196 _globals,
197 shapes,
198 &func_config.return_type,
199 module_name,
200 (),
201 errors,
202 );
203 add_function(
204 shapes,
205 Vec::new(),
206 FunctionSignatureBuilder {
207 positional_params: func_config.positional_params.clone(),
208 rest_param: func_config.rest_param,
209 callee_effect: func_config.callee_effect,
210 return_type,
211 return_value_kind: func_config.return_value_kind,
212 no_alias: func_config.no_alias.unwrap_or(false),
213 mutable_only_if_operands_are_mutable: func_config
214 .mutable_only_if_operands_are_mutable
215 .unwrap_or(false),
216 impure: func_config.impure.unwrap_or(false),
217 canonical_name: func_config.canonical_name.clone(),
218 aliasing: func_config.aliasing.clone(),
219 known_incompatible: func_config.known_incompatible.clone(),
220 ..Default::default()
221 },
222 None,
223 false,
224 )
225 }
226 TypeConfig::Hook(hook_config) => {
227 let return_type = install_type_config_inner(
229 _globals,
230 shapes,
231 &hook_config.return_type,
232 module_name,
233 (),
234 errors,
235 );
236 add_hook(
237 shapes,
238 HookSignatureBuilder {
239 hook_kind: HookKind::Custom,
240 positional_params: hook_config.positional_params.clone().unwrap_or_default(),
241 rest_param: hook_config.rest_param.or(Some(Effect::Freeze)),
242 callee_effect: Effect::Read,
243 return_type,
244 return_value_kind: hook_config.return_value_kind.unwrap_or(ValueKind::Frozen),
245 no_alias: hook_config.no_alias.unwrap_or(false),
246 aliasing: hook_config.aliasing.clone(),
247 known_incompatible: hook_config.known_incompatible.clone(),
248 ..Default::default()
249 },
250 None,
251 )
252 }
253 TypeConfig::Object(obj_config) => {
254 let properties: Vec<(String, Type)> = obj_config
255 .properties
256 .as_ref()
257 .map(|props| {
258 props
259 .iter()
260 .map(|(key, value)| {
261 let ty = install_type_config_inner(
262 _globals,
263 shapes,
264 value,
265 module_name,
266 (),
267 errors,
268 );
269 if let Some(errs) = errors {
271 let expect_hook = crate::environment::is_hook_name(key);
272 let is_hook = match &ty {
273 Type::Function { shape_id: Some(id), .. } => {
274 shapes.get(id)
275 .and_then(|shape| shape.function_type.as_ref())
276 .and_then(|ft| ft.hook_kind.as_ref())
277 .is_some()
278 }
279 _ => false,
280 };
281 if expect_hook != is_hook {
282 errs.push(format!(
283 "Expected type for object property '{}' from module '{}' {} based on the property name",
284 key,
285 module_name,
286 if expect_hook { "to be a hook" } else { "not to be a hook" }
287 ));
288 }
289 }
290 (key.clone(), ty)
291 })
292 .collect()
293 })
294 .unwrap_or_default();
295 add_object(shapes, None, properties)
296 }
297 }
298}
299
300pub fn build_builtin_shapes() -> ShapeRegistry {
307 let mut shapes = ShapeRegistry::new();
308
309 add_object(
311 &mut shapes,
312 Some(BUILT_IN_PROPS_ID),
313 vec![(
314 "ref".to_string(),
315 Type::Object {
316 shape_id: Some(BUILT_IN_USE_REF_ID.to_string()),
317 },
318 )],
319 );
320
321 build_array_shape(&mut shapes);
322 build_set_shape(&mut shapes);
323 build_map_shape(&mut shapes);
324 build_weak_set_shape(&mut shapes);
325 build_weak_map_shape(&mut shapes);
326 build_object_shape(&mut shapes);
327 build_ref_shapes(&mut shapes);
328 build_state_shapes(&mut shapes);
329 build_hook_shapes(&mut shapes);
330 build_misc_shapes(&mut shapes);
331
332 shapes
333}
334
335fn simple_function(
336 shapes: &mut ShapeRegistry,
337 positional_params: Vec<Effect>,
338 rest_param: Option<Effect>,
339 return_type: Type,
340 return_value_kind: ValueKind,
341) -> Type {
342 add_function(
343 shapes,
344 Vec::new(),
345 FunctionSignatureBuilder {
346 positional_params,
347 rest_param,
348 return_type,
349 return_value_kind,
350 ..Default::default()
351 },
352 None,
353 false,
354 )
355}
356
357fn pure_primitive_fn(shapes: &mut ShapeRegistry) -> Type {
359 simple_function(
360 shapes,
361 Vec::new(),
362 Some(Effect::Read),
363 Type::Primitive,
364 ValueKind::Primitive,
365 )
366}
367
368fn build_array_shape(shapes: &mut ShapeRegistry) {
369 let index_of = pure_primitive_fn(shapes);
370 let includes = pure_primitive_fn(shapes);
371 let pop = add_function(
372 shapes,
373 Vec::new(),
374 FunctionSignatureBuilder {
375 callee_effect: Effect::Store,
376 return_type: Type::Poly,
377 return_value_kind: ValueKind::Mutable,
378 ..Default::default()
379 },
380 None,
381 false,
382 );
383 let at = add_function(
384 shapes,
385 Vec::new(),
386 FunctionSignatureBuilder {
387 positional_params: vec![Effect::Read],
388 callee_effect: Effect::Capture,
389 return_type: Type::Poly,
390 return_value_kind: ValueKind::Mutable,
391 ..Default::default()
392 },
393 None,
394 false,
395 );
396 let concat = add_function(
397 shapes,
398 Vec::new(),
399 FunctionSignatureBuilder {
400 rest_param: Some(Effect::Capture),
401 return_type: Type::Object {
402 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
403 },
404 return_value_kind: ValueKind::Mutable,
405 callee_effect: Effect::Capture,
406 ..Default::default()
407 },
408 None,
409 false,
410 );
411 let join = pure_primitive_fn(shapes);
412 let slice = add_function(
413 shapes,
414 Vec::new(),
415 FunctionSignatureBuilder {
416 rest_param: Some(Effect::Read),
417 callee_effect: Effect::Capture,
418 return_type: Type::Object {
419 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
420 },
421 return_value_kind: ValueKind::Mutable,
422 ..Default::default()
423 },
424 None,
425 false,
426 );
427 let map = add_function(
428 shapes,
429 Vec::new(),
430 FunctionSignatureBuilder {
431 rest_param: Some(Effect::ConditionallyMutate),
432 callee_effect: Effect::ConditionallyMutate,
433 return_type: Type::Object {
434 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
435 },
436 return_value_kind: ValueKind::Mutable,
437 no_alias: true,
438 mutable_only_if_operands_are_mutable: true,
439 aliasing: Some(AliasingSignatureConfig {
440 receiver: "@receiver".to_string(),
441 params: vec!["@callback".to_string()],
442 rest: None,
443 returns: "@returns".to_string(),
444 temporaries: vec![
445 "@item".to_string(),
446 "@callbackReturn".to_string(),
447 "@thisArg".to_string(),
448 ],
449 effects: vec![
450 AliasingEffectConfig::Create {
452 into: "@returns".to_string(),
453 value: ValueKind::Mutable,
454 reason: ValueReason::KnownReturnSignature,
455 },
456 AliasingEffectConfig::CreateFrom {
458 from: "@receiver".to_string(),
459 into: "@item".to_string(),
460 },
461 AliasingEffectConfig::Create {
463 into: "@thisArg".to_string(),
464 value: ValueKind::Primitive,
465 reason: ValueReason::KnownReturnSignature,
466 },
467 AliasingEffectConfig::Apply {
469 receiver: "@thisArg".to_string(),
470 function: "@callback".to_string(),
471 mutates_function: false,
472 args: vec![
473 ApplyArgConfig::Place("@item".to_string()),
474 ApplyArgConfig::Hole {
475 kind: ApplyArgHoleKind::Hole,
476 },
477 ApplyArgConfig::Place("@receiver".to_string()),
478 ],
479 into: "@callbackReturn".to_string(),
480 },
481 AliasingEffectConfig::Capture {
483 from: "@callbackReturn".to_string(),
484 into: "@returns".to_string(),
485 },
486 ],
487 }),
488 ..Default::default()
489 },
490 None,
491 false,
492 );
493 let filter = add_function(
494 shapes,
495 Vec::new(),
496 FunctionSignatureBuilder {
497 rest_param: Some(Effect::ConditionallyMutate),
498 callee_effect: Effect::ConditionallyMutate,
499 return_type: Type::Object {
500 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
501 },
502 return_value_kind: ValueKind::Mutable,
503 no_alias: true,
504 mutable_only_if_operands_are_mutable: true,
505 ..Default::default()
506 },
507 None,
508 false,
509 );
510 let find = add_function(
511 shapes,
512 Vec::new(),
513 FunctionSignatureBuilder {
514 rest_param: Some(Effect::ConditionallyMutate),
515 callee_effect: Effect::ConditionallyMutate,
516 return_type: Type::Poly,
517 return_value_kind: ValueKind::Mutable,
518 no_alias: true,
519 mutable_only_if_operands_are_mutable: true,
520 ..Default::default()
521 },
522 None,
523 false,
524 );
525 let find_index = add_function(
526 shapes,
527 Vec::new(),
528 FunctionSignatureBuilder {
529 rest_param: Some(Effect::ConditionallyMutate),
530 callee_effect: Effect::ConditionallyMutate,
531 return_type: Type::Primitive,
532 return_value_kind: ValueKind::Primitive,
533 no_alias: true,
534 mutable_only_if_operands_are_mutable: true,
535 ..Default::default()
536 },
537 None,
538 false,
539 );
540 let every = add_function(
541 shapes,
542 Vec::new(),
543 FunctionSignatureBuilder {
544 rest_param: Some(Effect::ConditionallyMutate),
545 callee_effect: Effect::ConditionallyMutate,
546 return_type: Type::Primitive,
547 return_value_kind: ValueKind::Primitive,
548 no_alias: true,
549 mutable_only_if_operands_are_mutable: true,
550 ..Default::default()
551 },
552 None,
553 false,
554 );
555 let some = add_function(
556 shapes,
557 Vec::new(),
558 FunctionSignatureBuilder {
559 rest_param: Some(Effect::ConditionallyMutate),
560 callee_effect: Effect::ConditionallyMutate,
561 return_type: Type::Primitive,
562 return_value_kind: ValueKind::Primitive,
563 no_alias: true,
564 mutable_only_if_operands_are_mutable: true,
565 ..Default::default()
566 },
567 None,
568 false,
569 );
570 let flat_map = add_function(
571 shapes,
572 Vec::new(),
573 FunctionSignatureBuilder {
574 rest_param: Some(Effect::ConditionallyMutate),
575 callee_effect: Effect::ConditionallyMutate,
576 return_type: Type::Object {
577 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
578 },
579 return_value_kind: ValueKind::Mutable,
580 no_alias: true,
581 mutable_only_if_operands_are_mutable: true,
582 ..Default::default()
583 },
584 None,
585 false,
586 );
587 let length = Type::Primitive;
588 let push = add_function(
589 shapes,
590 Vec::new(),
591 FunctionSignatureBuilder {
592 rest_param: Some(Effect::Capture),
593 callee_effect: Effect::Store,
594 return_type: Type::Primitive,
595 return_value_kind: ValueKind::Primitive,
596 aliasing: Some(AliasingSignatureConfig {
597 receiver: "@receiver".to_string(),
598 params: Vec::new(),
599 rest: Some("@rest".to_string()),
600 returns: "@returns".to_string(),
601 temporaries: Vec::new(),
602 effects: vec![
603 AliasingEffectConfig::Mutate {
605 value: "@receiver".to_string(),
606 },
607 AliasingEffectConfig::Capture {
609 from: "@rest".to_string(),
610 into: "@receiver".to_string(),
611 },
612 AliasingEffectConfig::Create {
614 into: "@returns".to_string(),
615 value: ValueKind::Primitive,
616 reason: ValueReason::KnownReturnSignature,
617 },
618 ],
619 }),
620 ..Default::default()
621 },
622 None,
623 false,
624 );
625
626 add_object(
627 shapes,
628 Some(BUILT_IN_ARRAY_ID),
629 vec![
630 ("indexOf".to_string(), index_of),
631 ("includes".to_string(), includes),
632 ("pop".to_string(), pop),
633 ("at".to_string(), at),
634 ("concat".to_string(), concat),
635 ("length".to_string(), length),
636 ("push".to_string(), push),
637 ("slice".to_string(), slice),
638 ("map".to_string(), map),
639 ("flatMap".to_string(), flat_map),
640 ("filter".to_string(), filter),
641 ("every".to_string(), every),
642 ("some".to_string(), some),
643 ("find".to_string(), find),
644 ("findIndex".to_string(), find_index),
645 ("join".to_string(), join),
646 ],
648 );
649}
650
651fn build_set_shape(shapes: &mut ShapeRegistry) {
652 let has = add_function(
653 shapes,
654 Vec::new(),
655 FunctionSignatureBuilder {
656 positional_params: vec![Effect::Read],
657 return_type: Type::Primitive,
658 return_value_kind: ValueKind::Primitive,
659 ..Default::default()
660 },
661 None,
662 false,
663 );
664 let add = add_function(
665 shapes,
666 Vec::new(),
667 FunctionSignatureBuilder {
668 positional_params: vec![Effect::Capture],
669 callee_effect: Effect::Store,
670 return_type: Type::Object {
671 shape_id: Some(BUILT_IN_SET_ID.to_string()),
672 },
673 return_value_kind: ValueKind::Mutable,
674 aliasing: Some(AliasingSignatureConfig {
675 receiver: "@receiver".to_string(),
676 params: Vec::new(),
677 rest: Some("@rest".to_string()),
678 returns: "@returns".to_string(),
679 temporaries: Vec::new(),
680 effects: vec![
681 AliasingEffectConfig::Assign {
683 from: "@receiver".to_string(),
684 into: "@returns".to_string(),
685 },
686 AliasingEffectConfig::Mutate {
688 value: "@receiver".to_string(),
689 },
690 AliasingEffectConfig::Capture {
692 from: "@rest".to_string(),
693 into: "@receiver".to_string(),
694 },
695 ],
696 }),
697 ..Default::default()
698 },
699 None,
700 false,
701 );
702 let clear = add_function(
703 shapes,
704 Vec::new(),
705 FunctionSignatureBuilder {
706 callee_effect: Effect::Store,
707 return_type: Type::Primitive,
708 return_value_kind: ValueKind::Primitive,
709 ..Default::default()
710 },
711 None,
712 false,
713 );
714 let delete = add_function(
715 shapes,
716 Vec::new(),
717 FunctionSignatureBuilder {
718 positional_params: vec![Effect::Read],
719 callee_effect: Effect::Store,
720 return_type: Type::Primitive,
721 return_value_kind: ValueKind::Primitive,
722 ..Default::default()
723 },
724 None,
725 false,
726 );
727 let size = Type::Primitive;
728 let difference = add_function(
729 shapes,
730 Vec::new(),
731 FunctionSignatureBuilder {
732 positional_params: vec![Effect::Capture],
733 callee_effect: Effect::Capture,
734 return_type: Type::Object {
735 shape_id: Some(BUILT_IN_SET_ID.to_string()),
736 },
737 return_value_kind: ValueKind::Mutable,
738 ..Default::default()
739 },
740 None,
741 false,
742 );
743 let union = add_function(
744 shapes,
745 Vec::new(),
746 FunctionSignatureBuilder {
747 positional_params: vec![Effect::Capture],
748 callee_effect: Effect::Capture,
749 return_type: Type::Object {
750 shape_id: Some(BUILT_IN_SET_ID.to_string()),
751 },
752 return_value_kind: ValueKind::Mutable,
753 ..Default::default()
754 },
755 None,
756 false,
757 );
758 let symmetrical_difference = add_function(
759 shapes,
760 Vec::new(),
761 FunctionSignatureBuilder {
762 positional_params: vec![Effect::Capture],
763 callee_effect: Effect::Capture,
764 return_type: Type::Object {
765 shape_id: Some(BUILT_IN_SET_ID.to_string()),
766 },
767 return_value_kind: ValueKind::Mutable,
768 ..Default::default()
769 },
770 None,
771 false,
772 );
773 let is_subset_of = add_function(
774 shapes,
775 Vec::new(),
776 FunctionSignatureBuilder {
777 positional_params: vec![Effect::Read],
778 callee_effect: Effect::Read,
779 return_type: Type::Primitive,
780 return_value_kind: ValueKind::Primitive,
781 ..Default::default()
782 },
783 None,
784 false,
785 );
786 let is_superset_of = add_function(
787 shapes,
788 Vec::new(),
789 FunctionSignatureBuilder {
790 positional_params: vec![Effect::Read],
791 callee_effect: Effect::Read,
792 return_type: Type::Primitive,
793 return_value_kind: ValueKind::Primitive,
794 ..Default::default()
795 },
796 None,
797 false,
798 );
799 let for_each = add_function(
800 shapes,
801 Vec::new(),
802 FunctionSignatureBuilder {
803 rest_param: Some(Effect::ConditionallyMutate),
804 callee_effect: Effect::ConditionallyMutate,
805 return_type: Type::Primitive,
806 return_value_kind: ValueKind::Primitive,
807 no_alias: true,
808 mutable_only_if_operands_are_mutable: true,
809 ..Default::default()
810 },
811 None,
812 false,
813 );
814 let values = add_function(
815 shapes,
816 Vec::new(),
817 FunctionSignatureBuilder {
818 callee_effect: Effect::Capture,
819 return_type: Type::Poly,
820 return_value_kind: ValueKind::Mutable,
821 ..Default::default()
822 },
823 None,
824 false,
825 );
826 let keys = add_function(
827 shapes,
828 Vec::new(),
829 FunctionSignatureBuilder {
830 callee_effect: Effect::Capture,
831 return_type: Type::Poly,
832 return_value_kind: ValueKind::Mutable,
833 ..Default::default()
834 },
835 None,
836 false,
837 );
838 let entries = add_function(
839 shapes,
840 Vec::new(),
841 FunctionSignatureBuilder {
842 callee_effect: Effect::Capture,
843 return_type: Type::Poly,
844 return_value_kind: ValueKind::Mutable,
845 ..Default::default()
846 },
847 None,
848 false,
849 );
850
851 add_object(
852 shapes,
853 Some(BUILT_IN_SET_ID),
854 vec![
855 ("add".to_string(), add),
856 ("clear".to_string(), clear),
857 ("delete".to_string(), delete),
858 ("has".to_string(), has),
859 ("size".to_string(), size),
860 ("difference".to_string(), difference),
861 ("union".to_string(), union),
862 ("symmetricalDifference".to_string(), symmetrical_difference),
863 ("isSubsetOf".to_string(), is_subset_of),
864 ("isSupersetOf".to_string(), is_superset_of),
865 ("forEach".to_string(), for_each),
866 ("values".to_string(), values),
867 ("keys".to_string(), keys),
868 ("entries".to_string(), entries),
869 ],
870 );
871}
872
873fn build_map_shape(shapes: &mut ShapeRegistry) {
874 let has = add_function(
875 shapes,
876 Vec::new(),
877 FunctionSignatureBuilder {
878 positional_params: vec![Effect::Read],
879 return_type: Type::Primitive,
880 return_value_kind: ValueKind::Primitive,
881 ..Default::default()
882 },
883 None,
884 false,
885 );
886 let get = add_function(
887 shapes,
888 Vec::new(),
889 FunctionSignatureBuilder {
890 positional_params: vec![Effect::Read],
891 callee_effect: Effect::Capture,
892 return_type: Type::Poly,
893 return_value_kind: ValueKind::Mutable,
894 ..Default::default()
895 },
896 None,
897 false,
898 );
899 let clear = add_function(
900 shapes,
901 Vec::new(),
902 FunctionSignatureBuilder {
903 callee_effect: Effect::Store,
904 return_type: Type::Primitive,
905 return_value_kind: ValueKind::Primitive,
906 ..Default::default()
907 },
908 None,
909 false,
910 );
911 let set = add_function(
912 shapes,
913 Vec::new(),
914 FunctionSignatureBuilder {
915 positional_params: vec![Effect::Capture, Effect::Capture],
916 callee_effect: Effect::Store,
917 return_type: Type::Object {
918 shape_id: Some(BUILT_IN_MAP_ID.to_string()),
919 },
920 return_value_kind: ValueKind::Mutable,
921 ..Default::default()
922 },
923 None,
924 false,
925 );
926 let delete = add_function(
927 shapes,
928 Vec::new(),
929 FunctionSignatureBuilder {
930 positional_params: vec![Effect::Read],
931 callee_effect: Effect::Store,
932 return_type: Type::Primitive,
933 return_value_kind: ValueKind::Primitive,
934 ..Default::default()
935 },
936 None,
937 false,
938 );
939 let size = Type::Primitive;
940 let for_each = add_function(
941 shapes,
942 Vec::new(),
943 FunctionSignatureBuilder {
944 rest_param: Some(Effect::ConditionallyMutate),
945 callee_effect: Effect::ConditionallyMutate,
946 return_type: Type::Primitive,
947 return_value_kind: ValueKind::Primitive,
948 no_alias: true,
949 mutable_only_if_operands_are_mutable: true,
950 ..Default::default()
951 },
952 None,
953 false,
954 );
955 let values = add_function(
956 shapes,
957 Vec::new(),
958 FunctionSignatureBuilder {
959 callee_effect: Effect::Capture,
960 return_type: Type::Poly,
961 return_value_kind: ValueKind::Mutable,
962 ..Default::default()
963 },
964 None,
965 false,
966 );
967 let keys = add_function(
968 shapes,
969 Vec::new(),
970 FunctionSignatureBuilder {
971 callee_effect: Effect::Capture,
972 return_type: Type::Poly,
973 return_value_kind: ValueKind::Mutable,
974 ..Default::default()
975 },
976 None,
977 false,
978 );
979 let entries = add_function(
980 shapes,
981 Vec::new(),
982 FunctionSignatureBuilder {
983 callee_effect: Effect::Capture,
984 return_type: Type::Poly,
985 return_value_kind: ValueKind::Mutable,
986 ..Default::default()
987 },
988 None,
989 false,
990 );
991
992 add_object(
993 shapes,
994 Some(BUILT_IN_MAP_ID),
995 vec![
996 ("has".to_string(), has),
997 ("get".to_string(), get),
998 ("set".to_string(), set),
999 ("clear".to_string(), clear),
1000 ("delete".to_string(), delete),
1001 ("size".to_string(), size),
1002 ("forEach".to_string(), for_each),
1003 ("values".to_string(), values),
1004 ("keys".to_string(), keys),
1005 ("entries".to_string(), entries),
1006 ],
1007 );
1008}
1009
1010fn build_weak_set_shape(shapes: &mut ShapeRegistry) {
1011 let has = pure_primitive_fn(shapes);
1012 let add = add_function(
1013 shapes,
1014 Vec::new(),
1015 FunctionSignatureBuilder {
1016 positional_params: vec![Effect::Capture],
1017 callee_effect: Effect::Store,
1018 return_type: Type::Object {
1019 shape_id: Some(BUILT_IN_WEAK_SET_ID.to_string()),
1020 },
1021 return_value_kind: ValueKind::Mutable,
1022 ..Default::default()
1023 },
1024 None,
1025 false,
1026 );
1027 let delete = add_function(
1028 shapes,
1029 Vec::new(),
1030 FunctionSignatureBuilder {
1031 positional_params: vec![Effect::Read],
1032 callee_effect: Effect::Store,
1033 return_type: Type::Primitive,
1034 return_value_kind: ValueKind::Primitive,
1035 ..Default::default()
1036 },
1037 None,
1038 false,
1039 );
1040
1041 add_object(
1042 shapes,
1043 Some(BUILT_IN_WEAK_SET_ID),
1044 vec![
1045 ("has".to_string(), has),
1046 ("add".to_string(), add),
1047 ("delete".to_string(), delete),
1048 ],
1049 );
1050}
1051
1052fn build_weak_map_shape(shapes: &mut ShapeRegistry) {
1053 let has = pure_primitive_fn(shapes);
1054 let get = add_function(
1055 shapes,
1056 Vec::new(),
1057 FunctionSignatureBuilder {
1058 positional_params: vec![Effect::Read],
1059 callee_effect: Effect::Capture,
1060 return_type: Type::Poly,
1061 return_value_kind: ValueKind::Mutable,
1062 ..Default::default()
1063 },
1064 None,
1065 false,
1066 );
1067 let set = add_function(
1068 shapes,
1069 Vec::new(),
1070 FunctionSignatureBuilder {
1071 positional_params: vec![Effect::Capture, Effect::Capture],
1072 callee_effect: Effect::Store,
1073 return_type: Type::Object {
1074 shape_id: Some(BUILT_IN_WEAK_MAP_ID.to_string()),
1075 },
1076 return_value_kind: ValueKind::Mutable,
1077 ..Default::default()
1078 },
1079 None,
1080 false,
1081 );
1082 let delete = add_function(
1083 shapes,
1084 Vec::new(),
1085 FunctionSignatureBuilder {
1086 positional_params: vec![Effect::Read],
1087 callee_effect: Effect::Store,
1088 return_type: Type::Primitive,
1089 return_value_kind: ValueKind::Primitive,
1090 ..Default::default()
1091 },
1092 None,
1093 false,
1094 );
1095
1096 add_object(
1097 shapes,
1098 Some(BUILT_IN_WEAK_MAP_ID),
1099 vec![
1100 ("has".to_string(), has),
1101 ("get".to_string(), get),
1102 ("set".to_string(), set),
1103 ("delete".to_string(), delete),
1104 ],
1105 );
1106}
1107
1108fn build_object_shape(shapes: &mut ShapeRegistry) {
1109 let to_string = add_function(
1111 shapes,
1112 Vec::new(),
1113 FunctionSignatureBuilder {
1114 return_type: Type::Primitive,
1115 return_value_kind: ValueKind::Primitive,
1116 ..Default::default()
1117 },
1118 None,
1119 false,
1120 );
1121 add_object(
1122 shapes,
1123 Some(BUILT_IN_OBJECT_ID),
1124 vec![("toString".to_string(), to_string)],
1125 );
1126 add_object(shapes, Some(BUILT_IN_FUNCTION_ID), Vec::new());
1128 add_object(shapes, Some(BUILT_IN_JSX_ID), Vec::new());
1130 let mixed_to_string = add_function(
1133 shapes,
1134 Vec::new(),
1135 FunctionSignatureBuilder {
1136 rest_param: Some(Effect::Read),
1137 return_type: Type::Primitive,
1138 return_value_kind: ValueKind::Primitive,
1139 ..Default::default()
1140 },
1141 None,
1142 false,
1143 );
1144 let mixed_index_of = add_function(
1145 shapes,
1146 Vec::new(),
1147 FunctionSignatureBuilder {
1148 rest_param: Some(Effect::Read),
1149 return_type: Type::Primitive,
1150 return_value_kind: ValueKind::Primitive,
1151 ..Default::default()
1152 },
1153 None,
1154 false,
1155 );
1156 let mixed_includes = add_function(
1157 shapes,
1158 Vec::new(),
1159 FunctionSignatureBuilder {
1160 rest_param: Some(Effect::Read),
1161 return_type: Type::Primitive,
1162 return_value_kind: ValueKind::Primitive,
1163 ..Default::default()
1164 },
1165 None,
1166 false,
1167 );
1168 let mixed_at = add_function(
1169 shapes,
1170 Vec::new(),
1171 FunctionSignatureBuilder {
1172 positional_params: vec![Effect::Read],
1173 return_type: Type::Object {
1174 shape_id: Some(BUILT_IN_MIXED_READONLY_ID.to_string()),
1175 },
1176 callee_effect: Effect::Capture,
1177 return_value_kind: ValueKind::Frozen,
1178 ..Default::default()
1179 },
1180 None,
1181 false,
1182 );
1183 let mixed_map = add_function(
1184 shapes,
1185 Vec::new(),
1186 FunctionSignatureBuilder {
1187 rest_param: Some(Effect::ConditionallyMutate),
1188 return_type: Type::Object {
1189 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
1190 },
1191 callee_effect: Effect::ConditionallyMutate,
1192 return_value_kind: ValueKind::Mutable,
1193 no_alias: true,
1194 ..Default::default()
1195 },
1196 None,
1197 false,
1198 );
1199 let mixed_flat_map = add_function(
1200 shapes,
1201 Vec::new(),
1202 FunctionSignatureBuilder {
1203 rest_param: Some(Effect::ConditionallyMutate),
1204 return_type: Type::Object {
1205 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
1206 },
1207 callee_effect: Effect::ConditionallyMutate,
1208 return_value_kind: ValueKind::Mutable,
1209 no_alias: true,
1210 ..Default::default()
1211 },
1212 None,
1213 false,
1214 );
1215 let mixed_filter = add_function(
1216 shapes,
1217 Vec::new(),
1218 FunctionSignatureBuilder {
1219 rest_param: Some(Effect::ConditionallyMutate),
1220 return_type: Type::Object {
1221 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
1222 },
1223 callee_effect: Effect::ConditionallyMutate,
1224 return_value_kind: ValueKind::Mutable,
1225 no_alias: true,
1226 ..Default::default()
1227 },
1228 None,
1229 false,
1230 );
1231 let mixed_concat = add_function(
1232 shapes,
1233 Vec::new(),
1234 FunctionSignatureBuilder {
1235 rest_param: Some(Effect::Capture),
1236 return_type: Type::Object {
1237 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
1238 },
1239 callee_effect: Effect::Capture,
1240 return_value_kind: ValueKind::Mutable,
1241 ..Default::default()
1242 },
1243 None,
1244 false,
1245 );
1246 let mixed_slice = add_function(
1247 shapes,
1248 Vec::new(),
1249 FunctionSignatureBuilder {
1250 rest_param: Some(Effect::Read),
1251 return_type: Type::Object {
1252 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
1253 },
1254 callee_effect: Effect::Capture,
1255 return_value_kind: ValueKind::Mutable,
1256 ..Default::default()
1257 },
1258 None,
1259 false,
1260 );
1261 let mixed_every = add_function(
1262 shapes,
1263 Vec::new(),
1264 FunctionSignatureBuilder {
1265 rest_param: Some(Effect::ConditionallyMutate),
1266 return_type: Type::Primitive,
1267 callee_effect: Effect::ConditionallyMutate,
1268 return_value_kind: ValueKind::Primitive,
1269 no_alias: true,
1270 mutable_only_if_operands_are_mutable: true,
1271 ..Default::default()
1272 },
1273 None,
1274 false,
1275 );
1276 let mixed_some = add_function(
1277 shapes,
1278 Vec::new(),
1279 FunctionSignatureBuilder {
1280 rest_param: Some(Effect::ConditionallyMutate),
1281 return_type: Type::Primitive,
1282 callee_effect: Effect::ConditionallyMutate,
1283 return_value_kind: ValueKind::Primitive,
1284 no_alias: true,
1285 mutable_only_if_operands_are_mutable: true,
1286 ..Default::default()
1287 },
1288 None,
1289 false,
1290 );
1291 let mixed_find = add_function(
1292 shapes,
1293 Vec::new(),
1294 FunctionSignatureBuilder {
1295 rest_param: Some(Effect::ConditionallyMutate),
1296 return_type: Type::Object {
1297 shape_id: Some(BUILT_IN_MIXED_READONLY_ID.to_string()),
1298 },
1299 callee_effect: Effect::ConditionallyMutate,
1300 return_value_kind: ValueKind::Frozen,
1301 no_alias: true,
1302 mutable_only_if_operands_are_mutable: true,
1303 ..Default::default()
1304 },
1305 None,
1306 false,
1307 );
1308 let mixed_find_index = add_function(
1309 shapes,
1310 Vec::new(),
1311 FunctionSignatureBuilder {
1312 rest_param: Some(Effect::ConditionallyMutate),
1313 return_type: Type::Primitive,
1314 callee_effect: Effect::ConditionallyMutate,
1315 return_value_kind: ValueKind::Primitive,
1316 no_alias: true,
1317 mutable_only_if_operands_are_mutable: true,
1318 ..Default::default()
1319 },
1320 None,
1321 false,
1322 );
1323 let mixed_join = add_function(
1324 shapes,
1325 Vec::new(),
1326 FunctionSignatureBuilder {
1327 rest_param: Some(Effect::Read),
1328 return_type: Type::Primitive,
1329 return_value_kind: ValueKind::Primitive,
1330 ..Default::default()
1331 },
1332 None,
1333 false,
1334 );
1335 let mut mixed_props = HashMap::new();
1336 mixed_props.insert("toString".to_string(), mixed_to_string);
1337 mixed_props.insert("indexOf".to_string(), mixed_index_of);
1338 mixed_props.insert("includes".to_string(), mixed_includes);
1339 mixed_props.insert("at".to_string(), mixed_at);
1340 mixed_props.insert("map".to_string(), mixed_map);
1341 mixed_props.insert("flatMap".to_string(), mixed_flat_map);
1342 mixed_props.insert("filter".to_string(), mixed_filter);
1343 mixed_props.insert("concat".to_string(), mixed_concat);
1344 mixed_props.insert("slice".to_string(), mixed_slice);
1345 mixed_props.insert("every".to_string(), mixed_every);
1346 mixed_props.insert("some".to_string(), mixed_some);
1347 mixed_props.insert("find".to_string(), mixed_find);
1348 mixed_props.insert("findIndex".to_string(), mixed_find_index);
1349 mixed_props.insert("join".to_string(), mixed_join);
1350 mixed_props.insert(
1351 "*".to_string(),
1352 Type::Object {
1353 shape_id: Some(BUILT_IN_MIXED_READONLY_ID.to_string()),
1354 },
1355 );
1356 shapes.insert(
1357 BUILT_IN_MIXED_READONLY_ID.to_string(),
1358 ObjectShape {
1359 properties: mixed_props,
1360 function_type: None,
1361 },
1362 );
1363}
1364
1365fn build_ref_shapes(shapes: &mut ShapeRegistry) {
1366 add_object(
1368 shapes,
1369 Some(BUILT_IN_USE_REF_ID),
1370 vec![(
1371 "current".to_string(),
1372 Type::Object {
1373 shape_id: Some(BUILT_IN_REF_VALUE_ID.to_string()),
1374 },
1375 )],
1376 );
1377 add_object(
1379 shapes,
1380 Some(BUILT_IN_REF_VALUE_ID),
1381 vec![(
1382 "*".to_string(),
1383 Type::Object {
1384 shape_id: Some(BUILT_IN_REF_VALUE_ID.to_string()),
1385 },
1386 )],
1387 );
1388}
1389
1390fn build_state_shapes(shapes: &mut ShapeRegistry) {
1391 let set_state = add_function(
1393 shapes,
1394 Vec::new(),
1395 FunctionSignatureBuilder {
1396 rest_param: Some(Effect::Freeze),
1397 return_type: Type::Primitive,
1398 return_value_kind: ValueKind::Primitive,
1399 ..Default::default()
1400 },
1401 Some(BUILT_IN_SET_STATE_ID),
1402 false,
1403 );
1404
1405 add_object(
1407 shapes,
1408 Some(BUILT_IN_USE_STATE_ID),
1409 vec![("0".to_string(), Type::Poly), ("1".to_string(), set_state)],
1410 );
1411
1412 let set_action_state = add_function(
1414 shapes,
1415 Vec::new(),
1416 FunctionSignatureBuilder {
1417 rest_param: Some(Effect::Freeze),
1418 return_type: Type::Primitive,
1419 return_value_kind: ValueKind::Primitive,
1420 ..Default::default()
1421 },
1422 Some(BUILT_IN_SET_ACTION_STATE_ID),
1423 false,
1424 );
1425
1426 add_object(
1428 shapes,
1429 Some(BUILT_IN_USE_ACTION_STATE_ID),
1430 vec![
1431 ("0".to_string(), Type::Poly),
1432 ("1".to_string(), set_action_state),
1433 ],
1434 );
1435
1436 let dispatch = add_function(
1438 shapes,
1439 Vec::new(),
1440 FunctionSignatureBuilder {
1441 rest_param: Some(Effect::Freeze),
1442 return_type: Type::Primitive,
1443 return_value_kind: ValueKind::Primitive,
1444 ..Default::default()
1445 },
1446 Some(BUILT_IN_DISPATCH_ID),
1447 false,
1448 );
1449
1450 add_object(
1452 shapes,
1453 Some(BUILT_IN_USE_REDUCER_ID),
1454 vec![("0".to_string(), Type::Poly), ("1".to_string(), dispatch)],
1455 );
1456
1457 let start_transition = add_function(
1459 shapes,
1460 Vec::new(),
1461 FunctionSignatureBuilder {
1462 return_type: Type::Primitive,
1464 return_value_kind: ValueKind::Primitive,
1465 ..Default::default()
1466 },
1467 Some(BUILT_IN_START_TRANSITION_ID),
1468 false,
1469 );
1470
1471 add_object(
1473 shapes,
1474 Some(BUILT_IN_USE_TRANSITION_ID),
1475 vec![
1476 ("0".to_string(), Type::Primitive),
1477 ("1".to_string(), start_transition),
1478 ],
1479 );
1480
1481 let set_optimistic = add_function(
1483 shapes,
1484 Vec::new(),
1485 FunctionSignatureBuilder {
1486 rest_param: Some(Effect::Freeze),
1487 return_type: Type::Primitive,
1488 return_value_kind: ValueKind::Primitive,
1489 ..Default::default()
1490 },
1491 Some(BUILT_IN_SET_OPTIMISTIC_ID),
1492 false,
1493 );
1494
1495 add_object(
1497 shapes,
1498 Some(BUILT_IN_USE_OPTIMISTIC_ID),
1499 vec![
1500 ("0".to_string(), Type::Poly),
1501 ("1".to_string(), set_optimistic),
1502 ],
1503 );
1504}
1505
1506fn build_hook_shapes(shapes: &mut ShapeRegistry) {
1507 add_function(
1509 shapes,
1510 Vec::new(),
1511 FunctionSignatureBuilder {
1512 rest_param: Some(Effect::ConditionallyMutate),
1513 callee_effect: Effect::ConditionallyMutate,
1514 return_type: Type::Poly,
1515 return_value_kind: ValueKind::Mutable,
1516 ..Default::default()
1517 },
1518 Some(BUILT_IN_EFFECT_EVENT_ID),
1519 false,
1520 );
1521}
1522
1523fn build_misc_shapes(shapes: &mut ShapeRegistry) {
1524 add_object(shapes, Some(REANIMATED_SHARED_VALUE_ID), Vec::new());
1526}
1527
1528pub fn get_reanimated_module_type(shapes: &mut ShapeRegistry) -> Type {
1530 let mut reanimated_type: Vec<(String, Type)> = Vec::new();
1531
1532 let frozen_hooks = [
1534 "useFrameCallback",
1535 "useAnimatedStyle",
1536 "useAnimatedProps",
1537 "useAnimatedScrollHandler",
1538 "useAnimatedReaction",
1539 "useWorkletCallback",
1540 ];
1541 for hook in &frozen_hooks {
1542 let hook_type = add_hook(
1543 shapes,
1544 HookSignatureBuilder {
1545 rest_param: Some(Effect::Freeze),
1546 return_type: Type::Poly,
1547 return_value_kind: ValueKind::Frozen,
1548 no_alias: true,
1549 hook_kind: HookKind::Custom,
1550 ..Default::default()
1551 },
1552 None,
1553 );
1554 reanimated_type.push((hook.to_string(), hook_type));
1555 }
1556
1557 let mutable_hooks = ["useSharedValue", "useDerivedValue"];
1559 for hook in &mutable_hooks {
1560 let hook_type = add_hook(
1561 shapes,
1562 HookSignatureBuilder {
1563 rest_param: Some(Effect::Freeze),
1564 return_type: Type::Object {
1565 shape_id: Some(REANIMATED_SHARED_VALUE_ID.to_string()),
1566 },
1567 return_value_kind: ValueKind::Mutable,
1568 no_alias: true,
1569 hook_kind: HookKind::Custom,
1570 ..Default::default()
1571 },
1572 None,
1573 );
1574 reanimated_type.push((hook.to_string(), hook_type));
1575 }
1576
1577 let funcs = [
1579 "withTiming",
1580 "withSpring",
1581 "createAnimatedPropAdapter",
1582 "withDecay",
1583 "withRepeat",
1584 "runOnUI",
1585 "executeOnUIRuntimeSync",
1586 ];
1587 for func_name in &funcs {
1588 let func_type = add_function(
1589 shapes,
1590 Vec::new(),
1591 FunctionSignatureBuilder {
1592 rest_param: Some(Effect::Read),
1593 return_type: Type::Poly,
1594 return_value_kind: ValueKind::Mutable,
1595 no_alias: true,
1596 ..Default::default()
1597 },
1598 None,
1599 false,
1600 );
1601 reanimated_type.push((func_name.to_string(), func_type));
1602 }
1603
1604 add_object(shapes, None, reanimated_type)
1605}
1606
1607pub fn build_default_globals(shapes: &mut ShapeRegistry) -> GlobalRegistry {
1616 let mut globals = GlobalRegistry::new();
1617
1618 let react_apis = build_react_apis(shapes, &mut globals);
1620
1621 for name in UNTYPED_GLOBALS {
1624 globals.insert(name.to_string(), Type::Poly);
1625 }
1626
1627 let typed_globals = build_typed_globals(shapes, &mut globals, react_apis);
1630
1631 globals.insert(
1634 "globalThis".to_string(),
1635 add_object(shapes, Some("globalThis"), typed_globals.clone()),
1636 );
1637 globals.insert(
1638 "global".to_string(),
1639 add_object(shapes, Some("global"), typed_globals),
1640 );
1641
1642 globals
1643}
1644
1645const UNTYPED_GLOBALS: &[&str] = &[
1646 "Object",
1647 "Function",
1648 "RegExp",
1649 "Date",
1650 "Error",
1651 "TypeError",
1652 "RangeError",
1653 "ReferenceError",
1654 "SyntaxError",
1655 "URIError",
1656 "EvalError",
1657 "DataView",
1658 "Float32Array",
1659 "Float64Array",
1660 "Int8Array",
1661 "Int16Array",
1662 "Int32Array",
1663 "WeakMap",
1664 "Uint8Array",
1665 "Uint8ClampedArray",
1666 "Uint16Array",
1667 "Uint32Array",
1668 "ArrayBuffer",
1669 "JSON",
1670 "console",
1671 "eval",
1672];
1673
1674fn build_react_apis(
1678 shapes: &mut ShapeRegistry,
1679 globals: &mut GlobalRegistry,
1680) -> Vec<(String, Type)> {
1681 let mut react_apis: Vec<(String, Type)> = Vec::new();
1682
1683 let use_context = add_hook(
1685 shapes,
1686 HookSignatureBuilder {
1687 rest_param: Some(Effect::Read),
1688 return_type: Type::Poly,
1689 return_value_kind: ValueKind::Frozen,
1690 return_value_reason: Some(ValueReason::Context),
1691 hook_kind: HookKind::UseContext,
1692 ..Default::default()
1693 },
1694 Some(BUILT_IN_USE_CONTEXT_HOOK_ID),
1695 );
1696 react_apis.push(("useContext".to_string(), use_context));
1697
1698 let use_state = add_hook(
1700 shapes,
1701 HookSignatureBuilder {
1702 rest_param: Some(Effect::Freeze),
1703 return_type: Type::Object {
1704 shape_id: Some(BUILT_IN_USE_STATE_ID.to_string()),
1705 },
1706 return_value_kind: ValueKind::Frozen,
1707 return_value_reason: Some(ValueReason::State),
1708 hook_kind: HookKind::UseState,
1709 ..Default::default()
1710 },
1711 None,
1712 );
1713 react_apis.push(("useState".to_string(), use_state));
1714
1715 let use_action_state = add_hook(
1717 shapes,
1718 HookSignatureBuilder {
1719 rest_param: Some(Effect::Freeze),
1720 return_type: Type::Object {
1721 shape_id: Some(BUILT_IN_USE_ACTION_STATE_ID.to_string()),
1722 },
1723 return_value_kind: ValueKind::Frozen,
1724 return_value_reason: Some(ValueReason::State),
1725 hook_kind: HookKind::UseActionState,
1726 ..Default::default()
1727 },
1728 None,
1729 );
1730 react_apis.push(("useActionState".to_string(), use_action_state));
1731
1732 let use_reducer = add_hook(
1734 shapes,
1735 HookSignatureBuilder {
1736 rest_param: Some(Effect::Freeze),
1737 return_type: Type::Object {
1738 shape_id: Some(BUILT_IN_USE_REDUCER_ID.to_string()),
1739 },
1740 return_value_kind: ValueKind::Frozen,
1741 return_value_reason: Some(ValueReason::ReducerState),
1742 hook_kind: HookKind::UseReducer,
1743 ..Default::default()
1744 },
1745 None,
1746 );
1747 react_apis.push(("useReducer".to_string(), use_reducer));
1748
1749 let use_ref = add_hook(
1751 shapes,
1752 HookSignatureBuilder {
1753 rest_param: Some(Effect::Capture),
1754 return_type: Type::Object {
1755 shape_id: Some(BUILT_IN_USE_REF_ID.to_string()),
1756 },
1757 return_value_kind: ValueKind::Mutable,
1758 hook_kind: HookKind::UseRef,
1759 ..Default::default()
1760 },
1761 None,
1762 );
1763 react_apis.push(("useRef".to_string(), use_ref));
1764
1765 let use_imperative_handle = add_hook(
1767 shapes,
1768 HookSignatureBuilder {
1769 rest_param: Some(Effect::Freeze),
1770 return_type: Type::Primitive,
1771 return_value_kind: ValueKind::Frozen,
1772 hook_kind: HookKind::UseImperativeHandle,
1773 ..Default::default()
1774 },
1775 None,
1776 );
1777 react_apis.push(("useImperativeHandle".to_string(), use_imperative_handle));
1778
1779 let use_memo = add_hook(
1781 shapes,
1782 HookSignatureBuilder {
1783 rest_param: Some(Effect::Freeze),
1784 return_type: Type::Poly,
1785 return_value_kind: ValueKind::Frozen,
1786 hook_kind: HookKind::UseMemo,
1787 ..Default::default()
1788 },
1789 None,
1790 );
1791 react_apis.push(("useMemo".to_string(), use_memo));
1792
1793 let use_callback = add_hook(
1795 shapes,
1796 HookSignatureBuilder {
1797 rest_param: Some(Effect::Freeze),
1798 return_type: Type::Poly,
1799 return_value_kind: ValueKind::Frozen,
1800 hook_kind: HookKind::UseCallback,
1801 ..Default::default()
1802 },
1803 None,
1804 );
1805 react_apis.push(("useCallback".to_string(), use_callback));
1806
1807 let use_effect = add_hook(
1809 shapes,
1810 HookSignatureBuilder {
1811 rest_param: Some(Effect::Freeze),
1812 return_type: Type::Primitive,
1813 return_value_kind: ValueKind::Frozen,
1814 hook_kind: HookKind::UseEffect,
1815 aliasing: Some(AliasingSignatureConfig {
1816 receiver: "@receiver".to_string(),
1817 params: Vec::new(),
1818 rest: Some("@rest".to_string()),
1819 returns: "@returns".to_string(),
1820 temporaries: vec!["@effect".to_string()],
1821 effects: vec![
1822 AliasingEffectConfig::Freeze {
1823 value: "@rest".to_string(),
1824 reason: ValueReason::Effect,
1825 },
1826 AliasingEffectConfig::Create {
1827 into: "@effect".to_string(),
1828 value: ValueKind::Frozen,
1829 reason: ValueReason::KnownReturnSignature,
1830 },
1831 AliasingEffectConfig::Capture {
1832 from: "@rest".to_string(),
1833 into: "@effect".to_string(),
1834 },
1835 AliasingEffectConfig::Create {
1836 into: "@returns".to_string(),
1837 value: ValueKind::Primitive,
1838 reason: ValueReason::KnownReturnSignature,
1839 },
1840 ],
1841 }),
1842 ..Default::default()
1843 },
1844 Some(BUILT_IN_USE_EFFECT_HOOK_ID),
1845 );
1846 react_apis.push(("useEffect".to_string(), use_effect));
1847
1848 let use_layout_effect = add_hook(
1850 shapes,
1851 HookSignatureBuilder {
1852 rest_param: Some(Effect::Freeze),
1853 return_type: Type::Poly,
1854 return_value_kind: ValueKind::Frozen,
1855 hook_kind: HookKind::UseLayoutEffect,
1856 ..Default::default()
1857 },
1858 Some(BUILT_IN_USE_LAYOUT_EFFECT_HOOK_ID),
1859 );
1860 react_apis.push(("useLayoutEffect".to_string(), use_layout_effect));
1861
1862 let use_insertion_effect = add_hook(
1864 shapes,
1865 HookSignatureBuilder {
1866 rest_param: Some(Effect::Freeze),
1867 return_type: Type::Poly,
1868 return_value_kind: ValueKind::Frozen,
1869 hook_kind: HookKind::UseInsertionEffect,
1870 ..Default::default()
1871 },
1872 Some(BUILT_IN_USE_INSERTION_EFFECT_HOOK_ID),
1873 );
1874 react_apis.push(("useInsertionEffect".to_string(), use_insertion_effect));
1875
1876 let use_transition = add_hook(
1878 shapes,
1879 HookSignatureBuilder {
1880 rest_param: None,
1881 return_type: Type::Object {
1882 shape_id: Some(BUILT_IN_USE_TRANSITION_ID.to_string()),
1883 },
1884 return_value_kind: ValueKind::Frozen,
1885 hook_kind: HookKind::UseTransition,
1886 ..Default::default()
1887 },
1888 None,
1889 );
1890 react_apis.push(("useTransition".to_string(), use_transition));
1891
1892 let use_optimistic = add_hook(
1894 shapes,
1895 HookSignatureBuilder {
1896 rest_param: Some(Effect::Freeze),
1897 return_type: Type::Object {
1898 shape_id: Some(BUILT_IN_USE_OPTIMISTIC_ID.to_string()),
1899 },
1900 return_value_kind: ValueKind::Frozen,
1901 return_value_reason: Some(ValueReason::State),
1902 hook_kind: HookKind::UseOptimistic,
1903 ..Default::default()
1904 },
1905 None,
1906 );
1907 react_apis.push(("useOptimistic".to_string(), use_optimistic));
1908
1909 let use_fn = add_function(
1911 shapes,
1912 Vec::new(),
1913 FunctionSignatureBuilder {
1914 rest_param: Some(Effect::Freeze),
1915 return_type: Type::Poly,
1916 return_value_kind: ValueKind::Frozen,
1917 ..Default::default()
1918 },
1919 Some(BUILT_IN_USE_OPERATOR_ID),
1920 false,
1921 );
1922 react_apis.push(("use".to_string(), use_fn));
1923
1924 let use_effect_event = add_hook(
1926 shapes,
1927 HookSignatureBuilder {
1928 rest_param: Some(Effect::Freeze),
1929 return_type: Type::Function {
1930 shape_id: Some(BUILT_IN_EFFECT_EVENT_ID.to_string()),
1931 return_type: Box::new(Type::Poly),
1932 is_constructor: false,
1933 },
1934 return_value_kind: ValueKind::Frozen,
1935 hook_kind: HookKind::UseEffectEvent,
1936 ..Default::default()
1937 },
1938 Some(BUILT_IN_USE_EFFECT_EVENT_ID),
1939 );
1940 react_apis.push(("useEffectEvent".to_string(), use_effect_event));
1941
1942 for (name, ty) in &react_apis {
1944 globals.insert(name.clone(), ty.clone());
1945 }
1946
1947 react_apis
1948}
1949
1950fn build_typed_globals(
1952 shapes: &mut ShapeRegistry,
1953 globals: &mut GlobalRegistry,
1954 react_apis: Vec<(String, Type)>,
1955) -> Vec<(String, Type)> {
1956 let mut typed_globals: Vec<(String, Type)> = Vec::new();
1957 let obj_keys = add_function(
1959 shapes,
1960 Vec::new(),
1961 FunctionSignatureBuilder {
1962 positional_params: vec![Effect::Read],
1963 return_type: Type::Object {
1964 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
1965 },
1966 return_value_kind: ValueKind::Mutable,
1967 aliasing: Some(AliasingSignatureConfig {
1968 receiver: "@receiver".to_string(),
1969 params: vec!["@object".to_string()],
1970 rest: None,
1971 returns: "@returns".to_string(),
1972 temporaries: Vec::new(),
1973 effects: vec![
1974 AliasingEffectConfig::Create {
1975 into: "@returns".to_string(),
1976 value: ValueKind::Mutable,
1977 reason: ValueReason::KnownReturnSignature,
1978 },
1979 AliasingEffectConfig::ImmutableCapture {
1981 from: "@object".to_string(),
1982 into: "@returns".to_string(),
1983 },
1984 ],
1985 }),
1986 ..Default::default()
1987 },
1988 None,
1989 false,
1990 );
1991 let obj_from_entries = add_function(
1992 shapes,
1993 Vec::new(),
1994 FunctionSignatureBuilder {
1995 positional_params: vec![Effect::ConditionallyMutate],
1996 return_type: Type::Object {
1997 shape_id: Some(BUILT_IN_OBJECT_ID.to_string()),
1998 },
1999 return_value_kind: ValueKind::Mutable,
2000 ..Default::default()
2001 },
2002 None,
2003 false,
2004 );
2005 let obj_entries = add_function(
2006 shapes,
2007 Vec::new(),
2008 FunctionSignatureBuilder {
2009 positional_params: vec![Effect::Capture],
2010 return_type: Type::Object {
2011 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
2012 },
2013 return_value_kind: ValueKind::Mutable,
2014 aliasing: Some(AliasingSignatureConfig {
2015 receiver: "@receiver".to_string(),
2016 params: vec!["@object".to_string()],
2017 rest: None,
2018 returns: "@returns".to_string(),
2019 temporaries: Vec::new(),
2020 effects: vec![
2021 AliasingEffectConfig::Create {
2022 into: "@returns".to_string(),
2023 value: ValueKind::Mutable,
2024 reason: ValueReason::KnownReturnSignature,
2025 },
2026 AliasingEffectConfig::Capture {
2028 from: "@object".to_string(),
2029 into: "@returns".to_string(),
2030 },
2031 ],
2032 }),
2033 ..Default::default()
2034 },
2035 None,
2036 false,
2037 );
2038 let obj_values = add_function(
2039 shapes,
2040 Vec::new(),
2041 FunctionSignatureBuilder {
2042 positional_params: vec![Effect::Capture],
2043 return_type: Type::Object {
2044 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
2045 },
2046 return_value_kind: ValueKind::Mutable,
2047 aliasing: Some(AliasingSignatureConfig {
2048 receiver: "@receiver".to_string(),
2049 params: vec!["@object".to_string()],
2050 rest: None,
2051 returns: "@returns".to_string(),
2052 temporaries: Vec::new(),
2053 effects: vec![
2054 AliasingEffectConfig::Create {
2055 into: "@returns".to_string(),
2056 value: ValueKind::Mutable,
2057 reason: ValueReason::KnownReturnSignature,
2058 },
2059 AliasingEffectConfig::Capture {
2061 from: "@object".to_string(),
2062 into: "@returns".to_string(),
2063 },
2064 ],
2065 }),
2066 ..Default::default()
2067 },
2068 None,
2069 false,
2070 );
2071 let object_global = add_object(
2072 shapes,
2073 Some("Object"),
2074 vec![
2075 ("keys".to_string(), obj_keys),
2076 ("fromEntries".to_string(), obj_from_entries),
2077 ("entries".to_string(), obj_entries),
2078 ("values".to_string(), obj_values),
2079 ],
2080 );
2081 typed_globals.push(("Object".to_string(), object_global.clone()));
2082 globals.insert("Object".to_string(), object_global);
2083
2084 let array_is_array = add_function(
2086 shapes,
2087 Vec::new(),
2088 FunctionSignatureBuilder {
2089 positional_params: vec![Effect::Read],
2090 return_type: Type::Primitive,
2091 return_value_kind: ValueKind::Primitive,
2092 ..Default::default()
2093 },
2094 None,
2095 false,
2096 );
2097 let array_from = add_function(
2098 shapes,
2099 Vec::new(),
2100 FunctionSignatureBuilder {
2101 positional_params: vec![
2102 Effect::ConditionallyMutateIterator,
2103 Effect::ConditionallyMutate,
2104 Effect::ConditionallyMutate,
2105 ],
2106 rest_param: Some(Effect::Read),
2107 return_type: Type::Object {
2108 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
2109 },
2110 return_value_kind: ValueKind::Mutable,
2111 ..Default::default()
2112 },
2113 None,
2114 false,
2115 );
2116 let array_of = add_function(
2117 shapes,
2118 Vec::new(),
2119 FunctionSignatureBuilder {
2120 rest_param: Some(Effect::Read),
2121 return_type: Type::Object {
2122 shape_id: Some(BUILT_IN_ARRAY_ID.to_string()),
2123 },
2124 return_value_kind: ValueKind::Mutable,
2125 ..Default::default()
2126 },
2127 None,
2128 false,
2129 );
2130 let array_global = add_object(
2131 shapes,
2132 Some("Array"),
2133 vec![
2134 ("isArray".to_string(), array_is_array),
2135 ("from".to_string(), array_from),
2136 ("of".to_string(), array_of),
2137 ],
2138 );
2139 typed_globals.push(("Array".to_string(), array_global.clone()));
2140 globals.insert("Array".to_string(), array_global);
2141
2142 let math_fns: Vec<(String, Type)> = ["max", "min", "trunc", "ceil", "floor", "pow"]
2144 .iter()
2145 .map(|name| (name.to_string(), pure_primitive_fn(shapes)))
2146 .collect();
2147 let mut math_props = math_fns;
2148 math_props.push(("PI".to_string(), Type::Primitive));
2149 let math_random = add_function(
2151 shapes,
2152 Vec::new(),
2153 FunctionSignatureBuilder {
2154 return_type: Type::Poly,
2155 return_value_kind: ValueKind::Mutable,
2156 impure: true,
2157 canonical_name: Some("Math.random".to_string()),
2158 ..Default::default()
2159 },
2160 None,
2161 false,
2162 );
2163 math_props.push(("random".to_string(), math_random));
2164 let math_global = add_object(shapes, Some("Math"), math_props);
2165 typed_globals.push(("Math".to_string(), math_global.clone()));
2166 globals.insert("Math".to_string(), math_global);
2167
2168 let perf_now = add_function(
2170 shapes,
2171 Vec::new(),
2172 FunctionSignatureBuilder {
2173 rest_param: Some(Effect::Read),
2174 return_type: Type::Poly,
2175 return_value_kind: ValueKind::Mutable,
2176 impure: true,
2177 canonical_name: Some("performance.now".to_string()),
2178 ..Default::default()
2179 },
2180 None,
2181 false,
2182 );
2183 let perf_global = add_object(
2184 shapes,
2185 Some("performance"),
2186 vec![("now".to_string(), perf_now)],
2187 );
2188 typed_globals.push(("performance".to_string(), perf_global.clone()));
2189 globals.insert("performance".to_string(), perf_global);
2190
2191 let date_now = add_function(
2193 shapes,
2194 Vec::new(),
2195 FunctionSignatureBuilder {
2196 rest_param: Some(Effect::Read),
2197 return_type: Type::Poly,
2198 return_value_kind: ValueKind::Mutable,
2199 impure: true,
2200 canonical_name: Some("Date.now".to_string()),
2201 ..Default::default()
2202 },
2203 None,
2204 false,
2205 );
2206 let date_global = add_object(shapes, Some("Date"), vec![("now".to_string(), date_now)]);
2207 typed_globals.push(("Date".to_string(), date_global.clone()));
2208 globals.insert("Date".to_string(), date_global);
2209
2210 let console_methods: Vec<(String, Type)> = ["error", "info", "log", "table", "trace", "warn"]
2212 .iter()
2213 .map(|name| (name.to_string(), pure_primitive_fn(shapes)))
2214 .collect();
2215 let console_global = add_object(shapes, Some("console"), console_methods);
2216 typed_globals.push(("console".to_string(), console_global.clone()));
2217 globals.insert("console".to_string(), console_global);
2218
2219 for name in &[
2221 "Boolean",
2222 "Number",
2223 "String",
2224 "parseInt",
2225 "parseFloat",
2226 "isNaN",
2227 "isFinite",
2228 "encodeURI",
2229 "encodeURIComponent",
2230 "decodeURI",
2231 "decodeURIComponent",
2232 ] {
2233 let f = pure_primitive_fn(shapes);
2234 typed_globals.push((name.to_string(), f.clone()));
2235 globals.insert(name.to_string(), f);
2236 }
2237
2238 typed_globals.push(("Infinity".to_string(), Type::Primitive));
2240 globals.insert("Infinity".to_string(), Type::Primitive);
2241 typed_globals.push(("NaN".to_string(), Type::Primitive));
2242 globals.insert("NaN".to_string(), Type::Primitive);
2243
2244 let map_ctor = add_function(
2246 shapes,
2247 Vec::new(),
2248 FunctionSignatureBuilder {
2249 positional_params: vec![Effect::ConditionallyMutateIterator],
2250 return_type: Type::Object {
2251 shape_id: Some(BUILT_IN_MAP_ID.to_string()),
2252 },
2253 return_value_kind: ValueKind::Mutable,
2254 ..Default::default()
2255 },
2256 None,
2257 true,
2258 );
2259 typed_globals.push(("Map".to_string(), map_ctor.clone()));
2260 globals.insert("Map".to_string(), map_ctor);
2261
2262 let set_ctor = add_function(
2263 shapes,
2264 Vec::new(),
2265 FunctionSignatureBuilder {
2266 positional_params: vec![Effect::ConditionallyMutateIterator],
2267 return_type: Type::Object {
2268 shape_id: Some(BUILT_IN_SET_ID.to_string()),
2269 },
2270 return_value_kind: ValueKind::Mutable,
2271 ..Default::default()
2272 },
2273 None,
2274 true,
2275 );
2276 typed_globals.push(("Set".to_string(), set_ctor.clone()));
2277 globals.insert("Set".to_string(), set_ctor);
2278
2279 let weak_map_ctor = add_function(
2280 shapes,
2281 Vec::new(),
2282 FunctionSignatureBuilder {
2283 positional_params: vec![Effect::ConditionallyMutateIterator],
2284 return_type: Type::Object {
2285 shape_id: Some(BUILT_IN_WEAK_MAP_ID.to_string()),
2286 },
2287 return_value_kind: ValueKind::Mutable,
2288 ..Default::default()
2289 },
2290 None,
2291 true,
2292 );
2293 typed_globals.push(("WeakMap".to_string(), weak_map_ctor.clone()));
2294 globals.insert("WeakMap".to_string(), weak_map_ctor);
2295
2296 let weak_set_ctor = add_function(
2297 shapes,
2298 Vec::new(),
2299 FunctionSignatureBuilder {
2300 positional_params: vec![Effect::ConditionallyMutateIterator],
2301 return_type: Type::Object {
2302 shape_id: Some(BUILT_IN_WEAK_SET_ID.to_string()),
2303 },
2304 return_value_kind: ValueKind::Mutable,
2305 ..Default::default()
2306 },
2307 None,
2308 true,
2309 );
2310 typed_globals.push(("WeakSet".to_string(), weak_set_ctor.clone()));
2311 globals.insert("WeakSet".to_string(), weak_set_ctor);
2312
2313 let react_create_element = add_function(
2316 shapes,
2317 Vec::new(),
2318 FunctionSignatureBuilder {
2319 rest_param: Some(Effect::Freeze),
2320 return_type: Type::Poly,
2321 return_value_kind: ValueKind::Frozen,
2322 ..Default::default()
2323 },
2324 None,
2325 false,
2326 );
2327 let react_clone_element = add_function(
2328 shapes,
2329 Vec::new(),
2330 FunctionSignatureBuilder {
2331 rest_param: Some(Effect::Freeze),
2332 return_type: Type::Poly,
2333 return_value_kind: ValueKind::Frozen,
2334 ..Default::default()
2335 },
2336 None,
2337 false,
2338 );
2339 let react_create_ref = add_function(
2340 shapes,
2341 Vec::new(),
2342 FunctionSignatureBuilder {
2343 rest_param: Some(Effect::Capture),
2344 return_type: Type::Object {
2345 shape_id: Some(BUILT_IN_USE_REF_ID.to_string()),
2346 },
2347 return_value_kind: ValueKind::Mutable,
2348 ..Default::default()
2349 },
2350 None,
2351 false,
2352 );
2353
2354 let mut react_props: Vec<(String, Type)> = react_apis;
2356 react_props.push(("createElement".to_string(), react_create_element));
2357 react_props.push(("cloneElement".to_string(), react_clone_element));
2358 react_props.push(("createRef".to_string(), react_create_ref));
2359
2360 let react_global = add_object(shapes, None, react_props);
2361 typed_globals.push(("React".to_string(), react_global.clone()));
2362 globals.insert("React".to_string(), react_global);
2363
2364 let jsx_fn = add_function(
2366 shapes,
2367 Vec::new(),
2368 FunctionSignatureBuilder {
2369 rest_param: Some(Effect::Freeze),
2370 return_type: Type::Poly,
2371 return_value_kind: ValueKind::Frozen,
2372 ..Default::default()
2373 },
2374 None,
2375 false,
2376 );
2377 typed_globals.push(("_jsx".to_string(), jsx_fn.clone()));
2378 globals.insert("_jsx".to_string(), jsx_fn);
2379
2380 typed_globals
2381}