diff --git a/packages/react-native-reanimated/src/errors.ts b/packages/react-native-reanimated/src/errors.ts index 6eca95be2580..9ea62604609b 100644 --- a/packages/react-native-reanimated/src/errors.ts +++ b/packages/react-native-reanimated/src/errors.ts @@ -1,12 +1,33 @@ +/* eslint-disable reanimated/use-reanimated-error */ 'use strict'; -import { createCustomError, registerCustomError } from 'react-native-worklets'; - -export const ReanimatedError = createCustomError('Reanimated'); - -const ReanimatedErrorConstructor = ReanimatedError; +function ReanimatedErrorConstructor(message: string): ReanimatedError { + 'worklet'; + const prefix = '[Reanimated]'; + const errorInstance = new Error(message ? `${prefix} ${message}` : prefix); + errorInstance.name = 'ReanimatedError'; + return errorInstance as ReanimatedError; +} +/** + * Registers ReanimatedError in the global scope. Register only for Worklet + * runtimes. + */ export function registerReanimatedError() { 'worklet'; - registerCustomError(ReanimatedErrorConstructor, 'Reanimated'); + if (globalThis._WORKLET) { + globalThis.ReanimatedError = + ReanimatedErrorConstructor as IReanimatedErrorConstructor; + } } + +export const ReanimatedError = + ReanimatedErrorConstructor as IReanimatedErrorConstructor; + +export interface IReanimatedErrorConstructor extends Error { + new (message?: string): ReanimatedError; + (message?: string): ReanimatedError; + readonly prototype: ReanimatedError; +} + +export type ReanimatedError = Error & { name: 'Reanimated' }; // signed type diff --git a/packages/react-native-reanimated/src/privateGlobals.d.ts b/packages/react-native-reanimated/src/privateGlobals.d.ts index fb3027ec616a..bf8af91cfe53 100644 --- a/packages/react-native-reanimated/src/privateGlobals.d.ts +++ b/packages/react-native-reanimated/src/privateGlobals.d.ts @@ -11,6 +11,7 @@ import type { ShadowNodeWrapper, StyleProps, } from './commonTypes'; +import type { IReanimatedErrorConstructor } from './errors'; import type { FrameCallbackRegistryUI } from './frameCallback/FrameCallbackRegistryUI'; import type { AnimatedStyle } from './helperTypes'; import type { LayoutAnimationsManager } from './layoutReanimation/animationsManager'; @@ -101,4 +102,5 @@ declare global { value: T, nativeStateSource?: object ) => FlatShareableRef; + var ReanimatedError: IReanimatedErrorConstructor; } diff --git a/packages/react-native-worklets/src/WorkletsError.ts b/packages/react-native-worklets/src/WorkletsError.ts index 8a8eb111b28d..0b1a1fa7085e 100644 --- a/packages/react-native-worklets/src/WorkletsError.ts +++ b/packages/react-native-worklets/src/WorkletsError.ts @@ -1,13 +1,33 @@ +/* eslint-disable reanimated/use-worklets-error */ 'use strict'; -import { createCustomError, registerCustomError } from './errors'; - -export const WorkletsError = createCustomError('Worklets'); - -// To capture it in a the registering worklet's closure. -const WorkletsErrorConstructor = WorkletsError; +function WorkletsErrorConstructor(message?: string): WorkletsError { + 'worklet'; + const prefix = '[Worklets]'; + const errorInstance = new Error(message ? `${prefix} ${message}` : prefix); + errorInstance.name = `WorkletsError`; + return errorInstance as WorkletsError; +} +/** + * Registers WorkletsError in the global scope. Register only for Worklet + * runtimes. + */ export function registerWorkletsError() { 'worklet'; - registerCustomError(WorkletsErrorConstructor, 'Worklets'); + if (globalThis._WORKLET) { + globalThis.WorkletsError = + WorkletsErrorConstructor as IWorkletsErrorConstructor; + } +} + +export const WorkletsError = + WorkletsErrorConstructor as IWorkletsErrorConstructor; + +export type WorkletsError = Error & { name: 'Worklets' }; // signed type + +export interface IWorkletsErrorConstructor extends Error { + new (message?: string): WorkletsError; + (message?: string): WorkletsError; + readonly prototype: WorkletsError; } diff --git a/packages/react-native-worklets/src/errors.ts b/packages/react-native-worklets/src/errors.ts index 51c841c8af70..cfd9a3efd37f 100644 --- a/packages/react-native-worklets/src/errors.ts +++ b/packages/react-native-worklets/src/errors.ts @@ -2,46 +2,6 @@ import type { WorkletStackDetails } from './workletTypes'; -export type CustomError = Error & { name: TName }; // signed type - -export interface CustomErrorConstructor extends Error { - new (message?: string): CustomError; - (message?: string): CustomError; - readonly prototype: CustomError; -} - -export function createCustomError( - name: TName -): CustomErrorConstructor { - const constructor = function CustomError(message?: string) { - 'worklet'; - const prefix = `[${name}]`; - // eslint-disable-next-line reanimated/use-worklets-error - const errorInstance = new Error(message ? `${prefix} ${message}` : prefix); - errorInstance.name = `${name}Error`; - return errorInstance; - }; - - Object.defineProperty(constructor, 'name', { value: `${name}Error` }); - - return constructor as CustomErrorConstructor; -} - -/** Registers custom errors in global scope. Use it only for Worklet runtimes. */ -export function registerCustomError( - constructor: CustomErrorConstructor, - name: TName -) { - 'worklet'; - if (!globalThis._WORKLET) { - // eslint-disable-next-line reanimated/use-worklets-error - throw new Error( - '[Worklets] registerCustomError() must be called on a Worklet runtime' - ); - } - (global as Record)[`${name}Error`] = constructor; -} - const _workletStackDetails = new Map(); export function registerWorkletStackDetails( diff --git a/packages/react-native-worklets/src/index.ts b/packages/react-native-worklets/src/index.ts index 116696afdf39..8786ccd4e1ff 100644 --- a/packages/react-native-worklets/src/index.ts +++ b/packages/react-native-worklets/src/index.ts @@ -7,8 +7,6 @@ import { WorkletsModule } from './WorkletsModule'; // universal source of truth for it. initializeUIRuntime(WorkletsModule); -export type { CustomError } from './errors'; -export { createCustomError, registerCustomError } from './errors'; export type { LoggerConfig } from './logger'; export { logger, diff --git a/packages/react-native-worklets/src/privateGlobals.d.ts b/packages/react-native-worklets/src/privateGlobals.d.ts index 0a41afce4fed..cae2169bbe34 100644 --- a/packages/react-native-worklets/src/privateGlobals.d.ts +++ b/packages/react-native-worklets/src/privateGlobals.d.ts @@ -5,6 +5,7 @@ // This file works by accident - currently Builder Bob doesn't move `.d.ts` files to output types. // If it ever breaks, we should address it so we'd not pollute the user's global namespace. import type { callGuardDEV } from './initializers'; +import type { IWorkletsErrorConstructor } from './WorkletsError'; import type { WorkletsModuleProxy } from './WorkletsModule'; declare global { @@ -40,4 +41,5 @@ declare global { worklet: ShareableRef<() => void> ) => void; var _microtaskQueueFinalizers: (() => void)[]; + var WorkletsError: IWorkletsErrorConstructor; }