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
package/src/threads.ts ADDED
@@ -0,0 +1,275 @@
1
+ 'use strict';
2
+ import { isJest, shouldBeUseWeb } from './PlatformChecker';
3
+ import {
4
+ makeShareableCloneOnUIRecursive,
5
+ makeShareableCloneRecursive,
6
+ } from './shareables';
7
+ import { isWorkletFunction } from './workletFunction';
8
+ import { WorkletsError } from './WorkletsError';
9
+ import { WorkletsModule } from './WorkletsModule';
10
+ import type { WorkletFunction } from './workletTypes';
11
+
12
+ const IS_JEST = isJest();
13
+ const SHOULD_BE_USE_WEB = shouldBeUseWeb();
14
+
15
+ /** An array of [worklet, args] pairs. */
16
+ let _runOnUIQueue: Array<[WorkletFunction<unknown[], unknown>, unknown[]]> = [];
17
+
18
+ export function setupMicrotasks() {
19
+ 'worklet';
20
+
21
+ let microtasksQueue: Array<() => void> = [];
22
+ let isExecutingMicrotasksQueue = false;
23
+ global.queueMicrotask = (callback: () => void) => {
24
+ microtasksQueue.push(callback);
25
+ };
26
+ global._microtaskQueueFinalizers = [];
27
+
28
+ global.__callMicrotasks = () => {
29
+ if (isExecutingMicrotasksQueue) {
30
+ return;
31
+ }
32
+ try {
33
+ isExecutingMicrotasksQueue = true;
34
+ for (let index = 0; index < microtasksQueue.length; index += 1) {
35
+ // we use classic 'for' loop because the size of the currentTasks array may change while executing some of the callbacks due to queueMicrotask calls
36
+ microtasksQueue[index]();
37
+ }
38
+ microtasksQueue = [];
39
+ global._microtaskQueueFinalizers.forEach((finalizer) => finalizer());
40
+ } finally {
41
+ isExecutingMicrotasksQueue = false;
42
+ }
43
+ };
44
+ }
45
+
46
+ function callMicrotasksOnUIThread() {
47
+ 'worklet';
48
+ global.__callMicrotasks();
49
+ }
50
+
51
+ export const callMicrotasks = SHOULD_BE_USE_WEB
52
+ ? () => {
53
+ // on web flushing is a noop as immediates are handled by the browser
54
+ }
55
+ : callMicrotasksOnUIThread;
56
+
57
+ /**
58
+ * Lets you asynchronously run
59
+ * [workletized](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/glossary#to-workletize)
60
+ * functions on the [UI
61
+ * thread](https://docs.swmansion.com/react-native-reanimated/docs/threading/runOnUI).
62
+ *
63
+ * This method does not schedule the work immediately but instead waits for
64
+ * other worklets to be scheduled within the same JS loop. It uses
65
+ * queueMicrotask to schedule all the worklets at once making sure they will run
66
+ * within the same frame boundaries on the UI thread.
67
+ *
68
+ * @param fun - A reference to a function you want to execute on the [UI
69
+ * thread](https://docs.swmansion.com/react-native-reanimated/docs/threading/runOnUI)
70
+ * from the [JavaScript
71
+ * thread](https://docs.swmansion.com/react-native-reanimated/docs/threading/runOnUI).
72
+ * @returns A function that accepts arguments for the function passed as the
73
+ * first argument.
74
+ * @see https://docs.swmansion.com/react-native-reanimated/docs/threading/runOnUI
75
+ */
76
+ // @ts-expect-error This overload is correct since it's what user sees in his code
77
+ // before it's transformed by Reanimated Babel plugin.
78
+ export function runOnUI<Args extends unknown[], ReturnValue>(
79
+ worklet: (...args: Args) => ReturnValue
80
+ ): (...args: Args) => void;
81
+
82
+ export function runOnUI<Args extends unknown[], ReturnValue>(
83
+ worklet: WorkletFunction<Args, ReturnValue>
84
+ ): (...args: Args) => void {
85
+ 'worklet';
86
+ if (__DEV__ && !SHOULD_BE_USE_WEB && _WORKLET) {
87
+ throw new WorkletsError(
88
+ '`runOnUI` cannot be called on the UI runtime. Please call the function synchronously or use `queueMicrotask` or `requestAnimationFrame` instead.'
89
+ );
90
+ }
91
+ if (__DEV__ && !SHOULD_BE_USE_WEB && !isWorkletFunction(worklet)) {
92
+ throw new WorkletsError('`runOnUI` can only be used with worklets.');
93
+ }
94
+ return (...args) => {
95
+ if (IS_JEST) {
96
+ // Mocking time in Jest is tricky as both requestAnimationFrame and queueMicrotask
97
+ // callbacks run on the same queue and can be interleaved. There is no way
98
+ // to flush particular queue in Jest and the only control over mocked timers
99
+ // is by using jest.advanceTimersByTime() method which advances all types
100
+ // of timers including immediate and animation callbacks. Ideally we'd like
101
+ // to have some way here to schedule work along with React updates, but
102
+ // that's not possible, and hence in Jest environment instead of using scheduling
103
+ // mechanism we just schedule the work ommiting the queue. This is ok for the
104
+ // uses that we currently have but may not be ok for future tests that we write.
105
+ WorkletsModule.scheduleOnUI(
106
+ makeShareableCloneRecursive(() => {
107
+ 'worklet';
108
+ worklet(...args);
109
+ })
110
+ );
111
+ return;
112
+ }
113
+ if (__DEV__) {
114
+ // in DEV mode we call shareable conversion here because in case the object
115
+ // can't be converted, we will get a meaningful stack-trace as opposed to the
116
+ // situation when conversion is only done via microtask queue. This does not
117
+ // make the app particularily less efficient as converted objects are cached
118
+ // and for a given worklet the conversion only happens once.
119
+ makeShareableCloneRecursive(worklet);
120
+ makeShareableCloneRecursive(args);
121
+ }
122
+ _runOnUIQueue.push([worklet as WorkletFunction, args]);
123
+ if (_runOnUIQueue.length === 1) {
124
+ queueMicrotask(() => {
125
+ const queue = _runOnUIQueue;
126
+ _runOnUIQueue = [];
127
+ WorkletsModule.scheduleOnUI(
128
+ makeShareableCloneRecursive(() => {
129
+ 'worklet';
130
+ // eslint-disable-next-line @typescript-eslint/no-shadow
131
+ queue.forEach(([worklet, args]) => {
132
+ worklet(...args);
133
+ });
134
+ callMicrotasks();
135
+ })
136
+ );
137
+ });
138
+ }
139
+ };
140
+ }
141
+
142
+ // @ts-expect-error Check `executeOnUIRuntimeSync` overload above.
143
+ export function executeOnUIRuntimeSync<Args extends unknown[], ReturnValue>(
144
+ worklet: (...args: Args) => ReturnValue
145
+ ): (...args: Args) => ReturnValue;
146
+
147
+ export function executeOnUIRuntimeSync<Args extends unknown[], ReturnValue>(
148
+ worklet: WorkletFunction<Args, ReturnValue>
149
+ ): (...args: Args) => ReturnValue {
150
+ return (...args) => {
151
+ return WorkletsModule.executeOnUIRuntimeSync(
152
+ makeShareableCloneRecursive(() => {
153
+ 'worklet';
154
+ const result = worklet(...args);
155
+ return makeShareableCloneOnUIRecursive(result);
156
+ })
157
+ );
158
+ };
159
+ }
160
+
161
+ // @ts-expect-error Check `runOnUI` overload above.
162
+ export function runOnUIImmediately<Args extends unknown[], ReturnValue>(
163
+ worklet: (...args: Args) => ReturnValue
164
+ ): WorkletFunction<Args, ReturnValue>;
165
+ /** Schedule a worklet to execute on the UI runtime skipping batching mechanism. */
166
+ export function runOnUIImmediately<Args extends unknown[], ReturnValue>(
167
+ worklet: WorkletFunction<Args, ReturnValue>
168
+ ): (...args: Args) => void {
169
+ 'worklet';
170
+ if (__DEV__ && !SHOULD_BE_USE_WEB && _WORKLET) {
171
+ throw new WorkletsError(
172
+ '`runOnUIImmediately` cannot be called on the UI runtime. Please call the function synchronously or use `queueMicrotask` or `requestAnimationFrame` instead.'
173
+ );
174
+ }
175
+ if (__DEV__ && !SHOULD_BE_USE_WEB && !isWorkletFunction(worklet)) {
176
+ throw new WorkletsError(
177
+ '`runOnUIImmediately` can only be used with worklets.'
178
+ );
179
+ }
180
+ return (...args) => {
181
+ WorkletsModule.scheduleOnUI(
182
+ makeShareableCloneRecursive(() => {
183
+ 'worklet';
184
+ worklet(...args);
185
+ })
186
+ );
187
+ };
188
+ }
189
+
190
+ type ReleaseRemoteFunction<Args extends unknown[], ReturnValue> = {
191
+ (...args: Args): ReturnValue;
192
+ };
193
+
194
+ type DevRemoteFunction<Args extends unknown[], ReturnValue> = {
195
+ __remoteFunction: (...args: Args) => ReturnValue;
196
+ };
197
+
198
+ type RemoteFunction<Args extends unknown[], ReturnValue> =
199
+ | ReleaseRemoteFunction<Args, ReturnValue>
200
+ | DevRemoteFunction<Args, ReturnValue>;
201
+
202
+ function runWorkletOnJS<Args extends unknown[], ReturnValue>(
203
+ worklet: WorkletFunction<Args, ReturnValue>,
204
+ ...args: Args
205
+ ): void {
206
+ // remote function that calls a worklet synchronously on the JS runtime
207
+ worklet(...args);
208
+ }
209
+
210
+ /**
211
+ * Lets you asynchronously run
212
+ * non-[workletized](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/glossary#to-workletize)
213
+ * functions that couldn't otherwise run on the [UI
214
+ * thread](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/glossary#ui-thread).
215
+ * This applies to most external libraries as they don't have their functions
216
+ * marked with "worklet"; directive.
217
+ *
218
+ * @param fun - A reference to a function you want to execute on the JavaScript
219
+ * thread from the UI thread.
220
+ * @returns A function that accepts arguments for the function passed as the
221
+ * first argument.
222
+ * @see https://docs.swmansion.com/react-native-reanimated/docs/threading/runOnJS
223
+ */
224
+ export function runOnJS<Args extends unknown[], ReturnValue>(
225
+ fun:
226
+ | ((...args: Args) => ReturnValue)
227
+ | RemoteFunction<Args, ReturnValue>
228
+ | WorkletFunction<Args, ReturnValue>
229
+ ): (...args: Args) => void {
230
+ 'worklet';
231
+ type FunDevRemote = Extract<typeof fun, DevRemoteFunction<Args, ReturnValue>>;
232
+ if (SHOULD_BE_USE_WEB || !_WORKLET) {
233
+ // if we are already on the JS thread, we just schedule the worklet on the JS queue
234
+ return (...args) =>
235
+ queueMicrotask(
236
+ args.length
237
+ ? () => (fun as (...args: Args) => ReturnValue)(...args)
238
+ : (fun as () => ReturnValue)
239
+ );
240
+ }
241
+ if (isWorkletFunction<Args, ReturnValue>(fun)) {
242
+ // If `fun` is a worklet, we schedule a call of a remote function `runWorkletOnJS`
243
+ // and pass the worklet as a first argument followed by original arguments.
244
+
245
+ return (...args) =>
246
+ runOnJS(runWorkletOnJS<Args, ReturnValue>)(
247
+ fun as WorkletFunction<Args, ReturnValue>,
248
+ ...args
249
+ );
250
+ }
251
+ if ((fun as FunDevRemote).__remoteFunction) {
252
+ // In development mode the function provided as `fun` throws an error message
253
+ // such that when someone accidentally calls it directly on the UI runtime, they
254
+ // see that they should use `runOnJS` instead. To facilitate that we put the
255
+ // reference to the original remote function in the `__remoteFunction` property.
256
+ fun = (fun as FunDevRemote).__remoteFunction;
257
+ }
258
+
259
+ const scheduleOnJS =
260
+ typeof fun === 'function'
261
+ ? global._scheduleHostFunctionOnJS
262
+ : global._scheduleRemoteFunctionOnJS;
263
+
264
+ return (...args) => {
265
+ scheduleOnJS(
266
+ fun as
267
+ | ((...args: Args) => ReturnValue)
268
+ | WorkletFunction<Args, ReturnValue>,
269
+ args.length > 0
270
+ ? // TODO TYPESCRIPT this cast is terrible but will be fixed
271
+ (makeShareableCloneOnUIRecursive(args) as unknown as unknown[])
272
+ : undefined
273
+ );
274
+ };
275
+ }
@@ -0,0 +1,110 @@
1
+ /* eslint-disable reanimated/use-worklets-error */
2
+ 'use strict';
3
+ import { shouldBeUseWeb } from './PlatformChecker';
4
+ import { isWorkletFunction } from './workletFunction';
5
+ import type { WorkletFunction } from './workletTypes';
6
+
7
+ function valueUnpacker(
8
+ objectToUnpack: any,
9
+ category?: string,
10
+ remoteFunctionName?: string
11
+ ): any {
12
+ 'worklet';
13
+ let workletsCache = global.__workletsCache;
14
+ let handleCache = global.__handleCache;
15
+ if (workletsCache === undefined) {
16
+ // init
17
+ workletsCache = global.__workletsCache = new Map();
18
+ handleCache = global.__handleCache = new WeakMap();
19
+ }
20
+ const workletHash = objectToUnpack.__workletHash;
21
+ if (workletHash !== undefined) {
22
+ let workletFun = workletsCache.get(workletHash);
23
+ if (workletFun === undefined) {
24
+ const initData = objectToUnpack.__initData;
25
+ if (global.evalWithSourceMap) {
26
+ // if the runtime (hermes only for now) supports loading source maps
27
+ // we want to use the proper filename for the location as it guarantees
28
+ // that debugger understands and loads the source code of the file where
29
+ // the worklet is defined.
30
+ workletFun = global.evalWithSourceMap(
31
+ '(' + initData.code + '\n)',
32
+ initData.location,
33
+ initData.sourceMap
34
+ ) as (...args: any[]) => any;
35
+ } else if (global.evalWithSourceUrl) {
36
+ // if the runtime doesn't support loading source maps, in dev mode we
37
+ // can pass source url when evaluating the worklet. Now, instead of using
38
+ // the actual file location we use worklet hash, as it the allows us to
39
+ // properly symbolicate traces (see errors.ts for details)
40
+ workletFun = global.evalWithSourceUrl(
41
+ '(' + initData.code + '\n)',
42
+ `worklet_${workletHash}`
43
+ ) as (...args: any[]) => any;
44
+ } else {
45
+ // in release we use the regular eval to save on JSI calls
46
+ // eslint-disable-next-line no-eval
47
+ workletFun = eval('(' + initData.code + '\n)') as (
48
+ ...args: any[]
49
+ ) => any;
50
+ }
51
+ workletsCache.set(workletHash, workletFun);
52
+ }
53
+ const functionInstance = workletFun.bind(objectToUnpack);
54
+ objectToUnpack._recur = functionInstance;
55
+ return functionInstance;
56
+ } else if (objectToUnpack.__init !== undefined) {
57
+ let value = handleCache.get(objectToUnpack);
58
+ if (value === undefined) {
59
+ value = objectToUnpack.__init();
60
+ handleCache.set(objectToUnpack, value);
61
+ }
62
+ return value;
63
+ } else if (category === 'RemoteFunction') {
64
+ const fun = () => {
65
+ const label = remoteFunctionName
66
+ ? `function \`${remoteFunctionName}\``
67
+ : 'anonymous function';
68
+ throw new Error(`[Worklets] Tried to synchronously call a non-worklet ${label} on the UI thread.
69
+ See https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooting#tried-to-synchronously-call-a-non-worklet-function-on-the-ui-thread for more details.`);
70
+ };
71
+ fun.__remoteFunction = objectToUnpack;
72
+ return fun;
73
+ } else {
74
+ throw new Error(
75
+ `[Worklets] Data type in category "${category}" not recognized by value unpacker: "${_toString(
76
+ objectToUnpack
77
+ )}".`
78
+ );
79
+ }
80
+ }
81
+
82
+ type ValueUnpacker = WorkletFunction<
83
+ [objectToUnpack: any, category?: string],
84
+ any
85
+ >;
86
+
87
+ if (__DEV__ && !shouldBeUseWeb()) {
88
+ const testWorklet = (() => {
89
+ 'worklet';
90
+ }) as WorkletFunction<[], void>;
91
+ if (!isWorkletFunction(testWorklet)) {
92
+ throw new Error(
93
+ `[Worklets] Failed to create a worklet. See https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooting#failed-to-create-a-worklet for more details.`
94
+ );
95
+ }
96
+ if (!isWorkletFunction(valueUnpacker)) {
97
+ throw new Error('[Worklets] `valueUnpacker` is not a worklet');
98
+ }
99
+ const closure = (valueUnpacker as ValueUnpacker).__closure;
100
+ if (closure === undefined) {
101
+ throw new Error('[Worklets] `valueUnpacker` closure is undefined');
102
+ }
103
+ if (Object.keys(closure).length !== 0) {
104
+ throw new Error('[Worklets] `valueUnpacker` must have empty closure');
105
+ }
106
+ }
107
+
108
+ export function getValueUnpackerCode() {
109
+ return (valueUnpacker as ValueUnpacker).__initData.code;
110
+ }
@@ -0,0 +1,47 @@
1
+ 'use strict';
2
+
3
+ import type {
4
+ WorkletBaseDev,
5
+ WorkletBaseRelease,
6
+ WorkletFunction,
7
+ } from './workletTypes';
8
+
9
+ /**
10
+ * This function allows you to determine if a given function is a worklet. It
11
+ * only works with Reanimated Babel plugin enabled. Unless you are doing
12
+ * something with internals of Reanimated you shouldn't need to use this
13
+ * function.
14
+ *
15
+ * ### Note
16
+ *
17
+ * Do not call it before the worklet is declared, as it will always return false
18
+ * then. E.g.:
19
+ *
20
+ * ```ts
21
+ * isWorkletFunction(myWorklet); // Will always return false.
22
+ *
23
+ * function myWorklet() {
24
+ * 'worklet';
25
+ * }
26
+ * ```
27
+ *
28
+ * ### Maintainer note
29
+ *
30
+ * This function is supposed to be used only in the React Runtime. It always
31
+ * returns `false` in Worklet Runtimes.
32
+ */
33
+ export function isWorkletFunction<
34
+ Args extends unknown[] = unknown[],
35
+ ReturnValue = unknown,
36
+ BuildType extends WorkletBaseDev | WorkletBaseRelease = WorkletBaseDev,
37
+ >(value: unknown): value is WorkletFunction<Args, ReturnValue> & BuildType {
38
+ 'worklet';
39
+ // Since host objects always return true for `in` operator, we have to use dot notation to check if the property exists.
40
+ // See https://github.com/facebook/hermes/blob/340726ef8cf666a7cce75bc60b02fa56b3e54560/lib/VM/JSObject.cpp#L1276.
41
+
42
+ return (
43
+ // `__workletHash` isn't extracted in Worklet Runtimes.
44
+ typeof value === 'function' &&
45
+ !!(value as unknown as Record<string, unknown>).__workletHash
46
+ );
47
+ }
@@ -0,0 +1,76 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * The below type is used for HostObjects returned by the JSI API that don't
5
+ * have any accessible fields or methods but can carry data that is accessed
6
+ * from the c++ side. We add a field to the type to make it possible for
7
+ * typescript to recognize which JSI methods accept those types as arguments and
8
+ * to be able to correctly type check other methods that may use them. However,
9
+ * this field is not actually defined nor should be used for anything else as
10
+ * assigning any data to those objects will throw an error.
11
+ */
12
+ export type ShareableRef<T = unknown> = {
13
+ __hostObjectShareableJSRef: T;
14
+ };
15
+
16
+ // In case of objects with depth or arrays of objects or arrays of arrays etc.
17
+ // we add this utility type that makes it a `SharaebleRef` of the outermost type.
18
+ export type FlatShareableRef<T> =
19
+ T extends ShareableRef<infer U> ? ShareableRef<U> : ShareableRef<T>;
20
+
21
+ export type WorkletRuntime = {
22
+ __hostObjectWorkletRuntime: never;
23
+ readonly name: string;
24
+ };
25
+
26
+ export type WorkletStackDetails = [
27
+ error: Error,
28
+ lineOffset: number,
29
+ columnOffset: number,
30
+ ];
31
+
32
+ type WorkletClosure = Record<string, unknown>;
33
+
34
+ interface WorkletInitDataCommon {
35
+ code: string;
36
+ }
37
+
38
+ type WorkletInitDataRelease = WorkletInitDataCommon;
39
+
40
+ interface WorkletInitDataDev extends WorkletInitDataCommon {
41
+ location: string;
42
+ sourceMap: string;
43
+ version: string;
44
+ }
45
+
46
+ interface WorkletBaseCommon {
47
+ __closure: WorkletClosure;
48
+ __workletHash: number;
49
+ }
50
+
51
+ export interface WorkletBaseRelease extends WorkletBaseCommon {
52
+ __initData: WorkletInitDataRelease;
53
+ }
54
+
55
+ export interface WorkletBaseDev extends WorkletBaseCommon {
56
+ __initData: WorkletInitDataDev;
57
+ /** `__stackDetails` is removed after parsing. */
58
+ __stackDetails?: WorkletStackDetails;
59
+ }
60
+
61
+ export type WorkletFunctionDev<
62
+ Args extends unknown[] = unknown[],
63
+ ReturnValue = unknown,
64
+ > = ((...args: Args) => ReturnValue) & WorkletBaseDev;
65
+
66
+ type WorkletFunctionRelease<
67
+ Args extends unknown[] = unknown[],
68
+ ReturnValue = unknown,
69
+ > = ((...args: Args) => ReturnValue) & WorkletBaseRelease;
70
+
71
+ export type WorkletFunction<
72
+ Args extends unknown[] = unknown[],
73
+ ReturnValue = unknown,
74
+ > =
75
+ | WorkletFunctionDev<Args, ReturnValue>
76
+ | WorkletFunctionRelease<Args, ReturnValue>;
package/Animated.js DELETED
@@ -1,13 +0,0 @@
1
- import { Image, Text, View, ScrollView } from 'react-native';
2
- import AnimatedImplementation from './AnimatedImplementation';
3
-
4
- const Animated = {
5
- View: AnimatedImplementation.createAnimatedComponent(View),
6
- Text: AnimatedImplementation.createAnimatedComponent(Text),
7
- Image: AnimatedImplementation.createAnimatedComponent(Image),
8
- ScrollView: AnimatedImplementation.createAnimatedComponent(ScrollView),
9
- };
10
-
11
- Object.assign(Animated, AnimatedImplementation);
12
-
13
- export default Animated;
package/AnimatedEvent.js DELETED
@@ -1,167 +0,0 @@
1
- import AnimatedValue from './nodes/AnimatedValue';
2
- import NativeAnimatedHelper, {
3
- shouldUseNativeDriver,
4
- } from './NativeAnimatedHelper';
5
- import ReactNative from 'ReactNative';
6
-
7
- import invariant from 'fbjs/lib/invariant';
8
-
9
- function attachNativeEvent(viewRef, eventName, argMapping) {
10
- // Find animated values in `argMapping` and create an array representing their
11
- // key path inside the `nativeEvent` object. Ex.: ['contentOffset', 'x'].
12
- const eventMappings = [];
13
-
14
- const traverse = (value, path) => {
15
- if (value instanceof AnimatedValue) {
16
- value.__makeNative();
17
-
18
- eventMappings.push({
19
- nativeEventPath: path,
20
- animatedValueTag: value.__getNativeTag(),
21
- });
22
- } else if (typeof value === 'object') {
23
- for (const key in value) {
24
- traverse(value[key], path.concat(key));
25
- }
26
- }
27
- };
28
-
29
- invariant(
30
- argMapping[0] && argMapping[0].nativeEvent,
31
- 'Native driven events only support animated values contained inside `nativeEvent`.'
32
- );
33
-
34
- // Assume that the event containing `nativeEvent` is always the first argument.
35
- traverse(argMapping[0].nativeEvent, []);
36
-
37
- const viewTag = ReactNative.findNodeHandle(viewRef);
38
-
39
- eventMappings.forEach(mapping => {
40
- NativeAnimatedHelper.API.addAnimatedEventToView(
41
- viewTag,
42
- eventName,
43
- mapping
44
- );
45
- });
46
-
47
- return {
48
- detach() {
49
- eventMappings.forEach(mapping => {
50
- NativeAnimatedHelper.API.removeAnimatedEventFromView(
51
- viewTag,
52
- eventName,
53
- mapping.animatedValueTag
54
- );
55
- });
56
- },
57
- };
58
- }
59
-
60
- class AnimatedEvent {
61
- _listeners = [];
62
-
63
- constructor(argMapping, config = {}) {
64
- this._argMapping = argMapping;
65
- if (config.listener) {
66
- this.__addListener(config.listener);
67
- }
68
- this._callListeners = this._callListeners.bind(this);
69
- this._attachedEvent = null;
70
- this.__isNative = shouldUseNativeDriver(config);
71
-
72
- if (__DEV__) {
73
- this._validateMapping();
74
- }
75
- }
76
-
77
- __addListener(callback) {
78
- this._listeners.push(callback);
79
- }
80
-
81
- __removeListener(callback) {
82
- this._listeners = this._listeners.filter(listener => listener !== callback);
83
- }
84
-
85
- __attach(viewRef, eventName) {
86
- invariant(
87
- this.__isNative,
88
- 'Only native driven events need to be attached.'
89
- );
90
-
91
- this._attachedEvent = attachNativeEvent(
92
- viewRef,
93
- eventName,
94
- this._argMapping
95
- );
96
- }
97
-
98
- __detach(viewTag, eventName) {
99
- invariant(
100
- this.__isNative,
101
- 'Only native driven events need to be detached.'
102
- );
103
-
104
- this._attachedEvent && this._attachedEvent.detach();
105
- }
106
-
107
- __getHandler() {
108
- if (this.__isNative) {
109
- return this._callListeners;
110
- }
111
-
112
- return (...args) => {
113
- const traverse = (recMapping, recEvt, key) => {
114
- if (typeof recEvt === 'number' && recMapping instanceof AnimatedValue) {
115
- recMapping.setValue(recEvt);
116
- } else if (typeof recMapping === 'object') {
117
- for (const mappingKey in recMapping) {
118
- /* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
119
- * comment suppresses an error when upgrading Flow's support for
120
- * React. To see the error delete this comment and run Flow. */
121
- traverse(recMapping[mappingKey], recEvt[mappingKey], mappingKey);
122
- }
123
- }
124
- };
125
-
126
- if (!this.__isNative) {
127
- this._argMapping.forEach((mapping, idx) => {
128
- traverse(mapping, args[idx], 'arg' + idx);
129
- });
130
- }
131
- this._callListeners(...args);
132
- };
133
- }
134
-
135
- _callListeners(...args) {
136
- this._listeners.forEach(listener => listener(...args));
137
- }
138
-
139
- _validateMapping() {
140
- const traverse = (recMapping, recEvt, key) => {
141
- if (typeof recEvt === 'number') {
142
- invariant(
143
- recMapping instanceof AnimatedValue,
144
- 'Bad mapping of type ' +
145
- typeof recMapping +
146
- ' for key ' +
147
- key +
148
- ', event value must map to AnimatedValue'
149
- );
150
- return;
151
- }
152
- invariant(
153
- typeof recMapping === 'object',
154
- 'Bad mapping of type ' + typeof recMapping + ' for key ' + key
155
- );
156
- invariant(
157
- typeof recEvt === 'object',
158
- 'Bad event of type ' + typeof recEvt + ' for key ' + key
159
- );
160
- for (const mappingKey in recMapping) {
161
- traverse(recMapping[mappingKey], recEvt[mappingKey], mappingKey);
162
- }
163
- };
164
- }
165
- }
166
-
167
- export { AnimatedEvent, attachNativeEvent };