@shopify/react-native-skia 2.12.0-next.1 → 2.13.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 (295) hide show
  1. package/LICENSE.md +2 -1
  2. package/Package.swift +117 -0
  3. package/android/CMakeLists.txt +23 -179
  4. package/android/build.gradle +40 -209
  5. package/android/cpp/jni/JniSkiaManager.cpp +3 -45
  6. package/android/cpp/jni/include/JniPlatformContext.h +1 -1
  7. package/android/cpp/jni/include/JniSkiaBaseView.h +18 -11
  8. package/android/cpp/jni/include/JniSkiaManager.h +3 -4
  9. package/android/cpp/jni/include/JniSkiaPictureView.h +5 -5
  10. package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +0 -10
  11. package/android/cpp/rnskia-android/RNSkAndroidView.h +6 -6
  12. package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +4 -4
  13. package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h +2 -2
  14. package/android/src/main/AndroidManifest.xml +1 -1
  15. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/PlatformContext.java +1 -1
  16. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/RNSkVideo.java +1 -1
  17. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/RNSkiaModule.java +1 -8
  18. package/android/src/main/java/com/reactnative/skia/RNSkiaPackage.java +57 -0
  19. package/android/src/main/java/com/reactnative/skia/SkiaBaseView.java +185 -0
  20. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/SkiaBaseViewManager.java +20 -1
  21. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/SkiaManager.java +11 -6
  22. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/SkiaPictureView.java +3 -3
  23. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/SkiaPictureViewManager.java +1 -1
  24. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/SkiaSurfaceView.java +13 -3
  25. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/SkiaTextureView.java +5 -3
  26. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/SkiaViewAPI.java +1 -1
  27. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/ViewScreenshotService.java +10 -13
  28. package/apple/MetalContext.mm +1 -1
  29. package/apple/RNSkApplePlatformContext.h +0 -3
  30. package/apple/RNSkApplePlatformContext.mm +0 -11
  31. package/apple/RNSkiaModule.h +1 -10
  32. package/apple/RNSkiaModule.mm +2 -10
  33. package/apple/SkiaManager.h +0 -2
  34. package/apple/SkiaManager.mm +4 -6
  35. package/apple/SkiaPictureView.h +2 -2
  36. package/apple/SkiaPictureView.mm +0 -4
  37. package/apple/SkiaUIView.h +3 -18
  38. package/apple/SkiaUIView.mm +0 -30
  39. package/cpp/api/CustomBlendModes.h +17 -0
  40. package/cpp/api/JsiSkApi.h +0 -6
  41. package/cpp/api/JsiSkCanvas.h +19 -10
  42. package/cpp/api/JsiSkFont.h +5 -10
  43. package/cpp/api/JsiSkMatrix.h +4 -2
  44. package/cpp/api/JsiSkSVGFactory.h +4 -0
  45. package/cpp/api/recorder/Convertor.h +5 -2
  46. package/cpp/api/recorder/Drawings.h +13 -3
  47. package/cpp/api/recorder/ImageFilters.h +15 -1
  48. package/cpp/api/recorder/Paint.h +8 -1
  49. package/cpp/jsi/JSICache.cpp +99 -0
  50. package/cpp/jsi/JSICache.h +90 -0
  51. package/cpp/jsi/NativeObject.h +38 -87
  52. package/cpp/jsi/ViewProperty.h +0 -28
  53. package/cpp/rnskia/RNDawnContext.h +2 -1
  54. package/cpp/rnskia/RNDawnWindowContext.h +22 -0
  55. package/cpp/rnskia/RNSkManager.cpp +0 -6
  56. package/cpp/rnskia/RNSkPlatformContext.h +0 -3
  57. package/cpp/skia/include/core/RasterContext.h +25 -0
  58. package/cpp/skia/include/core/SkCanvas.h +0 -1
  59. package/cpp/skia/include/core/SkContext.h +62 -0
  60. package/cpp/skia/include/core/SkContextOptions.h +15 -0
  61. package/cpp/skia/include/core/SkMilestone.h +1 -1
  62. package/cpp/skia/include/core/SkPicture.h +36 -18
  63. package/cpp/skia/include/core/SkRecorder.h +8 -0
  64. package/cpp/skia/include/core/SkSerialProcs.h +2 -6
  65. package/cpp/skia/include/effects/SkImageFilters.h +15 -2
  66. package/cpp/skia/include/gpu/ganesh/GrDirectContext.h +73 -47
  67. package/cpp/skia/include/gpu/ganesh/SkSurfaceGanesh.h +7 -4
  68. package/cpp/skia/include/gpu/ganesh/d3d/GrD3DDirectContext.h +12 -0
  69. package/cpp/skia/include/gpu/ganesh/gl/GrGLDirectContext.h +11 -0
  70. package/cpp/skia/include/gpu/ganesh/mtl/GrMtlDirectContext.h +11 -0
  71. package/cpp/skia/include/gpu/ganesh/vk/GrVkDirectContext.h +13 -0
  72. package/cpp/skia/include/gpu/graphite/ContextOptions.h +6 -0
  73. package/cpp/skia/include/gpu/graphite/GraphiteTypes.h +5 -4
  74. package/cpp/skia/include/gpu/graphite/PrecompileContext.h +9 -1
  75. package/cpp/skia/include/gpu/graphite/Recorder.h +0 -2
  76. package/cpp/skia/include/gpu/graphite/Recording.h +3 -0
  77. package/cpp/skia/include/gpu/graphite/dawn/DawnBackendContext.h +8 -0
  78. package/cpp/skia/include/gpu/graphite/mtl/MtlBackendContext.h +11 -0
  79. package/cpp/skia/include/gpu/graphite/vk/VulkanGraphiteContext.h +11 -0
  80. package/cpp/skia/include/private/SkLog.h +1 -19
  81. package/cpp/skia/include/private/chromium/GrVkSecondaryCBDrawContext.h +2 -1
  82. package/cpp/skia/include/utils/SkLogHandler.h +53 -0
  83. package/cpp/skia/include/utils/SkNWayCanvas.h +1 -0
  84. package/cpp/skia/modules/skcms/src/Transform_inl.h +9 -10
  85. package/cpp/skia/modules/skcms/src/skcms_internals.h +8 -3
  86. package/cpp/skia/modules/skottie/include/SkottieProperty.h +2 -0
  87. package/cpp/skia/modules/skottie/include/TextShaper.h +1 -0
  88. package/cpp/skia/modules/skshaper/include/SkShaper.h +23 -1
  89. package/include/ReactNativeSkia.h +6 -0
  90. package/lib/commonjs/dom/nodes/datatypes/Rect.js +5 -1
  91. package/lib/commonjs/dom/nodes/datatypes/Rect.js.map +1 -1
  92. package/lib/commonjs/external/reanimated/useVideo.js +8 -2
  93. package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
  94. package/lib/commonjs/mock/index.js +0 -1
  95. package/lib/commonjs/mock/index.js.map +1 -1
  96. package/lib/commonjs/renderer/Canvas.d.ts +11 -3
  97. package/lib/commonjs/renderer/Canvas.js +8 -6
  98. package/lib/commonjs/renderer/Canvas.js.map +1 -1
  99. package/lib/commonjs/renderer/components/Mask.js +3 -9
  100. package/lib/commonjs/renderer/components/Mask.js.map +1 -1
  101. package/lib/commonjs/skia/types/JsiInstance.d.ts +1 -0
  102. package/lib/commonjs/skia/types/JsiInstance.js.map +1 -1
  103. package/lib/commonjs/skia/types/Matrix4.js +7 -2
  104. package/lib/commonjs/skia/types/Matrix4.js.map +1 -1
  105. package/lib/commonjs/skia/types/Skia.d.ts +1 -6
  106. package/lib/commonjs/skia/types/Skia.js.map +1 -1
  107. package/lib/commonjs/skia/web/JsiSkCanvas.js +12 -7
  108. package/lib/commonjs/skia/web/JsiSkCanvas.js.map +1 -1
  109. package/lib/commonjs/skia/web/JsiSkImage.js +6 -3
  110. package/lib/commonjs/skia/web/JsiSkImage.js.map +1 -1
  111. package/lib/commonjs/skia/web/JsiSkPathBuilder.d.ts +1 -1
  112. package/lib/commonjs/skia/web/JsiSkPathBuilder.js +2 -2
  113. package/lib/commonjs/skia/web/JsiSkPathBuilder.js.map +1 -1
  114. package/lib/commonjs/skia/web/JsiSkTextStyle.js +5 -5
  115. package/lib/commonjs/skia/web/JsiSkTextStyle.js.map +1 -1
  116. package/lib/commonjs/skia/web/JsiSkia.js +0 -3
  117. package/lib/commonjs/skia/web/JsiSkia.js.map +1 -1
  118. package/lib/commonjs/skia/web/JsiSkottieAnimation.js +8 -8
  119. package/lib/commonjs/skia/web/JsiSkottieAnimation.js.map +1 -1
  120. package/lib/commonjs/sksg/Recorder/DrawingContext.d.ts +1 -0
  121. package/lib/commonjs/sksg/Recorder/DrawingContext.js +15 -0
  122. package/lib/commonjs/sksg/Recorder/DrawingContext.js.map +1 -1
  123. package/lib/commonjs/sksg/Recorder/Player.js +1 -1
  124. package/lib/commonjs/sksg/Recorder/Player.js.map +1 -1
  125. package/lib/commonjs/sksg/Recorder/Visitor.js +6 -1
  126. package/lib/commonjs/sksg/Recorder/Visitor.js.map +1 -1
  127. package/lib/commonjs/sksg/Recorder/commands/Drawing.js +12 -9
  128. package/lib/commonjs/sksg/Recorder/commands/Drawing.js.map +1 -1
  129. package/lib/commonjs/sksg/Recorder/commands/ImageFilters.js +15 -1
  130. package/lib/commonjs/sksg/Recorder/commands/ImageFilters.js.map +1 -1
  131. package/lib/commonjs/sksg/Recorder/commands/Shaders.js +1 -1
  132. package/lib/commonjs/sksg/Recorder/commands/Shaders.js.map +1 -1
  133. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.d.ts +2 -0
  134. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.js.map +1 -1
  135. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.web.d.ts +3 -1
  136. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.web.js +3 -0
  137. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.web.js.map +1 -1
  138. package/lib/commonjs/views/SkiaPictureView.js +2 -12
  139. package/lib/commonjs/views/SkiaPictureView.js.map +1 -1
  140. package/lib/commonjs/views/SkiaPictureView.web.js +247 -57
  141. package/lib/commonjs/views/SkiaPictureView.web.js.map +1 -1
  142. package/lib/commonjs/views/types.d.ts +19 -8
  143. package/lib/commonjs/views/types.js.map +1 -1
  144. package/lib/module/dom/nodes/datatypes/Rect.js +5 -1
  145. package/lib/module/dom/nodes/datatypes/Rect.js.map +1 -1
  146. package/lib/module/external/reanimated/useVideo.js +8 -2
  147. package/lib/module/external/reanimated/useVideo.js.map +1 -1
  148. package/lib/module/mock/index.js +0 -1
  149. package/lib/module/mock/index.js.map +1 -1
  150. package/lib/module/renderer/Canvas.d.ts +11 -3
  151. package/lib/module/renderer/Canvas.js +7 -5
  152. package/lib/module/renderer/Canvas.js.map +1 -1
  153. package/lib/module/renderer/components/Mask.js +3 -9
  154. package/lib/module/renderer/components/Mask.js.map +1 -1
  155. package/lib/module/skia/types/JsiInstance.d.ts +1 -0
  156. package/lib/module/skia/types/JsiInstance.js.map +1 -1
  157. package/lib/module/skia/types/Matrix4.js +7 -2
  158. package/lib/module/skia/types/Matrix4.js.map +1 -1
  159. package/lib/module/skia/types/Skia.d.ts +1 -6
  160. package/lib/module/skia/types/Skia.js.map +1 -1
  161. package/lib/module/skia/web/JsiSkCanvas.js +12 -7
  162. package/lib/module/skia/web/JsiSkCanvas.js.map +1 -1
  163. package/lib/module/skia/web/JsiSkImage.js +6 -3
  164. package/lib/module/skia/web/JsiSkImage.js.map +1 -1
  165. package/lib/module/skia/web/JsiSkPathBuilder.d.ts +1 -1
  166. package/lib/module/skia/web/JsiSkPathBuilder.js +2 -2
  167. package/lib/module/skia/web/JsiSkPathBuilder.js.map +1 -1
  168. package/lib/module/skia/web/JsiSkTextStyle.js +5 -5
  169. package/lib/module/skia/web/JsiSkTextStyle.js.map +1 -1
  170. package/lib/module/skia/web/JsiSkia.js +0 -3
  171. package/lib/module/skia/web/JsiSkia.js.map +1 -1
  172. package/lib/module/skia/web/JsiSkottieAnimation.js +8 -8
  173. package/lib/module/skia/web/JsiSkottieAnimation.js.map +1 -1
  174. package/lib/module/sksg/Recorder/DrawingContext.d.ts +1 -0
  175. package/lib/module/sksg/Recorder/DrawingContext.js +15 -0
  176. package/lib/module/sksg/Recorder/DrawingContext.js.map +1 -1
  177. package/lib/module/sksg/Recorder/Player.js +1 -1
  178. package/lib/module/sksg/Recorder/Player.js.map +1 -1
  179. package/lib/module/sksg/Recorder/Visitor.js +6 -1
  180. package/lib/module/sksg/Recorder/Visitor.js.map +1 -1
  181. package/lib/module/sksg/Recorder/commands/Drawing.js +12 -9
  182. package/lib/module/sksg/Recorder/commands/Drawing.js.map +1 -1
  183. package/lib/module/sksg/Recorder/commands/ImageFilters.js +15 -1
  184. package/lib/module/sksg/Recorder/commands/ImageFilters.js.map +1 -1
  185. package/lib/module/sksg/Recorder/commands/Shaders.js +1 -1
  186. package/lib/module/sksg/Recorder/commands/Shaders.js.map +1 -1
  187. package/lib/module/specs/SkiaPictureViewNativeComponent.d.ts +2 -0
  188. package/lib/module/specs/SkiaPictureViewNativeComponent.js.map +1 -1
  189. package/lib/module/specs/SkiaPictureViewNativeComponent.web.d.ts +3 -1
  190. package/lib/module/specs/SkiaPictureViewNativeComponent.web.js +3 -0
  191. package/lib/module/specs/SkiaPictureViewNativeComponent.web.js.map +1 -1
  192. package/lib/module/views/SkiaPictureView.js +2 -12
  193. package/lib/module/views/SkiaPictureView.js.map +1 -1
  194. package/lib/module/views/SkiaPictureView.web.js +247 -57
  195. package/lib/module/views/SkiaPictureView.web.js.map +1 -1
  196. package/lib/module/views/types.d.ts +19 -8
  197. package/lib/module/views/types.js.map +1 -1
  198. package/lib/typescript/lib/commonjs/mock/index.d.ts +0 -1
  199. package/lib/typescript/lib/commonjs/renderer/Canvas.d.ts +2 -2
  200. package/lib/typescript/lib/commonjs/skia/web/JsiSkPathBuilder.d.ts +1 -1
  201. package/lib/typescript/lib/commonjs/skia/web/JsiSkia.d.ts +0 -1
  202. package/lib/typescript/lib/commonjs/sksg/Recorder/DrawingContext.d.ts +1 -0
  203. package/lib/typescript/lib/commonjs/specs/SkiaPictureViewNativeComponent.web.d.ts +3 -1
  204. package/lib/typescript/lib/module/mock/index.d.ts +0 -1
  205. package/lib/typescript/lib/module/renderer/Canvas.d.ts +2 -2
  206. package/lib/typescript/lib/module/skia/Skia.web.d.ts +0 -1
  207. package/lib/typescript/lib/module/skia/web/JsiSkPathBuilder.d.ts +1 -1
  208. package/lib/typescript/lib/module/skia/web/JsiSkia.d.ts +0 -1
  209. package/lib/typescript/lib/module/sksg/Recorder/DrawingContext.d.ts +1 -0
  210. package/lib/typescript/lib/module/specs/SkiaPictureViewNativeComponent.web.d.ts +3 -1
  211. package/lib/typescript/react-native.config.d.ts +3 -0
  212. package/lib/typescript/src/renderer/Canvas.d.ts +11 -3
  213. package/lib/typescript/src/skia/types/JsiInstance.d.ts +1 -0
  214. package/lib/typescript/src/skia/types/Skia.d.ts +1 -6
  215. package/lib/typescript/src/skia/web/JsiSkPathBuilder.d.ts +1 -1
  216. package/lib/typescript/src/sksg/Recorder/DrawingContext.d.ts +1 -0
  217. package/lib/typescript/src/specs/SkiaPictureViewNativeComponent.d.ts +2 -0
  218. package/lib/typescript/src/specs/SkiaPictureViewNativeComponent.web.d.ts +3 -1
  219. package/lib/typescript/src/views/types.d.ts +19 -8
  220. package/package.json +15 -12
  221. package/react-native-skia.podspec +4 -10
  222. package/react-native.config.js +5 -0
  223. package/src/dom/nodes/datatypes/Rect.ts +6 -1
  224. package/src/external/reanimated/useVideo.ts +7 -2
  225. package/src/mock/index.ts +0 -1
  226. package/src/renderer/Canvas.tsx +23 -5
  227. package/src/renderer/components/Mask.tsx +10 -3
  228. package/src/skia/types/JsiInstance.ts +2 -0
  229. package/src/skia/types/Matrix4.ts +6 -2
  230. package/src/skia/types/Skia.ts +1 -7
  231. package/src/skia/web/JsiSkCanvas.ts +22 -12
  232. package/src/skia/web/JsiSkImage.ts +6 -3
  233. package/src/skia/web/JsiSkPathBuilder.ts +2 -2
  234. package/src/skia/web/JsiSkTextStyle.ts +20 -15
  235. package/src/skia/web/JsiSkia.ts +0 -4
  236. package/src/skia/web/JsiSkottieAnimation.ts +8 -8
  237. package/src/sksg/Recorder/DrawingContext.ts +15 -0
  238. package/src/sksg/Recorder/Player.ts +1 -1
  239. package/src/sksg/Recorder/Visitor.ts +9 -6
  240. package/src/sksg/Recorder/commands/Drawing.ts +12 -9
  241. package/src/sksg/Recorder/commands/ImageFilters.ts +20 -1
  242. package/src/sksg/Recorder/commands/Shaders.ts +1 -1
  243. package/src/specs/SkiaPictureViewNativeComponent.ts +5 -0
  244. package/src/specs/SkiaPictureViewNativeComponent.web.ts +5 -0
  245. package/src/views/SkiaPictureView.tsx +2 -10
  246. package/src/views/SkiaPictureView.web.tsx +245 -57
  247. package/src/views/types.ts +23 -10
  248. package/android/src/latest/java/com/shopify/reactnative/skia/ReactNativeCompatible.java +0 -11
  249. package/android/src/main/java/com/shopify/reactnative/skia/RNSkiaPackage.java +0 -79
  250. package/android/src/main/java/com/shopify/reactnative/skia/SkiaAHBView.java +0 -113
  251. package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +0 -136
  252. package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaPictureViewManagerDelegate.java +0 -41
  253. package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaPictureViewManagerInterface.java +0 -20
  254. package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaWebGPUViewManagerDelegate.java +0 -35
  255. package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaWebGPUViewManagerInterface.java +0 -17
  256. package/android/src/paper/java/com/shopify/reactnative/skia/NativeSkiaModuleSpec.java +0 -38
  257. package/android/src/reactnative74/java/com/shopify/reactnative/skia/ReactNativeCompatible.java +0 -14
  258. package/apple/SkiaPictureViewManager.h +0 -8
  259. package/apple/SkiaPictureViewManager.mm +0 -60
  260. package/apple/SkiaWebGPUView.h +0 -20
  261. package/apple/WebGPUMetalView.h +0 -12
  262. package/cpp/api/JsiSkiaContext.h +0 -94
  263. package/cpp/dawn/include/dawn/dawn_proc.h +0 -53
  264. package/cpp/dawn/include/dawn/dawn_proc_table.h +0 -330
  265. package/cpp/dawn/include/dawn/dawn_thread_dispatch_proc.h +0 -47
  266. package/cpp/dawn/include/dawn/dawn_version.h +0 -41
  267. package/cpp/dawn/include/dawn/native/D3D11Backend.h +0 -65
  268. package/cpp/dawn/include/dawn/native/D3D12Backend.h +0 -103
  269. package/cpp/dawn/include/dawn/native/D3DBackend.h +0 -56
  270. package/cpp/dawn/include/dawn/native/DawnNative.h +0 -368
  271. package/cpp/dawn/include/dawn/native/MetalBackend.h +0 -56
  272. package/cpp/dawn/include/dawn/native/NullBackend.h +0 -39
  273. package/cpp/dawn/include/dawn/native/OpenGLBackend.h +0 -89
  274. package/cpp/dawn/include/dawn/native/VulkanBackend.h +0 -183
  275. package/cpp/dawn/include/dawn/native/WebGPUBackend.h +0 -49
  276. package/cpp/dawn/include/dawn/native/dawn_native_export.h +0 -49
  277. package/cpp/dawn/include/dawn/platform/DawnPlatform.h +0 -207
  278. package/cpp/dawn/include/dawn/platform/dawn_platform_export.h +0 -49
  279. package/cpp/dawn/include/dawn/replay/Replay.h +0 -99
  280. package/cpp/dawn/include/dawn/replay/dawn_replay_export.h +0 -49
  281. package/cpp/dawn/include/dawn/webgpu_cpp_print.h +0 -2856
  282. package/cpp/dawn/include/tint/tint.h +0 -91
  283. package/cpp/dawn/include/webgpu/webgpu.h +0 -5029
  284. package/cpp/dawn/include/webgpu/webgpu_cpp.h +0 -10353
  285. package/cpp/dawn/include/webgpu/webgpu_cpp_chained_struct.h +0 -57
  286. package/cpp/dawn/include/webgpu/webgpu_enum_class_bitmasks.h +0 -162
  287. package/cpp/dawn/include/webgpu/webgpu_glfw.h +0 -88
  288. package/cpp/jsi/RuntimeAwareCache.cpp +0 -7
  289. package/cpp/jsi/RuntimeAwareCache.h +0 -117
  290. package/cpp/jsi/RuntimeLifecycleMonitor.cpp +0 -72
  291. package/cpp/jsi/RuntimeLifecycleMonitor.h +0 -32
  292. package/cpp/skia/src/gpu/graphite/ContextOptionsPriv.h +0 -45
  293. package/cpp/skia/src/gpu/graphite/ResourceTypes.h +0 -360
  294. package/cpp/skia/src/gpu/graphite/TextureProxyView.h +0 -105
  295. package/libs/.graphite +0 -1
