'use strict'; import type { WorkletFunction } from 'react-native-worklets'; import { isWorkletFunction } from 'react-native-worklets'; import type { UnknownRecord } from '../common'; import type { ReanimatedEvent } from './commonTypes'; interface GeneralHandler< TEvent extends object, TContext extends UnknownRecord, > { (event: ReanimatedEvent, context: TContext): void; } export type GeneralHandlers< TEvent extends object, TContext extends UnknownRecord, > = Record | undefined>; export interface UseHandlerContext { context: TContext; doDependenciesDiffer: boolean; } export function ensureWorkletHandlers(handlers: UnknownRecord) { const nonWorkletNames = Object.entries(handlers).reduce( (acc, [name, handler]) => { if (!isWorkletFunction(handler)) acc.push(name); return acc; }, [] ); if (nonWorkletNames.length > 0) { throw new Error( `[Reanimated] Passed handlers that are not worklets. Only worklet functions are allowed. Handlers "${nonWorkletNames.join(', ')}" are not worklets.` ); } } const objectIs: (a: unknown, b: unknown) => boolean = typeof Object.is === 'function' ? Object.is : (x, y) => (x === y && (x !== 0 || 1 / (x as number) === 1 / (y as number))) || (Number.isNaN(x as number) && Number.isNaN(y as number)); const areWorkletClosuresEqual = areDependenciesEqual; function areWorkletsEqual( next: WorkletFunction, prev: WorkletFunction ): boolean { if (objectIs(next, prev)) { return true; } return ( next.__workletHash === prev.__workletHash && ((next.__closure === undefined && prev.__closure === undefined) || areWorkletClosuresEqual(next.__closure, prev.__closure)) ); } export function areWorkletHandlersEqual( next: Partial> | undefined, prev: Partial> | undefined ) { if (!next || !prev) { return false; } const nextKeys = Object.keys(next); const prevKeys = Object.keys(prev); if (nextKeys.length !== prevKeys.length) { return false; } return nextKeys.every((key) => { const nextValue = next[key]; const prevValue = prev[key]; if (!nextValue || !prevValue) { return false; } return areWorkletsEqual(nextValue, prevValue); }); } export function areDependenciesEqual( next: Array | undefined, prev: Array | undefined ): boolean { if (!next || !prev || next.length !== prev.length) { return false; } return next.every((value, index) => objectIs(value, prev[index])); }