1/**2 * Copyright (c) Meta Platforms, Inc. and affiliates.3 *4 * This source code is licensed under the MIT license found in the5 * LICENSE file in the root directory of this source tree.6 */78import {Effect, ValueKind, ValueReason} from './HIR';9import {10 BUILTIN_SHAPES,11 BuiltInArrayId,12 BuiltInMapId,13 BuiltInMixedReadonlyId,14 BuiltInObjectId,15 BuiltInSetId,16 BuiltInUseActionStateId,17 BuiltInUseContextHookId,18 BuiltInUseEffectEventId,19 BuiltInUseEffectHookId,20 BuiltInUseInsertionEffectHookId,21 BuiltInUseLayoutEffectHookId,22 BuiltInUseOperatorId,23 BuiltInUseOptimisticId,24 BuiltInUseReducerId,25 BuiltInUseRefId,26 BuiltInUseStateId,27 BuiltInUseTransitionId,28 BuiltInWeakMapId,29 BuiltInWeakSetId,30 BuiltInEffectEventId,31 ReanimatedSharedValueId,32 ShapeRegistry,33 addFunction,34 addHook,35 addObject,36} from './ObjectShape';37import {BuiltInType, ObjectType, PolyType} from './Types';38import {TypeConfig} from './TypeSchema';39import {assertExhaustive} from '../Utils/utils';40import {isHookName} from './Environment';41import {CompilerError, SourceLocation} from '..';4243/*44 * This file exports types and defaults for JavaScript global objects.45 * A Forget `Environment` stores the GlobalRegistry and ShapeRegistry46 * used for the current project. These ultimately help Forget refine47 * its inference of types (i.e. Object vs Primitive) and effects48 * (i.e. read vs mutate) in source programs.49 */5051// ShapeRegistry with default definitions for builtins and global objects.52export const DEFAULT_SHAPES: ShapeRegistry = new Map(BUILTIN_SHAPES);5354// Hack until we add ObjectShapes for all globals55const UNTYPED_GLOBALS: Set<string> = new Set([56 'Object',57 'Function',58 'RegExp',59 'Date',60 'Error',61 'TypeError',62 'RangeError',63 'ReferenceError',64 'SyntaxError',65 'URIError',66 'EvalError',67 'DataView',68 'Float32Array',69 'Float64Array',70 'Int8Array',71 'Int16Array',72 'Int32Array',73 'WeakMap',74 'Uint8Array',75 'Uint8ClampedArray',76 'Uint16Array',77 'Uint32Array',78 'ArrayBuffer',79 'JSON',80 'console',81 'eval',82]);8384const TYPED_GLOBALS: Array<[string, BuiltInType]> = [85 [86 'Object',87 addObject(DEFAULT_SHAPES, 'Object', [88 [89 'keys',90 addFunction(DEFAULT_SHAPES, [], {91 positionalParams: [Effect.Read],92 restParam: null,93 returnType: {kind: 'Object', shapeId: BuiltInArrayId},94 calleeEffect: Effect.Read,95 returnValueKind: ValueKind.Mutable,96 }),97 ],98 [99 /**100 * Object.fromEntries(iterable)101 * iterable: An iterable, such as an Array or Map, containing a list of102 * objects. Each object should have two properties.103 * Returns a new object whose properties are given by the entries of the104 * iterable.105 */106 'fromEntries',107 addFunction(DEFAULT_SHAPES, [], {108 positionalParams: [Effect.ConditionallyMutate],109 restParam: null,110 returnType: {kind: 'Object', shapeId: BuiltInObjectId},111 calleeEffect: Effect.Read,112 returnValueKind: ValueKind.Mutable,113 }),114 ],115 [116 'entries',117 addFunction(DEFAULT_SHAPES, [], {118 positionalParams: [Effect.Capture],119 restParam: null,120 returnType: {kind: 'Object', shapeId: BuiltInArrayId},121 calleeEffect: Effect.Read,122 returnValueKind: ValueKind.Mutable,123 aliasing: {124 receiver: '@receiver',125 params: ['@object'],126 rest: null,127 returns: '@returns',128 temporaries: [],129 effects: [130 {131 kind: 'Create',132 into: '@returns',133 reason: ValueReason.KnownReturnSignature,134 value: ValueKind.Mutable,135 },136 // Object values are captured into the return137 {138 kind: 'Capture',139 from: '@object',140 into: '@returns',141 },142 ],143 },144 }),145 ],146 [147 'keys',148 addFunction(DEFAULT_SHAPES, [], {149 positionalParams: [Effect.Read],150 restParam: null,151 returnType: {kind: 'Object', shapeId: BuiltInArrayId},152 calleeEffect: Effect.Read,153 returnValueKind: ValueKind.Mutable,154 aliasing: {155 receiver: '@receiver',156 params: ['@object'],157 rest: null,158 returns: '@returns',159 temporaries: [],160 effects: [161 {162 kind: 'Create',163 into: '@returns',164 reason: ValueReason.KnownReturnSignature,165 value: ValueKind.Mutable,166 },167 // Only keys are captured, and keys are immutable168 {169 kind: 'ImmutableCapture',170 from: '@object',171 into: '@returns',172 },173 ],174 },175 }),176 ],177 [178 'values',179 addFunction(DEFAULT_SHAPES, [], {180 positionalParams: [Effect.Capture],181 restParam: null,182 returnType: {kind: 'Object', shapeId: BuiltInArrayId},183 calleeEffect: Effect.Read,184 returnValueKind: ValueKind.Mutable,185 aliasing: {186 receiver: '@receiver',187 params: ['@object'],188 rest: null,189 returns: '@returns',190 temporaries: [],191 effects: [192 {193 kind: 'Create',194 into: '@returns',195 reason: ValueReason.KnownReturnSignature,196 value: ValueKind.Mutable,197 },198 // Object values are captured into the return199 {200 kind: 'Capture',201 from: '@object',202 into: '@returns',203 },204 ],205 },206 }),207 ],208 ]),209 ],210 [211 'Array',212 addObject(DEFAULT_SHAPES, 'Array', [213 [214 'isArray',215 // Array.isArray(value)216 addFunction(DEFAULT_SHAPES, [], {217 positionalParams: [Effect.Read],218 restParam: null,219 returnType: {kind: 'Primitive'},220 calleeEffect: Effect.Read,221 returnValueKind: ValueKind.Primitive,222 }),223 ],224 /*225 * https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.from226 * Array.from(arrayLike, optionalFn, optionalThis)227 * Note that the Effect of `arrayLike` is polymorphic i.e.228 * - Effect.read if229 * - it does not have an @iterator property and is array-like230 * (i.e. has a length property)231 * - it is an iterable object whose iterator does not mutate itself232 * - Effect.mutate if it is a self-mutative iterator (e.g. a generator233 * function)234 */235 [236 'from',237 addFunction(DEFAULT_SHAPES, [], {238 positionalParams: [239 Effect.ConditionallyMutateIterator,240 Effect.ConditionallyMutate,241 Effect.ConditionallyMutate,242 ],243 restParam: Effect.Read,244 returnType: {kind: 'Object', shapeId: BuiltInArrayId},245 calleeEffect: Effect.Read,246 returnValueKind: ValueKind.Mutable,247 }),248 ],249 [250 'of',251 // Array.of(element0, ..., elementN)252 addFunction(DEFAULT_SHAPES, [], {253 positionalParams: [],254 restParam: Effect.Read,255 returnType: {kind: 'Object', shapeId: BuiltInArrayId},256 calleeEffect: Effect.Read,257 returnValueKind: ValueKind.Mutable,258 }),259 ],260 ]),261 ],262 [263 'performance',264 addObject(DEFAULT_SHAPES, 'performance', [265 // Static methods (TODO)266 [267 'now',268 // Date.now()269 addFunction(DEFAULT_SHAPES, [], {270 positionalParams: [],271 restParam: Effect.Read,272 returnType: {kind: 'Poly'}, // TODO: could be Primitive, but that would change existing compilation273 calleeEffect: Effect.Read,274 returnValueKind: ValueKind.Mutable, // same here275 impure: true,276 canonicalName: 'performance.now',277 }),278 ],279 ]),280 ],281 [282 'Date',283 addObject(DEFAULT_SHAPES, 'Date', [284 // Static methods (TODO)285 [286 'now',287 // Date.now()288 addFunction(DEFAULT_SHAPES, [], {289 positionalParams: [],290 restParam: Effect.Read,291 returnType: {kind: 'Poly'}, // TODO: could be Primitive, but that would change existing compilation292 calleeEffect: Effect.Read,293 returnValueKind: ValueKind.Mutable, // same here294 impure: true,295 canonicalName: 'Date.now',296 }),297 ],298 ]),299 ],300 [301 'Math',302 addObject(DEFAULT_SHAPES, 'Math', [303 // Static properties (TODO)304 ['PI', {kind: 'Primitive'}],305 // Static methods (TODO)306 [307 'max',308 // Math.max(value0, ..., valueN)309 addFunction(DEFAULT_SHAPES, [], {310 positionalParams: [],311 restParam: Effect.Read,312 returnType: {kind: 'Primitive'},313 calleeEffect: Effect.Read,314 returnValueKind: ValueKind.Primitive,315 }),316 ],317 [318 'min',319 // Math.min(value0, ..., valueN)320 addFunction(DEFAULT_SHAPES, [], {321 positionalParams: [],322 restParam: Effect.Read,323 returnType: {kind: 'Primitive'},324 calleeEffect: Effect.Read,325 returnValueKind: ValueKind.Primitive,326 }),327 ],328 [329 'trunc',330 addFunction(DEFAULT_SHAPES, [], {331 positionalParams: [],332 restParam: Effect.Read,333 returnType: {kind: 'Primitive'},334 calleeEffect: Effect.Read,335 returnValueKind: ValueKind.Primitive,336 }),337 ],338 [339 'ceil',340 addFunction(DEFAULT_SHAPES, [], {341 positionalParams: [],342 restParam: Effect.Read,343 returnType: {kind: 'Primitive'},344 calleeEffect: Effect.Read,345 returnValueKind: ValueKind.Primitive,346 }),347 ],348 [349 'floor',350 addFunction(DEFAULT_SHAPES, [], {351 positionalParams: [],352 restParam: Effect.Read,353 returnType: {kind: 'Primitive'},354 calleeEffect: Effect.Read,355 returnValueKind: ValueKind.Primitive,356 }),357 ],358 [359 'pow',360 addFunction(DEFAULT_SHAPES, [], {361 positionalParams: [],362 restParam: Effect.Read,363 returnType: {kind: 'Primitive'},364 calleeEffect: Effect.Read,365 returnValueKind: ValueKind.Primitive,366 }),367 ],368 [369 'random',370 addFunction(DEFAULT_SHAPES, [], {371 positionalParams: [],372 restParam: Effect.Read,373 returnType: {kind: 'Poly'}, // TODO: could be Primitive, but that would change existing compilation374 calleeEffect: Effect.Read,375 returnValueKind: ValueKind.Mutable, // same here376 impure: true,377 canonicalName: 'Math.random',378 }),379 ],380 ]),381 ],382 ['Infinity', {kind: 'Primitive'}],383 ['NaN', {kind: 'Primitive'}],384 [385 'console',386 addObject(DEFAULT_SHAPES, 'console', [387 [388 'error',389 addFunction(DEFAULT_SHAPES, [], {390 positionalParams: [],391 restParam: Effect.Read,392 returnType: {kind: 'Primitive'},393 calleeEffect: Effect.Read,394 returnValueKind: ValueKind.Primitive,395 }),396 ],397 [398 'info',399 addFunction(DEFAULT_SHAPES, [], {400 positionalParams: [],401 restParam: Effect.Read,402 returnType: {kind: 'Primitive'},403 calleeEffect: Effect.Read,404 returnValueKind: ValueKind.Primitive,405 }),406 ],407 [408 'log',409 addFunction(DEFAULT_SHAPES, [], {410 positionalParams: [],411 restParam: Effect.Read,412 returnType: {kind: 'Primitive'},413 calleeEffect: Effect.Read,414 returnValueKind: ValueKind.Primitive,415 }),416 ],417 [418 'table',419 addFunction(DEFAULT_SHAPES, [], {420 positionalParams: [],421 restParam: Effect.Read,422 returnType: {kind: 'Primitive'},423 calleeEffect: Effect.Read,424 returnValueKind: ValueKind.Primitive,425 }),426 ],427 [428 'trace',429 addFunction(DEFAULT_SHAPES, [], {430 positionalParams: [],431 restParam: Effect.Read,432 returnType: {kind: 'Primitive'},433 calleeEffect: Effect.Read,434 returnValueKind: ValueKind.Primitive,435 }),436 ],437 [438 'warn',439 addFunction(DEFAULT_SHAPES, [], {440 positionalParams: [],441 restParam: Effect.Read,442 returnType: {kind: 'Primitive'},443 calleeEffect: Effect.Read,444 returnValueKind: ValueKind.Primitive,445 }),446 ],447 ]),448 ],449 [450 'Boolean',451 addFunction(DEFAULT_SHAPES, [], {452 positionalParams: [],453 restParam: Effect.Read,454 returnType: {kind: 'Primitive'},455 calleeEffect: Effect.Read,456 returnValueKind: ValueKind.Primitive,457 }),458 ],459 [460 'Number',461 addFunction(DEFAULT_SHAPES, [], {462 positionalParams: [],463 restParam: Effect.Read,464 returnType: {kind: 'Primitive'},465 calleeEffect: Effect.Read,466 returnValueKind: ValueKind.Primitive,467 }),468 ],469 [470 'String',471 addFunction(DEFAULT_SHAPES, [], {472 positionalParams: [],473 restParam: Effect.Read,474 returnType: {kind: 'Primitive'},475 calleeEffect: Effect.Read,476 returnValueKind: ValueKind.Primitive,477 }),478 ],479 [480 'parseInt',481 addFunction(DEFAULT_SHAPES, [], {482 positionalParams: [],483 restParam: Effect.Read,484 returnType: {kind: 'Primitive'},485 calleeEffect: Effect.Read,486 returnValueKind: ValueKind.Primitive,487 }),488 ],489 [490 'parseFloat',491 addFunction(DEFAULT_SHAPES, [], {492 positionalParams: [],493 restParam: Effect.Read,494 returnType: {kind: 'Primitive'},495 calleeEffect: Effect.Read,496 returnValueKind: ValueKind.Primitive,497 }),498 ],499 [500 'isNaN',501 addFunction(DEFAULT_SHAPES, [], {502 positionalParams: [],503 restParam: Effect.Read,504 returnType: {kind: 'Primitive'},505 calleeEffect: Effect.Read,506 returnValueKind: ValueKind.Primitive,507 }),508 ],509 [510 'isFinite',511 addFunction(DEFAULT_SHAPES, [], {512 positionalParams: [],513 restParam: Effect.Read,514 returnType: {kind: 'Primitive'},515 calleeEffect: Effect.Read,516 returnValueKind: ValueKind.Primitive,517 }),518 ],519 [520 'encodeURI',521 addFunction(DEFAULT_SHAPES, [], {522 positionalParams: [],523 restParam: Effect.Read,524 returnType: {kind: 'Primitive'},525 calleeEffect: Effect.Read,526 returnValueKind: ValueKind.Primitive,527 }),528 ],529 [530 'encodeURIComponent',531 addFunction(DEFAULT_SHAPES, [], {532 positionalParams: [],533 restParam: Effect.Read,534 returnType: {kind: 'Primitive'},535 calleeEffect: Effect.Read,536 returnValueKind: ValueKind.Primitive,537 }),538 ],539 [540 'decodeURI',541 addFunction(DEFAULT_SHAPES, [], {542 positionalParams: [],543 restParam: Effect.Read,544 returnType: {kind: 'Primitive'},545 calleeEffect: Effect.Read,546 returnValueKind: ValueKind.Primitive,547 }),548 ],549 [550 'decodeURIComponent',551 addFunction(DEFAULT_SHAPES, [], {552 positionalParams: [],553 restParam: Effect.Read,554 returnType: {kind: 'Primitive'},555 calleeEffect: Effect.Read,556 returnValueKind: ValueKind.Primitive,557 }),558 ],559 [560 'Map',561 addFunction(562 DEFAULT_SHAPES,563 [],564 {565 positionalParams: [Effect.ConditionallyMutateIterator],566 restParam: null,567 returnType: {kind: 'Object', shapeId: BuiltInMapId},568 calleeEffect: Effect.Read,569 returnValueKind: ValueKind.Mutable,570 },571 null,572 true,573 ),574 ],575 [576 'Set',577 addFunction(578 DEFAULT_SHAPES,579 [],580 {581 positionalParams: [Effect.ConditionallyMutateIterator],582 restParam: null,583 returnType: {kind: 'Object', shapeId: BuiltInSetId},584 calleeEffect: Effect.Read,585 returnValueKind: ValueKind.Mutable,586 },587 null,588 true,589 ),590 ],591 [592 'WeakMap',593 addFunction(594 DEFAULT_SHAPES,595 [],596 {597 positionalParams: [Effect.ConditionallyMutateIterator],598 restParam: null,599 returnType: {kind: 'Object', shapeId: BuiltInWeakMapId},600 calleeEffect: Effect.Read,601 returnValueKind: ValueKind.Mutable,602 },603 null,604 true,605 ),606 ],607 [608 'WeakSet',609 addFunction(610 DEFAULT_SHAPES,611 [],612 {613 positionalParams: [Effect.ConditionallyMutateIterator],614 restParam: null,615 returnType: {kind: 'Object', shapeId: BuiltInWeakSetId},616 calleeEffect: Effect.Read,617 returnValueKind: ValueKind.Mutable,618 },619 null,620 true,621 ),622 ],623 // TODO: rest of Global objects624];625626/*627 * TODO(mofeiZ): We currently only store rest param effects for hooks.628 * now that FeatureFlag `enableTreatHooksAsFunctions` is removed we can629 * use positional params too (?)630 */631const REACT_APIS: Array<[string, BuiltInType]> = [632 [633 'useContext',634 addHook(635 DEFAULT_SHAPES,636 {637 positionalParams: [],638 restParam: Effect.Read,639 returnType: {kind: 'Poly'},640 calleeEffect: Effect.Read,641 hookKind: 'useContext',642 returnValueKind: ValueKind.Frozen,643 returnValueReason: ValueReason.Context,644 },645 BuiltInUseContextHookId,646 ),647 ],648 [649 'useState',650 addHook(DEFAULT_SHAPES, {651 positionalParams: [],652 restParam: Effect.Freeze,653 returnType: {kind: 'Object', shapeId: BuiltInUseStateId},654 calleeEffect: Effect.Read,655 hookKind: 'useState',656 returnValueKind: ValueKind.Frozen,657 returnValueReason: ValueReason.State,658 }),659 ],660 [661 'useActionState',662 addHook(DEFAULT_SHAPES, {663 positionalParams: [],664 restParam: Effect.Freeze,665 returnType: {kind: 'Object', shapeId: BuiltInUseActionStateId},666 calleeEffect: Effect.Read,667 hookKind: 'useActionState',668 returnValueKind: ValueKind.Frozen,669 returnValueReason: ValueReason.State,670 }),671 ],672 [673 'useReducer',674 addHook(DEFAULT_SHAPES, {675 positionalParams: [],676 restParam: Effect.Freeze,677 returnType: {kind: 'Object', shapeId: BuiltInUseReducerId},678 calleeEffect: Effect.Read,679 hookKind: 'useReducer',680 returnValueKind: ValueKind.Frozen,681 returnValueReason: ValueReason.ReducerState,682 }),683 ],684 [685 'useRef',686 addHook(DEFAULT_SHAPES, {687 positionalParams: [],688 restParam: Effect.Capture,689 returnType: {kind: 'Object', shapeId: BuiltInUseRefId},690 calleeEffect: Effect.Read,691 hookKind: 'useRef',692 returnValueKind: ValueKind.Mutable,693 }),694 ],695 [696 'useImperativeHandle',697 addHook(DEFAULT_SHAPES, {698 positionalParams: [],699 restParam: Effect.Freeze,700 returnType: {kind: 'Primitive'},701 calleeEffect: Effect.Read,702 hookKind: 'useImperativeHandle',703 returnValueKind: ValueKind.Frozen,704 }),705 ],706 [707 'useMemo',708 addHook(DEFAULT_SHAPES, {709 positionalParams: [],710 restParam: Effect.Freeze,711 returnType: {kind: 'Poly'},712 calleeEffect: Effect.Read,713 hookKind: 'useMemo',714 returnValueKind: ValueKind.Frozen,715 }),716 ],717 [718 'useCallback',719 addHook(DEFAULT_SHAPES, {720 positionalParams: [],721 restParam: Effect.Freeze,722 returnType: {kind: 'Poly'},723 calleeEffect: Effect.Read,724 hookKind: 'useCallback',725 returnValueKind: ValueKind.Frozen,726 }),727 ],728 [729 'useEffect',730 addHook(731 DEFAULT_SHAPES,732 {733 positionalParams: [],734 restParam: Effect.Freeze,735 returnType: {kind: 'Primitive'},736 calleeEffect: Effect.Read,737 hookKind: 'useEffect',738 returnValueKind: ValueKind.Frozen,739 aliasing: {740 receiver: '@receiver',741 params: [],742 rest: '@rest',743 returns: '@returns',744 temporaries: ['@effect'],745 effects: [746 // Freezes the function and deps747 {748 kind: 'Freeze',749 value: '@rest',750 reason: ValueReason.Effect,751 },752 // Internally creates an effect object that captures the function and deps753 {754 kind: 'Create',755 into: '@effect',756 value: ValueKind.Frozen,757 reason: ValueReason.KnownReturnSignature,758 },759 // The effect stores the function and dependencies760 {761 kind: 'Capture',762 from: '@rest',763 into: '@effect',764 },765 // Returns undefined766 {767 kind: 'Create',768 into: '@returns',769 value: ValueKind.Primitive,770 reason: ValueReason.KnownReturnSignature,771 },772 ],773 },774 },775 BuiltInUseEffectHookId,776 ),777 ],778 [779 'useLayoutEffect',780 addHook(781 DEFAULT_SHAPES,782 {783 positionalParams: [],784 restParam: Effect.Freeze,785 returnType: {kind: 'Poly'},786 calleeEffect: Effect.Read,787 hookKind: 'useLayoutEffect',788 returnValueKind: ValueKind.Frozen,789 },790 BuiltInUseLayoutEffectHookId,791 ),792 ],793 [794 'useInsertionEffect',795 addHook(796 DEFAULT_SHAPES,797 {798 positionalParams: [],799 restParam: Effect.Freeze,800 returnType: {kind: 'Poly'},801 calleeEffect: Effect.Read,802 hookKind: 'useInsertionEffect',803 returnValueKind: ValueKind.Frozen,804 },805 BuiltInUseInsertionEffectHookId,806 ),807 ],808 [809 'useTransition',810 addHook(DEFAULT_SHAPES, {811 positionalParams: [],812 restParam: null,813 returnType: {kind: 'Object', shapeId: BuiltInUseTransitionId},814 calleeEffect: Effect.Read,815 hookKind: 'useTransition',816 returnValueKind: ValueKind.Frozen,817 }),818 ],819 [820 'useOptimistic',821 addHook(DEFAULT_SHAPES, {822 positionalParams: [],823 restParam: Effect.Freeze,824 returnType: {kind: 'Object', shapeId: BuiltInUseOptimisticId},825 calleeEffect: Effect.Read,826 hookKind: 'useOptimistic',827 returnValueKind: ValueKind.Frozen,828 returnValueReason: ValueReason.State,829 }),830 ],831 [832 'use',833 addFunction(834 DEFAULT_SHAPES,835 [],836 {837 positionalParams: [],838 restParam: Effect.Freeze,839 returnType: {kind: 'Poly'},840 calleeEffect: Effect.Read,841 returnValueKind: ValueKind.Frozen,842 },843 BuiltInUseOperatorId,844 ),845 ],846 [847 'useEffectEvent',848 addHook(849 DEFAULT_SHAPES,850 {851 positionalParams: [],852 restParam: Effect.Freeze,853 returnType: {854 kind: 'Function',855 return: {kind: 'Poly'},856 shapeId: BuiltInEffectEventId,857 isConstructor: false,858 },859 calleeEffect: Effect.Read,860 hookKind: 'useEffectEvent',861 // Frozen because it should not mutate any locally-bound values862 returnValueKind: ValueKind.Frozen,863 },864 BuiltInUseEffectEventId,865 ),866 ],867];868869TYPED_GLOBALS.push(870 [871 'React',872 addObject(DEFAULT_SHAPES, null, [873 ...REACT_APIS,874 [875 'createElement',876 addFunction(DEFAULT_SHAPES, [], {877 positionalParams: [],878 restParam: Effect.Freeze,879 returnType: {kind: 'Poly'},880 calleeEffect: Effect.Read,881 returnValueKind: ValueKind.Frozen,882 }),883 ],884 [885 'cloneElement',886 addFunction(DEFAULT_SHAPES, [], {887 positionalParams: [],888 restParam: Effect.Freeze,889 returnType: {kind: 'Poly'},890 calleeEffect: Effect.Read,891 returnValueKind: ValueKind.Frozen,892 }),893 ],894 [895 'createRef',896 addFunction(DEFAULT_SHAPES, [], {897 positionalParams: [],898 restParam: Effect.Capture, // createRef takes no paramters899 returnType: {kind: 'Object', shapeId: BuiltInUseRefId},900 calleeEffect: Effect.Read,901 returnValueKind: ValueKind.Mutable,902 }),903 ],904 ]),905 ],906 [907 '_jsx',908 addFunction(DEFAULT_SHAPES, [], {909 positionalParams: [],910 restParam: Effect.Freeze,911 returnType: {kind: 'Poly'},912 calleeEffect: Effect.Read,913 returnValueKind: ValueKind.Frozen,914 }),915 ],916);917918export type Global = BuiltInType | PolyType;919export type GlobalRegistry = Map<string, Global>;920export const DEFAULT_GLOBALS: GlobalRegistry = new Map(REACT_APIS);921922// Hack until we add ObjectShapes for all globals923for (const name of UNTYPED_GLOBALS) {924 DEFAULT_GLOBALS.set(name, {925 kind: 'Poly',926 });927}928929for (const [name, type_] of TYPED_GLOBALS) {930 DEFAULT_GLOBALS.set(name, type_);931}932933// Recursive global types934DEFAULT_GLOBALS.set(935 'globalThis',936 addObject(DEFAULT_SHAPES, 'globalThis', TYPED_GLOBALS),937);938DEFAULT_GLOBALS.set(939 'global',940 addObject(DEFAULT_SHAPES, 'global', TYPED_GLOBALS),941);942943export function installTypeConfig(944 globals: GlobalRegistry,945 shapes: ShapeRegistry,946 typeConfig: TypeConfig,947 moduleName: string,948 loc: SourceLocation,949): Global {950 switch (typeConfig.kind) {951 case 'type': {952 switch (typeConfig.name) {953 case 'Array': {954 return {kind: 'Object', shapeId: BuiltInArrayId};955 }956 case 'MixedReadonly': {957 return {kind: 'Object', shapeId: BuiltInMixedReadonlyId};958 }959 case 'Primitive': {960 return {kind: 'Primitive'};961 }962 case 'Ref': {963 return {kind: 'Object', shapeId: BuiltInUseRefId};964 }965 case 'Any': {966 return {kind: 'Poly'};967 }968 default: {969 assertExhaustive(970 typeConfig.name,971 `Unexpected type '${(typeConfig as any).name}'`,972 );973 }974 }975 }976 case 'function': {977 return addFunction(shapes, [], {978 positionalParams: typeConfig.positionalParams,979 restParam: typeConfig.restParam,980 calleeEffect: typeConfig.calleeEffect,981 returnType: installTypeConfig(982 globals,983 shapes,984 typeConfig.returnType,985 moduleName,986 loc,987 ),988 returnValueKind: typeConfig.returnValueKind,989 noAlias: typeConfig.noAlias === true,990 mutableOnlyIfOperandsAreMutable:991 typeConfig.mutableOnlyIfOperandsAreMutable === true,992 aliasing: typeConfig.aliasing,993 knownIncompatible: typeConfig.knownIncompatible ?? null,994 });995 }996 case 'hook': {997 return addHook(shapes, {998 hookKind: 'Custom',999 positionalParams: typeConfig.positionalParams ?? [],1000 restParam: typeConfig.restParam ?? Effect.Freeze,1001 calleeEffect: Effect.Read,1002 returnType: installTypeConfig(1003 globals,1004 shapes,1005 typeConfig.returnType,1006 moduleName,1007 loc,1008 ),1009 returnValueKind: typeConfig.returnValueKind ?? ValueKind.Frozen,1010 noAlias: typeConfig.noAlias === true,1011 aliasing: typeConfig.aliasing,1012 knownIncompatible: typeConfig.knownIncompatible ?? null,1013 });1014 }1015 case 'object': {1016 return addObject(1017 shapes,1018 null,1019 Object.entries(typeConfig.properties ?? {}).map(([key, value]) => {1020 const type = installTypeConfig(1021 globals,1022 shapes,1023 value,1024 moduleName,1025 loc,1026 );1027 const expectHook = isHookName(key);1028 let isHook = false;1029 if (type.kind === 'Function' && type.shapeId !== null) {1030 const functionType = shapes.get(type.shapeId);1031 if (functionType?.functionType?.hookKind !== null) {1032 isHook = true;1033 }1034 }1035 if (expectHook !== isHook) {1036 CompilerError.throwInvalidConfig({1037 reason: `Invalid type configuration for module`,1038 description: `Expected type for object property '${key}' from module '${moduleName}' ${expectHook ? 'to be a hook' : 'not to be a hook'} based on the property name`,1039 loc,1040 });1041 }1042 return [key, type];1043 }),1044 );1045 }1046 default: {1047 assertExhaustive(1048 typeConfig,1049 `Unexpected type kind '${(typeConfig as any).kind}'`,1050 );1051 }1052 }1053}10541055export function getReanimatedModuleType(registry: ShapeRegistry): ObjectType {1056 // hooks that freeze args and return frozen value1057 const frozenHooks = [1058 'useFrameCallback',1059 'useAnimatedStyle',1060 'useAnimatedProps',1061 'useAnimatedScrollHandler',1062 'useAnimatedReaction',1063 'useWorkletCallback',1064 ];1065 const reanimatedType: Array<[string, BuiltInType]> = [];1066 for (const hook of frozenHooks) {1067 reanimatedType.push([1068 hook,1069 addHook(registry, {1070 positionalParams: [],1071 restParam: Effect.Freeze,1072 returnType: {kind: 'Poly'},1073 returnValueKind: ValueKind.Frozen,1074 noAlias: true,1075 calleeEffect: Effect.Read,1076 hookKind: 'Custom',1077 }),1078 ]);1079 }10801081 /**1082 * hooks that return a mutable value. ideally these should be modelled as a1083 * ref, but this works for now.1084 */1085 const mutableHooks = ['useSharedValue', 'useDerivedValue'];1086 for (const hook of mutableHooks) {1087 reanimatedType.push([1088 hook,1089 addHook(registry, {1090 positionalParams: [],1091 restParam: Effect.Freeze,1092 returnType: {kind: 'Object', shapeId: ReanimatedSharedValueId},1093 returnValueKind: ValueKind.Mutable,1094 noAlias: true,1095 calleeEffect: Effect.Read,1096 hookKind: 'Custom',1097 }),1098 ]);1099 }11001101 // functions that return mutable value1102 const funcs = [1103 'withTiming',1104 'withSpring',1105 'createAnimatedPropAdapter',1106 'withDecay',1107 'withRepeat',1108 'runOnUI',1109 'executeOnUIRuntimeSync',1110 ];1111 for (const fn of funcs) {1112 reanimatedType.push([1113 fn,1114 addFunction(registry, [], {1115 positionalParams: [],1116 restParam: Effect.Read,1117 returnType: {kind: 'Poly'},1118 calleeEffect: Effect.Read,1119 returnValueKind: ValueKind.Mutable,1120 noAlias: true,1121 }),1122 ]);1123 }11241125 return addObject(registry, null, reanimatedType);1126}
Findings
✓ No findings reported for this file.