basalt-core 0.0.0-rc5

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 (325) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cli/basalt.d.ts +3 -0
  3. package/dist/cli/basalt.d.ts.map +1 -0
  4. package/dist/cli/basalt.js +47 -0
  5. package/dist/cli/basalt.js.map +1 -0
  6. package/dist/cli/bundle-cli.d.ts +12 -0
  7. package/dist/cli/bundle-cli.d.ts.map +1 -0
  8. package/dist/cli/bundle-cli.js +124 -0
  9. package/dist/cli/bundle-cli.js.map +1 -0
  10. package/dist/cli/bundleWithAssets.d.ts +79 -0
  11. package/dist/cli/bundleWithAssets.d.ts.map +1 -0
  12. package/dist/cli/bundleWithAssets.js +198 -0
  13. package/dist/cli/bundleWithAssets.js.map +1 -0
  14. package/dist/cli/desktop.d.ts +339 -0
  15. package/dist/cli/desktop.d.ts.map +1 -0
  16. package/dist/cli/desktop.js +1029 -0
  17. package/dist/cli/desktop.js.map +1 -0
  18. package/dist/cli/doctor.d.ts +31 -0
  19. package/dist/cli/doctor.d.ts.map +1 -0
  20. package/dist/cli/doctor.js +283 -0
  21. package/dist/cli/doctor.js.map +1 -0
  22. package/dist/cli/init.d.ts +77 -0
  23. package/dist/cli/init.d.ts.map +1 -0
  24. package/dist/cli/init.js +442 -0
  25. package/dist/cli/init.js.map +1 -0
  26. package/dist/cli/metro.d.ts +49 -0
  27. package/dist/cli/metro.d.ts.map +1 -0
  28. package/dist/cli/metro.js +148 -0
  29. package/dist/cli/metro.js.map +1 -0
  30. package/dist/cli/packageApp.d.ts +102 -0
  31. package/dist/cli/packageApp.d.ts.map +1 -0
  32. package/dist/cli/packageApp.js +319 -0
  33. package/dist/cli/packageApp.js.map +1 -0
  34. package/dist/cli/steps.d.ts +34 -0
  35. package/dist/cli/steps.d.ts.map +1 -0
  36. package/dist/cli/steps.js +53 -0
  37. package/dist/cli/steps.js.map +1 -0
  38. package/dist/metro-config.d.ts +168 -0
  39. package/dist/metro-config.d.ts.map +1 -0
  40. package/dist/metro-config.js +671 -0
  41. package/dist/metro-config.js.map +1 -0
  42. package/dist/react-native.config.d.ts +7 -0
  43. package/dist/react-native.config.d.ts.map +1 -0
  44. package/dist/react-native.config.js +80 -0
  45. package/dist/react-native.config.js.map +1 -0
  46. package/dist/src/DragSource.d.ts +52 -0
  47. package/dist/src/DragSource.d.ts.map +1 -0
  48. package/dist/src/DragSource.js +97 -0
  49. package/dist/src/DragSource.js.map +1 -0
  50. package/dist/src/DropTarget.d.ts +58 -0
  51. package/dist/src/DropTarget.d.ts.map +1 -0
  52. package/dist/src/DropTarget.js +131 -0
  53. package/dist/src/DropTarget.js.map +1 -0
  54. package/dist/src/KeyHandler.d.ts +57 -0
  55. package/dist/src/KeyHandler.d.ts.map +1 -0
  56. package/dist/src/KeyHandler.js +48 -0
  57. package/dist/src/KeyHandler.js.map +1 -0
  58. package/dist/src/Menu.d.ts +72 -0
  59. package/dist/src/Menu.d.ts.map +1 -0
  60. package/dist/src/Menu.js +179 -0
  61. package/dist/src/Menu.js.map +1 -0
  62. package/dist/src/TitleBar.d.ts +75 -0
  63. package/dist/src/TitleBar.d.ts.map +1 -0
  64. package/dist/src/TitleBar.js +236 -0
  65. package/dist/src/TitleBar.js.map +1 -0
  66. package/dist/src/Window.d.ts +87 -0
  67. package/dist/src/Window.d.ts.map +1 -0
  68. package/dist/src/Window.js +248 -0
  69. package/dist/src/Window.js.map +1 -0
  70. package/dist/src/closeRequest.d.ts +55 -0
  71. package/dist/src/closeRequest.d.ts.map +1 -0
  72. package/dist/src/closeRequest.js +134 -0
  73. package/dist/src/closeRequest.js.map +1 -0
  74. package/dist/src/index.d.ts +45 -0
  75. package/dist/src/index.d.ts.map +1 -0
  76. package/dist/src/index.js +92 -0
  77. package/dist/src/index.js.map +1 -0
  78. package/dist/src/overrides/Alert.d.ts +69 -0
  79. package/dist/src/overrides/Alert.d.ts.map +1 -0
  80. package/dist/src/overrides/Alert.js +112 -0
  81. package/dist/src/overrides/Alert.js.map +1 -0
  82. package/dist/src/overrides/BaseViewConfig.d.ts +28 -0
  83. package/dist/src/overrides/BaseViewConfig.d.ts.map +1 -0
  84. package/dist/src/overrides/BaseViewConfig.js +72 -0
  85. package/dist/src/overrides/BaseViewConfig.js.map +1 -0
  86. package/dist/src/overrides/Platform.linux.d.ts +10 -0
  87. package/dist/src/overrides/Platform.linux.d.ts.map +1 -0
  88. package/dist/src/overrides/Platform.linux.js +15 -0
  89. package/dist/src/overrides/Platform.linux.js.map +1 -0
  90. package/dist/src/overrides/Platform.macos.d.ts +10 -0
  91. package/dist/src/overrides/Platform.macos.d.ts.map +1 -0
  92. package/dist/src/overrides/Platform.macos.js +15 -0
  93. package/dist/src/overrides/Platform.macos.js.map +1 -0
  94. package/dist/src/overrides/Platform.windows.d.ts +10 -0
  95. package/dist/src/overrides/Platform.windows.d.ts.map +1 -0
  96. package/dist/src/overrides/Platform.windows.js +15 -0
  97. package/dist/src/overrides/Platform.windows.js.map +1 -0
  98. package/dist/src/overrides/ReactDevToolsSettingsManager.d.ts +24 -0
  99. package/dist/src/overrides/ReactDevToolsSettingsManager.d.ts.map +1 -0
  100. package/dist/src/overrides/ReactDevToolsSettingsManager.js +30 -0
  101. package/dist/src/overrides/ReactDevToolsSettingsManager.js.map +1 -0
  102. package/dist/src/overrides/RefreshControl.d.ts +52 -0
  103. package/dist/src/overrides/RefreshControl.d.ts.map +1 -0
  104. package/dist/src/overrides/RefreshControl.js +92 -0
  105. package/dist/src/overrides/RefreshControl.js.map +1 -0
  106. package/dist/src/overrides/ScrollView.d.ts +39 -0
  107. package/dist/src/overrides/ScrollView.d.ts.map +1 -0
  108. package/dist/src/overrides/ScrollView.js +59 -0
  109. package/dist/src/overrides/ScrollView.js.map +1 -0
  110. package/dist/src/overrides/Share.d.ts +96 -0
  111. package/dist/src/overrides/Share.d.ts.map +1 -0
  112. package/dist/src/overrides/Share.js +97 -0
  113. package/dist/src/overrides/Share.js.map +1 -0
  114. package/dist/src/overrides/TextInput.d.ts +81 -0
  115. package/dist/src/overrides/TextInput.d.ts.map +1 -0
  116. package/dist/src/overrides/TextInput.js +213 -0
  117. package/dist/src/overrides/TextInput.js.map +1 -0
  118. package/dist/src/overrides/View.d.ts +36 -0
  119. package/dist/src/overrides/View.d.ts.map +1 -0
  120. package/dist/src/overrides/View.js +99 -0
  121. package/dist/src/overrides/View.js.map +1 -0
  122. package/dist/src/overrides/createPlatform.d.ts +32 -0
  123. package/dist/src/overrides/createPlatform.d.ts.map +1 -0
  124. package/dist/src/overrides/createPlatform.js +84 -0
  125. package/dist/src/overrides/createPlatform.js.map +1 -0
  126. package/dist/src/overrides/setUpDeveloperTools.d.ts +28 -0
  127. package/dist/src/overrides/setUpDeveloperTools.d.ts.map +1 -0
  128. package/dist/src/overrides/setUpDeveloperTools.js +84 -0
  129. package/dist/src/overrides/setUpDeveloperTools.js.map +1 -0
  130. package/dist/src/overrides/setUpXHR.d.ts +46 -0
  131. package/dist/src/overrides/setUpXHR.d.ts.map +1 -0
  132. package/dist/src/overrides/setUpXHR.js +236 -0
  133. package/dist/src/overrides/setUpXHR.js.map +1 -0
  134. package/dist/src/quitRequest.d.ts +55 -0
  135. package/dist/src/quitRequest.d.ts.map +1 -0
  136. package/dist/src/quitRequest.js +121 -0
  137. package/dist/src/quitRequest.js.map +1 -0
  138. package/dist/src/resourcePath.d.ts +18 -0
  139. package/dist/src/resourcePath.d.ts.map +1 -0
  140. package/dist/src/resourcePath.js +31 -0
  141. package/dist/src/resourcePath.js.map +1 -0
  142. package/dist/src/responseBody.d.ts +76 -0
  143. package/dist/src/responseBody.d.ts.map +1 -0
  144. package/dist/src/responseBody.js +94 -0
  145. package/dist/src/responseBody.js.map +1 -0
  146. package/dist/src/responseHeaders.d.ts +40 -0
  147. package/dist/src/responseHeaders.d.ts.map +1 -0
  148. package/dist/src/responseHeaders.js +75 -0
  149. package/dist/src/responseHeaders.js.map +1 -0
  150. package/dist/src/titleBarState.d.ts +43 -0
  151. package/dist/src/titleBarState.d.ts.map +1 -0
  152. package/dist/src/titleBarState.js +77 -0
  153. package/dist/src/titleBarState.js.map +1 -0
  154. package/dist/src/useContextMenu.d.ts +113 -0
  155. package/dist/src/useContextMenu.d.ts.map +1 -0
  156. package/dist/src/useContextMenu.js +109 -0
  157. package/dist/src/useContextMenu.js.map +1 -0
  158. package/dist/src/useDialog.d.ts +98 -0
  159. package/dist/src/useDialog.d.ts.map +1 -0
  160. package/dist/src/useDialog.js +112 -0
  161. package/dist/src/useDialog.js.map +1 -0
  162. package/dist/src/useDisplays.d.ts +70 -0
  163. package/dist/src/useDisplays.d.ts.map +1 -0
  164. package/dist/src/useDisplays.js +118 -0
  165. package/dist/src/useDisplays.js.map +1 -0
  166. package/dist/src/useHandledKeys.d.ts +38 -0
  167. package/dist/src/useHandledKeys.d.ts.map +1 -0
  168. package/dist/src/useHandledKeys.js +70 -0
  169. package/dist/src/useHandledKeys.js.map +1 -0
  170. package/dist/src/useWindow.d.ts +140 -0
  171. package/dist/src/useWindow.d.ts.map +1 -0
  172. package/dist/src/useWindow.js +233 -0
  173. package/dist/src/useWindow.js.map +1 -0
  174. package/dist/tsconfig.tsbuildinfo +1 -0
  175. package/native/CMakeLists.txt +355 -0
  176. package/native/bootstrap.sh +613 -0
  177. package/native/cmake/CompilerFlags.cmake +49 -0
  178. package/native/cmake/Expo.cmake +125 -0
  179. package/native/cmake/ReactNativeCore.cmake +612 -0
  180. package/native/cmake/Reanimated.cmake +108 -0
  181. package/native/cmake/Skia.cmake +379 -0
  182. package/native/cmake/ThirdParty.cmake +290 -0
  183. package/native/cmake/Worklets.cmake +67 -0
  184. package/native/cmake/codegen/CMakeLists.txt +32 -0
  185. package/native/core/AppIdentity.cpp +85 -0
  186. package/native/core/AppIdentity.h +59 -0
  187. package/native/core/AppPaths.cpp +96 -0
  188. package/native/core/AppPaths.h +53 -0
  189. package/native/core/AppearanceModule.cpp +60 -0
  190. package/native/core/AppearanceModule.h +40 -0
  191. package/native/core/Backface.h +59 -0
  192. package/native/core/BlobModule.cpp +283 -0
  193. package/native/core/BlobModule.h +76 -0
  194. package/native/core/BlobRegistry.cpp +75 -0
  195. package/native/core/BlobRegistry.h +44 -0
  196. package/native/core/ColorScheme.cpp +105 -0
  197. package/native/core/ColorScheme.h +59 -0
  198. package/native/core/ComponentRegistry.h +30 -0
  199. package/native/core/ControlMetrics.h +37 -0
  200. package/native/core/CoreModules.cpp +592 -0
  201. package/native/core/CoreModules.h +308 -0
  202. package/native/core/DebuggingOverlay.cpp +106 -0
  203. package/native/core/DebuggingOverlay.h +65 -0
  204. package/native/core/DesktopControls.cpp +232 -0
  205. package/native/core/DesktopControls.h +170 -0
  206. package/native/core/DevBundle.cpp +108 -0
  207. package/native/core/DevBundle.h +69 -0
  208. package/native/core/DevMenu.cpp +99 -0
  209. package/native/core/DevMenu.h +75 -0
  210. package/native/core/DialogModule.cpp +150 -0
  211. package/native/core/DialogModule.h +51 -0
  212. package/native/core/DragAndDrop.cpp +45 -0
  213. package/native/core/DragAndDrop.h +225 -0
  214. package/native/core/ExpoImageComponent.cpp +79 -0
  215. package/native/core/ExpoImageComponent.h +80 -0
  216. package/native/core/ExpoModules.cpp +415 -0
  217. package/native/core/ExpoModules.h +115 -0
  218. package/native/core/ExpoRuntime.cpp +366 -0
  219. package/native/core/ExpoRuntime.h +42 -0
  220. package/native/core/FocusRing.h +36 -0
  221. package/native/core/FontRegistry.h +51 -0
  222. package/native/core/GestureHandlerModule.cpp +136 -0
  223. package/native/core/GestureHandlerModule.h +71 -0
  224. package/native/core/Gestures.cpp +533 -0
  225. package/native/core/Gestures.h +145 -0
  226. package/native/core/HoverTracker.cpp +69 -0
  227. package/native/core/HoverTracker.h +109 -0
  228. package/native/core/HttpClient.cpp +282 -0
  229. package/native/core/ImageBytes.cpp +205 -0
  230. package/native/core/ImageBytes.h +29 -0
  231. package/native/core/ImageCache.cpp +51 -0
  232. package/native/core/ImageCache.h +89 -0
  233. package/native/core/JsRuntimeAccess.cpp +70 -0
  234. package/native/core/JsRuntimeAccess.h +60 -0
  235. package/native/core/JsiPromise.h +51 -0
  236. package/native/core/KeyEvents.cpp +116 -0
  237. package/native/core/KeyEvents.h +144 -0
  238. package/native/core/LogBoxSurface.cpp +46 -0
  239. package/native/core/LogBoxSurface.h +68 -0
  240. package/native/core/MenuModel.h +117 -0
  241. package/native/core/MenuModule.cpp +209 -0
  242. package/native/core/MenuModule.h +66 -0
  243. package/native/core/MountingWalk.h +524 -0
  244. package/native/core/PackageModules.cpp.in +25 -0
  245. package/native/core/PackageModules.h +50 -0
  246. package/native/core/PlatformConstantsModule.cpp +63 -0
  247. package/native/core/PlatformConstantsModule.h +64 -0
  248. package/native/core/PlatformServices.h +213 -0
  249. package/native/core/PointerButtons.h +63 -0
  250. package/native/core/PullToRefresh.cpp +57 -0
  251. package/native/core/PullToRefresh.h +73 -0
  252. package/native/core/ReanimatedCompat.h +47 -0
  253. package/native/core/ReanimatedModule.cpp +203 -0
  254. package/native/core/ReanimatedModule.h +55 -0
  255. package/native/core/ScrollAnimation.cpp +59 -0
  256. package/native/core/ScrollAnimation.h +70 -0
  257. package/native/core/ScrollBounds.cpp +26 -0
  258. package/native/core/ScrollBounds.h +68 -0
  259. package/native/core/ScrollIndicator.cpp +50 -0
  260. package/native/core/ScrollIndicator.h +69 -0
  261. package/native/core/ScrollMomentum.cpp +71 -0
  262. package/native/core/ScrollMomentum.h +73 -0
  263. package/native/core/ScrollSnap.cpp +123 -0
  264. package/native/core/ScrollSnap.h +80 -0
  265. package/native/core/ShareFallback.cpp +101 -0
  266. package/native/core/ShareFallback.h +45 -0
  267. package/native/core/SkiaPictureViewComponent.cpp +11 -0
  268. package/native/core/SkiaPictureViewComponent.h +47 -0
  269. package/native/core/SourceCodeModule.cpp +55 -0
  270. package/native/core/SourceCodeModule.h +53 -0
  271. package/native/core/StatusBarModule.cpp +23 -0
  272. package/native/core/StatusBarModule.h +42 -0
  273. package/native/core/TestDialog.cpp +148 -0
  274. package/native/core/TestDialog.h +96 -0
  275. package/native/core/TestKeys.cpp +78 -0
  276. package/native/core/TestKeys.h +50 -0
  277. package/native/core/TestQuitFile.cpp +33 -0
  278. package/native/core/TestQuitFile.h +60 -0
  279. package/native/core/TestSettle.h +192 -0
  280. package/native/core/TitleBarRegions.h +31 -0
  281. package/native/core/TurboModuleProxy.cpp +51 -0
  282. package/native/core/TurboModuleProxy.h +46 -0
  283. package/native/core/UIManagerAccess.cpp +43 -0
  284. package/native/core/UIManagerAccess.h +43 -0
  285. package/native/core/WindowBoundsCache.cpp +319 -0
  286. package/native/core/WindowControl.h +235 -0
  287. package/native/core/WindowHost.h +158 -0
  288. package/native/core/WindowMethods.cpp +167 -0
  289. package/native/core/WindowMethods.h +84 -0
  290. package/native/core/WindowsModule.cpp +448 -0
  291. package/native/core/WindowsModule.h +133 -0
  292. package/native/core/WorkletsModule.cpp +199 -0
  293. package/native/core/WorkletsModule.h +57 -0
  294. package/native/core/portability_probe.cpp +210 -0
  295. package/native/tests/EventRecorder.h +124 -0
  296. package/native/tests/TestHarness.cpp +109 -0
  297. package/native/tests/TestHarness.h +89 -0
  298. package/native/tests/TreeDump.h +49 -0
  299. package/native/tests/test_app_identity.cpp +114 -0
  300. package/native/tests/test_app_paths.cpp +48 -0
  301. package/native/tests/test_appearance.cpp +107 -0
  302. package/native/tests/test_backface.cpp +79 -0
  303. package/native/tests/test_blobs.cpp +157 -0
  304. package/native/tests/test_controls.cpp +185 -0
  305. package/native/tests/test_devbundle.cpp +103 -0
  306. package/native/tests/test_drag_and_drop.cpp +143 -0
  307. package/native/tests/test_gestures.cpp +331 -0
  308. package/native/tests/test_hover.cpp +92 -0
  309. package/native/tests/test_image_cache.cpp +109 -0
  310. package/native/tests/test_js_runtime_access.cpp +137 -0
  311. package/native/tests/test_key_events.cpp +235 -0
  312. package/native/tests/test_momentum.cpp +138 -0
  313. package/native/tests/test_quit_file.cpp +104 -0
  314. package/native/tests/test_scroll_animation.cpp +120 -0
  315. package/native/tests/test_scroll_bounds.cpp +66 -0
  316. package/native/tests/test_scroll_indicator.cpp +149 -0
  317. package/native/tests/test_scroll_snap.cpp +112 -0
  318. package/native/tests/test_settle.cpp +115 -0
  319. package/native/tests/test_share.cpp +75 -0
  320. package/native/tests/test_sourcecode.cpp +62 -0
  321. package/native/tests/test_window_close.cpp +119 -0
  322. package/native/tests/test_window_limits.cpp +123 -0
  323. package/package.json +43 -0
  324. package/react-native.config.js +86 -0
  325. package/supported-versions.json +66 -0