@@ -10,29 +10,14 @@
10
10
  #import <React/RCTUIKit.h>
11
11
  #endif // !TARGET_OS_OSX
12
12
 
13
+ #import <React/RCTViewComponentView.h>
14
+
13
15
  #import "RNSkAppleView.h"
14
16
  #import "RNSkManager.h"
15
17
  #import "SkiaManager.h"
16
18
 
17
- #if RCT_NEW_ARCH_ENABLED
18
- #import <React/RCTViewComponentView.h>
19
- #endif // RCT_NEW_ARCH_ENABLED
20
-
21
- @interface SkiaUIView :
22
- #if RCT_NEW_ARCH_ENABLED
23
- RCTViewComponentView
24
- #else
25
- #if !TARGET_OS_OSX
26
- UIView
27
- #else
28
- RCTUIView
29
- #endif // !TARGET_OS_OSX
30
- #endif // RCT_NEW_ARCH_ENABLED
19
+ @interface SkiaUIView : RCTViewComponentView
31
20
 
32
- - (instancetype)
33
- initWithManager:(RNSkia::RNSkManager *)manager
34
- factory:(std::function<std::shared_ptr<RNSkBaseAppleView>(
35
- std::shared_ptr<RNSkia::RNSkPlatformContext>)>)factory;
36
21
  - (void)initCommon:(RNSkia::RNSkManager *)manager
