react-native-wgpu 0.4.1 → 0.5.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 (197) hide show
  1. package/README.md +59 -14
  2. package/android/CMakeLists.txt +3 -3
  3. package/cpp/jsi/{RNFEnumMapper.h → EnumMapper.h} +2 -6
  4. package/cpp/jsi/{RNFJSIConverter.h → JSIConverter.h} +27 -110
  5. package/cpp/jsi/NativeObject.h +607 -0
  6. package/cpp/jsi/{RNFPromise.cpp → Promise.cpp} +3 -6
  7. package/cpp/jsi/{RNFPromise.h → Promise.h} +2 -5
  8. package/cpp/jsi/RuntimeAwareCache.cpp +7 -0
  9. package/cpp/jsi/RuntimeAwareCache.h +100 -0
  10. package/cpp/jsi/RuntimeLifecycleMonitor.cpp +72 -0
  11. package/cpp/jsi/RuntimeLifecycleMonitor.h +32 -0
  12. package/cpp/rnwgpu/ArrayBuffer.h +8 -12
  13. package/cpp/rnwgpu/RNWebGPUManager.cpp +187 -28
  14. package/cpp/rnwgpu/RNWebGPUManager.h +7 -0
  15. package/cpp/rnwgpu/api/Canvas.h +14 -12
  16. package/cpp/rnwgpu/api/GPU.cpp +4 -6
  17. package/cpp/rnwgpu/api/GPU.h +13 -11
  18. package/cpp/rnwgpu/api/GPUAdapter.cpp +9 -9
  19. package/cpp/rnwgpu/api/GPUAdapter.h +14 -11
  20. package/cpp/rnwgpu/api/GPUAdapterInfo.h +17 -15
  21. package/cpp/rnwgpu/api/GPUBindGroup.h +11 -10
  22. package/cpp/rnwgpu/api/GPUBindGroupLayout.h +12 -11
  23. package/cpp/rnwgpu/api/GPUBuffer.h +19 -16
  24. package/cpp/rnwgpu/api/GPUCanvasContext.h +17 -13
  25. package/cpp/rnwgpu/api/GPUCommandBuffer.h +12 -10
  26. package/cpp/rnwgpu/api/GPUCommandEncoder.h +35 -32
  27. package/cpp/rnwgpu/api/GPUCompilationInfo.h +19 -19
  28. package/cpp/rnwgpu/api/GPUCompilationMessage.h +10 -7
  29. package/cpp/rnwgpu/api/GPUComputePassEncoder.h +28 -27
  30. package/cpp/rnwgpu/api/GPUComputePipeline.h +14 -13
  31. package/cpp/rnwgpu/api/GPUDevice.cpp +111 -95
  32. package/cpp/rnwgpu/api/GPUDevice.h +51 -43
  33. package/cpp/rnwgpu/api/GPUDeviceLostInfo.h +12 -10
  34. package/cpp/rnwgpu/api/GPUError.h +19 -29
  35. package/cpp/rnwgpu/api/GPUExtent3D.h +7 -10
  36. package/cpp/rnwgpu/api/GPUExternalTexture.h +12 -11
  37. package/cpp/rnwgpu/api/GPUInternalError.h +31 -0
  38. package/cpp/rnwgpu/api/GPUOrigin2D.h +6 -10
  39. package/cpp/rnwgpu/api/GPUOrigin3D.h +6 -10
  40. package/cpp/rnwgpu/api/GPUOutOfMemoryError.h +33 -0
  41. package/cpp/rnwgpu/api/GPUPipelineLayout.h +12 -10
  42. package/cpp/rnwgpu/api/GPUQuerySet.h +14 -12
  43. package/cpp/rnwgpu/api/GPUQueue.h +18 -17
  44. package/cpp/rnwgpu/api/GPURenderBundle.h +11 -10
  45. package/cpp/rnwgpu/api/GPURenderBundleEncoder.h +36 -33
  46. package/cpp/rnwgpu/api/GPURenderPassEncoder.h +49 -47
  47. package/cpp/rnwgpu/api/GPURenderPipeline.h +14 -12
  48. package/cpp/rnwgpu/api/GPUSampler.h +11 -10
  49. package/cpp/rnwgpu/api/GPUShaderModule.cpp +7 -8
  50. package/cpp/rnwgpu/api/GPUShaderModule.h +13 -12
  51. package/cpp/rnwgpu/api/GPUSupportedLimits.h +73 -93
  52. package/cpp/rnwgpu/api/GPUTexture.h +24 -20
  53. package/cpp/rnwgpu/api/GPUTextureView.h +11 -10
  54. package/cpp/rnwgpu/api/GPUValidationError.h +32 -0
  55. package/cpp/rnwgpu/api/ImageBitmap.h +10 -6
  56. package/cpp/rnwgpu/api/RNWebGPU.h +21 -21
  57. package/cpp/rnwgpu/api/descriptors/GPUBindGroupDescriptor.h +3 -7
  58. package/cpp/rnwgpu/api/descriptors/GPUBindGroupEntry.h +7 -11
  59. package/cpp/rnwgpu/api/descriptors/GPUBindGroupLayoutDescriptor.h +3 -7
  60. package/cpp/rnwgpu/api/descriptors/GPUBindGroupLayoutEntry.h +3 -7
  61. package/cpp/rnwgpu/api/descriptors/GPUBlendComponent.h +3 -8
  62. package/cpp/rnwgpu/api/descriptors/GPUBlendState.h +3 -7
  63. package/cpp/rnwgpu/api/descriptors/GPUBufferBinding.h +3 -7
  64. package/cpp/rnwgpu/api/descriptors/GPUBufferBindingLayout.h +3 -8
  65. package/cpp/rnwgpu/api/descriptors/GPUBufferDescriptor.h +3 -8
  66. package/cpp/rnwgpu/api/descriptors/GPUBufferUsage.h +28 -32
  67. package/cpp/rnwgpu/api/descriptors/GPUCanvasConfiguration.h +3 -7
  68. package/cpp/rnwgpu/api/descriptors/GPUColor.h +3 -8
  69. package/cpp/rnwgpu/api/descriptors/GPUColorTargetState.h +3 -7
  70. package/cpp/rnwgpu/api/descriptors/GPUColorWrite.h +18 -20
  71. package/cpp/rnwgpu/api/descriptors/GPUCommandBufferDescriptor.h +3 -8
  72. package/cpp/rnwgpu/api/descriptors/GPUCommandEncoderDescriptor.h +3 -8
  73. package/cpp/rnwgpu/api/descriptors/GPUComputePassDescriptor.h +3 -7
  74. package/cpp/rnwgpu/api/descriptors/GPUComputePassTimestampWrites.h +3 -7
  75. package/cpp/rnwgpu/api/descriptors/GPUComputePipelineDescriptor.h +3 -7
  76. package/cpp/rnwgpu/api/descriptors/GPUDepthStencilState.h +3 -7
  77. package/cpp/rnwgpu/api/descriptors/GPUDeviceDescriptor.h +3 -7
  78. package/cpp/rnwgpu/api/descriptors/GPUExternalTextureBindingLayout.h +3 -8
  79. package/cpp/rnwgpu/api/descriptors/GPUExternalTextureDescriptor.h +3 -7
  80. package/cpp/rnwgpu/api/descriptors/GPUFragmentState.h +3 -7
  81. package/cpp/rnwgpu/api/descriptors/GPUImageCopyBuffer.h +3 -7
  82. package/cpp/rnwgpu/api/descriptors/GPUImageCopyExternalImage.h +3 -7
  83. package/cpp/rnwgpu/api/descriptors/GPUImageCopyTexture.h +3 -7
  84. package/cpp/rnwgpu/api/descriptors/GPUImageCopyTextureTagged.h +3 -7
  85. package/cpp/rnwgpu/api/descriptors/GPUImageDataLayout.h +3 -8
  86. package/cpp/rnwgpu/api/descriptors/GPUMapMode.h +11 -14
  87. package/cpp/rnwgpu/api/descriptors/GPUMultisampleState.h +3 -8
  88. package/cpp/rnwgpu/api/descriptors/GPUPipelineLayoutDescriptor.h +3 -7
  89. package/cpp/rnwgpu/api/descriptors/GPUPrimitiveState.h +3 -8
  90. package/cpp/rnwgpu/api/descriptors/GPUProgrammableStage.h +3 -7
  91. package/cpp/rnwgpu/api/descriptors/GPUQuerySetDescriptor.h +3 -8
  92. package/cpp/rnwgpu/api/descriptors/GPUQueueDescriptor.h +3 -8
  93. package/cpp/rnwgpu/api/descriptors/GPURenderBundleDescriptor.h +3 -8
  94. package/cpp/rnwgpu/api/descriptors/GPURenderBundleEncoderDescriptor.h +3 -8
  95. package/cpp/rnwgpu/api/descriptors/GPURenderPassColorAttachment.h +3 -7
  96. package/cpp/rnwgpu/api/descriptors/GPURenderPassDepthStencilAttachment.h +3 -7
  97. package/cpp/rnwgpu/api/descriptors/GPURenderPassDescriptor.h +3 -7
  98. package/cpp/rnwgpu/api/descriptors/GPURenderPassTimestampWrites.h +3 -7
  99. package/cpp/rnwgpu/api/descriptors/GPURenderPipelineDescriptor.h +3 -7
  100. package/cpp/rnwgpu/api/descriptors/GPURequestAdapterOptions.h +3 -8
  101. package/cpp/rnwgpu/api/descriptors/GPUSamplerBindingLayout.h +3 -8
  102. package/cpp/rnwgpu/api/descriptors/GPUSamplerDescriptor.h +3 -8
  103. package/cpp/rnwgpu/api/descriptors/GPUShaderModuleCompilationHint.h +3 -7
  104. package/cpp/rnwgpu/api/descriptors/GPUShaderModuleDescriptor.h +3 -7
  105. package/cpp/rnwgpu/api/descriptors/GPUShaderStage.h +14 -16
  106. package/cpp/rnwgpu/api/descriptors/GPUStencilFaceState.h +3 -8
  107. package/cpp/rnwgpu/api/descriptors/GPUStorageTextureBindingLayout.h +3 -8
  108. package/cpp/rnwgpu/api/descriptors/GPUTextureBindingLayout.h +3 -8
  109. package/cpp/rnwgpu/api/descriptors/GPUTextureDescriptor.h +3 -7
  110. package/cpp/rnwgpu/api/descriptors/GPUTextureUsage.h +18 -29
  111. package/cpp/rnwgpu/api/descriptors/GPUTextureViewDescriptor.h +3 -8
  112. package/cpp/rnwgpu/api/descriptors/GPUUncapturedErrorEventInit.h +3 -7
  113. package/cpp/rnwgpu/api/descriptors/GPUVertexAttribute.h +3 -8
  114. package/cpp/rnwgpu/api/descriptors/GPUVertexBufferLayout.h +3 -7
  115. package/cpp/rnwgpu/api/descriptors/GPUVertexState.h +3 -7
  116. package/cpp/rnwgpu/api/descriptors/Unions.h +3 -3
  117. package/cpp/rnwgpu/async/AsyncTaskHandle.cpp +10 -10
  118. package/cpp/rnwgpu/async/AsyncTaskHandle.h +2 -2
  119. package/lib/commonjs/Canvas.js +9 -14
  120. package/lib/commonjs/Canvas.js.map +1 -1
  121. package/lib/commonjs/external/ModuleProxy.js +36 -0
  122. package/lib/commonjs/external/ModuleProxy.js.map +1 -0
  123. package/lib/commonjs/external/index.js +17 -0
  124. package/lib/commonjs/external/index.js.map +1 -0
  125. package/lib/commonjs/external/reanimated/ReanimatedProxy.js +18 -0
  126. package/lib/commonjs/external/reanimated/ReanimatedProxy.js.map +1 -0
  127. package/lib/commonjs/external/reanimated/index.js +21 -0
  128. package/lib/commonjs/external/reanimated/index.js.map +1 -0
  129. package/lib/commonjs/external/reanimated/registerWebGPUForReanimated.js +50 -0
  130. package/lib/commonjs/external/reanimated/registerWebGPUForReanimated.js.map +1 -0
  131. package/lib/commonjs/main/index.js +2 -142
  132. package/lib/commonjs/main/index.js.map +1 -1
  133. package/lib/module/Canvas.js +10 -16
  134. package/lib/module/Canvas.js.map +1 -1
  135. package/lib/module/external/ModuleProxy.js +28 -0
  136. package/lib/module/external/ModuleProxy.js.map +1 -0
  137. package/lib/module/external/index.js +2 -0
  138. package/lib/module/external/index.js.map +1 -0
  139. package/lib/module/external/reanimated/ReanimatedProxy.js +12 -0
  140. package/lib/module/external/reanimated/ReanimatedProxy.js.map +1 -0
  141. package/lib/module/external/reanimated/index.js +3 -0
  142. package/lib/module/external/reanimated/index.js.map +1 -0
  143. package/lib/module/external/reanimated/registerWebGPUForReanimated.js +43 -0
  144. package/lib/module/external/reanimated/registerWebGPUForReanimated.js.map +1 -0
  145. package/lib/module/main/index.js +2 -141
  146. package/lib/module/main/index.js.map +1 -1
  147. package/lib/typescript/babel.config.d.ts +1 -0
  148. package/lib/typescript/lib/commonjs/Canvas.d.ts +5 -1
  149. package/lib/typescript/lib/commonjs/Canvas.d.ts.map +1 -1
  150. package/lib/typescript/lib/commonjs/external/ModuleProxy.d.ts +12 -0
  151. package/lib/typescript/lib/commonjs/external/ModuleProxy.d.ts.map +1 -0
  152. package/lib/typescript/lib/commonjs/external/index.d.ts +2 -0
  153. package/lib/typescript/lib/commonjs/external/index.d.ts.map +1 -0
  154. package/lib/typescript/lib/commonjs/external/reanimated/ReanimatedProxy.d.ts +6 -0
  155. package/lib/typescript/lib/commonjs/external/reanimated/ReanimatedProxy.d.ts.map +1 -0
  156. package/lib/typescript/lib/commonjs/external/reanimated/index.d.ts +4 -0
  157. package/lib/typescript/lib/commonjs/external/reanimated/index.d.ts.map +1 -0
  158. package/lib/typescript/lib/commonjs/external/reanimated/registerWebGPUForReanimated.d.ts +9 -0
  159. package/lib/typescript/lib/commonjs/external/reanimated/registerWebGPUForReanimated.d.ts.map +1 -0
  160. package/lib/typescript/lib/module/Canvas.d.ts +6 -1
  161. package/lib/typescript/lib/module/Canvas.d.ts.map +1 -1
  162. package/lib/typescript/lib/module/external/ModuleProxy.d.ts +7 -0
  163. package/lib/typescript/lib/module/external/ModuleProxy.d.ts.map +1 -0
  164. package/lib/typescript/lib/module/external/index.d.ts +2 -0
  165. package/lib/typescript/lib/module/external/index.d.ts.map +1 -0
  166. package/lib/typescript/lib/module/external/reanimated/ReanimatedProxy.d.ts +5 -0
  167. package/lib/typescript/lib/module/external/reanimated/ReanimatedProxy.d.ts.map +1 -0
  168. package/lib/typescript/lib/module/external/reanimated/index.d.ts +3 -0
  169. package/lib/typescript/lib/module/external/reanimated/index.d.ts.map +1 -0
  170. package/lib/typescript/lib/module/external/reanimated/registerWebGPUForReanimated.d.ts +2 -0
  171. package/lib/typescript/lib/module/external/reanimated/registerWebGPUForReanimated.d.ts.map +1 -0
  172. package/lib/typescript/src/Canvas.d.ts +4 -2
  173. package/lib/typescript/src/Canvas.d.ts.map +1 -1
  174. package/lib/typescript/src/external/ModuleProxy.d.ts +11 -0
  175. package/lib/typescript/src/external/ModuleProxy.d.ts.map +1 -0
  176. package/lib/typescript/src/external/index.d.ts +2 -0
  177. package/lib/typescript/src/external/index.d.ts.map +1 -0
  178. package/lib/typescript/src/external/reanimated/ReanimatedProxy.d.ts +4 -0
  179. package/lib/typescript/src/external/reanimated/ReanimatedProxy.d.ts.map +1 -0
  180. package/lib/typescript/src/external/reanimated/index.d.ts +3 -0
  181. package/lib/typescript/src/external/reanimated/index.d.ts.map +1 -0
  182. package/lib/typescript/src/external/reanimated/registerWebGPUForReanimated.d.ts +8 -0
  183. package/lib/typescript/src/external/reanimated/registerWebGPUForReanimated.d.ts.map +1 -0
  184. package/package.json +15 -2
  185. package/src/Canvas.tsx +16 -22
  186. package/src/external/ModuleProxy.ts +30 -0
  187. package/src/external/index.ts +1 -0
  188. package/src/external/reanimated/ReanimatedProxy.ts +19 -0
  189. package/src/external/reanimated/index.ts +2 -0
  190. package/src/external/reanimated/registerWebGPUForReanimated.ts +43 -0
  191. package/src/main/index.tsx +3 -170
  192. package/cpp/jsi/RNFHybridObject.cpp +0 -150
  193. package/cpp/jsi/RNFHybridObject.h +0 -181
  194. package/cpp/jsi/RNFJSIHelper.h +0 -51
  195. package/cpp/jsi/RNFPointerHolder.h +0 -95
  196. package/cpp/jsi/RNFRuntimeState.cpp +0 -18
  197. package/cpp/jsi/RNFRuntimeState.h +0 -106
