File is large — showing lines 1–2,000 of 2,382.
1// Copyright (c) Meta Platforms, Inc. and affiliates.2//3// This source code is licensed under the MIT license found in the4// LICENSE file in the root directory of this source tree.56//! Global type registry and built-in shape definitions, ported from Globals.ts.7//!8//! Provides `DEFAULT_SHAPES` (built-in object shapes) and `DEFAULT_GLOBALS`9//! (global variable types including React hooks and JS built-ins).1011use rustc_hash::FxHashMap;12use std::sync::LazyLock;1314use 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;2627/// Type alias matching TS `Global = BuiltInType | PolyType`.28/// In the Rust port, both map to our `Type` enum.29pub type Global = Type;3031/// Registry mapping global names to their types.32///33/// Supports two modes:34/// - **Builder mode** (`base=None`): wraps a single FxHashMap, used during35/// `build_default_globals` to construct the static base.36/// - **Overlay mode** (`base=Some`): holds a `&'static FxHashMap` base plus a small37/// extras FxHashMap. Lookups check extras first, then base. Inserts go into extras.38/// Cloning only copies the extras map (the base pointer is shared).39pub struct GlobalRegistry {40 base: Option<&'static FxHashMap<String, Global>>,41 entries: FxHashMap<String, Global>,42}4344impl GlobalRegistry {45 /// Create an empty builder-mode registry.46 pub fn new() -> Self {47 Self {48 base: None,49 entries: FxHashMap::default(),50 }51 }5253 /// Create an overlay-mode registry backed by a static base.54 pub fn with_base(base: &'static FxHashMap<String, Global>) -> Self {55 Self {56 base: Some(base),57 entries: FxHashMap::default(),58 }59 }6061 pub fn get(&self, key: &str) -> Option<&Global> {62 self.entries63 .get(key)64 .or_else(|| self.base.and_then(|b| b.get(key)))65 }6667 pub fn insert(&mut self, key: String, value: Global) {68 self.entries.insert(key, value);69 }7071 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 }7475 /// Iterate over all keys in the registry (base + extras).76 /// Keys in extras that shadow base keys appear only once.77 pub fn keys(&self) -> impl Iterator<Item = &String> {78 let base_keys = self79 .base80 .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 }8586 /// Consume the registry and return the inner FxHashMap.87 /// Only valid in builder mode (no base).88 pub fn into_inner(self) -> FxHashMap<String, Global> {89 debug_assert!(90 self.base.is_none(),91 "into_inner() called on overlay-mode GlobalRegistry"92 );93 self.entries94 }95}9697impl Clone for GlobalRegistry {98 fn clone(&self) -> Self {99 Self {100 base: self.base,101 entries: self.entries.clone(),102 }103 }104}105106// =============================================================================107// Static base registries (initialized once, shared across all Environments)108// =============================================================================109110struct BaseRegistries {111 shapes: FxHashMap<String, ObjectShape>,112 globals: FxHashMap<String, Global>,113}114115static 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});123124/// Get a reference to the static base shapes registry.125pub fn base_shapes() -> &'static FxHashMap<String, ObjectShape> {126 &BASE.shapes127}128129/// Get a reference to the static base globals registry.130pub fn base_globals() -> &'static FxHashMap<String, Global> {131 &BASE.globals132}133134// =============================================================================135// installTypeConfig — converts TypeConfig to internal Type136// =============================================================================137138/// Convert a user-provided TypeConfig into an internal Type, registering shapes139/// as needed. Ported from TS `installTypeConfig` in Globals.ts.140/// If `errors` is provided, hook-name vs hook-type consistency validation141/// errors are collected there.142pub 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}151152/// Like `install_type_config` but collects validation errors.153pub 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}170171fn 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 // Compute return type first to avoid double-borrow of shapes195 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_config214 .mutable_only_if_operands_are_mutable215 .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 // Compute return type first to avoid double-borrow of shapes228 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_config255 .properties256 .as_ref()257 .map(|props| {258 props259 .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 // Validate hook-name vs hook-type consistency (matching TS installTypeConfig)270 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}299300// =============================================================================301// Build built-in shapes (BUILTIN_SHAPES from ObjectShape.ts)302// =============================================================================303304/// Build the built-in shapes registry. This corresponds to TS `BUILTIN_SHAPES`305/// defined at module level in ObjectShape.ts.306pub fn build_builtin_shapes() -> ShapeRegistry {307 let mut shapes = ShapeRegistry::new();308309 // BuiltInProps: { ref: UseRefType }310 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 );320321 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);331332 shapes333}334335fn 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}356357/// Shorthand for a pure function returning Primitive.358fn 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}367368fn 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 // Map creates a new mutable array451 AliasingEffectConfig::Create {452 into: "@returns".to_string(),453 value: ValueKind::Mutable,454 reason: ValueReason::KnownReturnSignature,455 },456 // The first arg to the callback is an item extracted from the receiver array457 AliasingEffectConfig::CreateFrom {458 from: "@receiver".to_string(),459 into: "@item".to_string(),460 },461 // The undefined this for the callback462 AliasingEffectConfig::Create {463 into: "@thisArg".to_string(),464 value: ValueKind::Primitive,465 reason: ValueReason::KnownReturnSignature,466 },467 // Calls the callback, returning the result into a temporary468 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 // Captures the result of the callback into the return array482 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 // Push directly mutates the array itself604 AliasingEffectConfig::Mutate {605 value: "@receiver".to_string(),606 },607 // The arguments are captured into the array608 AliasingEffectConfig::Capture {609 from: "@rest".to_string(),610 into: "@receiver".to_string(),611 },612 // Returns the new length, a primitive613 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 );625626 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 // TODO: rest of Array properties647 ],648 );649}650651fn 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 // Set.add returns the receiver Set682 AliasingEffectConfig::Assign {683 from: "@receiver".to_string(),684 into: "@returns".to_string(),685 },686 // Set.add mutates the set itself687 AliasingEffectConfig::Mutate {688 value: "@receiver".to_string(),689 },690 // Captures the rest params into the set691 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 );850851 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}872873fn 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 );991992 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}10091010fn 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 );10401041 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}10511052fn 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 );10951096 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}11071108fn build_object_shape(shapes: &mut ShapeRegistry) {1109 // BuiltInObject: has toString() returning Primitive (matches TS BuiltInObjectId shape)1110 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 // BuiltInFunction: empty shape1127 add_object(shapes, Some(BUILT_IN_FUNCTION_ID), Vec::new());1128 // BuiltInJsx: empty shape1129 add_object(shapes, Some(BUILT_IN_JSX_ID), Vec::new());1130 // BuiltInMixedReadonly: has explicit method types + wildcard returning MixedReadonly1131 // (matches TS BuiltInMixedReadonlyId shape)1132 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 = FxHashMap::default();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}13641365fn build_ref_shapes(shapes: &mut ShapeRegistry) {1366 // BuiltInUseRefId: { current: Object { shapeId: BuiltInRefValue } }1367 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 // BuiltInRefValue: { *: Object { shapeId: BuiltInRefValue } } (self-referencing)1378 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}13891390fn build_state_shapes(shapes: &mut ShapeRegistry) {1391 // BuiltInSetState: function that freezes its argument1392 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 );14041405 // BuiltInUseState: object with [0] = Poly (state), [1] = setState function1406 add_object(1407 shapes,1408 Some(BUILT_IN_USE_STATE_ID),1409 vec![("0".to_string(), Type::Poly), ("1".to_string(), set_state)],1410 );14111412 // BuiltInSetActionState1413 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 );14251426 // BuiltInUseActionState: [0] = Poly, [1] = setActionState function1427 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 );14351436 // BuiltInDispatch1437 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 );14491450 // BuiltInUseReducer: [0] = Poly, [1] = dispatch function1451 add_object(1452 shapes,1453 Some(BUILT_IN_USE_REDUCER_ID),1454 vec![("0".to_string(), Type::Poly), ("1".to_string(), dispatch)],1455 );14561457 // BuiltInStartTransition1458 let start_transition = add_function(1459 shapes,1460 Vec::new(),1461 FunctionSignatureBuilder {1462 // Note: TS uses restParam: null for startTransition1463 return_type: Type::Primitive,1464 return_value_kind: ValueKind::Primitive,1465 ..Default::default()1466 },1467 Some(BUILT_IN_START_TRANSITION_ID),1468 false,1469 );14701471 // BuiltInUseTransition: [0] = Primitive (isPending), [1] = startTransition function1472 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 );14801481 // BuiltInSetOptimistic1482 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 );14941495 // BuiltInUseOptimistic: [0] = Poly, [1] = setOptimistic function1496 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}15051506fn build_hook_shapes(shapes: &mut ShapeRegistry) {1507 // BuiltInEffectEvent function shape (the return value of useEffectEvent)1508 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}15221523fn build_misc_shapes(shapes: &mut ShapeRegistry) {1524 // ReanimatedSharedValue: empty properties (matching TS)1525 add_object(shapes, Some(REANIMATED_SHARED_VALUE_ID), Vec::new());1526}15271528/// Build the reanimated module type. Ported from TS `getReanimatedModuleType`.1529pub fn get_reanimated_module_type(shapes: &mut ShapeRegistry) -> Type {1530 let mut reanimated_type: Vec<(String, Type)> = Vec::new();15311532 // hooks that freeze args and return frozen value1533 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 }15561557 // hooks that return a mutable value (modelled as shared value)1558 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 }15761577 // functions that return mutable value1578 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 }16031604 add_object(shapes, None, reanimated_type)1605}16061607// =============================================================================1608// Build default globals (DEFAULT_GLOBALS from Globals.ts)1609// =============================================================================16101611/// Build the default globals registry. This corresponds to TS `DEFAULT_GLOBALS`.1612///1613/// Requires a mutable reference to the shapes registry because some globals1614/// (like Object.keys, Array.isArray) register new shapes.1615pub fn build_default_globals(shapes: &mut ShapeRegistry) -> GlobalRegistry {1616 let mut globals = GlobalRegistry::new();16171618 // React APIs — returns the list so we can reuse them for the React namespace1619 let react_apis = build_react_apis(shapes, &mut globals);16201621 // Untyped globals (treated as Poly) — must come before typed globals1622 // so typed definitions take priority (matching TS ordering)1623 for name in UNTYPED_GLOBALS {1624 globals.insert(name.to_string(), Type::Poly);1625 }16261627 // Typed JS globals (overwrites Poly entries from UNTYPED_GLOBALS).1628 // Returns the list of typed globals for use as globalThis/global properties.1629 let typed_globals = build_typed_globals(shapes, &mut globals, react_apis);16301631 // globalThis and global — populated with all typed globals as properties1632 // (matching TS: `addObject(DEFAULT_SHAPES, 'globalThis', TYPED_GLOBALS)`)1633 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 );16411642 globals1643}16441645const 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];16731674/// Build the React API types (REACT_APIS from TS). Returns the list of (name, type) pairs1675/// so they can be reused as properties of the React namespace object (matching TS behavior1676/// where the SAME type objects are used in both DEFAULT_GLOBALS and the React namespace).1677fn 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();16821683 // useContext1684 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));16971698 // useState1699 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));17141715 // useActionState1716 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));17311732 // useReducer1733 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));17481749 // useRef1750 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));17641765 // useImperativeHandle1766 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));17781779 // useMemo1780 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));17921793 // useCallback1794 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));18061807 // useEffect (with aliasing signature)1808 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));18471848 // useLayoutEffect1849 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));18611862 // useInsertionEffect1863 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));18751876 // useTransition1877 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));18911892 // useOptimistic1893 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));19081909 // use (not a hook, it's a function)1910 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));19231924 // useEffectEvent1925 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));19411942 // Insert all React APIs as standalone globals1943 for (name, ty) in &react_apis {1944 globals.insert(name.clone(), ty.clone());1945 }19461947 react_apis1948}19491950/// Build typed globals and return them as a list for use as globalThis/global properties.1951fn 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 // Object1958 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 // Only keys are captured, and keys are immutable1980 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()