37
22
  factory:(std::function<std::shared_ptr<RNSkBaseAppleView>(
38
23
  std::shared_ptr<RNSkia::RNSkPlatformContext>)>)factory;
@@ -1,5 +1,4 @@
1
1
  #import <QuartzCore/CATransaction.h>
2
- #import <React/RCTBridge.h>
3
2
 
4
3
  #import "RNSkiaModule.h"
5
4
  #import "SkiaUIView.h"
@@ -24,24 +23,6 @@
24
23
 
25
24
  #pragma mark Initialization and destruction
26
25
 
27
- - (instancetype)initWithManager:(RNSkia::RNSkManager *)manager
28
- factory:
29
- (std::function<std::shared_ptr<RNSkBaseAppleView>(
30
- std::shared_ptr<RNSkia::RNSkPlatformContext>)>)
31
- factory {
32
- self = [super init];
33
- if (self) {
34
- [self initCommon:manager factory:factory];
35
- }
36
- // Listen to notifications about module invalidation
37
- [[NSNotificationCenter defaultCenter]
38
- addObserver:self
39
- selector:@selector(willInvalidateModules)
40
- name:RCTBridgeWillInvalidateModulesNotification
41
- object:nil];
42
- return self;
43
- }
44
-
45
26
  - (void)initCommon:(RNSkia::RNSkManager *)manager