@@ -0,0 +1,199 @@
1
+ #include "WorkletsModule.h"
2
+
3
+ #include "Gestures.h"
4
+ #include "PlatformServices.h"
5
+
6
+ #include <glog/logging.h>
7
+
8
+ #ifdef BASALT_HAS_WORKLETS
9
+ #include <worklets/NativeModules/WorkletsModuleProxy.h>
10
+ #include <worklets/Tools/PlatformLogger.h>
11
+ #include <worklets/Tools/RNRuntimeStatus.h>
12
+ #include <worklets/Tools/UIScheduler.h>
13
+ #include <worklets/WorkletRuntime/RuntimeBindings.h>
14
+
15
+ #include <thread>
16
+ #endif
17
+
18
+ namespace basalt {
19
+
20
+ bool hasWorklets() {
21
+ #ifdef BASALT_HAS_WORKLETS
22
+ return true;
23
+ #else
24
+ return false;
25
+ #endif
26
+ }
27
+
28
+ #ifdef BASALT_HAS_WORKLETS
29
+
30
+ namespace {
31
+
32
+ using facebook::jsi::Runtime;
33
+ using facebook::jsi::Value;
34
+ using facebook::react::TurboModule;
35
+
36
+ // The thread the bundle runs on, learned at install time -- which happens from
37
+ // JavaScript, so whichever thread that is, is the one. Worklets asks about it
38
+ // to decide whether a job can run now or has to be scheduled.
39
+ std::thread::id &javaScriptThread() {
40
+ static std::thread::id id;
41
+ return id;
42
+ }
43
+
44
+ // The UI thread's scheduler. `postToUiThread` is the platform's, and the base
45
+ // class does the queueing; this only has to get `triggerUI` called over there.
46
+ class DesktopUIScheduler final : public worklets::UIScheduler,
47
+ public std::enable_shared_from_this<DesktopUIScheduler> {
48
+ public:
49
+ void scheduleOnUI(std::function<void()> job) override {
50
+ // Already on the UI thread: run it now rather than a frame later, which is
51
+ // what makes a gesture handler's worklet feel immediate.
52
+ if (std::this_thread::get_id() != javaScriptThread()) {
53
+ job();
54
+ return;
55
+ }
56
+
57
+ UIScheduler::scheduleOnUI(std::move(job));
58
+ if (!scheduledOnUI_) {
59
+ postToUiThread([weakThis = weak_from_this()]() {
60
+ // The scheduler can be gone by the time this runs -- the runtime it
61
+ // belongs to is torn down on reload.
62
+ if (auto self = weakThis.lock()) {
63
+ self->triggerUI();
64
+ }
65
+ });
66
+ }
67
+ }
68
+ };
69
+
70
+ // Held for reanimated, which needs the same proxy rather than a second one, and
71
+ // so that `start()` can reach what `installTurboModule()` made. Weak, because
72
+ // the module owns it and the module goes away with the runtime.
73
+ std::weak_ptr<worklets::WorkletsModuleProxy> &installedProxy() {
74
+ static std::weak_ptr<worklets::WorkletsModuleProxy> proxy;
75
+ return proxy;
76
+ }
77
+
78
+ std::shared_ptr<worklets::WorkletsModuleProxy> &heldProxy() {
79
+ static std::shared_ptr<worklets::WorkletsModuleProxy> proxy;
80
+ return proxy;
81
+ }
82
+
83
+ std::shared_ptr<worklets::RNRuntimeStatus> &runtimeStatus() {
84
+ static std::shared_ptr<worklets::RNRuntimeStatus> status;
85
+ return status;
86
+ }
87
+
88
+ } // namespace
89
+
90
+ DesktopWorkletsModule::DesktopWorkletsModule(
91
+ std::shared_ptr<facebook::react::CallInvoker> jsInvoker)
92
+ : TurboModule(kModuleName, std::move(jsInvoker)) {
93
+ methodMap_["installTurboModule"] = MethodMetadata{1, installTurboModule};
94
+ methodMap_["start"] = MethodMetadata{0, start};
95
+ methodMap_["toggleSlowAnimationsOnUIRuntime"] = MethodMetadata{0, toggleSlowAnimations};
96
+ }
97
+
98
+ DesktopWorkletsModule::~DesktopWorkletsModule() {
99
+ if (runtimeStatus() != nullptr) {
100
+ // Tells the worklet runtime that the runtime it was talking to is gone, so
101
+ // that a job still in flight stops rather than reaching into it.
102
+ runtimeStatus()->setDead();
103
+ }
104
+ heldProxy().reset();
105
+ installedProxy().reset();
106
+ }
107
+
108
+ Value DesktopWorkletsModule::installTurboModule(Runtime &runtime,
109
+ TurboModule &module,
110
+ const Value * /*args*/,
111
+ size_t /*count*/) {
112
+ javaScriptThread() = std::this_thread::get_id();
113
+
114
+ auto &self = static_cast<DesktopWorkletsModule &>(module);
115
+ auto uiScheduler = std::make_shared<DesktopUIScheduler>();
116
+ runtimeStatus() = std::make_shared<worklets::RNRuntimeStatus>();
117
+
118
+ auto runtimeBindings = std::make_shared<worklets::RuntimeBindings>(worklets::RuntimeBindings{
119
+ // A timer rather than the display's refresh. The display link on each
120
+ // platform belongs to React Native's own AnimationChoreographer, which
121
+ // pauses whenever React Native has no animation running -- exactly when a
122
+ // Reanimated one might be. Sixteen milliseconds is the honest
123
+ // approximation until there is a frame source both can share; see
124
+ .requestAnimationFrame =
125
+ [](std::function<void(const double)> callback) {
126
+ postDelayed(16, [callback = std::move(callback)]() {
127
+ callback(monotonicMilliseconds());
128
+ });
129
+ },
130
+ // Only used in bundle mode, which this is not.
131
+ .nativeLoggingHook = {},
132
+ });
133
+
134
+ auto proxy = std::make_shared<worklets::WorkletsModuleProxy>(
135
+ runtime,
136
+ self.jsInvoker_,
137
+ uiScheduler,
138
+ []() -> bool { return std::this_thread::get_id() == javaScriptThread(); },
139
+ runtimeBindings,
140
+ worklets::BundleModeConfig{.enabled = false, .script = nullptr, .sourceURL = ""},
141
+ runtimeStatus());
142
+
143
+ heldProxy() = proxy;
144
+ installedProxy() = proxy;
145
+ return Value(true);
146
+ }
147
+
148
+ Value DesktopWorkletsModule::start(Runtime & /*runtime*/,
149
+ TurboModule & /*module*/,
150
+ const Value * /*args*/,
151
+ size_t /*count*/) {
152
+ if (auto proxy = installedProxy().lock()) {
153
+ proxy->start();
154
+ return Value(true);
155
+ }
156
+ return Value(false);
157
+ }
158
+
159
+ Value DesktopWorkletsModule::toggleSlowAnimations(Runtime & /*runtime*/,
160
+ TurboModule & /*module*/,
161
+ const Value * /*args*/,
162
+ size_t /*count*/) {
163
+ // A developer-menu affordance; iOS throws here for the same reason.
164
+ LOG(WARNING) << "worklets: slow animations are not supported on this platform";
165
+ return Value(false);
166
+ }
167
+
168
+ #endif
169
+
170
+ } // namespace basalt
171
+
172
+ #ifdef BASALT_HAS_WORKLETS
173
+ // The logging seam worklets' C++ declares and leaves to each platform: Android
174
+ // writes to logcat, Apple to os_log, and this to the same place every other log
175
+ // line in this project goes.
176
+ namespace worklets {
177
+
178
+ void PlatformLogger::log(const char *str) {
179
+ LOG(INFO) << "[worklets] " << str;
180
+ }
181
+
182
+ void PlatformLogger::log(const std::string &str) {
183
+ LOG(INFO) << "[worklets] " << str;
184
+ }
185
+
186
+ void PlatformLogger::log(const double d) {
187
+ LOG(INFO) << "[worklets] " << d;
188
+ }
189
+
190
+ void PlatformLogger::log(const int i) {
191
+ LOG(INFO) << "[worklets] " << i;
192
+ }
193
+
194
+ void PlatformLogger::log(const bool b) {
195
+ LOG(INFO) << "[worklets] " << (b ? "true" : "false");
196
+ }
197
+
198
+ } // namespace worklets
199
+ #endif
@@ -0,0 +1,57 @@
1
+ // react-native-worklets, which is what Reanimated 4 is built on.
2
+ //
3
+ // The package ships its portable half as C++ in `Common/cpp` -- a second
4
+ // JavaScript runtime for the UI thread, the serialisation that gets a function
5
+ // into it, the schedulers between the two -- depending on jsi, Hermes, a call
6
+ // invoker and nothing else. So it compiles here unmodified, at the app's own
7
+ // version, the same arrangement expo-modules-core has. See cmake/Worklets.cmake.
8
+ //
9
+ // What the package does not ship for a desktop is the host half, and this is
10
+ // it: the TurboModule its JavaScript looks up, a UI scheduler, a frame source,
11
+ // and the platform logger its C++ declares and leaves to each platform.
12
+ //
13
+ // The whole of the port is those four things, which is worth saying plainly:
14
+ // the hard part of worklets -- a separate Hermes runtime, capturing a closure
15
+ // across it, keeping shared values coherent between two runtimes -- is written
16
+ // once, portably, by the people who wrote it. A platform contributes a thread
17
+ // to run on and a heartbeat.
18
+
19
+ #pragma once
20
+
21
+ #include <ReactCommon/TurboModule.h>
22
+
23
+ #include <memory>
24
+
25
+ namespace basalt {
26
+
27
+ // Whether this build has react-native-worklets compiled into it, for the log
28
+ // line that tells a developer which of the two situations they are in.
29
+ bool hasWorklets();
30
+
31
+ #ifdef BASALT_HAS_WORKLETS
32
+
33
+ class DesktopWorkletsModule : public facebook::react::TurboModule {
34
+ public:
35
+ static constexpr const char *kModuleName = "WorkletsModule";
36
+
37
+ explicit DesktopWorkletsModule(std::shared_ptr<facebook::react::CallInvoker> jsInvoker);
38
+ ~DesktopWorkletsModule() override;
39
+
40
+ private:
41
+ static facebook::jsi::Value installTurboModule(facebook::jsi::Runtime &runtime,
42
+ facebook::react::TurboModule &module,
43
+ const facebook::jsi::Value *args,
44
+ size_t count);
45
+ static facebook::jsi::Value start(facebook::jsi::Runtime &runtime,
46
+ facebook::react::TurboModule &module,
47
+ const facebook::jsi::Value *args,
48
+ size_t count);
49
+ static facebook::jsi::Value toggleSlowAnimations(facebook::jsi::Runtime &runtime,
50
+ facebook::react::TurboModule &module,
51
+ const facebook::jsi::Value *args,
52
+ size_t count);
53
+ };
54
+
55
+ #endif
56
+
57
+ } // namespace basalt
@@ -0,0 +1,210 @@
1
+ // Does the shared core actually stand on its own?
2
+ //
3
+ // `basalt_core` compiles without a toolkit on the include path, which says
4
+ // nothing about whether it *links* without one. A header that is never included
5
+ // cannot betray you; an undefined symbol at link time can.
6
+ //
7
+ // So this is a program that links the core and nothing platform-specific, and
8
+ // touches each module the core provides. If it links, a new desktop platform
9
+ // can build the core as-is. If it does not, the missing symbols are exactly the
10
+ // list of what that platform has to implement -- which is the more useful
11
+ // outcome of the two, and the reason this prints them rather than asserting.
12
+ //
13
+ // It is not a test of behaviour. It never constructs a runtime and never
14
+ // renders anything. It answers one question: what does a second platform owe?
15
+ //
16
+ // What it deliberately does not include is any capability package's header.
17
+ // A package's core half is compiled into `basalt_core`, so its seam is a
18
+ // symbol this has to satisfy -- but an app installs the packages it wants and
19
+ // core has to compile in one that installed none. So a package brings its own
20
+ // stub, through BASALT_PACKAGE_PROBE_SOURCES; see
21
+ // packages/basalt-notifications/native/probe_stub.cpp. Including
22
+ // one here made core fail to compile in an app without that package, and the
23
+ // failure read as a missing file in core rather than as a dependency core
24
+ // should never have had.
25
+
26
+ #include "AppearanceModule.h"
27
+ #include "ColorScheme.h"
28
+ #include "CoreModules.h"
29
+ #include "ComponentRegistry.h"
30
+ #include "ExpoRuntime.h"
31
+ #include "FontRegistry.h"
32
+ #include "PlatformConstantsModule.h"
33
+ #include "SourceCodeModule.h"
34
+ #include "PlatformServices.h"
35
+ #include "MenuModel.h"
36
+ #include "WindowControl.h"
37
+ #include "WindowHost.h"
38
+ #include "StatusBarModule.h"
39
+ #include "WorkletsModule.h"
40
+
41
+ #include <cstdio>
42
+ #include <string>
43
+ #include <vector>
44
+
45
+ // The seam, stubbed, so that the link answers the question fully rather than
46
+ // stopping at the first thing missing. A real platform implements these against
47
+ // fontconfig, Core Text or DirectWrite; a platform that has not yet gets this
48
+ // far and no further, which is the point.
49
+ namespace basalt {
50
+ bool registerFont(const std::string &, const std::string &) {
51
+ return false;
52
+ }
53
+ std::string resolveFontFamily(const std::string &name) {
54
+ return name;
55
+ }
56
+ bool isFontRegistered(const std::string &) {
57
+ return false;
58
+ }
59
+ unsigned long fontGeneration() {
60
+ return 0;
61
+ }
62
+ std::string registeredFontNamesJoined(char) {
63
+ return {};
64
+ }
65
+
66
+ // The colour-scheme seam, stubbed the same way. A real platform answers from
67
+ // NSAppearance, GtkSettings or the Windows registry; one that has not yet gets
68
+ // this far and no further.
69
+ ColorScheme systemColorScheme() {
70
+ return ColorScheme::Light;
71
+ }
72
+ void startObservingColorScheme() {}
73
+
74
+ // The platform-services seam, stubbed the same way: clipboard, opening a URL
75
+ // and showing a dialog are the three things a core module cannot do alone.
76
+ std::string clipboardText() {
77
+ return {};
78
+ }
79
+ void setClipboardText(const std::string &) {}
80
+ bool canOpenUrl(const std::string &) {
81
+ return false;
82
+ }
83
+ bool openUrl(const std::string &) {
84
+ return false;
85
+ }
86
+ void showAlert(const AlertRequest &, AlertCallback) {}
87
+ // A file dialog and a share sheet, stubbed the same way. Both answer "the person
88
+ // cancelled", which is what a platform that cannot ask them should say.
89
+ //
90
+ // Missing here until a capability package called one. The probe only ever sees
91
+ // the symbols something in core's link closure *references*, and nothing in core
92
+ // reached these two -- the dialog module and the share module are both only
93
+ // reachable from a host. So the seam was one a new port owed and the probe did
94
+ // not say so, which is the one thing this file exists to prevent.
95
+ void showFileDialog(const FileDialogRequest &, FileDialogCallback onDone) {
96
+ if (onDone) {
97
+ onDone(true, {});
98
+ }
99
+ }
100
+ void shareContent(const ShareRequest &, ShareCallback onDone) {
101
+ if (onDone) {
102
+ onDone(ShareOutcome::Dismissed, {});
103
+ }
104
+ }
105
+ // A popup menu, stubbed the same way. Answering -1 is the seam's "dismissed",
106
+ // which is the honest reply from a platform that cannot show one.
107
+ void showMenu(const MenuRequest &, MenuCallback onChosen) {
108
+ if (onChosen) {
109
+ onChosen(-1);
110
+ }
111
+ }
112
+ // Added when the gesture recognisers arrived: "run this on the UI thread", now
113
+ // and later. A platform with a run loop has both already; this one has neither
114
+ // and says so.
115
+ // The window seam, stubbed the same way. A real platform answers from a
116
+ // GtkWindow, an NSWindow or an HWND; one that has not yet reports a window of
117
+ // no size, which is what an app reading bounds before there is one sees.
118
+ WindowBounds windowBounds() {
119
+ return {};
120
+ }
121
+ void setWindowSize(double, double) {}
122
+ void setWindowPosition(double, double) {}
123
+ void centerWindow() {}
124
+ void setWindowFullScreen(bool) {}
125
+ void applyWindowSizeLimits() {}
126
+ void setWindowResizable(bool) {}
127
+ void setWindowAlwaysOnTop(bool) {}
128
+ WindowCapabilities windowCapabilities() {
129
+ // A platform with no window manager does none of them, which is the honest
130
+ // answer rather than a convenient one: this probe exists to say what a new
131
+ // port owes, and four falses is the starting position.
132
+ return WindowCapabilities{};
133
+ }
134
+
135
+ // The application menu, stubbed the same way. A platform with no menu bar
136
+ // answers exactly this, which is also what GTK answers for real.
137
+ bool applicationMenuSupported() {
138
+ return false;
139
+ }
140
+ void setApplicationMenu(const MenuModel &, std::function<void(int)>) {}
141
+ std::string describeApplicationMenu() {
142
+ return {};
143
+ }
144
+
145
+ // The window seam's other half: opening one. A platform that cannot answers
146
+ // zero, which every caller reads as "no window was opened".
147
+ facebook::react::SurfaceId openHostWindow(const NewWindowOptions &) {
148
+ return 0;
149
+ }
150
+ void closeHostWindow(facebook::react::SurfaceId) {}
151
+ std::vector<facebook::react::SurfaceId> hostWindows() {
152
+ return {};
153
+ }
154
+
155
+ void postDelayed(double, std::function<void()>) {}
156
+ void postToUiThread(std::function<void()>) {}
157
+ bool isUiThread() {
158
+ return false;
159
+ }
160
+ } // namespace basalt
161
+
162
+ int main() {
163
+ using basalt::DesktopPlatformConstantsModule;
164
+ using basalt::DesktopAccessibilityInfoModule;
165
+ using basalt::DesktopAlertModule;
166
+ using basalt::DesktopAppearanceModule;
167
+ using basalt::DesktopClipboardModule;
168
+ using basalt::DesktopI18nManagerModule;
169
+ using basalt::DesktopLinkingModule;
170
+ using basalt::DesktopSourceCodeModule;
171
+ using basalt::DesktopStatusBarModule;
172
+
173
+ // Each of these is a symbol the linker must find in the core alone.
174
+ const std::string url =
175
+ basalt::scriptURLFor("bundle.js", false, "localhost", 8081, "index", "probe");
176
+ const bool expo = basalt::hasExpoRuntime();
177
+ const bool worklets = basalt::hasWorklets();
178
+
179
+ // The seams: declared by the core, implemented by a platform. On a platform
180
+ // that has not implemented them, the link fails here and names them.
181
+ const bool registered = basalt::isFontRegistered("nothing");
182
+ const unsigned long generation = basalt::fontGeneration();
183
+ const char *scheme = basalt::colorSchemeName(basalt::effectiveColorScheme());
184
+
185
+ // Named so the link has to find each module the core claims to provide.
186
+ std::printf("core links.\n");
187
+ // Named so the link has to find each module the core claims to provide.
188
+ std::printf(" modules %s, %s, %s, %s,\n",
189
+ std::string(DesktopPlatformConstantsModule::kModuleName).c_str(),
190
+ std::string(DesktopSourceCodeModule::kModuleName).c_str(),
191
+ std::string(DesktopStatusBarModule::kModuleName).c_str(),
192
+ std::string(DesktopAppearanceModule::kModuleName).c_str());
193
+ std::printf(" %s, %s, %s, %s, %s\n",
194
+ std::string(DesktopClipboardModule::kModuleName).c_str(),
195
+ std::string(DesktopAlertModule::kModuleName).c_str(),
196
+ std::string(DesktopLinkingModule::kModuleName).c_str(),
197
+ std::string(DesktopI18nManagerModule::kModuleName).c_str(),
198
+ std::string(DesktopAccessibilityInfoModule::kModuleName).c_str());
199
+ std::printf(" scriptURLFor %s\n", url.c_str());
200
+ std::printf(" expo runtime %s\n", expo ? "compiled in" : "not compiled in");
201
+ std::printf(" worklets %s\n", worklets ? "compiled in" : "not compiled in");
202
+ std::printf(" font seam isFontRegistered=%d generation=%lu\n",
203
+ registered ? 1 : 0,
204
+ generation);
205
+ std::printf(" colour scheme %s\n", scheme);
206
+ std::printf(" services seam canOpenUrl=%d clipboard=\"%s\"\n",
207
+ basalt::canOpenUrl("https://example.com") ? 1 : 0,
208
+ basalt::clipboardText().c_str());
209
+ return 0;
210
+ }
@@ -0,0 +1,124 @@
1
+ // A place for a unit test to watch events arrive.
2
+ //
3
+ // Neither host suite could see an event. The managers ask
4
+ // `eventEmitterForTag` for an emitter and call `onChange`, `onFocus`,
5
+ // `onKeyPress` on it, and the shadow views the tests hand-build carry no
6
+ // emitter at all -- so `test_appkit_textinput.mm` says, accurately, that what
7
+ // it pins is "that the round trip did not throw". Nothing below the
8
+ // end-to-end suite knew whether an event fired, let alone in what order.
9
+ //
10
+ // ## Why there is no stub emitter here
11
+ //
12
+ // The obvious fix is a fake emitter handed back through the lookup, and it
13
+ // cannot work: `TextInputEventEmitter` contains the word `virtual` zero
14
+ // times, so there is nothing to override. Every `onX` calls the non-virtual
15
+ // `EventEmitter::dispatchEvent`, which locks a `weak_ptr<const
16
+ // EventDispatcher>` and returns quietly when it is empty. That empty weak
17
+ // pointer is exactly the state the suites were in.
18
+ //
19
+ // ## So this builds the real thing instead
20
+ //
21
+ // `EventDispatcher` offers a listener -- `std::function<bool(const RawEvent
22
+ // &)>` -- and consults it at the top of `dispatchEvent`, before the logger and
23
+ // before the queue. Returning true says the event was handled and stops the
24
+ // default dispatch, so nothing downstream ever runs and no beat is needed to
25
+ // flush anything.
26
+ //
27
+ // The one awkward piece is that `EventQueue`'s constructor calls
28
+ // `setBeatCallback` on the beat immediately, so it cannot be null, and
29
+ // `EventBeat` holds a `RuntimeScheduler &`. That sounds like the whole JS
30
+ // machinery and is not: `RuntimeScheduler` takes a `RuntimeExecutor`, which is
31
+ // a `std::function`, and a runtime only appears when something invokes it.
32
+ // Nothing here does.
33
+ //
34
+ // ## What can be asserted, and what cannot
35
+ //
36
+ // Event *types* and their *order*, which is what the payload-free half of an
37
+ // event is. Payload values cannot: `TextInputEventEmitter` builds a
38
+ // `jsi::Object` through a `ValueFactory`, and reading one back needs a
39
+ // `jsi::Runtime` -- which is the machinery these suites exist to avoid. What
40
+ // a value ends up as is the end-to-end suite's to check; that the event fired
41
+ // at all, and before or after its neighbour, is this one's.
42
+
43
+ #pragma once
44
+
45
+ #include <react/renderer/core/EventDispatcher.h>
46
+ #include <react/renderer/core/EventEmitter.h>
47
+ #include <react/renderer/core/EventListener.h>
48
+ #include <react/renderer/core/EventQueueProcessor.h>
49
+ #include <react/renderer/core/RawEvent.h>
50
+ #include <react/renderer/runtimescheduler/RuntimeScheduler.h>
51
+
52
+ #include <functional>
53
+ #include <memory>
54
+ #include <mutex>
55
+ #include <string>
56
+ #include <utility>
57
+ #include <vector>
58
+
59
+ namespace basalt::testing {
60
+
61
+ // An EventBeat that never beats. `EventQueue` requires one and this test never
62
+ // reaches the queue, so what matters is that it exists and does nothing.
63
+ class IdleEventBeat : public facebook::react::EventBeat {
64
+ public:
65
+ IdleEventBeat(std::shared_ptr<OwnerBox> ownerBox,
66
+ facebook::react::RuntimeScheduler &scheduler)
67
+ : EventBeat(std::move(ownerBox), scheduler) {}
68
+
69
+ void request() const override {}
70
+ };
71
+
72
+ class EventRecorder {
73
+ public:
74
+ EventRecorder()
75
+ : scheduler_([](std::function<void(facebook::jsi::Runtime &)> &&) {}),
76
+ dispatcher_(std::make_shared<const facebook::react::EventDispatcher>(
77
+ facebook::react::EventQueueProcessor(nullptr, nullptr, nullptr, {}),
78
+ std::make_unique<IdleEventBeat>(
79
+ std::make_shared<facebook::react::EventBeat::OwnerBox>(), scheduler_),
80
+ [](const facebook::react::StateUpdate &) {},
81
+ std::weak_ptr<facebook::react::EventLogger>{})),
82
+ listener_(std::make_shared<const facebook::react::EventListener>(
83
+ [this](const facebook::react::RawEvent &event) {
84
+ std::scoped_lock lock(mutex_);
85
+ seen_.push_back(event.type);
86
+ // Handled: the event stops here rather than going on to a queue
87
+ // that would need a JavaScript thread to drain it.
88
+ return true;
89
+ })) {
90
+ dispatcher_->addListener(listener_);
91
+ }
92
+
93
+ // An emitter of the kind a manager will look for. The event target is null,
94
+ // which `EventEmitter::dispatchEvent` moves into the `RawEvent` without
95
+ // touching -- a tag is not what is being asserted here.
96
+ // Non-const, because that is what `ShadowView::eventEmitter` is at this
97
+ // React Native. Every `onX` is a const method, so it makes no difference to
98
+ // the caller.
99
+ template <typename Emitter>
100
+ std::shared_ptr<Emitter> emitter() const {
101
+ return std::make_shared<Emitter>(nullptr, dispatcher_);
102
+ }
103
+
104
+ // The event types seen so far, in the order they were dispatched. Names are
105
+ // React Native's own normalised spelling: see `normalizeEventType`.
106
+ std::vector<std::string> seen() const {
107
+ std::scoped_lock lock(mutex_);
108
+ return seen_;
109
+ }
110
+
111
+ void clear() {
112
+ std::scoped_lock lock(mutex_);
113
+ seen_.clear();
114
+ }
115
+
116
+ private:
117
+ facebook::react::RuntimeScheduler scheduler_;
118
+ std::shared_ptr<const facebook::react::EventDispatcher> dispatcher_;
119
+ std::shared_ptr<const facebook::react::EventListener> listener_;
120
+ mutable std::mutex mutex_;
121
+ std::vector<std::string> seen_;
122
+ };
123
+
124
+ } // namespace basalt::testing