react-native-worklets 0.0.1-alpha → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Common/cpp/worklets/AnimationFrameQueue/AnimationFrameBatchinator.cpp +71 -0
- package/Common/cpp/worklets/AnimationFrameQueue/AnimationFrameBatchinator.h +38 -0
- package/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp +131 -0
- package/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h +82 -0
- package/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp +72 -0
- package/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h +44 -0
- package/Common/cpp/worklets/Registries/EventHandlerRegistry.cpp +94 -0
- package/Common/cpp/worklets/Registries/EventHandlerRegistry.h +49 -0
- package/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.cpp +8 -0
- package/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.h +39 -0
- package/Common/cpp/worklets/SharedItems/Shareables.cpp +326 -0
- package/Common/cpp/worklets/SharedItems/Shareables.h +345 -0
- package/Common/cpp/worklets/Tools/AsyncQueue.cpp +52 -0
- package/Common/cpp/worklets/Tools/AsyncQueue.h +35 -0
- package/Common/cpp/worklets/Tools/Defs.h +10 -0
- package/Common/cpp/worklets/Tools/JSISerializer.cpp +342 -0
- package/Common/cpp/worklets/Tools/JSISerializer.h +47 -0
- package/Common/cpp/worklets/Tools/JSLogger.cpp +16 -0
- package/Common/cpp/worklets/Tools/JSLogger.h +20 -0
- package/Common/cpp/worklets/Tools/JSScheduler.cpp +10 -0
- package/Common/cpp/worklets/Tools/JSScheduler.h +29 -0
- package/Common/cpp/worklets/Tools/PlatformLogger.h +16 -0
- package/Common/cpp/worklets/Tools/SingleInstanceChecker.h +72 -0
- package/Common/cpp/worklets/Tools/ThreadSafeQueue.h +49 -0
- package/Common/cpp/worklets/Tools/UIScheduler.cpp +19 -0
- package/Common/cpp/worklets/Tools/UIScheduler.h +22 -0
- package/Common/cpp/worklets/Tools/WorkletEventHandler.cpp +29 -0
- package/Common/cpp/worklets/Tools/WorkletEventHandler.h +41 -0
- package/Common/cpp/worklets/Tools/WorkletsJSIUtils.cpp +26 -0
- package/Common/cpp/worklets/Tools/WorkletsJSIUtils.h +199 -0
- package/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.cpp +20 -0
- package/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h +19 -0
- package/Common/cpp/worklets/WorkletRuntime/RuntimeInitialization.md +191 -0
- package/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.cpp +19 -0
- package/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.h +16 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletHermesRuntime.cpp +108 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletHermesRuntime.h +127 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.cpp +183 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.h +90 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeCollector.h +36 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp +179 -0
- package/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.h +22 -0
- package/LICENSE +20 -0
- package/README.md +27 -0
- package/RNWorklets.podspec +70 -0
- package/android/CMakeLists.txt +56 -0
- package/android/build.gradle +313 -0
- package/android/gradle.properties +5 -0
- package/android/proguard-rules.pro +3 -0
- package/android/spotless.gradle +9 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/worklets/CMakeLists.txt +85 -0
- package/android/src/main/cpp/worklets/android/AndroidUIScheduler.cpp +63 -0
- package/android/src/main/cpp/worklets/android/AndroidUIScheduler.h +41 -0
- package/android/src/main/cpp/worklets/android/AnimationFrameCallback.h +32 -0
- package/android/src/main/cpp/worklets/android/PlatformLogger.cpp +29 -0
- package/android/src/main/cpp/worklets/android/WorkletsModule.cpp +83 -0
- package/android/src/main/cpp/worklets/android/WorkletsModule.h +63 -0
- package/android/src/main/cpp/worklets/android/WorkletsOnLoad.cpp +13 -0
- package/android/src/main/java/com/swmansion/worklets/AndroidUIScheduler.java +60 -0
- package/android/src/main/java/com/swmansion/worklets/AnimationFrameQueue/AnimationFrameCallback.java +20 -0
- package/android/src/main/java/com/swmansion/worklets/AnimationFrameQueue/AnimationFrameQueue.java +113 -0
- package/android/src/main/java/com/swmansion/worklets/JSCallInvokerResolver.java +27 -0
- package/android/src/main/java/com/swmansion/worklets/WorkletsMessageQueueThread.java +16 -0
- package/android/src/main/java/com/swmansion/worklets/WorkletsMessageQueueThreadBase.java +72 -0
- package/android/src/main/java/com/swmansion/worklets/WorkletsModule.java +106 -0
- package/android/src/main/java/com/swmansion/worklets/WorkletsPackage.java +49 -0
- package/android/src/paper/com/swmansion/worklets/NativeWorkletsModuleSpec.java +26 -0
- package/apple/worklets/apple/AnimationFrameQueue.h +15 -0
- package/apple/worklets/apple/AnimationFrameQueue.mm +81 -0
- package/apple/worklets/apple/AssertJavaScriptQueue.h +14 -0
- package/apple/worklets/apple/AssertTurboModuleManagerQueue.h +16 -0
- package/apple/worklets/apple/IOSUIScheduler.h +14 -0
- package/apple/worklets/apple/IOSUIScheduler.mm +24 -0
- package/apple/worklets/apple/PlatformLogger.mm +31 -0
- package/apple/worklets/apple/SlowAnimations.h +8 -0
- package/apple/worklets/apple/SlowAnimations.mm +47 -0
- package/apple/worklets/apple/WorkletsDisplayLink.h +21 -0
- package/apple/worklets/apple/WorkletsMessageThread.h +16 -0
- package/apple/worklets/apple/WorkletsMessageThread.mm +32 -0
- package/apple/worklets/apple/WorkletsModule.h +10 -0
- package/apple/worklets/apple/WorkletsModule.mm +85 -0
- package/lib/module/PlatformChecker.js +35 -0
- package/lib/module/PlatformChecker.js.map +1 -0
- package/lib/module/WorkletsError.js +13 -0
- package/lib/module/WorkletsError.js.map +1 -0
- package/lib/module/WorkletsModule/JSWorklets.js +36 -0
- package/lib/module/WorkletsModule/JSWorklets.js.map +1 -0
- package/lib/module/WorkletsModule/NativeWorklets.js +39 -0
- package/lib/module/WorkletsModule/NativeWorklets.js.map +1 -0
- package/lib/module/WorkletsModule/index.js +4 -0
- package/lib/module/WorkletsModule/index.js.map +1 -0
- package/lib/module/WorkletsModule/workletsModuleInstance.js +7 -0
- package/lib/module/WorkletsModule/workletsModuleInstance.js.map +1 -0
- package/lib/module/WorkletsModule/workletsModuleInstance.web.js +5 -0
- package/lib/module/WorkletsModule/workletsModuleInstance.web.js.map +1 -0
- package/lib/module/WorkletsModule/workletsModuleProxy.js +4 -0
- package/lib/module/WorkletsModule/workletsModuleProxy.js.map +1 -0
- package/lib/module/animationFrameQueue/mockedRequestAnimationFrame.js +10 -0
- package/lib/module/animationFrameQueue/mockedRequestAnimationFrame.js.map +1 -0
- package/lib/module/animationFrameQueue/requestAnimationFrame.js +36 -0
- package/lib/module/animationFrameQueue/requestAnimationFrame.js.map +1 -0
- package/lib/module/errors.js +78 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/index.js +17 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/initializers.js +158 -0
- package/lib/module/initializers.js.map +1 -0
- package/lib/module/logger/LogBox.js +15 -0
- package/lib/module/logger/LogBox.js.map +1 -0
- package/lib/module/logger/index.js +5 -0
- package/lib/module/logger/index.js.map +1 -0
- package/lib/module/logger/logger.js +137 -0
- package/lib/module/logger/logger.js.map +1 -0
- package/lib/module/privateGlobals.d.js +8 -0
- package/lib/module/privateGlobals.d.js.map +1 -0
- package/lib/module/runtimes.js +63 -0
- package/lib/module/runtimes.js.map +1 -0
- package/lib/module/shareableMappingCache.js +39 -0
- package/lib/module/shareableMappingCache.js.map +1 -0
- package/lib/module/shareables.js +417 -0
- package/lib/module/shareables.js.map +1 -0
- package/lib/module/specs/NativeWorkletsModule.js +5 -0
- package/lib/module/specs/NativeWorkletsModule.js.map +1 -0
- package/lib/module/specs/index.js +5 -0
- package/lib/module/specs/index.js.map +1 -0
- package/lib/module/threads.js +204 -0
- package/lib/module/threads.js.map +1 -0
- package/lib/module/valueUnpacker.js +83 -0
- package/lib/module/valueUnpacker.js.map +1 -0
- package/lib/module/workletFunction.js +37 -0
- package/lib/module/workletFunction.js.map +1 -0
- package/lib/module/workletTypes.js +12 -0
- package/lib/module/workletTypes.js.map +1 -0
- package/lib/typescript/PlatformChecker.d.ts +7 -0
- package/lib/typescript/PlatformChecker.d.ts.map +1 -0
- package/lib/typescript/WorkletsError.d.ts +3 -0
- package/lib/typescript/WorkletsError.d.ts.map +1 -0
- package/lib/typescript/WorkletsModule/JSWorklets.d.ts +3 -0
- package/lib/typescript/WorkletsModule/JSWorklets.d.ts.map +1 -0
- package/lib/typescript/WorkletsModule/NativeWorklets.d.ts +5 -0
- package/lib/typescript/WorkletsModule/NativeWorklets.d.ts.map +1 -0
- package/lib/typescript/WorkletsModule/index.d.ts +3 -0
- package/lib/typescript/WorkletsModule/index.d.ts.map +1 -0
- package/lib/typescript/WorkletsModule/workletsModuleInstance.d.ts +2 -0
- package/lib/typescript/WorkletsModule/workletsModuleInstance.d.ts.map +1 -0
- package/lib/typescript/WorkletsModule/workletsModuleInstance.web.d.ts +2 -0
- package/lib/typescript/WorkletsModule/workletsModuleInstance.web.d.ts.map +1 -0
- package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts +12 -0
- package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts.map +1 -0
- package/lib/typescript/animationFrameQueue/mockedRequestAnimationFrame.d.ts +6 -0
- package/lib/typescript/animationFrameQueue/mockedRequestAnimationFrame.d.ts.map +1 -0
- package/lib/typescript/animationFrameQueue/requestAnimationFrame.d.ts +2 -0
- package/lib/typescript/animationFrameQueue/requestAnimationFrame.d.ts.map +1 -0
- package/lib/typescript/errors.d.ts +19 -0
- package/lib/typescript/errors.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +13 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/initializers.d.ts +6 -0
- package/lib/typescript/initializers.d.ts.map +1 -0
- package/lib/typescript/logger/LogBox.d.ts +32 -0
- package/lib/typescript/logger/LogBox.d.ts.map +1 -0
- package/lib/typescript/logger/index.d.ts +3 -0
- package/lib/typescript/logger/index.d.ts.map +1 -0
- package/lib/typescript/logger/logger.d.ts +52 -0
- package/lib/typescript/logger/logger.d.ts.map +1 -0
- package/lib/typescript/runtimes.d.ts +16 -0
- package/lib/typescript/runtimes.d.ts.map +1 -0
- package/lib/typescript/shareableMappingCache.d.ts +16 -0
- package/lib/typescript/shareableMappingCache.d.ts.map +1 -0
- package/lib/typescript/shareables.d.ts +15 -0
- package/lib/typescript/shareables.d.ts.map +1 -0
- package/lib/typescript/specs/NativeWorkletsModule.d.ts +7 -0
- package/lib/typescript/specs/NativeWorkletsModule.d.ts.map +1 -0
- package/lib/typescript/specs/index.d.ts +3 -0
- package/lib/typescript/specs/index.d.ts.map +1 -0
- package/lib/typescript/threads.d.ts +49 -0
- package/lib/typescript/threads.d.ts.map +1 -0
- package/lib/typescript/valueUnpacker.d.ts +2 -0
- package/lib/typescript/valueUnpacker.d.ts.map +1 -0
- package/lib/typescript/workletFunction.d.ts +27 -0
- package/lib/typescript/workletFunction.d.ts.map +1 -0
- package/lib/typescript/workletTypes.d.ts +49 -0
- package/lib/typescript/workletTypes.d.ts.map +1 -0
- package/package.json +106 -8
- package/plugin/index.js +3 -0
- package/scripts/worklets_utils.rb +53 -0
- package/src/PlatformChecker.ts +43 -0
- package/src/WorkletsError.ts +13 -0
- package/src/WorkletsModule/JSWorklets.ts +57 -0
- package/src/WorkletsModule/NativeWorklets.ts +68 -0
- package/src/WorkletsModule/index.ts +7 -0
- package/src/WorkletsModule/workletsModuleInstance.ts +9 -0
- package/src/WorkletsModule/workletsModuleInstance.web.ts +5 -0
- package/src/WorkletsModule/workletsModuleProxy.ts +30 -0
- package/src/animationFrameQueue/mockedRequestAnimationFrame.ts +11 -0
- package/src/animationFrameQueue/requestAnimationFrame.ts +41 -0
- package/src/errors.ts +103 -0
- package/src/index.ts +42 -0
- package/src/initializers.ts +175 -0
- package/src/logger/LogBox.ts +55 -0
- package/src/logger/index.ts +3 -0
- package/src/logger/logger.ts +155 -0
- package/src/privateGlobals.d.ts +41 -0
- package/src/runtimes.ts +92 -0
- package/src/shareableMappingCache.ts +44 -0
- package/src/shareables.ts +577 -0
- package/src/specs/NativeWorkletsModule.ts +9 -0
- package/src/specs/index.ts +5 -0
- package/src/threads.ts +275 -0
- package/src/valueUnpacker.ts +110 -0
- package/src/workletFunction.ts +47 -0
- package/src/workletTypes.ts +76 -0
- package/Animated.js +0 -13
- package/AnimatedEvent.js +0 -167
- package/AnimatedImplementation.js +0 -666
- package/CoreAnimated.js +0 -43
- package/Easing.js +0 -236
- package/NativeAnimatedHelper.js +0 -226
- package/SpringConfig.js +0 -79
- package/animations/Animation.js +0 -36
- package/animations/DecayAnimation.js +0 -70
- package/animations/SpringAnimation.js +0 -125
- package/animations/TimingAnimation.js +0 -70
- package/bezier.js +0 -128
- package/createAnimatedComponent.js +0 -188
- package/nodes/AnimatedBlock.js +0 -19
- package/nodes/AnimatedClock.js +0 -76
- package/nodes/AnimatedCond.js +0 -23
- package/nodes/AnimatedDetach.js +0 -15
- package/nodes/AnimatedInterpolation.js +0 -338
- package/nodes/AnimatedNode.js +0 -97
- package/nodes/AnimatedOnChange.js +0 -28
- package/nodes/AnimatedOp.js +0 -17
- package/nodes/AnimatedProps.js +0 -154
- package/nodes/AnimatedSet.js +0 -19
- package/nodes/AnimatedStartClock.js +0 -21
- package/nodes/AnimatedStopClock.js +0 -21
- package/nodes/AnimatedStyle.js +0 -89
- package/nodes/AnimatedTracking.js +0 -36
- package/nodes/AnimatedTransform.js +0 -93
- package/nodes/AnimatedValue.js +0 -271
- package/nodes/AnimatedWithInput.js +0 -21
- package/nodes/SpringNode.js +0 -106
- package/nodes/TimingStep.js +0 -44
- package/utils.js +0 -28
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/* eslint-disable reanimated/use-reanimated-error */
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
import { mockedRequestAnimationFrame } from '../animationFrameQueue/mockedRequestAnimationFrame';
|
|
5
|
+
import { isJest } from '../PlatformChecker';
|
|
6
|
+
import { WorkletsError } from '../WorkletsError';
|
|
7
|
+
import type { ShareableRef, WorkletRuntime } from '../workletTypes';
|
|
8
|
+
import type { IWorkletsModule } from './workletsModuleProxy';
|
|
9
|
+
|
|
10
|
+
export function createJSWorkletsModule(): IWorkletsModule {
|
|
11
|
+
return new JSWorklets();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// In Node.js environments (like when static rendering with Expo Router)
|
|
15
|
+
// requestAnimationFrame is unavailable, so we use our mock.
|
|
16
|
+
// It also has to be mocked for Jest purposes (see `initializeUIRuntime`).
|
|
17
|
+
const requestAnimationFrameImpl =
|
|
18
|
+
isJest() || !globalThis.requestAnimationFrame
|
|
19
|
+
? mockedRequestAnimationFrame
|
|
20
|
+
: globalThis.requestAnimationFrame;
|
|
21
|
+
|
|
22
|
+
class JSWorklets implements IWorkletsModule {
|
|
23
|
+
makeShareableClone<TValue>(): ShareableRef<TValue> {
|
|
24
|
+
throw new WorkletsError(
|
|
25
|
+
'makeShareableClone should never be called in JSWorklets.'
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
scheduleOnUI<TValue>(worklet: ShareableRef<TValue>) {
|
|
30
|
+
// TODO: `requestAnimationFrame` should be used exclusively in Reanimated
|
|
31
|
+
|
|
32
|
+
// @ts-ignore web implementation has still not been updated after the rewrite,
|
|
33
|
+
// this will be addressed once the web implementation updates are ready
|
|
34
|
+
requestAnimationFrameImpl(worklet);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
executeOnUIRuntimeSync<T, R>(_shareable: ShareableRef<T>): R {
|
|
38
|
+
throw new WorkletsError(
|
|
39
|
+
'`executeOnUIRuntimeSync` is not available in JSWorklets.'
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
createWorkletRuntime(
|
|
44
|
+
_name: string,
|
|
45
|
+
_initializer: ShareableRef<() => void>
|
|
46
|
+
): WorkletRuntime {
|
|
47
|
+
throw new WorkletsError(
|
|
48
|
+
'createWorkletRuntime is not available in JSWorklets.'
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
scheduleOnRuntime() {
|
|
53
|
+
throw new WorkletsError(
|
|
54
|
+
'scheduleOnRuntime is not available in JSWorklets.'
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/* eslint-disable reanimated/use-reanimated-error */
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
import { WorkletsTurboModule } from '../specs';
|
|
5
|
+
import { getValueUnpackerCode } from '../valueUnpacker';
|
|
6
|
+
import { WorkletsError } from '../WorkletsError';
|
|
7
|
+
import type { ShareableRef, WorkletRuntime } from '../workletTypes';
|
|
8
|
+
import type { WorkletsModuleProxy } from './workletsModuleProxy';
|
|
9
|
+
|
|
10
|
+
export interface IWorkletsModule extends WorkletsModuleProxy {}
|
|
11
|
+
|
|
12
|
+
export function createNativeWorkletsModule(): IWorkletsModule {
|
|
13
|
+
return new NativeWorklets();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class NativeWorklets {
|
|
17
|
+
#workletsModuleProxy: WorkletsModuleProxy;
|
|
18
|
+
|
|
19
|
+
constructor() {
|
|
20
|
+
if (global.__workletsModuleProxy === undefined) {
|
|
21
|
+
const valueUnpackerCode = getValueUnpackerCode();
|
|
22
|
+
WorkletsTurboModule?.installTurboModule(valueUnpackerCode);
|
|
23
|
+
}
|
|
24
|
+
if (global.__workletsModuleProxy === undefined) {
|
|
25
|
+
throw new WorkletsError(
|
|
26
|
+
`Native part of Worklets doesn't seem to be initialized.
|
|
27
|
+
See https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooting#native-part-of-reanimated-doesnt-seem-to-be-initialized for more details.`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
this.#workletsModuleProxy = global.__workletsModuleProxy;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
makeShareableClone<TValue>(
|
|
34
|
+
value: TValue,
|
|
35
|
+
shouldPersistRemote: boolean,
|
|
36
|
+
nativeStateSource?: object
|
|
37
|
+
) {
|
|
38
|
+
return this.#workletsModuleProxy.makeShareableClone(
|
|
39
|
+
value,
|
|
40
|
+
shouldPersistRemote,
|
|
41
|
+
nativeStateSource
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
scheduleOnUI<TValue>(shareable: ShareableRef<TValue>) {
|
|
46
|
+
return this.#workletsModuleProxy.scheduleOnUI(shareable);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
executeOnUIRuntimeSync<TValue, TReturn>(
|
|
50
|
+
shareable: ShareableRef<TValue>
|
|
51
|
+
): TReturn {
|
|
52
|
+
return this.#workletsModuleProxy.executeOnUIRuntimeSync(shareable);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
createWorkletRuntime(name: string, initializer: ShareableRef<() => void>) {
|
|
56
|
+
return this.#workletsModuleProxy.createWorkletRuntime(name, initializer);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
scheduleOnRuntime<T>(
|
|
60
|
+
workletRuntime: WorkletRuntime,
|
|
61
|
+
shareableWorklet: ShareableRef<T>
|
|
62
|
+
) {
|
|
63
|
+
return this.#workletsModuleProxy.scheduleOnRuntime(
|
|
64
|
+
workletRuntime,
|
|
65
|
+
shareableWorklet
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { shouldBeUseWeb } from '../PlatformChecker';
|
|
4
|
+
import { createJSWorkletsModule } from './JSWorklets';
|
|
5
|
+
import { createNativeWorkletsModule } from './NativeWorklets';
|
|
6
|
+
|
|
7
|
+
export const WorkletsModule = shouldBeUseWeb()
|
|
8
|
+
? createJSWorkletsModule()
|
|
9
|
+
: createNativeWorkletsModule();
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import type { ShareableRef, WorkletRuntime } from '../workletTypes';
|
|
4
|
+
|
|
5
|
+
/** Type of `__workletsModuleProxy` injected with JSI. */
|
|
6
|
+
export interface WorkletsModuleProxy {
|
|
7
|
+
makeShareableClone<TValue>(
|
|
8
|
+
value: TValue,
|
|
9
|
+
shouldPersistRemote: boolean,
|
|
10
|
+
nativeStateSource?: object
|
|
11
|
+
): ShareableRef<TValue>;
|
|
12
|
+
|
|
13
|
+
scheduleOnUI<TValue>(shareable: ShareableRef<TValue>): void;
|
|
14
|
+
|
|
15
|
+
executeOnUIRuntimeSync<TValue, TReturn>(
|
|
16
|
+
shareable: ShareableRef<TValue>
|
|
17
|
+
): TReturn;
|
|
18
|
+
|
|
19
|
+
createWorkletRuntime(
|
|
20
|
+
name: string,
|
|
21
|
+
initializer: ShareableRef<() => void>
|
|
22
|
+
): WorkletRuntime;
|
|
23
|
+
|
|
24
|
+
scheduleOnRuntime<TValue>(
|
|
25
|
+
workletRuntime: WorkletRuntime,
|
|
26
|
+
worklet: ShareableRef<TValue>
|
|
27
|
+
): void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface IWorkletsModule extends WorkletsModuleProxy {}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This is Jest implementation of `requestAnimationFrame` that is required by
|
|
5
|
+
* React Native for test purposes.
|
|
6
|
+
*/
|
|
7
|
+
export function mockedRequestAnimationFrame(
|
|
8
|
+
callback: (timestamp: number) => void
|
|
9
|
+
): ReturnType<typeof setTimeout> {
|
|
10
|
+
return setTimeout(() => callback(performance.now()), 0);
|
|
11
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { callMicrotasks } from '../threads';
|
|
4
|
+
|
|
5
|
+
export function setupRequestAnimationFrame() {
|
|
6
|
+
'worklet';
|
|
7
|
+
|
|
8
|
+
// Jest mocks requestAnimationFrame API and it does not like if that mock gets overridden
|
|
9
|
+
// so we avoid doing requestAnimationFrame batching in Jest environment.
|
|
10
|
+
const nativeRequestAnimationFrame = global.requestAnimationFrame;
|
|
11
|
+
|
|
12
|
+
let animationFrameCallbacks: Array<(timestamp: number) => void> = [];
|
|
13
|
+
let flushRequested = false;
|
|
14
|
+
|
|
15
|
+
global.__flushAnimationFrame = (frameTimestamp: number) => {
|
|
16
|
+
const currentCallbacks = animationFrameCallbacks;
|
|
17
|
+
animationFrameCallbacks = [];
|
|
18
|
+
currentCallbacks.forEach((f) => f(frameTimestamp));
|
|
19
|
+
callMicrotasks();
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
global.requestAnimationFrame = (
|
|
23
|
+
callback: (timestamp: number) => void
|
|
24
|
+
): number => {
|
|
25
|
+
animationFrameCallbacks.push(callback);
|
|
26
|
+
if (!flushRequested) {
|
|
27
|
+
flushRequested = true;
|
|
28
|
+
nativeRequestAnimationFrame((timestamp) => {
|
|
29
|
+
flushRequested = false;
|
|
30
|
+
global.__frameTimestamp = timestamp;
|
|
31
|
+
global.__flushAnimationFrame(timestamp);
|
|
32
|
+
global.__frameTimestamp = undefined;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
// Reanimated currently does not support cancelling callbacks requested with
|
|
36
|
+
// requestAnimationFrame. We return -1 as identifier which isn't in line
|
|
37
|
+
// with the spec but it should give users better clue in case they actually
|
|
38
|
+
// attempt to store the value returned from rAF and use it for cancelling.
|
|
39
|
+
return -1;
|
|
40
|
+
};
|
|
41
|
+
}
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import type { WorkletStackDetails } from './workletTypes';
|
|
4
|
+
|
|
5
|
+
export type CustomError<TName extends string> = Error & { name: TName }; // signed type
|
|
6
|
+
|
|
7
|
+
export interface CustomErrorConstructor<TName extends string> extends Error {
|
|
8
|
+
new (message?: string): CustomError<TName>;
|
|
9
|
+
(message?: string): CustomError<TName>;
|
|
10
|
+
readonly prototype: CustomError<TName>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function createCustomError<TName extends string>(
|
|
14
|
+
name: TName
|
|
15
|
+
): CustomErrorConstructor<TName> {
|
|
16
|
+
const constructor = function CustomError(message?: string) {
|
|
17
|
+
'worklet';
|
|
18
|
+
const prefix = `[${name}]`;
|
|
19
|
+
// eslint-disable-next-line reanimated/use-worklets-error
|
|
20
|
+
const errorInstance = new Error(message ? `${prefix} ${message}` : prefix);
|
|
21
|
+
errorInstance.name = `${name}Error`;
|
|
22
|
+
return errorInstance;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
Object.defineProperty(constructor, 'name', { value: `${name}Error` });
|
|
26
|
+
|
|
27
|
+
return constructor as CustomErrorConstructor<TName>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Registers custom errors in global scope. Use it only for Worklet runtimes. */
|
|
31
|
+
export function registerCustomError<TName extends string>(
|
|
32
|
+
constructor: CustomErrorConstructor<TName>,
|
|
33
|
+
name: TName
|
|
34
|
+
) {
|
|
35
|
+
'worklet';
|
|
36
|
+
if (!_WORKLET) {
|
|
37
|
+
// eslint-disable-next-line reanimated/use-worklets-error
|
|
38
|
+
throw new Error(
|
|
39
|
+
'[Worklets] registerCustomError() must be called on a Worklet runtime'
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
(global as Record<string, unknown>)[`${name}Error`] = constructor;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const _workletStackDetails = new Map<number, WorkletStackDetails>();
|
|
46
|
+
|
|
47
|
+
export function registerWorkletStackDetails(
|
|
48
|
+
hash: number,
|
|
49
|
+
stackDetails: WorkletStackDetails
|
|
50
|
+
) {
|
|
51
|
+
_workletStackDetails.set(hash, stackDetails);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getBundleOffset(error: Error): [string, number, number] {
|
|
55
|
+
const frame = error.stack?.split('\n')?.[0];
|
|
56
|
+
if (frame) {
|
|
57
|
+
const parsedFrame = /@([^@]+):(\d+):(\d+)/.exec(frame);
|
|
58
|
+
if (parsedFrame) {
|
|
59
|
+
const [, file, line, col] = parsedFrame;
|
|
60
|
+
return [file, Number(line), Number(col)];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return ['unknown', 0, 0];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function processStack(stack: string): string {
|
|
67
|
+
const workletStackEntries = stack.match(/worklet_(\d+):(\d+):(\d+)/g);
|
|
68
|
+
let result = stack;
|
|
69
|
+
workletStackEntries?.forEach((match) => {
|
|
70
|
+
const [, hash, origLine, origCol] = match.split(/:|_/).map(Number);
|
|
71
|
+
const errorDetails = _workletStackDetails.get(hash);
|
|
72
|
+
if (!errorDetails) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const [error, lineOffset, colOffset] = errorDetails;
|
|
76
|
+
const [bundleFile, bundleLine, bundleCol] = getBundleOffset(error);
|
|
77
|
+
const line = origLine + bundleLine + lineOffset;
|
|
78
|
+
const col = origCol + bundleCol + colOffset;
|
|
79
|
+
|
|
80
|
+
result = result.replace(match, `${bundleFile}:${line}:${col}`);
|
|
81
|
+
});
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function reportFatalErrorOnJS({
|
|
86
|
+
message,
|
|
87
|
+
stack,
|
|
88
|
+
moduleName,
|
|
89
|
+
}: {
|
|
90
|
+
message: string;
|
|
91
|
+
stack?: string;
|
|
92
|
+
moduleName: string;
|
|
93
|
+
}) {
|
|
94
|
+
// eslint-disable-next-line reanimated/use-worklets-error
|
|
95
|
+
const error = new Error();
|
|
96
|
+
error.message = message;
|
|
97
|
+
error.stack = stack ? processStack(stack) : undefined;
|
|
98
|
+
error.name = `${moduleName}Error`;
|
|
99
|
+
// @ts-ignore React Native's ErrorUtils implementation extends the Error type with jsEngine field
|
|
100
|
+
error.jsEngine = moduleName;
|
|
101
|
+
// @ts-ignore the reportFatalError method is an internal method of ErrorUtils not exposed in the type definitions
|
|
102
|
+
global.ErrorUtils.reportFatalError(error);
|
|
103
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { initializeUIRuntime } from './initializers';
|
|
4
|
+
import { WorkletsModule } from './WorkletsModule';
|
|
5
|
+
|
|
6
|
+
// TODO: Specify the initialization pipeline since now there's no
|
|
7
|
+
// universal source of truth for it.
|
|
8
|
+
initializeUIRuntime(WorkletsModule);
|
|
9
|
+
|
|
10
|
+
export type { CustomError } from './errors';
|
|
11
|
+
export { createCustomError, registerCustomError } from './errors';
|
|
12
|
+
export type { LoggerConfig } from './logger';
|
|
13
|
+
export {
|
|
14
|
+
logger,
|
|
15
|
+
LogLevel,
|
|
16
|
+
registerLoggerConfig,
|
|
17
|
+
updateLoggerConfig,
|
|
18
|
+
} from './logger';
|
|
19
|
+
export { createWorkletRuntime, runOnRuntime } from './runtimes';
|
|
20
|
+
export { shareableMappingCache } from './shareableMappingCache';
|
|
21
|
+
export {
|
|
22
|
+
makeShareable,
|
|
23
|
+
makeShareableCloneOnUIRecursive,
|
|
24
|
+
makeShareableCloneRecursive,
|
|
25
|
+
} from './shareables';
|
|
26
|
+
export {
|
|
27
|
+
callMicrotasks,
|
|
28
|
+
executeOnUIRuntimeSync,
|
|
29
|
+
runOnJS,
|
|
30
|
+
runOnUI,
|
|
31
|
+
runOnUIImmediately,
|
|
32
|
+
} from './threads';
|
|
33
|
+
export { isWorkletFunction } from './workletFunction';
|
|
34
|
+
export type { IWorkletsModule, WorkletsModuleProxy } from './WorkletsModule';
|
|
35
|
+
export { WorkletsModule } from './WorkletsModule';
|
|
36
|
+
export type {
|
|
37
|
+
ShareableRef,
|
|
38
|
+
WorkletFunction,
|
|
39
|
+
WorkletFunctionDev,
|
|
40
|
+
WorkletRuntime,
|
|
41
|
+
WorkletStackDetails,
|
|
42
|
+
} from './workletTypes';
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { mockedRequestAnimationFrame } from './animationFrameQueue/mockedRequestAnimationFrame';
|
|
4
|
+
import { setupRequestAnimationFrame } from './animationFrameQueue/requestAnimationFrame';
|
|
5
|
+
import { reportFatalErrorOnJS } from './errors';
|
|
6
|
+
import {
|
|
7
|
+
DEFAULT_LOGGER_CONFIG,
|
|
8
|
+
logToLogBoxAndConsole,
|
|
9
|
+
registerLoggerConfig,
|
|
10
|
+
replaceLoggerImplementation,
|
|
11
|
+
} from './logger';
|
|
12
|
+
import {
|
|
13
|
+
isChromeDebugger,
|
|
14
|
+
isJest,
|
|
15
|
+
isWeb,
|
|
16
|
+
shouldBeUseWeb,
|
|
17
|
+
} from './PlatformChecker';
|
|
18
|
+
import { executeOnUIRuntimeSync, runOnJS, setupMicrotasks } from './threads';
|
|
19
|
+
import { registerWorkletsError, WorkletsError } from './WorkletsError';
|
|
20
|
+
import type { IWorkletsModule } from './WorkletsModule';
|
|
21
|
+
|
|
22
|
+
const IS_JEST = isJest();
|
|
23
|
+
const SHOULD_BE_USE_WEB = shouldBeUseWeb();
|
|
24
|
+
const IS_CHROME_DEBUGGER = isChromeDebugger();
|
|
25
|
+
|
|
26
|
+
// Override the logFunction implementation with the one that adds logs
|
|
27
|
+
// with better stack traces to the LogBox (need to override it after `runOnJS`
|
|
28
|
+
// is defined).
|
|
29
|
+
function overrideLogFunctionImplementation() {
|
|
30
|
+
'worklet';
|
|
31
|
+
replaceLoggerImplementation((data) => {
|
|
32
|
+
'worklet';
|
|
33
|
+
runOnJS(logToLogBoxAndConsole)(data);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Register logger config and replace the log function implementation in
|
|
38
|
+
// the React runtime global scope
|
|
39
|
+
registerLoggerConfig(DEFAULT_LOGGER_CONFIG);
|
|
40
|
+
overrideLogFunctionImplementation();
|
|
41
|
+
|
|
42
|
+
// this is for web implementation
|
|
43
|
+
if (SHOULD_BE_USE_WEB) {
|
|
44
|
+
global._WORKLET = false;
|
|
45
|
+
global._log = console.log;
|
|
46
|
+
global._getAnimationTimestamp = () => performance.now();
|
|
47
|
+
} else {
|
|
48
|
+
// Register WorkletsError and logger config in the UI runtime global scope.
|
|
49
|
+
// (we are using `executeOnUIRuntimeSync` here to make sure that the changes
|
|
50
|
+
// are applied before any async operations are executed on the UI runtime)
|
|
51
|
+
executeOnUIRuntimeSync(registerWorkletsError)();
|
|
52
|
+
executeOnUIRuntimeSync(registerLoggerConfig)(DEFAULT_LOGGER_CONFIG);
|
|
53
|
+
executeOnUIRuntimeSync(overrideLogFunctionImplementation)();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// callGuard is only used with debug builds
|
|
57
|
+
export function callGuardDEV<Args extends unknown[], ReturnValue>(
|
|
58
|
+
fn: (...args: Args) => ReturnValue,
|
|
59
|
+
...args: Args
|
|
60
|
+
): ReturnValue | void {
|
|
61
|
+
'worklet';
|
|
62
|
+
try {
|
|
63
|
+
return fn(...args);
|
|
64
|
+
} catch (e) {
|
|
65
|
+
if (global.__ErrorUtils) {
|
|
66
|
+
global.__ErrorUtils.reportFatalError(e as Error);
|
|
67
|
+
} else {
|
|
68
|
+
throw e;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function setupCallGuard() {
|
|
74
|
+
'worklet';
|
|
75
|
+
global.__callGuardDEV = callGuardDEV;
|
|
76
|
+
global.__ErrorUtils = {
|
|
77
|
+
reportFatalError: (error: Error) => {
|
|
78
|
+
runOnJS(reportFatalErrorOnJS)({
|
|
79
|
+
message: error.message,
|
|
80
|
+
moduleName: 'Worklets',
|
|
81
|
+
stack: error.stack,
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Currently there seems to be a bug in the JSI layer which causes a crash when
|
|
89
|
+
* we try to copy some of the console methods, i.e. `clear` or `dirxml`.
|
|
90
|
+
*
|
|
91
|
+
* The crash happens only in React Native 0.75. It's not reproducible in neither
|
|
92
|
+
* 0.76 nor 0.74. It also happens only in the configuration of a debug app and
|
|
93
|
+
* production bundle.
|
|
94
|
+
*
|
|
95
|
+
* I haven't yet discovered what exactly causes the crash. It's tied to the
|
|
96
|
+
* console methods sometimes being `HostFunction`s. Therefore, as a workaround
|
|
97
|
+
* we don't copy the methods as they are in the original console object, we copy
|
|
98
|
+
* JavaScript wrappers instead.
|
|
99
|
+
*/
|
|
100
|
+
function createMemorySafeCapturableConsole(): typeof console {
|
|
101
|
+
const consoleCopy = Object.fromEntries(
|
|
102
|
+
Object.entries(console).map(([methodName, method]) => {
|
|
103
|
+
const methodWrapper = function methodWrapper(...args: unknown[]) {
|
|
104
|
+
return method(...args);
|
|
105
|
+
};
|
|
106
|
+
if (method.name) {
|
|
107
|
+
/**
|
|
108
|
+
* Set the original method name as the wrapper name if available.
|
|
109
|
+
*
|
|
110
|
+
* It might be unnecessary but if we want to fully mimic the console
|
|
111
|
+
* object we should take into the account the fact some code might rely
|
|
112
|
+
* on the method name.
|
|
113
|
+
*/
|
|
114
|
+
Object.defineProperty(methodWrapper, 'name', {
|
|
115
|
+
value: method.name,
|
|
116
|
+
writable: false,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return [methodName, methodWrapper];
|
|
120
|
+
})
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
return consoleCopy as unknown as typeof console;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// We really have to create a copy of console here. Function runOnJS we use on elements inside
|
|
127
|
+
// this object makes it not configurable
|
|
128
|
+
const capturableConsole = createMemorySafeCapturableConsole();
|
|
129
|
+
|
|
130
|
+
export function setupConsole() {
|
|
131
|
+
'worklet';
|
|
132
|
+
if (!IS_CHROME_DEBUGGER) {
|
|
133
|
+
// @ts-ignore TypeScript doesn't like that there are missing methods in console object, but we don't provide all the methods for the UI runtime console version
|
|
134
|
+
global.console = {
|
|
135
|
+
/* eslint-disable @typescript-eslint/unbound-method */
|
|
136
|
+
assert: runOnJS(capturableConsole.assert),
|
|
137
|
+
debug: runOnJS(capturableConsole.debug),
|
|
138
|
+
log: runOnJS(capturableConsole.log),
|
|
139
|
+
warn: runOnJS(capturableConsole.warn),
|
|
140
|
+
error: runOnJS(capturableConsole.error),
|
|
141
|
+
info: runOnJS(capturableConsole.info),
|
|
142
|
+
/* eslint-enable @typescript-eslint/unbound-method */
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function initializeUIRuntime(WorkletsModule: IWorkletsModule) {
|
|
148
|
+
if (isWeb()) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (!WorkletsModule) {
|
|
152
|
+
throw new WorkletsError(
|
|
153
|
+
'Worklets are trying to initialize the UI runtime without a valid WorkletsModule'
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
if (IS_JEST) {
|
|
157
|
+
// requestAnimationFrame react-native jest's setup is incorrect as it polyfills
|
|
158
|
+
// the method directly using setTimeout, therefore the callback doesn't get the
|
|
159
|
+
// expected timestamp as the only argument: https://github.com/facebook/react-native/blob/main/packages/react-native/jest/setup.js#L28
|
|
160
|
+
// We override this setup here to make sure that callbacks get the proper timestamps
|
|
161
|
+
// when executed. For non-jest environments we define requestAnimationFrame in setupRequestAnimationFrame
|
|
162
|
+
// @ts-ignore TypeScript uses Node definition for rAF, setTimeout, etc which returns a Timeout object rather than a number
|
|
163
|
+
globalThis.requestAnimationFrame = mockedRequestAnimationFrame;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (!SHOULD_BE_USE_WEB) {
|
|
167
|
+
executeOnUIRuntimeSync(() => {
|
|
168
|
+
'worklet';
|
|
169
|
+
setupCallGuard();
|
|
170
|
+
setupConsole();
|
|
171
|
+
setupMicrotasks();
|
|
172
|
+
setupRequestAnimationFrame();
|
|
173
|
+
})();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* Copied from: react-native/Libraries/LogBox/Data/LogBoxData.js
|
|
4
|
+
* react-native/Libraries/LogBox/Data/parseLogBoxLog.js
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { LogBoxStatic } from 'react-native';
|
|
8
|
+
import { LogBox as RNLogBox } from 'react-native';
|
|
9
|
+
|
|
10
|
+
export type LogBoxLogLevel = 'warn' | 'error' | 'fatal' | 'syntax';
|
|
11
|
+
|
|
12
|
+
type Message = {
|
|
13
|
+
content: string;
|
|
14
|
+
substitutions: { length: number; offset: number }[];
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type Category = string;
|
|
18
|
+
|
|
19
|
+
interface Location {
|
|
20
|
+
row: number;
|
|
21
|
+
column: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface CodeFrame {
|
|
25
|
+
content: string;
|
|
26
|
+
location?: Location | null;
|
|
27
|
+
fileName: string;
|
|
28
|
+
collapse?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
type ComponentStack = CodeFrame[];
|
|
32
|
+
|
|
33
|
+
type ComponentStackType = 'legacy' | 'stack';
|
|
34
|
+
|
|
35
|
+
export type LogData = {
|
|
36
|
+
level: LogBoxLogLevel;
|
|
37
|
+
message: Message;
|
|
38
|
+
category: Category;
|
|
39
|
+
componentStack: ComponentStack;
|
|
40
|
+
componentStackType: ComponentStackType | null;
|
|
41
|
+
stack?: string;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
interface LogBoxExtended extends LogBoxStatic {
|
|
45
|
+
addLog(data: LogData): void;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const LogBox = RNLogBox as LogBoxExtended;
|
|
49
|
+
|
|
50
|
+
const noop = () => {
|
|
51
|
+
// do nothing
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Do nothing when addLogBoxLog is called if LogBox is not available
|
|
55
|
+
export const addLogBoxLog = LogBox?.addLog?.bind(LogBox) ?? noop;
|