46
27
  factory:(std::function<std::shared_ptr<RNSkBaseAppleView>(
47
28
  std::shared_ptr<RNSkia::RNSkPlatformContext>)>)factory {
@@ -51,11 +32,6 @@
51
32
  _factory = factory;
52
33
  }
53
34
 
54
- - (void)willInvalidateModules {
55
- _impl = nullptr;
56
- _manager = nullptr;
57
- }
58
-
59
35
  #pragma mark Lifecycle
60
36
 
61
37
  #if !TARGET_OS_OSX
@@ -99,13 +75,8 @@
99
75
 
100
76
  - (void)dealloc {
101
77
  [self unregisterView];
102
- [[NSNotificationCenter defaultCenter]
103
- removeObserver:self
104
- name:RCTBridgeWillInvalidateModulesNotification
105
- object:nil];
106
78
  }
107
79
 
108
- #ifdef RCT_NEW_ARCH_ENABLED
109
80
  - (void)prepareForRecycle {
110
81
  [super prepareForRecycle];
111
82
  [self unregisterView];
@@ -120,7 +91,6 @@
120
91
  _manager = [SkiaManager latestActiveSkManager].get();
121
92
  }
122
93
  }
123
- #endif // RCT_NEW_ARCH_ENABLED
124
94
 