@@ -1,150 +0,0 @@
1
- //
2
- // Created by Marc Rousavy on 21.02.24.
3
- //
4
- #include "RNFHybridObject.h"
5
- #include "RNFJSIConverter.h"
6
- #include "WGPULogger.h"
7
-
8
- #include <unordered_map>
9
- #include <utility>
10
- #include <string>
11
- #include <vector>
12
-
13
- namespace margelo {
14
-
15
- #if DEBUG && RNF_ENABLE_LOGS
16
- static std::unordered_map<const char*, int> _instanceIds;
17
- static std::mutex _mutex;
18
-
19
- static int getId(const char* name) {
20
- std::unique_lock lock(_mutex);
21
- if (_instanceIds.find(name) == _instanceIds.end()) {
22
- _instanceIds.insert({name, 1});
23
- }
24
- auto iterator = _instanceIds.find(name);
25
- return iterator->second++;
26
- }
27
- #endif
28
-
29
- HybridObject::HybridObject(const char* name) : _name(name) {
30
- #if DEBUG && RNF_ENABLE_LOGS
31
- _instanceId = getId(name);
32
- Logger::logToConsole(TAG, "(MEMORY) Creating %s (#%i)... ✅", _name, _instanceId);
33
- #endif
34
- }
35
-
36
- HybridObject::~HybridObject() {
37
- #if DEBUG && RNF_ENABLE_LOGS
38
- Logger::log(TAG, "(MEMORY) Deleting %s (#%i)... ❌", _name, _instanceId);
39
- #endif
40
- _functionCache.clear();
41
- }
42
-
43
- std::string HybridObject::toString(jsi::Runtime& runtime) {
44
- std::string result = std::string(_name) + " { ";
45
- std::vector<jsi::PropNameID> props = getPropertyNames(runtime);
46
- for (size_t i = 0; i < props.size(); i++) {
47
- auto suffix = i < props.size() - 1 ? ", " : " ";
48
- result += "\"" + props[i].utf8(runtime) + "\"" + suffix;
49
- }
50
- return result + "}";
51
- }
52
-
53
- std::vector<jsi::PropNameID> HybridObject::getPropertyNames(facebook::jsi::Runtime& runtime) {
54
- std::unique_lock lock(_mutex);
55
- ensureInitialized(runtime);
56
-
57
- std::vector<jsi::PropNameID> result;
58
- size_t totalSize = _methods.size() + _getters.size() + _setters.size();
59
- result.reserve(totalSize);
60
-
61
- for (const auto& item : _methods) {
62
- result.push_back(jsi::PropNameID::forUtf8(runtime, item.first));
63
- }
64
- for (const auto& item : _getters) {
65
- result.push_back(jsi::PropNameID::forUtf8(runtime, item.first));
66
- }
67
- for (const auto& item : _setters) {
68
- result.push_back(jsi::PropNameID::forUtf8(runtime, item.first));
69
- }
70
- return result;
71
- }
72
-
73
- jsi::Value HybridObject::get(facebook::jsi::Runtime& runtime, const facebook::jsi::PropNameID& propName) {
74
- std::unique_lock lock(_mutex);
75
- ensureInitialized(runtime);
76
-
77
- std::string name = propName.utf8(runtime);
78
- auto& functionCache = _functionCache[&runtime];
79
-
80
- if (_getters.count(name) > 0) {
81
- // it's a property getter
82
- return _getters[name](runtime, jsi::Value::undefined(), nullptr, 0);
83
- }
84
-
85
- if (functionCache.count(name) > 0) {
86
- [[likely]];
87
- // cache hit
88
- return jsi::Value(runtime, *functionCache[name]);
89
- }
90
-
91
- if (_methods.count(name) > 0) {
92
- // cache miss - create jsi::Function and cache it.
93
- HybridFunction& hybridFunction = _methods.at(name);
94
- jsi::Function function = jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, name),
95
- hybridFunction.parameterCount, hybridFunction.function);
96
-
97
- functionCache[name] = JSIHelper::createSharedJsiFunction(runtime, std::move(function));
98
- return jsi::Value(runtime, *functionCache[name]);
99
- }
100
-
101
- if (name == "toString") {
102
- return jsi::Function::createFromHostFunction(
103
- runtime, jsi::PropNameID::forUtf8(runtime, "toString"), 0,
104
- [=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* args, size_t count) -> jsi::Value {
105
- std::string stringRepresentation = this->toString(runtime);
106
- return jsi::String::createFromUtf8(runtime, stringRepresentation);
107
- });
108
- }
109
-
110
- return jsi::HostObject::get(runtime, propName);
111
- }
112
-
113
- void HybridObject::set(facebook::jsi::Runtime& runtime, const facebook::jsi::PropNameID& propName, const facebook::jsi::Value& value) {
114
- std::unique_lock lock(_mutex);
115
- ensureInitialized(runtime);
116
-
117
- std::string name = propName.utf8(runtime);
118
-
119
- if (_setters.count(name) > 0) {
120
- // Call setter
121
- _setters[name](runtime, jsi::Value::undefined(), &value, 1);
122
- return;
123
- }
124
-
125
- HostObject::set(runtime, propName, value);
126
- }
127
-
128
- void HybridObject::ensureInitialized(facebook::jsi::Runtime& runtime) {
129
- if (!_didLoadMethods) {
130
- [[unlikely]];
131
- _creationRuntime = &runtime;
132
- _runtimeState = rnwgpu::RNFRuntimeState::get(runtime);
133
- // lazy-load all exposed methods
134
- loadHybridMethods();
135
- _didLoadMethods = true;
136
- }
137
- }
138
-
139
- bool HybridObject::isRuntimeAlive() {
140
- return !_runtimeState.expired();
141
- }
142
-
143
- facebook::jsi::Runtime* HybridObject::getCreationRuntime() const {
144
- if (_runtimeState.expired()) {
145
- return nullptr;
146
- }
147
- return _creationRuntime;
148
- }
149
-
150
- } // namespace margelo
@@ -1,181 +0,0 @@
1
- //
2
- // Created by Marc Rousavy on 21.02.24.
3
- //
4
-
5
- #pragma once
6
-
7
- #include "WGPULogger.h"
8
- #include "RNFRuntimeState.h"
9
- #include <functional>
10
- #include <jsi/jsi.h>
11
- #include <memory>
12
- #include <mutex>
13
- #include <type_traits>
14
- #include <unordered_map>
15
- #include <vector>
16
- #include <utility>
17
- #include <string>
18
-
19
- // Forward declare to avoid circular dependency
20
- namespace margelo {
21
- template <typename ArgType, typename SFINAE>
22
- struct JSIConverter;
23
- }
24
-
25
- // Include the converter - this must come after forward declaration
26
- #include "RNFJSIConverter.h"
27
-
28
- namespace margelo {
29
-
30
- namespace jsi = facebook::jsi;
31
-
32
- class HybridObject : public jsi::HostObject, public std::enable_shared_from_this<HybridObject> {
33
- public:
34
- struct HybridFunction {
35
- jsi::HostFunctionType function;
36
- size_t parameterCount;
37
- };
38
-
39
- public:
40
- explicit HybridObject(const char* name);
41
- ~HybridObject();
42
-
43
- void set(jsi::Runtime&, const jsi::PropNameID& name, const jsi::Value& value) override;
44
- jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& propName) override;
45
- std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& runtime) override;
46
-
47
- /**
48
- * Get the `std::shared_ptr` instance of this HybridObject.
49
- * The HybridObject must be managed inside a `shared_ptr` already, otherwise this will fail.
50
- */
51
- template <typename Derived> std::shared_ptr<Derived> shared() {
52
- return std::static_pointer_cast<Derived>(shared_from_this());
53
- }
54
-
55
- /**
56
- * Loads all native methods of this `HybridObject` to be exposed to JavaScript.
57
- * Example:
58
- *
59
- * ```cpp
60
- * int User::getAge() {
61
- * return 23;
62
- * }
63
- *
64
- * void User::loadHybridMethods() {
65
- * registerHybridMethod("getAge", &User::getAge, this);
66
- * }
67
- * ```
68
- */
69
- virtual void loadHybridMethods() = 0;
70
-
71
- /**
72
- * Get a string representation of this HostObject, useful for logging or debugging.
73
- */
74
- virtual std::string toString(jsi::Runtime& runtime);
75
-
76
- /**
77
- * Get the memory pressure of this HostObject in bytes.
78
- * This is used to inform the JavaScript runtime about memory usage for garbage collection.
79
- */
80
- virtual size_t getMemoryPressure() { return 1024; }
81
-
82
- private:
83
- static constexpr auto TAG = "HybridObject";
84
- int _instanceId = 1;
85
- bool _didLoadMethods = false;
86
- std::mutex _mutex;
87
- std::unordered_map<std::string, HybridFunction> _methods;
88
- std::unordered_map<std::string, jsi::HostFunctionType> _getters;
89
- std::unordered_map<std::string, jsi::HostFunctionType> _setters;
90
- std::unordered_map<jsi::Runtime*, std::unordered_map<std::string, std::shared_ptr<jsi::Function>>> _functionCache;
91
-
92
- protected:
93
- const char* _name = TAG;
94
- // Store a pointer to the runtime for convenience; ensure it is only used while the runtime state is alive.
95
- jsi::Runtime* _creationRuntime = nullptr;
96
- std::weak_ptr<rnwgpu::RNFRuntimeState> _runtimeState;
97
-
98
- private:
99
- inline void ensureInitialized(facebook::jsi::Runtime& runtime);
100
-
101
- private:
102
- template <typename Derived, typename ReturnType, typename... Args, size_t... Is>
103
- static inline jsi::Value callMethod(Derived* obj, ReturnType (Derived::*method)(Args...), jsi::Runtime& runtime, const jsi::Value* args,
104
- std::index_sequence<Is...>, size_t count) {
105
- if constexpr (std::is_same_v<ReturnType, void>) {
106
- // It's a void method.
107
- (obj->*method)(JSIConverter<std::decay_t<Args>>::fromJSI(runtime, args[Is], Is >= count)...);
108
- return jsi::Value::undefined();
109
- } else {
110
- // It's returning some C++ type, we need to convert that to a JSI value now.
111
- ReturnType result = (obj->*method)(JSIConverter<std::decay_t<Args>>::fromJSI(runtime, args[Is], Is >= count)...);
112
- return JSIConverter<std::decay_t<ReturnType>>::toJSI(runtime, std::move(result));
113
- }
114
- }
115
-
116
- template <typename Derived, typename ReturnType, typename... Args>
117
- static jsi::HostFunctionType createHybridMethod(ReturnType (Derived::*method)(Args...), Derived* derivedInstance) {
118
-
119
- return [derivedInstance, method](jsi::Runtime& runtime, const jsi::Value& thisVal, const jsi::Value* args, size_t count) -> jsi::Value {
120
- if constexpr (std::is_same_v<ReturnType, jsi::Value>) {
121
- // If the return type is a jsi::Value, we assume the user wants full JSI code control.
122
- // The signature must be identical to jsi::HostFunction (jsi::Runtime&, jsi::Value& this, ...)
123
- return (derivedInstance->*method)(runtime, thisVal, args, count);
124
- } else {
125
- // Call the actual method with JSI values as arguments and return a JSI value again.
126
- // Internally, this method converts the JSI values to C++ values.
127
- return callMethod(derivedInstance, method, runtime, args, std::index_sequence_for<Args...>{}, count);
128
- }
129
- };
130
- }
131
-
132
- protected:
133
- facebook::jsi::Runtime* getCreationRuntime() const;
134
- std::weak_ptr<rnwgpu::RNFRuntimeState> getRuntimeStateWeak() const { return _runtimeState; }
135
-
136
- protected:
137
- template <typename Derived, typename ReturnType, typename... Args>
138
- void registerHybridMethod(std::string name, ReturnType (Derived::*method)(Args...), Derived* derivedInstance, bool override = false) {
139
- if (!override && (_getters.count(name) > 0 || _setters.count(name) > 0)) {
140
- [[unlikely]];
141
- throw std::runtime_error("Cannot add Hybrid Method \"" + name + "\" - a property with that name already exists!");
142
- }
143
- if (!override && (_methods.count(name) > 0)) {
144
- throw std::runtime_error("Cannot add Hybrid Method \"" + name + "\" - a method with that name already exists!");
145
- }
146
-
147
- _methods[name] = HybridFunction{.function = createHybridMethod(method, derivedInstance), .parameterCount = sizeof...(Args)};
148
- }
149
-
150
- template <typename Derived, typename ReturnType>
151
- void registerHybridGetter(std::string name, ReturnType (Derived::*method)(), Derived* derivedInstance) {
152
- if (_getters.count(name) > 0) {
153
- [[unlikely]];
154
- throw std::runtime_error("Cannot add Hybrid Property Getter \"" + name + "\" - a getter with that name already exists!");
155
- }
156
- if (_methods.count(name) > 0) {
157
- [[unlikely]];
158
- throw std::runtime_error("Cannot add Hybrid Property Getter \"" + name + "\" - a method with that name already exists!");
159
- }
160
-
161
- _getters[name] = createHybridMethod(method, derivedInstance);
162
- }
163
-
164
- template <typename Derived, typename ValueType>
165
- void registerHybridSetter(std::string name, void (Derived::*method)(ValueType), Derived* derivedInstance) {
166
- if (_setters.count(name) > 0) {
167
- [[unlikely]];
168
- throw std::runtime_error("Cannot add Hybrid Property Setter \"" + name + "\" - a setter with that name already exists!");
169
- }
170
- if (_methods.count(name) > 0) {
171
- [[unlikely]];
172
- throw std::runtime_error("Cannot add Hybrid Property Setter \"" + name + "\" - a method with that name already exists!");
173
- }
174
-
175
- _setters[name] = createHybridMethod(method, derivedInstance);
176
- }
177
-
178
- bool isRuntimeAlive();
179
- };
180
-
181
- } // namespace margelo
@@ -1,51 +0,0 @@
1
- //
2
- // Created by Hanno Gödecke on 15.05.24.
3
- //
4
-
5
- #pragma once
6
-
7
- #include "RNFRuntimeState.h"
8
- #include <jsi/jsi.h>
9
- #include <memory>
10
- #include <utility>
11
-
12
- namespace margelo {
13
-
14
- namespace jsi = facebook::jsi;
15
-
16
- class JSIHelper {
17
- public:
18
- /**
19
- * Takes a jsi::Function and wraps it in a shared_ptr so its shareable.
20
- * Every jsi::Function you intend to share or hold should be wrapped using this function.
21
- */
22
- static std::shared_ptr<jsi::Function> createSharedJsiFunction(jsi::Runtime& runtime, jsi::Function&& function) {
23
- auto runtimeState = rnwgpu::RNFRuntimeState::get(runtime);
24
- std::weak_ptr<rnwgpu::RNFRuntimeState> runtimeStateWeak = runtimeState;
25
- std::shared_ptr<jsi::Function> sharedFunction(new jsi::Function(std::move(function)), [runtimeStateWeak](jsi::Function* ptr) {
26
- if (!runtimeStateWeak.expired()) {
27
- // Only delete the jsi::Function when the runtime it created is still alive.
28
- // Otherwise leak memory. We do this on purpose, as sometimes we would keep
29
- // references to JSI objects past the lifetime of its runtime (e.g.,
30
- // shared values references from the RN VM holds reference to JSI objects
31
- // on the UI runtime). When the runtime is terminated, the orphaned JSI
32
- // objects would crash the app when their destructors are called, because
33
- // they call into a memory that's managed by the terminated runtime. We
34
- // accept the tradeoff of leaking memory here, as it has a limited impact.
35
- // This scenario can only occur when the React instance is torn down which
36
- // happens in development mode during app reloads, or in production when
37
- // the app is being shut down gracefully by the system. An alternative
38
- // solution would require us to keep track of all JSI values that are in
39
- // use which would require additional data structure and compute spent on
40
- // bookkeeping that only for the sake of destroying the values in time
41
- // before the runtime is terminated. Note that the underlying memory that
42
- // jsi::Value refers to is managed by the VM and gets freed along with the
43
- // runtime.
44
- delete ptr;
45
- }
46
- });
47
-
48
- return sharedFunction;
49
- }
50
- };
51
- } // namespace margelo
@@ -1,95 +0,0 @@
1
- //
2
- // Created by Marc Rousavy on 16.04.24.
3
- //
4
-
5
- #pragma once
6
-
7
- #include "RNFHybridObject.h"
8
- #include "RNFLogger.h"
9
- #include <memory>
10
- #include <mutex>
11
- #include <utility>
12
- #include <string>
13
-
14
- namespace margelo {
15
-
16
- namespace jsi = facebook::jsi;
17
-
18
- template <typename T> class PointerHolder : public HybridObject {
19
- protected:
20
- // no default constructor
21
- PointerHolder() = delete;
22
-
23
- /**
24
- * Create a new instance of a pointer holder which holds the given shared_ptr.
25
- * @param name The name of the implementing class, for example "ViewWrapper".
26
- * @param pointer The pointer this class will hold. It might be released from JS at any point via `release()`.
27
- */
28
- PointerHolder(const char* name, std::shared_ptr<T> pointer) : HybridObject(name), _name(name), _pointer(pointer) {
29
- // eagerly initialize the release() method instead of putting it in `loadHybridMethods`
30
- registerHybridMethod("release", &PointerHolder<T>::release, this);
31
- registerHybridGetter("isValid", &PointerHolder<T>::getIsValid, this);
32
- }
33
-
34
- /**
35
- * Create a new instance of a pointer holder which holds a shared_ptr of the given value.
36
- * The shared_ptr will be move-constructed.
37
- * @param name The name of the implementing class, for example "ViewWrapper".
38
- * @param value The value this class will hold as a shared_ptr. It might be destroyed from JS at any point via `release()`.
39
- */
40
- PointerHolder(const char* name, T&& value) : PointerHolder(name, std::make_shared<T>(std::move(value))) {}
41
-
42
- /**
43
- * Called when the PointerHolder gets automatically destroyed (e.g. via GC) and the shared_ptr will be destroyed.
44
- */
45
- ~PointerHolder() {
46
- if (_pointer != nullptr) {
47
- Logger::log(TAG, "Automatically releasing %s... (~PointerHolder())", _name.c_str());
48
- }
49
- }
50
-
51
- protected:
52
- /**
53
- * Manually release this reference to the pointer.
54
- * If there are any other references to this pointer, no memory will be force-deleted.
55
- */
56
- virtual void release() {
57
- std::unique_lock lock(_mutex);
58
-
59
- if (_pointer == nullptr) {
60
- throw std::runtime_error("Pointer " + _name + " has already been manually released!");
61
- }
62
- Logger::log(TAG, "Manually releasing %s... (PointerHolder::release())", _name.c_str());
63
- _pointer = nullptr;
64
- }
65
-
66
- /**
67
- * Get the shared_ptr this class is holding.
68
- * If it has already been manually released from JS, this method will throw a runtime_error.
69
- */
70
- std::shared_ptr<T> pointee() {
71
- std::unique_lock lock(_mutex);
72
-
73
- if (_pointer == nullptr) {
74
- throw std::runtime_error("Pointer " + _name + " has already been manually released!");
75
- }
76
- return _pointer;
77
- }
78
-
79
- /**
80
- * Get if the pointer is still valid and strong.
81
- */
82
- bool getIsValid() {
83
- std::unique_lock lock(_mutex);
84
-
85
- return _pointer != nullptr;
86
- }
87
-
88
- private:
89
- std::string _name;
90
- std::shared_ptr<T> _pointer;
91
- std::mutex _mutex;
92
- static constexpr auto TAG = "PointerHolder";
93
- };
94
-
95
- } // namespace margelo
@@ -1,18 +0,0 @@
1
- #include "RNFRuntimeState.h"
2
-
3
- namespace rnwgpu {
4
-
5
- const facebook::jsi::UUID RNFRuntimeState::kRuntimeStateKey = facebook::jsi::UUID();
6
-
7
- std::shared_ptr<RNFRuntimeState> RNFRuntimeState::get(facebook::jsi::Runtime& runtime) {
8
- auto existing = runtime.getRuntimeData(kRuntimeStateKey);
9
- if (existing) {
10
- return std::static_pointer_cast<RNFRuntimeState>(existing);
11
- }
12
-
13
- auto state = std::shared_ptr<RNFRuntimeState>(new RNFRuntimeState());
14
- runtime.setRuntimeData(kRuntimeStateKey, state);
15
- return state;
16
- }
17
-
18
- } // namespace rnwgpu
@@ -1,106 +0,0 @@
1
- #pragma once
2
-
3
- #include <jsi/jsi.h>
4
-
5
- #include <memory>
6
- #include <mutex>
7
- #include <unordered_map>
8
- #include <unordered_set>
9
-
10
- namespace rnwgpu {
11
-
12
- namespace jsi = facebook::jsi;
13
-
14
- /**
15
- * Runtime state management using Hermes' runtime.setRuntimeData API.
16
- * This replaces the old RuntimeLifecycleMonitor/RuntimeAwareCache system.
17
- */
18
- class RNFRuntimeState {
19
- public:
20
- // UUID key for storing our runtime state
21
- static const jsi::UUID kRuntimeStateKey;
22
-
23
- /**
24
- * Get or create the runtime state for the given runtime
25
- */
26
- static std::shared_ptr<RNFRuntimeState> get(jsi::Runtime& runtime);
27
-
28
- /**
29
- * Template cache that can store any type T per object pointer
30
- */
31
- template <typename T>
32
- class ObjectCache {
33
- public:
34
- std::shared_ptr<T> getOrCreate(void* object) {
35
- std::lock_guard<std::mutex> lock(mutex_);
36
- auto it = cache_.find(object);
37
- if (it != cache_.end()) {
38
- return it->second;
39
- }
40
-
41
- auto value = std::make_shared<T>();
42
- cache_[object] = value;
43
- return value;
44
- }
45
-
46
- void remove(void* object) {
47
- std::lock_guard<std::mutex> lock(mutex_);
48
- cache_.erase(object);
49
- }
50
-
51
- void clear() {
52
- std::lock_guard<std::mutex> lock(mutex_);
53
- cache_.clear();
54
- }
55
-
56
- private:
57
- std::mutex mutex_;
58
- std::unordered_map<void*, std::shared_ptr<T>> cache_;
59
- };
60
-
61
- /**
62
- * Get or create a cache for a specific type T
63
- */
64
- template <typename T>
65
- std::shared_ptr<ObjectCache<T>> getCache() {
66
- std::lock_guard<std::mutex> lock(mutex_);
67
-
68
- // Use type_info as key for the cache type
69
- const std::type_info& typeId = typeid(T);
70
- auto it = typeCaches_.find(&typeId);
71
-
72
- if (it != typeCaches_.end()) {
73
- return std::static_pointer_cast<ObjectCache<T>>(it->second);
74
- }
75
-
76
- auto cache = std::make_shared<ObjectCache<T>>();
77
- typeCaches_[&typeId] = cache;
78
- return cache;
79
- }
80
-
81
- private:
82
- RNFRuntimeState() = default;
83
-
84
- std::mutex mutex_;
85
- // Map from type_info to cache instance
86
- std::unordered_map<const std::type_info*, std::shared_ptr<void>> typeCaches_;
87
- };
88
-
89
- /**
90
- * Template helper for runtime-aware caching compatible with the old API
91
- * This provides a migration path from RuntimeAwareCache
92
- */
93
- template <typename T>
94
- class RuntimeAwareCache {
95
- public:
96
- T& get(jsi::Runtime& rt) {
97
- auto state = RNFRuntimeState::get(rt);
98
- auto cache = state->getCache<T>();
99
-
100
- // For compatibility, we use the runtime pointer as the object key
101
- auto ptr = cache->getOrCreate(&rt);
102
- return *ptr;
103
- }
104
- };
105
-
106
- } // namespace rnwgpu