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.
Files changed (246) hide show
  1. package/Common/cpp/worklets/AnimationFrameQueue/AnimationFrameBatchinator.cpp +71 -0
  2. package/Common/cpp/worklets/AnimationFrameQueue/AnimationFrameBatchinator.h +38 -0
  3. package/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp +131 -0
  4. package/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h +82 -0
  5. package/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp +72 -0
  6. package/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h +44 -0
  7. package/Common/cpp/worklets/Registries/EventHandlerRegistry.cpp +94 -0
  8. package/Common/cpp/worklets/Registries/EventHandlerRegistry.h +49 -0
  9. package/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.cpp +8 -0
  10. package/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.h +39 -0
  11. package/Common/cpp/worklets/SharedItems/Shareables.cpp +326 -0
  12. package/Common/cpp/worklets/SharedItems/Shareables.h +345 -0
  13. package/Common/cpp/worklets/Tools/AsyncQueue.cpp +52 -0
  14. package/Common/cpp/worklets/Tools/AsyncQueue.h +35 -0
  15. package/Common/cpp/worklets/Tools/Defs.h +10 -0
  16. package/Common/cpp/worklets/Tools/JSISerializer.cpp +342 -0
  17. package/Common/cpp/worklets/Tools/JSISerializer.h +47 -0
  18. package/Common/cpp/worklets/Tools/JSLogger.cpp +16 -0
  19. package/Common/cpp/worklets/Tools/JSLogger.h +20 -0
  20. package/Common/cpp/worklets/Tools/JSScheduler.cpp +10 -0
  21. package/Common/cpp/worklets/Tools/JSScheduler.h +29 -0
  22. package/Common/cpp/worklets/Tools/PlatformLogger.h +16 -0
  23. package/Common/cpp/worklets/Tools/SingleInstanceChecker.h +72 -0
  24. package/Common/cpp/worklets/Tools/ThreadSafeQueue.h +49 -0
  25. package/Common/cpp/worklets/Tools/UIScheduler.cpp +19 -0
  26. package/Common/cpp/worklets/Tools/UIScheduler.h +22 -0
  27. package/Common/cpp/worklets/Tools/WorkletEventHandler.cpp +29 -0
  28. package/Common/cpp/worklets/Tools/WorkletEventHandler.h +41 -0
  29. package/Common/cpp/worklets/Tools/WorkletsJSIUtils.cpp +26 -0
  30. package/Common/cpp/worklets/Tools/WorkletsJSIUtils.h +199 -0
  31. package/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.cpp +20 -0
  32. package/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h +19 -0
  33. package/Common/cpp/worklets/WorkletRuntime/RuntimeInitialization.md +191 -0
  34. package/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.cpp +19 -0
  35. package/Common/cpp/worklets/WorkletRuntime/UIRuntimeDecorator.h +16 -0
  36. package/Common/cpp/worklets/WorkletRuntime/WorkletHermesRuntime.cpp +108 -0
  37. package/Common/cpp/worklets/WorkletRuntime/WorkletHermesRuntime.h +127 -0
  38. package/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.cpp +183 -0
  39. package/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.h +90 -0
  40. package/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeCollector.h +36 -0
  41. package/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp +179 -0
  42. package/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.h +22 -0
  43. package/LICENSE +20 -0
  44. package/README.md +27 -0
  45. package/RNWorklets.podspec +70 -0
  46. package/android/CMakeLists.txt +56 -0
  47. package/android/build.gradle +313 -0
  48. package/android/gradle.properties +5 -0
  49. package/android/proguard-rules.pro +3 -0
  50. package/android/spotless.gradle +9 -0
  51. package/android/src/main/AndroidManifest.xml +2 -0
  52. package/android/src/main/cpp/worklets/CMakeLists.txt +85 -0
  53. package/android/src/main/cpp/worklets/android/AndroidUIScheduler.cpp +63 -0
  54. package/android/src/main/cpp/worklets/android/AndroidUIScheduler.h +41 -0
  55. package/android/src/main/cpp/worklets/android/AnimationFrameCallback.h +32 -0
  56. package/android/src/main/cpp/worklets/android/PlatformLogger.cpp +29 -0
  57. package/android/src/main/cpp/worklets/android/WorkletsModule.cpp +83 -0
  58. package/android/src/main/cpp/worklets/android/WorkletsModule.h +63 -0
  59. package/android/src/main/cpp/worklets/android/WorkletsOnLoad.cpp +13 -0
  60. package/android/src/main/java/com/swmansion/worklets/AndroidUIScheduler.java +60 -0
  61. package/android/src/main/java/com/swmansion/worklets/AnimationFrameQueue/AnimationFrameCallback.java +20 -0
  62. package/android/src/main/java/com/swmansion/worklets/AnimationFrameQueue/AnimationFrameQueue.java +113 -0
  63. package/android/src/main/java/com/swmansion/worklets/JSCallInvokerResolver.java +27 -0
  64. package/android/src/main/java/com/swmansion/worklets/WorkletsMessageQueueThread.java +16 -0
  65. package/android/src/main/java/com/swmansion/worklets/WorkletsMessageQueueThreadBase.java +72 -0
  66. package/android/src/main/java/com/swmansion/worklets/WorkletsModule.java +106 -0
  67. package/android/src/main/java/com/swmansion/worklets/WorkletsPackage.java +49 -0
  68. package/android/src/paper/com/swmansion/worklets/NativeWorkletsModuleSpec.java +26 -0
  69. package/apple/worklets/apple/AnimationFrameQueue.h +15 -0
  70. package/apple/worklets/apple/AnimationFrameQueue.mm +81 -0
  71. package/apple/worklets/apple/AssertJavaScriptQueue.h +14 -0
  72. package/apple/worklets/apple/AssertTurboModuleManagerQueue.h +16 -0
  73. package/apple/worklets/apple/IOSUIScheduler.h +14 -0
  74. package/apple/worklets/apple/IOSUIScheduler.mm +24 -0
  75. package/apple/worklets/apple/PlatformLogger.mm +31 -0
  76. package/apple/worklets/apple/SlowAnimations.h +8 -0
  77. package/apple/worklets/apple/SlowAnimations.mm +47 -0
  78. package/apple/worklets/apple/WorkletsDisplayLink.h +21 -0
  79. package/apple/worklets/apple/WorkletsMessageThread.h +16 -0
  80. package/apple/worklets/apple/WorkletsMessageThread.mm +32 -0
  81. package/apple/worklets/apple/WorkletsModule.h +10 -0
  82. package/apple/worklets/apple/WorkletsModule.mm +85 -0
  83. package/lib/module/PlatformChecker.js +35 -0
  84. package/lib/module/PlatformChecker.js.map +1 -0
  85. package/lib/module/WorkletsError.js +13 -0
  86. package/lib/module/WorkletsError.js.map +1 -0
  87. package/lib/module/WorkletsModule/JSWorklets.js +36 -0
  88. package/lib/module/WorkletsModule/JSWorklets.js.map +1 -0
  89. package/lib/module/WorkletsModule/NativeWorklets.js +39 -0
  90. package/lib/module/WorkletsModule/NativeWorklets.js.map +1 -0
  91. package/lib/module/WorkletsModule/index.js +4 -0
  92. package/lib/module/WorkletsModule/index.js.map +1 -0
  93. package/lib/module/WorkletsModule/workletsModuleInstance.js +7 -0
  94. package/lib/module/WorkletsModule/workletsModuleInstance.js.map +1 -0
  95. package/lib/module/WorkletsModule/workletsModuleInstance.web.js +5 -0
  96. package/lib/module/WorkletsModule/workletsModuleInstance.web.js.map +1 -0
  97. package/lib/module/WorkletsModule/workletsModuleProxy.js +4 -0
  98. package/lib/module/WorkletsModule/workletsModuleProxy.js.map +1 -0
  99. package/lib/module/animationFrameQueue/mockedRequestAnimationFrame.js +10 -0
  100. package/lib/module/animationFrameQueue/mockedRequestAnimationFrame.js.map +1 -0
  101. package/lib/module/animationFrameQueue/requestAnimationFrame.js +36 -0
  102. package/lib/module/animationFrameQueue/requestAnimationFrame.js.map +1 -0
  103. package/lib/module/errors.js +78 -0
  104. package/lib/module/errors.js.map +1 -0
  105. package/lib/module/index.js +17 -0
  106. package/lib/module/index.js.map +1 -0
  107. package/lib/module/initializers.js +158 -0
  108. package/lib/module/initializers.js.map +1 -0
  109. package/lib/module/logger/LogBox.js +15 -0
  110. package/lib/module/logger/LogBox.js.map +1 -0
  111. package/lib/module/logger/index.js +5 -0
  112. package/lib/module/logger/index.js.map +1 -0
  113. package/lib/module/logger/logger.js +137 -0
  114. package/lib/module/logger/logger.js.map +1 -0
  115. package/lib/module/privateGlobals.d.js +8 -0
  116. package/lib/module/privateGlobals.d.js.map +1 -0
  117. package/lib/module/runtimes.js +63 -0
  118. package/lib/module/runtimes.js.map +1 -0
  119. package/lib/module/shareableMappingCache.js +39 -0
  120. package/lib/module/shareableMappingCache.js.map +1 -0
  121. package/lib/module/shareables.js +417 -0
  122. package/lib/module/shareables.js.map +1 -0
  123. package/lib/module/specs/NativeWorkletsModule.js +5 -0
  124. package/lib/module/specs/NativeWorkletsModule.js.map +1 -0
  125. package/lib/module/specs/index.js +5 -0
  126. package/lib/module/specs/index.js.map +1 -0
  127. package/lib/module/threads.js +204 -0
  128. package/lib/module/threads.js.map +1 -0
  129. package/lib/module/valueUnpacker.js +83 -0
  130. package/lib/module/valueUnpacker.js.map +1 -0
  131. package/lib/module/workletFunction.js +37 -0
  132. package/lib/module/workletFunction.js.map +1 -0
  133. package/lib/module/workletTypes.js +12 -0
  134. package/lib/module/workletTypes.js.map +1 -0
  135. package/lib/typescript/PlatformChecker.d.ts +7 -0
  136. package/lib/typescript/PlatformChecker.d.ts.map +1 -0
  137. package/lib/typescript/WorkletsError.d.ts +3 -0
  138. package/lib/typescript/WorkletsError.d.ts.map +1 -0
  139. package/lib/typescript/WorkletsModule/JSWorklets.d.ts +3 -0
  140. package/lib/typescript/WorkletsModule/JSWorklets.d.ts.map +1 -0
  141. package/lib/typescript/WorkletsModule/NativeWorklets.d.ts +5 -0
  142. package/lib/typescript/WorkletsModule/NativeWorklets.d.ts.map +1 -0
  143. package/lib/typescript/WorkletsModule/index.d.ts +3 -0
  144. package/lib/typescript/WorkletsModule/index.d.ts.map +1 -0
  145. package/lib/typescript/WorkletsModule/workletsModuleInstance.d.ts +2 -0
  146. package/lib/typescript/WorkletsModule/workletsModuleInstance.d.ts.map +1 -0
  147. package/lib/typescript/WorkletsModule/workletsModuleInstance.web.d.ts +2 -0
  148. package/lib/typescript/WorkletsModule/workletsModuleInstance.web.d.ts.map +1 -0
  149. package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts +12 -0
  150. package/lib/typescript/WorkletsModule/workletsModuleProxy.d.ts.map +1 -0
  151. package/lib/typescript/animationFrameQueue/mockedRequestAnimationFrame.d.ts +6 -0
  152. package/lib/typescript/animationFrameQueue/mockedRequestAnimationFrame.d.ts.map +1 -0
  153. package/lib/typescript/animationFrameQueue/requestAnimationFrame.d.ts +2 -0
  154. package/lib/typescript/animationFrameQueue/requestAnimationFrame.d.ts.map +1 -0
  155. package/lib/typescript/errors.d.ts +19 -0
  156. package/lib/typescript/errors.d.ts.map +1 -0
  157. package/lib/typescript/index.d.ts +13 -0
  158. package/lib/typescript/index.d.ts.map +1 -0
  159. package/lib/typescript/initializers.d.ts +6 -0
  160. package/lib/typescript/initializers.d.ts.map +1 -0
  161. package/lib/typescript/logger/LogBox.d.ts +32 -0
  162. package/lib/typescript/logger/LogBox.d.ts.map +1 -0
  163. package/lib/typescript/logger/index.d.ts +3 -0
  164. package/lib/typescript/logger/index.d.ts.map +1 -0
  165. package/lib/typescript/logger/logger.d.ts +52 -0
  166. package/lib/typescript/logger/logger.d.ts.map +1 -0
  167. package/lib/typescript/runtimes.d.ts +16 -0
  168. package/lib/typescript/runtimes.d.ts.map +1 -0
  169. package/lib/typescript/shareableMappingCache.d.ts +16 -0
  170. package/lib/typescript/shareableMappingCache.d.ts.map +1 -0
  171. package/lib/typescript/shareables.d.ts +15 -0
  172. package/lib/typescript/shareables.d.ts.map +1 -0
  173. package/lib/typescript/specs/NativeWorkletsModule.d.ts +7 -0
  174. package/lib/typescript/specs/NativeWorkletsModule.d.ts.map +1 -0
  175. package/lib/typescript/specs/index.d.ts +3 -0
  176. package/lib/typescript/specs/index.d.ts.map +1 -0
  177. package/lib/typescript/threads.d.ts +49 -0
  178. package/lib/typescript/threads.d.ts.map +1 -0
  179. package/lib/typescript/valueUnpacker.d.ts +2 -0
  180. package/lib/typescript/valueUnpacker.d.ts.map +1 -0
  181. package/lib/typescript/workletFunction.d.ts +27 -0
  182. package/lib/typescript/workletFunction.d.ts.map +1 -0
  183. package/lib/typescript/workletTypes.d.ts +49 -0
  184. package/lib/typescript/workletTypes.d.ts.map +1 -0
  185. package/package.json +106 -8
  186. package/plugin/index.js +3 -0
  187. package/scripts/worklets_utils.rb +53 -0
  188. package/src/PlatformChecker.ts +43 -0
  189. package/src/WorkletsError.ts +13 -0
  190. package/src/WorkletsModule/JSWorklets.ts +57 -0
  191. package/src/WorkletsModule/NativeWorklets.ts +68 -0
  192. package/src/WorkletsModule/index.ts +7 -0
  193. package/src/WorkletsModule/workletsModuleInstance.ts +9 -0
  194. package/src/WorkletsModule/workletsModuleInstance.web.ts +5 -0
  195. package/src/WorkletsModule/workletsModuleProxy.ts +30 -0
  196. package/src/animationFrameQueue/mockedRequestAnimationFrame.ts +11 -0
  197. package/src/animationFrameQueue/requestAnimationFrame.ts +41 -0
  198. package/src/errors.ts +103 -0
  199. package/src/index.ts +42 -0
  200. package/src/initializers.ts +175 -0
  201. package/src/logger/LogBox.ts +55 -0
  202. package/src/logger/index.ts +3 -0
  203. package/src/logger/logger.ts +155 -0
  204. package/src/privateGlobals.d.ts +41 -0
  205. package/src/runtimes.ts +92 -0
  206. package/src/shareableMappingCache.ts +44 -0
  207. package/src/shareables.ts +577 -0
  208. package/src/specs/NativeWorkletsModule.ts +9 -0
  209. package/src/specs/index.ts +5 -0
  210. package/src/threads.ts +275 -0
  211. package/src/valueUnpacker.ts +110 -0
  212. package/src/workletFunction.ts +47 -0
  213. package/src/workletTypes.ts +76 -0
  214. package/Animated.js +0 -13
  215. package/AnimatedEvent.js +0 -167
  216. package/AnimatedImplementation.js +0 -666
  217. package/CoreAnimated.js +0 -43
  218. package/Easing.js +0 -236
  219. package/NativeAnimatedHelper.js +0 -226
  220. package/SpringConfig.js +0 -79
  221. package/animations/Animation.js +0 -36
  222. package/animations/DecayAnimation.js +0 -70
  223. package/animations/SpringAnimation.js +0 -125
  224. package/animations/TimingAnimation.js +0 -70
  225. package/bezier.js +0 -128
  226. package/createAnimatedComponent.js +0 -188
  227. package/nodes/AnimatedBlock.js +0 -19
  228. package/nodes/AnimatedClock.js +0 -76
  229. package/nodes/AnimatedCond.js +0 -23
  230. package/nodes/AnimatedDetach.js +0 -15
  231. package/nodes/AnimatedInterpolation.js +0 -338
  232. package/nodes/AnimatedNode.js +0 -97
  233. package/nodes/AnimatedOnChange.js +0 -28
  234. package/nodes/AnimatedOp.js +0 -17
  235. package/nodes/AnimatedProps.js +0 -154
  236. package/nodes/AnimatedSet.js +0 -19
  237. package/nodes/AnimatedStartClock.js +0 -21
  238. package/nodes/AnimatedStopClock.js +0 -21
  239. package/nodes/AnimatedStyle.js +0 -89
  240. package/nodes/AnimatedTracking.js +0 -36
  241. package/nodes/AnimatedTransform.js +0 -93
  242. package/nodes/AnimatedValue.js +0 -271
  243. package/nodes/AnimatedWithInput.js +0 -21
  244. package/nodes/SpringNode.js +0 -106
  245. package/nodes/TimingStep.js +0 -44
  246. 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,7 @@
1
+ 'use strict';
2
+
3
+ export { WorkletsModule } from './workletsModuleInstance';
4
+ export type {
5
+ IWorkletsModule,
6
+ WorkletsModuleProxy,
7
+ } from './workletsModuleProxy';
@@ -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,5 @@
1
+ 'use strict';
2
+
3
+ import { createJSWorkletsModule } from './JSWorklets';
4
+
5
+ export const WorkletsModule = createJSWorkletsModule();
@@ -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;
@@ -0,0 +1,3 @@
1
+ 'use strict';
2
+ export * from './LogBox';
3
+ export * from './logger';