125
95
  - (void)unregisterView {
126
96
  if (_manager != nullptr && _nativeId != 0) {
@@ -1,5 +1,8 @@
1
1
  #pragma once
2
2
 
3
+ #include <stdexcept>
4
+ #include <string>
5
+
3
6
  #include "include/core/SkBlender.h"
4
7
  #include "include/core/SkPaint.h"
5
8
  #include "include/core/SkString.h"
@@ -94,4 +97,18 @@ inline void applyBlendMode(SkPaint &paint, int blendModeValue) {
94
97
  }
95
98
  }
96
99
 
100
+ // Converts a JS blend mode value to an SkBlendMode for the Skia entry points
101
+ // that take a plain SkBlendMode rather than a paint (drawPatch, drawVertices,
102
+ // drawAtlas, drawColor). The custom blend modes above are implemented as
103
+ // blenders on an SkPaint and have no SkBlendMode equivalent, so they - and any
104
+ // other out of range value - are rejected instead of being cast blindly.
105
+ inline SkBlendMode toBlendMode(double blendModeValue) {
106
+ auto value = static_cast<int>(blendModeValue);
107
+ if (value < 0 || value > static_cast<int>(SkBlendMode::kLastMode)) {
108
+ throw std::invalid_argument("Unsupported blend mode: " +
109
+ std::to_string(value));
110
+ }
111
+ return static_cast<SkBlendMode>(value);
112
+ }
113
+
97
114
  } // namespace RNSkia
@@ -56,7 +56,6 @@
56
56
  #include "JsiSkTypefaceFactory.h"
57
57
  #include "JsiSkTypefaceFontProviderFactory.h"
58
58
  #include "JsiSkVertices.h"
59
- #include "JsiSkiaContext.h"
60
59
  #include "JsiSkottieFactory.h"
61
60
  #include "JsiVideo.h"
62
61
  #include "api/recorder/JsiRecorder.h"
@@ -116,10 +115,6 @@ public:
116
115
  return JsiVideo::createCtor(getContext())(runtime, thisValue, arguments,
117
116
  count);
118
117
  }
119
- JSI_HOST_FUNCTION(Context) {
120
- return JsiSkiaContext::createCtor(getContext())(runtime, thisValue,
121
- arguments, count);
122
- }
123
118
  JSI_HOST_FUNCTION(Font) {
124
119
  return JsiSkFont::createCtor(getContext())(runtime, thisValue, arguments,
125
120
  count);
@@ -256,7 +251,6 @@ public:
256
251
 
257
252
  static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
258
253
  installHostMethod(runtime, prototype, "Video", &JsiSkApi::Video);
259
- installHostMethod(runtime, prototype, "Context", &JsiSkApi::Context);
260
254
  installHostMethod(runtime, prototype, "getNativeDevice",
261
255
  &JsiSkApi::getNativeDevice);
262
256
  installHostMethod(runtime, prototype, "Font", &JsiSkApi::Font);
@@ -5,6 +5,7 @@
5
5
  #include <utility>
6
6
  #include <vector>
7
7
 
8
+ #include "CustomBlendModes.h"
8
9
  #include "JsiSkConverters.h"
9
10
  #include "JsiSkFont.h"
10
11
  #include "JsiSkImage.h"
@@ -226,8 +227,7 @@ public:
226
227
 
227
228
  void drawVertices(sk_sp<SkVertices> vertices, double blendMode,
228
229
  std::shared_ptr<SkPaint> paint) {
229
- _canvas->drawVertices(vertices, static_cast<SkBlendMode>(blendMode),
230
- *paint);
230
+ _canvas->drawVertices(vertices, toBlendMode(blendMode), *paint);
231
231
  }
232
232
 
233
233
  JSI_HOST_FUNCTION(drawPatch) {
@@ -287,11 +287,19 @@ public:
287
287
  }
288
288
  }
289
289
 
290
- auto paint =
291
- count >= 4 ? JsiSkPaint::fromValue(runtime, arguments[4]) : nullptr;
292
- auto blendMode = static_cast<SkBlendMode>(arguments[3].asNumber());
290
+ auto blendMode =
291
+ count >= 4 && !arguments[3].isNull() && !arguments[3].isUndefined()
292
+ ? toBlendMode(arguments[3].asNumber())
293
+ : SkBlendMode::kModulate;
294
+
295
+ std::shared_ptr<SkPaint> paint;
296
+ if (count >= 5 && !arguments[4].isNull() && !arguments[4].isUndefined()) {
297
+ paint = JsiSkPaint::fromValue(runtime, arguments[4]);
298
+ }
299
+ SkPaint defaultPaint;
293
300
  _canvas->drawPatch(cubics.data(), colors.empty() ? nullptr : colors.data(),
294
- texs.empty() ? nullptr : texs.data(), blendMode, *paint);
301
+ texs.empty() ? nullptr : texs.data(), blendMode,
302
+ paint ? *paint : defaultPaint);
295
303
  return jsi::Value::undefined();
296
304
  }
297
305
 
@@ -392,7 +400,7 @@ public:
392
400
 
393
401
  void drawColor(JsiColor cl, JsiOptional<double> mode) {
394
402
  if (mode.has_value()) {
395
- _canvas->drawColor(cl, static_cast<SkBlendMode>(*mode));
403
+ _canvas->drawColor(cl, toBlendMode(*mode));
396
404
  } else {
397
405
  _canvas->drawColor(cl);
398
406
  }
@@ -411,9 +419,10 @@ public:
411
419
  auto rects = arguments[1].asObject(runtime).asArray(runtime);
412
420
  auto transforms = arguments[2].asObject(runtime).asArray(runtime);
413
421
  auto paint = JsiSkPaint::fromValue(runtime, arguments[3]);
414
- auto blendMode = count > 5 && !arguments[4].isUndefined()
415
- ? static_cast<SkBlendMode>(arguments[4].asNumber())
416
- : SkBlendMode::kDstOver;
422
+ auto blendMode =
423
+ count > 4 && !arguments[4].isNull() && !arguments[4].isUndefined()
424
+ ? toBlendMode(arguments[4].asNumber())
425
+ : SkBlendMode::kDstOver;
417
426
 
418
427
  std::vector<SkRSXform> xforms;
419
428
  int xformsSize = static_cast<int>(transforms.size(runtime));
@@ -135,8 +135,9 @@ public:
135
135
  bool isEmbolden() { return getObject()->isEmbolden(); }
136
136
 
137
137
  std::shared_ptr<JsiSkTypeface> getTypeface() {
138
- return std::make_shared<JsiSkTypeface>(
139
- getContext(), sk_sp<SkTypeface>(getObject()->getTypeface()));
138
+ // refTypeface(), not getTypeface(): the wrapper owns what it is handed.
139
+ return std::make_shared<JsiSkTypeface>(getContext(),
140
+ getObject()->refTypeface());
140
141
  }
141
142
 
142
143
  void setEdging(double edging) {
@@ -161,15 +162,9 @@ public:
161
162
 
162
163
  void setSize(double size) { getObject()->setSize(size); }
163
164
 
164
- // The JS API declares booleans here, but the previous implementation read
165
- // the arguments with asNumber() — keep accepting numbers.
166
- void setEmbolden(double embolden) {
167
- getObject()->setEmbolden(static_cast<bool>(embolden));
168
- }
165
+ void setEmbolden(bool embolden) { getObject()->setEmbolden(embolden); }
169
166
 
170
- void setSubpixel(double subpixel) {
171
- getObject()->setSubpixel(static_cast<bool>(subpixel));
172
- }
167
+ void setSubpixel(bool subpixel) { getObject()->setSubpixel(subpixel); }
173
168
 
174
169
  void setTypeface(std::variant<std::nullptr_t, sk_sp<SkTypeface>> typeface) {
175
170
  getObject()->setTypeface(
@@ -69,12 +69,14 @@ public:
69
69
 
70
70
  void postTranslate(double x, double y) { getObject()->postTranslate(x, y); }
71
71
 
72
+ // A missing y means a uniform scale, matching the CanvasKit backend and the
73
+ // SkMatrix type, where y is optional rather than defaulted to 1.
72
74
  void scale(double x, JsiOptional<double> y) {
73
- getObject()->preScale(x, y.has_value() ? *y : 1);
75
+ getObject()->preScale(x, y.has_value() ? *y : x);
74
76
  }
75
77
 
76
78
  void postScale(double x, JsiOptional<double> y) {
77
- getObject()->postScale(x, y.has_value() ? *y : 1);
79
+ getObject()->postScale(x, y.has_value() ? *y : x);
78
80
  }
79
81
 
80
82
  void skew(double x, double y) { getObject()->preSkew(x, y); }
@@ -116,6 +116,10 @@ private:
116
116
  builder.setResourceProvider(provider);
117
117
 
118
118
  auto svg_dom = builder.make(*stream);
119
+ if (!svg_dom) {
120
+ return jsi::Value::null();
121
+ }
122
+
119
123
  return makeJsiObject(
120
124
  runtime, std::make_shared<JsiSkSVG>(getContext(), std::move(svg_dom)));
121
125
  }
@@ -361,13 +361,16 @@ SkM44 getPropertyValue(jsi::Runtime &runtime, const jsi::Value &value) {
361
361
  m4.preScale(1, s);
362
362
  } else if (key == "skewX") {
363
363
  auto angle = value.getProperty(runtime, key.c_str()).asNumber();
364
- SkM44 skewX(1, 0, 0, 0, std::tan(angle), 1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
364
+ // The SkM44 constructor takes its arguments in row-major reading
365
+ // order, so the shear factor of a horizontal skew belongs in row 0,
366
+ // where it scales y into x.
367
+ SkM44 skewX(1, std::tan(angle), 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
365
368
  1);
366
369
  m4.preConcat(skewX);
367
370
 
368
371
  } else if (key == "skewY") {
369
372
  auto angle = value.getProperty(runtime, key.c_str()).asNumber();
370
- SkM44 skewY(1, std::tan(angle), 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
373
+ SkM44 skewY(1, 0, 0, 0, std::tan(angle), 1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
371
374
  1);
372
375
  m4.preConcat(skewY);
373
376
  } else if (key == "rotate" || key == "rotateZ") {
@@ -149,6 +149,9 @@ public:
149
149
  if (hasStrokeOptions) {
150
150
  const auto &stroke = props.stroke.value();
151
151
  SkPaint strokePaint;
152
+ // A default SkPaint is fill-style, and FillPathWithPaint only
153
+ // outlines a paint that strokes.
154
+ strokePaint.setStyle(SkPaint::kStroke_Style);
152
155
 
153
156
  if (stroke.cap.has_value()) {
154
157
  strokePaint.setStrokeCap(stroke.cap.value());
@@ -166,11 +169,18 @@ public:
166
169
  strokePaint.setStrokeMiter(stroke.miter_limit.value());
167
170
  }
168
171
 
172
+ float precision = stroke.precision.value_or(1.0f);
173
+
169
174
  SkPathBuilder resultBuilder;
170
- if (!skpathutils::FillPathWithPaint(*p, strokePaint, &resultBuilder)) {
171
- throw std::runtime_error("Failed to apply stroke to path");
175
+ auto ctm = SkMatrix::Scale(precision, precision);
176
+ if (skpathutils::FillPathWithPaint(*p, strokePaint, &resultBuilder,
177
+ nullptr, ctm)) {
178
+ pathToUse = std::make_shared<const SkPath>(resultBuilder.snapshot());
179
+ } else {
180
+ // The JS player keeps the unstroked path when Path.Stroke returns
181
+ // null (e.g. a hairline width of 0).
182
+ pathToUse = std::const_pointer_cast<const SkPath>(p);
172
183
  }
173
- pathToUse = std::make_shared<const SkPath>(resultBuilder.snapshot());
174
184
  } else {
175
185
  pathToUse = std::const_pointer_cast<const SkPath>(p);
176
186
  }
@@ -135,8 +135,22 @@ private:
135
135
  auto sourceAlpha = SkImageFilters::ColorFilter(
136
136
  SkColorFilters::Blend(SK_ColorBLACK, SkBlendMode::kSrcIn), nullptr);
137
137
 
138
+ // The shadow is generated outside the shape and then clipped back into it,
139
+ // so "outside" has to be the complement of the shape's silhouette. Taking
140
+ // SrcOut against the source graphic itself makes it the complement of the
141
+ // source's *alpha*: inside a translucent shape 1 - alpha is non-zero, so
142
+ // the shadow is generated across the whole interior and tints it, no matter
143
+ // how small the blur and the offset are (issue #2990). Saturating alpha
144
+ // first keeps the shadow tied to the shape's outline instead of to its
145
+ // opacity. 255 is the saturation point of an 8-bit alpha channel, so one
146
+ // unit of coverage is enough to reach 1.
147
+ static constexpr float kAlphaSaturate[20] = {
148
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0};
149
+ auto coverage = SkImageFilters::ColorFilter(
150
+ SkColorFilters::Matrix(kAlphaSaturate), nullptr);
151
+
138
152
  auto f1 = SkImageFilters::ColorFilter(
139
- SkColorFilters::Blend(color, SkBlendMode::kSrcOut), nullptr);
153
+ SkColorFilters::Blend(color, SkBlendMode::kSrcOut), coverage);
140
154
 
141
155
  auto f2 = SkImageFilters::Offset(dx, dy, f1);
142
156
  auto f3 = SkImageFilters::Blur(sigmaX, sigmaY, SkTileMode::kDecal, f2);
@@ -154,8 +154,15 @@ public:
154
154
  }
155
155
  ctx->savePaint();
156
156
  if (standalone) {
157
+ // Reset the paint that savePaint() just pushed instead of pushing a
158
+ // second one: the matching RestorePaintDeclaration pops a single frame,
159
+ // so an extra push would leave the enclosing group's opacity on the
160
+ // stack and leak it onto every sibling drawn afterwards. The fresh
161
+ // paint is anti-aliased to match the TS player, which resets with
162
+ // Skia.Paint().
157
163
  SkPaint freshPaint;
158
- ctx->pushPaint(freshPaint);
164
+ freshPaint.setAntiAlias(true);
165
+ ctx->getPaint() = freshPaint;
159
166
  }
160
167
  auto &paint = ctx->getPaint();
161
168
  if (props.opacity.has_value()) {
@@ -0,0 +1,99 @@
1
+ #include "JSICache.h"
2
+
3
+ #include <iterator>
4
+ #include <memory>
5
+ #include <stdexcept>
6
+ #include <string>
7
+ #include <unordered_map>
8
+ #include <utility>
9
+
10
+ namespace RNJsi {
11
+
12
+ namespace {
13
+ // Hidden global holding the per-runtime cache object. Named so it is
14
+ // obviously ours if it ever shows up in a debugger or heap snapshot.
15
+ constexpr const char *kGlobalName = "__rnskiaJsiCache";
16
+ } // namespace
17
+
18
+ std::mutex JSICache::_registryMutex;
19
+ std::unordered_map<jsi::Runtime *, std::weak_ptr<JSICache>> JSICache::_registry;
20
+
21
+ JSICache &JSICache::get(jsi::Runtime &runtime) {
22
+ {
23
+ std::lock_guard<std::mutex> lock(_registryMutex);
24
+ auto it = _registry.find(&runtime);
25
+ if (it != _registry.end()) {
26
+ if (auto cache = it->second.lock()) {
27
+ // The cache is kept alive by `runtime`'s global, so the raw
28
+ // reference stays valid for as long as the caller may legally use
29
+ // `runtime` on this thread.
30
+ return *cache;
31
+ }
32
+ // Expired: the runtime that owned this entry is gone and `&runtime` is
33
+ // a new runtime reusing the address. Fall through and recreate.
34
+ }
35
+ }
36
+ auto cache = getOrCreateOnGlobal(runtime);
37
+ {
38
+ std::lock_guard<std::mutex> lock(_registryMutex);
39
+ // Drop entries of runtimes that are gone so the map does not grow by one
40
+ // stale pointer per reload / worklet runtime.
41
+ for (auto it = _registry.begin(); it != _registry.end();) {
42
+ it = it->second.expired() ? _registry.erase(it) : std::next(it);
43
+ }
44
+ _registry[&runtime] = cache;
45
+ }
46
+ return *cache;
47
+ }
48
+
49
+ std::shared_ptr<JSICache> JSICache::getOrCreateOnGlobal(jsi::Runtime &runtime) {
50
+ auto global = runtime.global();
51
+ auto existing = global.getProperty(runtime, kGlobalName);
52
+ if (existing.isObject()) {
53
+ auto obj = existing.getObject(runtime);
54
+ if (obj.hasNativeState<JSICache>(runtime)) {
55
+ return obj.getNativeState<JSICache>(runtime);
56
+ }
57
+ }
58
+ if (!existing.isUndefined()) {
59
+ // Something else already claimed our global. The most likely cause is two
60
+ // copies of react-native-skia loaded in one process (each has its own
61
+ // JSICache type, so the NativeState check above fails). Say so instead of
62
+ // letting Object.defineProperty throw a bare TypeError on the
63
+ // non-configurable property.
64
+ throw std::runtime_error(
65
+ std::string("react-native-skia: global.") + kGlobalName +
66
+ " already exists but is not our JSICache. Is react-native-skia "
67
+ "linked twice, or is another module using this global?");
68
+ }
69
+ auto cache = std::make_shared<JSICache>();
70
+ jsi::Object holder(runtime);
71
+ holder.setNativeState(runtime, cache);
72
+ // Non-enumerable, non-writable, non-configurable: JS code must not be able
73
+ // to drop the holder (which would finalize the cache under our feet).
74
+ auto objectCtor = global.getPropertyAsObject(runtime, "Object");
75
+ auto defineProperty =
76
+ objectCtor.getPropertyAsFunction(runtime, "defineProperty");
77
+ jsi::Object descriptor(runtime);
78
+ descriptor.setProperty(runtime, "value", std::move(holder));
79
+ descriptor.setProperty(runtime, "writable", false);
80
+ descriptor.setProperty(runtime, "enumerable", false);
81
+ descriptor.setProperty(runtime, "configurable", false);
82
+ defineProperty.call(runtime, global,
83
+ jsi::String::createFromAscii(runtime, kGlobalName),
84
+ descriptor);
85
+ return cache;
86
+ }
87
+
88
+ jsi::Object *JSICache::getPrototype(PrototypeKey key) {
89
+ auto it = _prototypes.find(key);
90
+ return it == _prototypes.end() ? nullptr : &it->second;
91
+ }
92
+
93
+ jsi::Object &JSICache::setPrototype(PrototypeKey key, jsi::Object prototype) {
94
+ auto [it, inserted] = _prototypes.insert_or_assign(key, std::move(prototype));
95
+ (void)inserted;
96
+ return it->second;
97
+ }
98
+
99
+ } // namespace RNJsi
@@ -0,0 +1,90 @@
1
+ #pragma once
2
+
3
+ #include <jsi/jsi.h>
4
+
5
+ #include <memory>
6
+ #include <mutex>
7
+ #include <typeindex>
8
+ #include <unordered_map>
9
+
10
+ namespace RNJsi {
11
+
12
+ namespace jsi = facebook::jsi;
13
+
14
+ /**
15
+ * Per-runtime store for JSI values that native code wants to keep across
16
+ * calls (currently: the prototype object of every NativeObject class).
17
+ *
18
+ * Ownership model (borrowed from react-native-nitro-modules' JSICache):
19
+ *
20
+ * - One JSICache exists per jsi::Runtime. It is attached as the NativeState
21
+ * of a hidden object stored on that runtime's `global`, so the RUNTIME owns
22
+ * the cache. When the runtime is destroyed the engine finalizes the object,
23
+ * ~JSICache runs while the runtime is still alive, and every cached
24
+ * jsi::Object is released correctly. Nothing outlives its runtime and
25
+ * nothing has to be leaked.
26
+ *
27
+ * - Native code reaches the cache through JSICache::get(runtime). A static
28
+ * map of std::weak_ptr, keyed by jsi::Runtime*, makes the lookup cheap; the
29
+ * pointer is only a map key, never proof that a runtime is alive. If the
30
+ * weak_ptr is expired (the runtime that owned it is gone) the entry is
31
+ * recreated on the runtime asking for it. This is what makes an in-process
32
+ * runtime recreate (expo-updates OTA apply, DevSettings.reload) safe even
33
+ * when the new runtime is allocated at the address of the freed one: the
34
+ * old cache was destroyed with the old runtime, so the reused address can
35
+ * only ever resolve to a fresh cache.
36
+ *
37
+ * - The cache itself is not locked: a jsi::Runtime is single-threaded, and
38
+ * the cache is only ever touched from its runtime's thread. Only the static
39
+ * runtime -> cache map is guarded.
40
+ *
41
+ * The same mechanism works for worklet runtimes (Reanimated UI runtime,
42
+ * createWorkletRuntime, ...); each gets its own JSICache.
43
+ */
44
+ class JSICache final : public jsi::NativeState {
45
+ public:
46
+ /**
47
+ * Key identifying one cached prototype: the C++ type of the NativeObject
48
+ * subclass (std::type_index(typeid(Derived))), as in Nitro. It prints as
49
+ * the class name in a debugger.
50
+ */
51
+ using PrototypeKey = std::type_index;
52
+
53
+ /**
54
+ * Returns the cache owned by `runtime`, creating it on first use. Must be
55
+ * called on the runtime's thread.
56
+ */
57
+ static JSICache &get(jsi::Runtime &runtime);
58
+
59
+ /**
60
+ * Returns the cached prototype for `key` or nullptr if none was stored.
61
+ *
62
+ * The pointer points into `_prototypes`. std::unordered_map never
63
+ * invalidates pointers/references to elements on insert or rehash (only on
64
+ * erase of that element, which we never do), so it stays valid for as long
65
+ * as the runtime does. Do not swap the container for one without that
66
+ * guarantee (std::vector, absl::flat_hash_map, ...).
67
+ */
68
+ jsi::Object *getPrototype(PrototypeKey key);
69
+
70
+ /**
71
+ * Stores (or replaces) the prototype for `key` and returns it.
72
+ */
73
+ jsi::Object &setPrototype(PrototypeKey key, jsi::Object prototype);
74
+
75
+ JSICache() = default;
76
+ ~JSICache() override = default;
77
+ JSICache(const JSICache &) = delete;
78
+ JSICache &operator=(const JSICache &) = delete;
79
+
80
+ private:
81
+ static std::shared_ptr<JSICache> getOrCreateOnGlobal(jsi::Runtime &runtime);
82
+
83
+ std::unordered_map<PrototypeKey, jsi::Object> _prototypes;
84
+
85
+ // Runtime -> cache. Weak on purpose: the runtime's global owns the cache.
86
+ static std::mutex _registryMutex;
87
+ static std::unordered_map<jsi::Runtime *, std::weak_ptr<JSICache>> _registry;
88
+ };
89
+
90
+ } // namespace RNJsi