react-native-wgpu 0.4.2 → 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.
- package/README.md +31 -0
- package/android/CMakeLists.txt +3 -3
- package/cpp/jsi/{RNFEnumMapper.h → EnumMapper.h} +2 -6
- package/cpp/jsi/{RNFJSIConverter.h → JSIConverter.h} +27 -110
- package/cpp/jsi/NativeObject.h +607 -0
- package/cpp/jsi/{RNFPromise.cpp → Promise.cpp} +3 -6
- package/cpp/jsi/{RNFPromise.h → Promise.h} +2 -5
- package/cpp/jsi/RuntimeAwareCache.cpp +7 -0
- package/cpp/jsi/RuntimeAwareCache.h +100 -0
- package/cpp/jsi/RuntimeLifecycleMonitor.cpp +72 -0
- package/cpp/jsi/RuntimeLifecycleMonitor.h +32 -0
- package/cpp/rnwgpu/ArrayBuffer.h +8 -12
- package/cpp/rnwgpu/RNWebGPUManager.cpp +187 -28
- package/cpp/rnwgpu/RNWebGPUManager.h +7 -0
- package/cpp/rnwgpu/api/Canvas.h +14 -12
- package/cpp/rnwgpu/api/GPU.cpp +4 -6
- package/cpp/rnwgpu/api/GPU.h +13 -11
- package/cpp/rnwgpu/api/GPUAdapter.cpp +9 -9
- package/cpp/rnwgpu/api/GPUAdapter.h +14 -11
- package/cpp/rnwgpu/api/GPUAdapterInfo.h +17 -15
- package/cpp/rnwgpu/api/GPUBindGroup.h +11 -10
- package/cpp/rnwgpu/api/GPUBindGroupLayout.h +12 -11
- package/cpp/rnwgpu/api/GPUBuffer.h +19 -16
- package/cpp/rnwgpu/api/GPUCanvasContext.h +17 -13
- package/cpp/rnwgpu/api/GPUCommandBuffer.h +12 -10
- package/cpp/rnwgpu/api/GPUCommandEncoder.h +35 -32
- package/cpp/rnwgpu/api/GPUCompilationInfo.h +19 -19
- package/cpp/rnwgpu/api/GPUCompilationMessage.h +10 -7
- package/cpp/rnwgpu/api/GPUComputePassEncoder.h +28 -27
- package/cpp/rnwgpu/api/GPUComputePipeline.h +14 -13
- package/cpp/rnwgpu/api/GPUDevice.cpp +111 -95
- package/cpp/rnwgpu/api/GPUDevice.h +51 -43
- package/cpp/rnwgpu/api/GPUDeviceLostInfo.h +12 -10
- package/cpp/rnwgpu/api/GPUError.h +19 -29
- package/cpp/rnwgpu/api/GPUExtent3D.h +7 -10
- package/cpp/rnwgpu/api/GPUExternalTexture.h +12 -11
- package/cpp/rnwgpu/api/GPUInternalError.h +31 -0
- package/cpp/rnwgpu/api/GPUOrigin2D.h +6 -10
- package/cpp/rnwgpu/api/GPUOrigin3D.h +6 -10
- package/cpp/rnwgpu/api/GPUOutOfMemoryError.h +33 -0
- package/cpp/rnwgpu/api/GPUPipelineLayout.h +12 -10
- package/cpp/rnwgpu/api/GPUQuerySet.h +14 -12
- package/cpp/rnwgpu/api/GPUQueue.h +18 -17
- package/cpp/rnwgpu/api/GPURenderBundle.h +11 -10
- package/cpp/rnwgpu/api/GPURenderBundleEncoder.h +36 -33
- package/cpp/rnwgpu/api/GPURenderPassEncoder.h +49 -47
- package/cpp/rnwgpu/api/GPURenderPipeline.h +14 -12
- package/cpp/rnwgpu/api/GPUSampler.h +11 -10
- package/cpp/rnwgpu/api/GPUShaderModule.cpp +7 -8
- package/cpp/rnwgpu/api/GPUShaderModule.h +13 -12
- package/cpp/rnwgpu/api/GPUSupportedLimits.h +73 -93
- package/cpp/rnwgpu/api/GPUTexture.h +24 -20
- package/cpp/rnwgpu/api/GPUTextureView.h +11 -10
- package/cpp/rnwgpu/api/GPUValidationError.h +32 -0
- package/cpp/rnwgpu/api/ImageBitmap.h +10 -6
- package/cpp/rnwgpu/api/RNWebGPU.h +21 -21
- package/cpp/rnwgpu/api/descriptors/GPUBindGroupDescriptor.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUBindGroupEntry.h +7 -11
- package/cpp/rnwgpu/api/descriptors/GPUBindGroupLayoutDescriptor.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUBindGroupLayoutEntry.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUBlendComponent.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUBlendState.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUBufferBinding.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUBufferBindingLayout.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUBufferDescriptor.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUBufferUsage.h +28 -32
- package/cpp/rnwgpu/api/descriptors/GPUCanvasConfiguration.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUColor.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUColorTargetState.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUColorWrite.h +18 -20
- package/cpp/rnwgpu/api/descriptors/GPUCommandBufferDescriptor.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUCommandEncoderDescriptor.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUComputePassDescriptor.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUComputePassTimestampWrites.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUComputePipelineDescriptor.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUDepthStencilState.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUDeviceDescriptor.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUExternalTextureBindingLayout.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUExternalTextureDescriptor.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUFragmentState.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUImageCopyBuffer.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUImageCopyExternalImage.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUImageCopyTexture.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUImageCopyTextureTagged.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUImageDataLayout.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUMapMode.h +11 -14
- package/cpp/rnwgpu/api/descriptors/GPUMultisampleState.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUPipelineLayoutDescriptor.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUPrimitiveState.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUProgrammableStage.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUQuerySetDescriptor.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUQueueDescriptor.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPURenderBundleDescriptor.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPURenderBundleEncoderDescriptor.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPURenderPassColorAttachment.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPURenderPassDepthStencilAttachment.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPURenderPassDescriptor.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPURenderPassTimestampWrites.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPURenderPipelineDescriptor.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPURequestAdapterOptions.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUSamplerBindingLayout.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUSamplerDescriptor.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUShaderModuleCompilationHint.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUShaderModuleDescriptor.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUShaderStage.h +14 -16
- package/cpp/rnwgpu/api/descriptors/GPUStencilFaceState.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUStorageTextureBindingLayout.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUTextureBindingLayout.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUTextureDescriptor.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUTextureUsage.h +18 -29
- package/cpp/rnwgpu/api/descriptors/GPUTextureViewDescriptor.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUUncapturedErrorEventInit.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUVertexAttribute.h +3 -8
- package/cpp/rnwgpu/api/descriptors/GPUVertexBufferLayout.h +3 -7
- package/cpp/rnwgpu/api/descriptors/GPUVertexState.h +3 -7
- package/cpp/rnwgpu/api/descriptors/Unions.h +3 -3
- package/cpp/rnwgpu/async/AsyncTaskHandle.cpp +10 -10
- package/cpp/rnwgpu/async/AsyncTaskHandle.h +2 -2
- package/lib/commonjs/external/ModuleProxy.js +36 -0
- package/lib/commonjs/external/ModuleProxy.js.map +1 -0
- package/lib/commonjs/external/index.js +17 -0
- package/lib/commonjs/external/index.js.map +1 -0
- package/lib/commonjs/external/reanimated/ReanimatedProxy.js +18 -0
- package/lib/commonjs/external/reanimated/ReanimatedProxy.js.map +1 -0
- package/lib/commonjs/external/reanimated/index.js +21 -0
- package/lib/commonjs/external/reanimated/index.js.map +1 -0
- package/lib/commonjs/external/reanimated/registerWebGPUForReanimated.js +50 -0
- package/lib/commonjs/external/reanimated/registerWebGPUForReanimated.js.map +1 -0
- package/lib/commonjs/main/index.js +2 -142
- package/lib/commonjs/main/index.js.map +1 -1
- package/lib/module/external/ModuleProxy.js +28 -0
- package/lib/module/external/ModuleProxy.js.map +1 -0
- package/lib/module/external/index.js +2 -0
- package/lib/module/external/index.js.map +1 -0
- package/lib/module/external/reanimated/ReanimatedProxy.js +12 -0
- package/lib/module/external/reanimated/ReanimatedProxy.js.map +1 -0
- package/lib/module/external/reanimated/index.js +3 -0
- package/lib/module/external/reanimated/index.js.map +1 -0
- package/lib/module/external/reanimated/registerWebGPUForReanimated.js +43 -0
- package/lib/module/external/reanimated/registerWebGPUForReanimated.js.map +1 -0
- package/lib/module/main/index.js +2 -141
- package/lib/module/main/index.js.map +1 -1
- package/lib/typescript/babel.config.d.ts +1 -0
- package/lib/typescript/lib/commonjs/external/ModuleProxy.d.ts +12 -0
- package/lib/typescript/lib/commonjs/external/ModuleProxy.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/external/index.d.ts +2 -0
- package/lib/typescript/lib/commonjs/external/index.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/external/reanimated/ReanimatedProxy.d.ts +6 -0
- package/lib/typescript/lib/commonjs/external/reanimated/ReanimatedProxy.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/external/reanimated/index.d.ts +4 -0
- package/lib/typescript/lib/commonjs/external/reanimated/index.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/external/reanimated/registerWebGPUForReanimated.d.ts +9 -0
- package/lib/typescript/lib/commonjs/external/reanimated/registerWebGPUForReanimated.d.ts.map +1 -0
- package/lib/typescript/lib/module/external/ModuleProxy.d.ts +7 -0
- package/lib/typescript/lib/module/external/ModuleProxy.d.ts.map +1 -0
- package/lib/typescript/lib/module/external/index.d.ts +2 -0
- package/lib/typescript/lib/module/external/index.d.ts.map +1 -0
- package/lib/typescript/lib/module/external/reanimated/ReanimatedProxy.d.ts +5 -0
- package/lib/typescript/lib/module/external/reanimated/ReanimatedProxy.d.ts.map +1 -0
- package/lib/typescript/lib/module/external/reanimated/index.d.ts +3 -0
- package/lib/typescript/lib/module/external/reanimated/index.d.ts.map +1 -0
- package/lib/typescript/lib/module/external/reanimated/registerWebGPUForReanimated.d.ts +2 -0
- package/lib/typescript/lib/module/external/reanimated/registerWebGPUForReanimated.d.ts.map +1 -0
- package/lib/typescript/src/external/ModuleProxy.d.ts +11 -0
- package/lib/typescript/src/external/ModuleProxy.d.ts.map +1 -0
- package/lib/typescript/src/external/index.d.ts +2 -0
- package/lib/typescript/src/external/index.d.ts.map +1 -0
- package/lib/typescript/src/external/reanimated/ReanimatedProxy.d.ts +4 -0
- package/lib/typescript/src/external/reanimated/ReanimatedProxy.d.ts.map +1 -0
- package/lib/typescript/src/external/reanimated/index.d.ts +3 -0
- package/lib/typescript/src/external/reanimated/index.d.ts.map +1 -0
- package/lib/typescript/src/external/reanimated/registerWebGPUForReanimated.d.ts +8 -0
- package/lib/typescript/src/external/reanimated/registerWebGPUForReanimated.d.ts.map +1 -0
- package/package.json +16 -3
- package/src/external/ModuleProxy.ts +30 -0
- package/src/external/index.ts +1 -0
- package/src/external/reanimated/ReanimatedProxy.ts +19 -0
- package/src/external/reanimated/index.ts +2 -0
- package/src/external/reanimated/registerWebGPUForReanimated.ts +43 -0
- package/src/main/index.tsx +3 -170
- package/cpp/jsi/RNFHybridObject.cpp +0 -150
- package/cpp/jsi/RNFHybridObject.h +0 -181
- package/cpp/jsi/RNFJSIHelper.h +0 -51
- package/cpp/jsi/RNFPointerHolder.h +0 -95
- package/cpp/jsi/RNFRuntimeState.cpp +0 -18
- package/cpp/jsi/RNFRuntimeState.h +0 -106
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
//
|
|
2
|
+
// NativeObject base class for JSI NativeState pattern
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
#pragma once
|
|
6
|
+
|
|
7
|
+
#include <functional>
|
|
8
|
+
#include <jsi/jsi.h>
|
|
9
|
+
#include <memory>
|
|
10
|
+
#include <mutex>
|
|
11
|
+
#include <optional>
|
|
12
|
+
#include <string>
|
|
13
|
+
#include <type_traits>
|
|
14
|
+
#include <unordered_map>
|
|
15
|
+
#include <utility>
|
|
16
|
+
|
|
17
|
+
#include "RuntimeAwareCache.h"
|
|
18
|
+
#include "WGPULogger.h"
|
|
19
|
+
|
|
20
|
+
// Forward declare to avoid circular dependency
|
|
21
|
+
namespace rnwgpu {
|
|
22
|
+
template <typename ArgType, typename SFINAE> struct JSIConverter;
|
|
23
|
+
} // namespace rnwgpu
|
|
24
|
+
|
|
25
|
+
// Include the converter - must come after forward declaration
|
|
26
|
+
#include "JSIConverter.h"
|
|
27
|
+
|
|
28
|
+
namespace rnwgpu {
|
|
29
|
+
|
|
30
|
+
namespace jsi = facebook::jsi;
|
|
31
|
+
|
|
32
|
+
// Forward declaration
|
|
33
|
+
template <typename Derived> class NativeObject;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Registry for NativeObject prototype installers.
|
|
37
|
+
* This allows BoxedWebGPUObject::unbox() to install prototypes on any runtime
|
|
38
|
+
* by looking up the brand name and calling the appropriate installer.
|
|
39
|
+
*/
|
|
40
|
+
class NativeObjectRegistry {
|
|
41
|
+
public:
|
|
42
|
+
using InstallerFunc = std::function<void(jsi::Runtime &)>;
|
|
43
|
+
|
|
44
|
+
static NativeObjectRegistry &getInstance() {
|
|
45
|
+
static NativeObjectRegistry instance;
|
|
46
|
+
return instance;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
void registerInstaller(const std::string &brand, InstallerFunc installer) {
|
|
50
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
|
51
|
+
_installers[brand] = std::move(installer);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
bool installPrototype(jsi::Runtime &runtime, const std::string &brand) {
|
|
55
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
|
56
|
+
auto it = _installers.find(brand);
|
|
57
|
+
if (it != _installers.end()) {
|
|
58
|
+
it->second(runtime);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private:
|
|
65
|
+
NativeObjectRegistry() = default;
|
|
66
|
+
std::mutex _mutex;
|
|
67
|
+
std::unordered_map<std::string, InstallerFunc> _installers;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Per-runtime cache entry for a prototype object.
|
|
72
|
+
* Uses std::optional<jsi::Object> so the prototype is stored directly
|
|
73
|
+
* without extra indirection.
|
|
74
|
+
*/
|
|
75
|
+
struct PrototypeCacheEntry {
|
|
76
|
+
std::optional<jsi::Object> prototype;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Wrapper for static RuntimeAwareCache that handles hot reload.
|
|
81
|
+
*
|
|
82
|
+
* When used with static storage (like prototype caches), the cache persists
|
|
83
|
+
* across hot reloads. But the JSI objects inside become invalid when the
|
|
84
|
+
* runtime is destroyed. This wrapper tracks which runtime the cache was
|
|
85
|
+
* created for and allocates a new cache when the runtime changes.
|
|
86
|
+
*
|
|
87
|
+
* The old cache is intentionally leaked - we cannot safely destroy JSI
|
|
88
|
+
* objects after their runtime is gone.
|
|
89
|
+
*/
|
|
90
|
+
template <typename T> struct StaticRuntimeAwareCache {
|
|
91
|
+
RuntimeAwareCache<T> *cache = nullptr;
|
|
92
|
+
jsi::Runtime *cacheRuntime = nullptr;
|
|
93
|
+
|
|
94
|
+
RuntimeAwareCache<T> &get(jsi::Runtime &rt) {
|
|
95
|
+
auto mainRuntime = BaseRuntimeAwareCache::getMainJsRuntime();
|
|
96
|
+
if (&rt == mainRuntime && cacheRuntime != mainRuntime) {
|
|
97
|
+
// Main runtime changed (hot reload) - allocate new cache, leak old one
|
|
98
|
+
cache = new RuntimeAwareCache<T>();
|
|
99
|
+
cacheRuntime = mainRuntime;
|
|
100
|
+
}
|
|
101
|
+
if (cache == nullptr) {
|
|
102
|
+
cache = new RuntimeAwareCache<T>();
|
|
103
|
+
cacheRuntime = mainRuntime;
|
|
104
|
+
}
|
|
105
|
+
return *cache;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* BoxedWebGPUObject is a HostObject wrapper that holds a reference to ANY
|
|
111
|
+
* WebGPU NativeObject. This is used for Reanimated/Worklets serialization.
|
|
112
|
+
*
|
|
113
|
+
* Since NativeObject uses NativeState (not HostObject), Worklets can't
|
|
114
|
+
* serialize them directly. But Worklets CAN serialize HostObjects.
|
|
115
|
+
*
|
|
116
|
+
* This class stores:
|
|
117
|
+
* - The NativeState from the original object
|
|
118
|
+
* - The brand name for prototype reconstruction
|
|
119
|
+
*
|
|
120
|
+
* Usage pattern with registerCustomSerializable:
|
|
121
|
+
* - pack(): Call WebGPU.box(obj) to create a BoxedWebGPUObject (HostObject)
|
|
122
|
+
* - The HostObject is serialized by Worklets and transferred to UI runtime
|
|
123
|
+
* - unpack(): Call boxed.unbox() to get back the original object with prototype
|
|
124
|
+
*
|
|
125
|
+
* This is similar to NitroModules.box()/unbox() pattern.
|
|
126
|
+
*/
|
|
127
|
+
class BoxedWebGPUObject : public jsi::HostObject {
|
|
128
|
+
public:
|
|
129
|
+
BoxedWebGPUObject(std::shared_ptr<jsi::NativeState> nativeState,
|
|
130
|
+
const std::string &brand)
|
|
131
|
+
: _nativeState(std::move(nativeState)), _brand(brand) {}
|
|
132
|
+
|
|
133
|
+
jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &name) override {
|
|
134
|
+
auto propName = name.utf8(runtime);
|
|
135
|
+
if (propName == "unbox") {
|
|
136
|
+
return jsi::Function::createFromHostFunction(
|
|
137
|
+
runtime, jsi::PropNameID::forUtf8(runtime, "unbox"), 0,
|
|
138
|
+
[this](jsi::Runtime &rt, const jsi::Value & /*thisVal*/,
|
|
139
|
+
const jsi::Value * /*args*/,
|
|
140
|
+
size_t /*count*/) -> jsi::Value {
|
|
141
|
+
// Try to get the prototype from the global constructor
|
|
142
|
+
auto ctor = rt.global().getProperty(rt, _brand.c_str());
|
|
143
|
+
if (!ctor.isObject()) {
|
|
144
|
+
// Constructor doesn't exist on this runtime - install it
|
|
145
|
+
NativeObjectRegistry::getInstance().installPrototype(rt, _brand);
|
|
146
|
+
ctor = rt.global().getProperty(rt, _brand.c_str());
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Create a new object and attach the native state
|
|
150
|
+
jsi::Object obj(rt);
|
|
151
|
+
obj.setNativeState(rt, _nativeState);
|
|
152
|
+
|
|
153
|
+
// Set the prototype if constructor exists
|
|
154
|
+
if (ctor.isObject()) {
|
|
155
|
+
auto ctorObj = ctor.getObject(rt);
|
|
156
|
+
auto proto = ctorObj.getProperty(rt, "prototype");
|
|
157
|
+
if (proto.isObject()) {
|
|
158
|
+
auto objectCtor =
|
|
159
|
+
rt.global().getPropertyAsObject(rt, "Object");
|
|
160
|
+
auto setPrototypeOf =
|
|
161
|
+
objectCtor.getPropertyAsFunction(rt, "setPrototypeOf");
|
|
162
|
+
setPrototypeOf.call(rt, obj, proto);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return std::move(obj);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
if (propName == "__boxedWebGPU") {
|
|
170
|
+
return jsi::Value(true);
|
|
171
|
+
}
|
|
172
|
+
if (propName == "__brand") {
|
|
173
|
+
return jsi::String::createFromUtf8(runtime, _brand);
|
|
174
|
+
}
|
|
175
|
+
return jsi::Value::undefined();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
void set(jsi::Runtime &runtime, const jsi::PropNameID &name,
|
|
179
|
+
const jsi::Value &value) override {
|
|
180
|
+
throw jsi::JSError(runtime, "BoxedWebGPUObject is read-only");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
std::vector<jsi::PropNameID>
|
|
184
|
+
getPropertyNames(jsi::Runtime &runtime) override {
|
|
185
|
+
std::vector<jsi::PropNameID> names;
|
|
186
|
+
names.reserve(3);
|
|
187
|
+
names.push_back(jsi::PropNameID::forUtf8(runtime, "unbox"));
|
|
188
|
+
names.push_back(jsi::PropNameID::forUtf8(runtime, "__boxedWebGPU"));
|
|
189
|
+
names.push_back(jsi::PropNameID::forUtf8(runtime, "__brand"));
|
|
190
|
+
return names;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private:
|
|
194
|
+
std::shared_ptr<jsi::NativeState> _nativeState;
|
|
195
|
+
std::string _brand;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Base class for native objects using the NativeState pattern.
|
|
200
|
+
*
|
|
201
|
+
* Instead of using HostObject (which intercepts all property access),
|
|
202
|
+
* this pattern:
|
|
203
|
+
* 1. Stores native data via jsi::Object::setNativeState()
|
|
204
|
+
* 2. Installs methods on a shared prototype object (once per runtime)
|
|
205
|
+
* 3. Creates plain JS objects that use the prototype chain
|
|
206
|
+
*
|
|
207
|
+
* Usage:
|
|
208
|
+
* ```cpp
|
|
209
|
+
* class MyClass : public NativeObject<MyClass> {
|
|
210
|
+
* public:
|
|
211
|
+
* static constexpr const char* CLASS_NAME = "MyClass";
|
|
212
|
+
*
|
|
213
|
+
* MyClass(...) : NativeObject(CLASS_NAME), ... {}
|
|
214
|
+
*
|
|
215
|
+
* std::string getValue() { return _value; }
|
|
216
|
+
*
|
|
217
|
+
* static void definePrototype(jsi::Runtime& rt, jsi::Object& proto) {
|
|
218
|
+
* installGetter(rt, proto, "value", &MyClass::getValue);
|
|
219
|
+
* }
|
|
220
|
+
*
|
|
221
|
+
* private:
|
|
222
|
+
* std::string _value;
|
|
223
|
+
* };
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
template <typename Derived>
|
|
227
|
+
class NativeObject : public jsi::NativeState,
|
|
228
|
+
public std::enable_shared_from_this<Derived> {
|
|
229
|
+
public:
|
|
230
|
+
// Marker type for SFINAE detection in JSIConverter
|
|
231
|
+
using IsNativeObject = std::true_type;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Get the prototype cache for this type.
|
|
235
|
+
* Each NativeObject<Derived> type has its own static cache.
|
|
236
|
+
* Uses StaticRuntimeAwareCache to properly handle runtime lifecycle
|
|
237
|
+
* and hot reload (where the main runtime is destroyed and recreated).
|
|
238
|
+
*/
|
|
239
|
+
static RuntimeAwareCache<PrototypeCacheEntry> &
|
|
240
|
+
getPrototypeCache(jsi::Runtime &runtime) {
|
|
241
|
+
static StaticRuntimeAwareCache<PrototypeCacheEntry> cache;
|
|
242
|
+
return cache.get(runtime);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Ensure the prototype is installed for this runtime.
|
|
247
|
+
* Called automatically by create(), but can be called manually.
|
|
248
|
+
*/
|
|
249
|
+
static void installPrototype(jsi::Runtime &runtime) {
|
|
250
|
+
auto &entry = getPrototypeCache(runtime).get(runtime);
|
|
251
|
+
if (entry.prototype.has_value()) {
|
|
252
|
+
return; // Already installed
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Create prototype object
|
|
256
|
+
jsi::Object prototype(runtime);
|
|
257
|
+
|
|
258
|
+
// Let derived class define its methods/properties
|
|
259
|
+
Derived::definePrototype(runtime, prototype);
|
|
260
|
+
|
|
261
|
+
// Add Symbol.toStringTag for proper object identification in console.log
|
|
262
|
+
auto symbolCtor = runtime.global().getPropertyAsObject(runtime, "Symbol");
|
|
263
|
+
auto toStringTag = symbolCtor.getProperty(runtime, "toStringTag");
|
|
264
|
+
if (!toStringTag.isUndefined()) {
|
|
265
|
+
// Use Object.defineProperty to set symbol property since setProperty
|
|
266
|
+
// doesn't support symbols directly
|
|
267
|
+
auto objectCtor =
|
|
268
|
+
runtime.global().getPropertyAsObject(runtime, "Object");
|
|
269
|
+
auto defineProperty =
|
|
270
|
+
objectCtor.getPropertyAsFunction(runtime, "defineProperty");
|
|
271
|
+
jsi::Object descriptor(runtime);
|
|
272
|
+
descriptor.setProperty(
|
|
273
|
+
runtime, "value",
|
|
274
|
+
jsi::String::createFromUtf8(runtime, Derived::CLASS_NAME));
|
|
275
|
+
descriptor.setProperty(runtime, "writable", false);
|
|
276
|
+
descriptor.setProperty(runtime, "enumerable", false);
|
|
277
|
+
descriptor.setProperty(runtime, "configurable", true);
|
|
278
|
+
defineProperty.call(runtime, prototype, toStringTag, descriptor);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Cache the prototype
|
|
282
|
+
entry.prototype = std::move(prototype);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Install a constructor function on the global object.
|
|
287
|
+
* This enables `instanceof` checks: `obj instanceof ClassName`
|
|
288
|
+
*
|
|
289
|
+
* The constructor throws if called directly (these objects are only
|
|
290
|
+
* created internally by the native code).
|
|
291
|
+
*
|
|
292
|
+
* Also registers this class with NativeObjectRegistry so that
|
|
293
|
+
* BoxedWebGPUObject::unbox() can install prototypes on secondary runtimes.
|
|
294
|
+
*/
|
|
295
|
+
static void installConstructor(jsi::Runtime &runtime) {
|
|
296
|
+
// Register this class's installer in the registry (only needs to happen once)
|
|
297
|
+
static std::once_flag registryFlag;
|
|
298
|
+
std::call_once(registryFlag, []() {
|
|
299
|
+
NativeObjectRegistry::getInstance().registerInstaller(
|
|
300
|
+
Derived::CLASS_NAME,
|
|
301
|
+
[](jsi::Runtime &rt) { Derived::installConstructor(rt); });
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
installPrototype(runtime);
|
|
305
|
+
|
|
306
|
+
auto &entry = getPrototypeCache(runtime).get(runtime);
|
|
307
|
+
if (!entry.prototype.has_value()) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Create a constructor function that throws when called directly
|
|
312
|
+
auto ctor = jsi::Function::createFromHostFunction(
|
|
313
|
+
runtime, jsi::PropNameID::forUtf8(runtime, Derived::CLASS_NAME), 0,
|
|
314
|
+
[](jsi::Runtime &rt, const jsi::Value & /*thisVal*/,
|
|
315
|
+
const jsi::Value * /*args*/, size_t /*count*/) -> jsi::Value {
|
|
316
|
+
throw jsi::JSError(
|
|
317
|
+
rt, std::string("Illegal constructor: ") + Derived::CLASS_NAME +
|
|
318
|
+
" objects are created by the WebGPU API");
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// Set the prototype property on the constructor
|
|
322
|
+
// This is what makes `instanceof` work
|
|
323
|
+
ctor.setProperty(runtime, "prototype", *entry.prototype);
|
|
324
|
+
|
|
325
|
+
// Set constructor property on prototype pointing back to constructor
|
|
326
|
+
entry.prototype->setProperty(runtime, "constructor", ctor);
|
|
327
|
+
|
|
328
|
+
// Install on global
|
|
329
|
+
runtime.global().setProperty(runtime, Derived::CLASS_NAME, std::move(ctor));
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Create a JS object with native state attached.
|
|
334
|
+
*/
|
|
335
|
+
static jsi::Value create(jsi::Runtime &runtime,
|
|
336
|
+
std::shared_ptr<Derived> instance) {
|
|
337
|
+
installPrototype(runtime);
|
|
338
|
+
|
|
339
|
+
// Store creation runtime for logging etc.
|
|
340
|
+
instance->setCreationRuntime(&runtime);
|
|
341
|
+
|
|
342
|
+
// Create a new object
|
|
343
|
+
jsi::Object obj(runtime);
|
|
344
|
+
|
|
345
|
+
// Attach native state
|
|
346
|
+
obj.setNativeState(runtime, instance);
|
|
347
|
+
|
|
348
|
+
// Set prototype
|
|
349
|
+
auto &entry = getPrototypeCache(runtime).get(runtime);
|
|
350
|
+
if (entry.prototype.has_value()) {
|
|
351
|
+
// Use Object.setPrototypeOf to set the prototype
|
|
352
|
+
auto objectCtor =
|
|
353
|
+
runtime.global().getPropertyAsObject(runtime, "Object");
|
|
354
|
+
auto setPrototypeOf =
|
|
355
|
+
objectCtor.getPropertyAsFunction(runtime, "setPrototypeOf");
|
|
356
|
+
setPrototypeOf.call(runtime, obj, *entry.prototype);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Set memory pressure hint for GC
|
|
360
|
+
auto pressure = instance->getMemoryPressure();
|
|
361
|
+
if (pressure > 0) {
|
|
362
|
+
obj.setExternalMemoryPressure(runtime, pressure);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return std::move(obj);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Get the native state from a JS value.
|
|
370
|
+
* Throws if the value doesn't have the expected native state.
|
|
371
|
+
*/
|
|
372
|
+
static std::shared_ptr<Derived> fromValue(jsi::Runtime &runtime,
|
|
373
|
+
const jsi::Value &value) {
|
|
374
|
+
if (!value.isObject()) {
|
|
375
|
+
throw jsi::JSError(runtime, std::string("Expected ") +
|
|
376
|
+
Derived::CLASS_NAME +
|
|
377
|
+
" but got non-object");
|
|
378
|
+
}
|
|
379
|
+
jsi::Object obj = value.getObject(runtime);
|
|
380
|
+
if (!obj.hasNativeState<Derived>(runtime)) {
|
|
381
|
+
throw jsi::JSError(runtime, std::string("Expected ") +
|
|
382
|
+
Derived::CLASS_NAME +
|
|
383
|
+
" but got different type");
|
|
384
|
+
}
|
|
385
|
+
return obj.getNativeState<Derived>(runtime);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Memory pressure for GC hints. Override in derived classes.
|
|
390
|
+
*/
|
|
391
|
+
virtual size_t getMemoryPressure() { return 1024; }
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Set the creation runtime. Called during create().
|
|
395
|
+
*/
|
|
396
|
+
void setCreationRuntime(jsi::Runtime *runtime) { _creationRuntime = runtime; }
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Get the creation runtime.
|
|
400
|
+
* WARNING: This pointer may become invalid if the runtime is destroyed.
|
|
401
|
+
*/
|
|
402
|
+
jsi::Runtime *getCreationRuntime() const { return _creationRuntime; }
|
|
403
|
+
|
|
404
|
+
protected:
|
|
405
|
+
explicit NativeObject(const char *name) : _name(name) {
|
|
406
|
+
#if DEBUG && RNF_ENABLE_LOGS
|
|
407
|
+
Logger::logToConsole("NativeObject", "(MEMORY) Creating %s... ✅", _name);
|
|
408
|
+
#endif
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
virtual ~NativeObject() {
|
|
412
|
+
#if DEBUG && RNF_ENABLE_LOGS
|
|
413
|
+
Logger::log("NativeObject", "(MEMORY) Deleting %s... ❌", _name);
|
|
414
|
+
#endif
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
const char *_name;
|
|
418
|
+
jsi::Runtime *_creationRuntime = nullptr;
|
|
419
|
+
|
|
420
|
+
// ============================================================
|
|
421
|
+
// Helper methods for definePrototype() implementations
|
|
422
|
+
// ============================================================
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Install a method on the prototype.
|
|
426
|
+
*/
|
|
427
|
+
template <typename ReturnType, typename... Args>
|
|
428
|
+
static void installMethod(jsi::Runtime &runtime, jsi::Object &prototype,
|
|
429
|
+
const char *name,
|
|
430
|
+
ReturnType (Derived::*method)(Args...)) {
|
|
431
|
+
auto func = jsi::Function::createFromHostFunction(
|
|
432
|
+
runtime, jsi::PropNameID::forUtf8(runtime, name), sizeof...(Args),
|
|
433
|
+
[method](jsi::Runtime &rt, const jsi::Value &thisVal,
|
|
434
|
+
const jsi::Value *args, size_t count) -> jsi::Value {
|
|
435
|
+
auto native = Derived::fromValue(rt, thisVal);
|
|
436
|
+
return callMethod(native.get(), method, rt, args,
|
|
437
|
+
std::index_sequence_for<Args...>{}, count);
|
|
438
|
+
});
|
|
439
|
+
prototype.setProperty(runtime, name, func);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Install a getter on the prototype.
|
|
444
|
+
*/
|
|
445
|
+
template <typename ReturnType>
|
|
446
|
+
static void installGetter(jsi::Runtime &runtime, jsi::Object &prototype,
|
|
447
|
+
const char *name, ReturnType (Derived::*getter)()) {
|
|
448
|
+
// Create a getter function
|
|
449
|
+
auto getterFunc = jsi::Function::createFromHostFunction(
|
|
450
|
+
runtime, jsi::PropNameID::forUtf8(runtime, std::string("get_") + name),
|
|
451
|
+
0,
|
|
452
|
+
[getter](jsi::Runtime &rt, const jsi::Value &thisVal,
|
|
453
|
+
const jsi::Value *args, size_t count) -> jsi::Value {
|
|
454
|
+
auto native = Derived::fromValue(rt, thisVal);
|
|
455
|
+
if constexpr (std::is_same_v<ReturnType, void>) {
|
|
456
|
+
(native.get()->*getter)();
|
|
457
|
+
return jsi::Value::undefined();
|
|
458
|
+
} else {
|
|
459
|
+
ReturnType result = (native.get()->*getter)();
|
|
460
|
+
return rnwgpu::JSIConverter<std::decay_t<ReturnType>>::toJSI(
|
|
461
|
+
rt, std::move(result));
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
// Use Object.defineProperty to create a proper getter
|
|
466
|
+
auto objectCtor = runtime.global().getPropertyAsObject(runtime, "Object");
|
|
467
|
+
auto defineProperty =
|
|
468
|
+
objectCtor.getPropertyAsFunction(runtime, "defineProperty");
|
|
469
|
+
|
|
470
|
+
jsi::Object descriptor(runtime);
|
|
471
|
+
descriptor.setProperty(runtime, "get", getterFunc);
|
|
472
|
+
descriptor.setProperty(runtime, "enumerable", true);
|
|
473
|
+
descriptor.setProperty(runtime, "configurable", true);
|
|
474
|
+
|
|
475
|
+
defineProperty.call(runtime, prototype,
|
|
476
|
+
jsi::String::createFromUtf8(runtime, name), descriptor);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Install a setter on the prototype.
|
|
481
|
+
*/
|
|
482
|
+
template <typename ValueType>
|
|
483
|
+
static void installSetter(jsi::Runtime &runtime, jsi::Object &prototype,
|
|
484
|
+
const char *name,
|
|
485
|
+
void (Derived::*setter)(ValueType)) {
|
|
486
|
+
auto setterFunc = jsi::Function::createFromHostFunction(
|
|
487
|
+
runtime, jsi::PropNameID::forUtf8(runtime, std::string("set_") + name),
|
|
488
|
+
1,
|
|
489
|
+
[setter](jsi::Runtime &rt, const jsi::Value &thisVal,
|
|
490
|
+
const jsi::Value *args, size_t count) -> jsi::Value {
|
|
491
|
+
if (count < 1) {
|
|
492
|
+
throw jsi::JSError(rt, "Setter requires a value argument");
|
|
493
|
+
}
|
|
494
|
+
auto native = Derived::fromValue(rt, thisVal);
|
|
495
|
+
auto value =
|
|
496
|
+
rnwgpu::JSIConverter<std::decay_t<ValueType>>::fromJSI(rt, args[0], false);
|
|
497
|
+
(native.get()->*setter)(std::move(value));
|
|
498
|
+
return jsi::Value::undefined();
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
// Use Object.defineProperty to create a proper setter
|
|
502
|
+
auto objectCtor = runtime.global().getPropertyAsObject(runtime, "Object");
|
|
503
|
+
auto defineProperty =
|
|
504
|
+
objectCtor.getPropertyAsFunction(runtime, "defineProperty");
|
|
505
|
+
|
|
506
|
+
// Check if property already has a getter
|
|
507
|
+
auto getOwnPropertyDescriptor =
|
|
508
|
+
objectCtor.getPropertyAsFunction(runtime, "getOwnPropertyDescriptor");
|
|
509
|
+
auto existingDesc = getOwnPropertyDescriptor.call(
|
|
510
|
+
runtime, prototype, jsi::String::createFromUtf8(runtime, name));
|
|
511
|
+
|
|
512
|
+
jsi::Object descriptor(runtime);
|
|
513
|
+
if (existingDesc.isObject()) {
|
|
514
|
+
auto existingDescObj = existingDesc.getObject(runtime);
|
|
515
|
+
if (existingDescObj.hasProperty(runtime, "get")) {
|
|
516
|
+
descriptor.setProperty(
|
|
517
|
+
runtime, "get", existingDescObj.getProperty(runtime, "get"));
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
descriptor.setProperty(runtime, "set", setterFunc);
|
|
521
|
+
descriptor.setProperty(runtime, "enumerable", true);
|
|
522
|
+
descriptor.setProperty(runtime, "configurable", true);
|
|
523
|
+
|
|
524
|
+
defineProperty.call(runtime, prototype,
|
|
525
|
+
jsi::String::createFromUtf8(runtime, name), descriptor);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Install both getter and setter for a property.
|
|
530
|
+
*/
|
|
531
|
+
template <typename ReturnType, typename ValueType>
|
|
532
|
+
static void installGetterSetter(jsi::Runtime &runtime, jsi::Object &prototype,
|
|
533
|
+
const char *name,
|
|
534
|
+
ReturnType (Derived::*getter)(),
|
|
535
|
+
void (Derived::*setter)(ValueType)) {
|
|
536
|
+
auto getterFunc = jsi::Function::createFromHostFunction(
|
|
537
|
+
runtime, jsi::PropNameID::forUtf8(runtime, std::string("get_") + name),
|
|
538
|
+
0,
|
|
539
|
+
[getter](jsi::Runtime &rt, const jsi::Value &thisVal,
|
|
540
|
+
const jsi::Value *args, size_t count) -> jsi::Value {
|
|
541
|
+
auto native = Derived::fromValue(rt, thisVal);
|
|
542
|
+
ReturnType result = (native.get()->*getter)();
|
|
543
|
+
return rnwgpu::JSIConverter<std::decay_t<ReturnType>>::toJSI(rt,
|
|
544
|
+
std::move(result));
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
auto setterFunc = jsi::Function::createFromHostFunction(
|
|
548
|
+
runtime, jsi::PropNameID::forUtf8(runtime, std::string("set_") + name),
|
|
549
|
+
1,
|
|
550
|
+
[setter](jsi::Runtime &rt, const jsi::Value &thisVal,
|
|
551
|
+
const jsi::Value *args, size_t count) -> jsi::Value {
|
|
552
|
+
if (count < 1) {
|
|
553
|
+
throw jsi::JSError(rt, "Setter requires a value argument");
|
|
554
|
+
}
|
|
555
|
+
auto native = Derived::fromValue(rt, thisVal);
|
|
556
|
+
auto value =
|
|
557
|
+
rnwgpu::JSIConverter<std::decay_t<ValueType>>::fromJSI(rt, args[0], false);
|
|
558
|
+
(native.get()->*setter)(std::move(value));
|
|
559
|
+
return jsi::Value::undefined();
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
auto objectCtor = runtime.global().getPropertyAsObject(runtime, "Object");
|
|
563
|
+
auto defineProperty =
|
|
564
|
+
objectCtor.getPropertyAsFunction(runtime, "defineProperty");
|
|
565
|
+
|
|
566
|
+
jsi::Object descriptor(runtime);
|
|
567
|
+
descriptor.setProperty(runtime, "get", getterFunc);
|
|
568
|
+
descriptor.setProperty(runtime, "set", setterFunc);
|
|
569
|
+
descriptor.setProperty(runtime, "enumerable", true);
|
|
570
|
+
descriptor.setProperty(runtime, "configurable", true);
|
|
571
|
+
|
|
572
|
+
defineProperty.call(runtime, prototype,
|
|
573
|
+
jsi::String::createFromUtf8(runtime, name), descriptor);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
private:
|
|
577
|
+
// Helper to call a method with JSI argument conversion
|
|
578
|
+
template <typename ReturnType, typename... Args, size_t... Is>
|
|
579
|
+
static jsi::Value callMethod(Derived *obj,
|
|
580
|
+
ReturnType (Derived::*method)(Args...),
|
|
581
|
+
jsi::Runtime &runtime, const jsi::Value *args,
|
|
582
|
+
std::index_sequence<Is...>, size_t count) {
|
|
583
|
+
if constexpr (std::is_same_v<ReturnType, void>) {
|
|
584
|
+
(obj->*method)(rnwgpu::JSIConverter<std::decay_t<Args>>::fromJSI(
|
|
585
|
+
runtime, args[Is], Is >= count)...);
|
|
586
|
+
return jsi::Value::undefined();
|
|
587
|
+
} else if constexpr (std::is_same_v<ReturnType, jsi::Value>) {
|
|
588
|
+
// Special case: if return type is jsi::Value, method has full control
|
|
589
|
+
// This requires the method signature to match HostFunction
|
|
590
|
+
return (obj->*method)(runtime, jsi::Value::undefined(), args, count);
|
|
591
|
+
} else {
|
|
592
|
+
ReturnType result = (obj->*method)(rnwgpu::JSIConverter<std::decay_t<Args>>::fromJSI(
|
|
593
|
+
runtime, args[Is], Is >= count)...);
|
|
594
|
+
return rnwgpu::JSIConverter<std::decay_t<ReturnType>>::toJSI(runtime,
|
|
595
|
+
std::move(result));
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
// Type trait to detect NativeObject-derived classes
|
|
601
|
+
template <typename T> struct is_native_object : std::false_type {};
|
|
602
|
+
|
|
603
|
+
template <typename T>
|
|
604
|
+
struct is_native_object<std::shared_ptr<T>>
|
|
605
|
+
: std::bool_constant<std::is_base_of_v<NativeObject<T>, T>> {};
|
|
606
|
+
|
|
607
|
+
} // namespace rnwgpu
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
// Created by Marc Rousavy on 22.02.24.
|
|
3
|
-
//
|
|
4
|
-
#include "RNFPromise.h"
|
|
1
|
+
#include "Promise.h"
|
|
5
2
|
#include <future>
|
|
6
3
|
#include <jsi/jsi.h>
|
|
7
4
|
#include <memory>
|
|
@@ -9,7 +6,7 @@
|
|
|
9
6
|
#include <utility>
|
|
10
7
|
#include <vector>
|
|
11
8
|
|
|
12
|
-
namespace
|
|
9
|
+
namespace rnwgpu {
|
|
13
10
|
|
|
14
11
|
namespace jsi = facebook::jsi;
|
|
15
12
|
|
|
@@ -44,4 +41,4 @@ void Promise::reject(std::string message) {
|
|
|
44
41
|
_rejecter.call(runtime, error.value());
|
|
45
42
|
}
|
|
46
43
|
|
|
47
|
-
} // namespace
|
|
44
|
+
} // namespace rnwgpu
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Created by Marc Rousavy on 22.02.24.
|
|
3
|
-
//
|
|
4
1
|
#pragma once
|
|
5
2
|
|
|
6
3
|
#include <jsi/jsi.h>
|
|
@@ -9,7 +6,7 @@
|
|
|
9
6
|
#include <string>
|
|
10
7
|
#include <memory>
|
|
11
8
|
|
|
12
|
-
namespace
|
|
9
|
+
namespace rnwgpu {
|
|
13
10
|
|
|
14
11
|
namespace jsi = facebook::jsi;
|
|
15
12
|
|
|
@@ -35,4 +32,4 @@ public:
|
|
|
35
32
|
static jsi::Value createPromise(jsi::Runtime& runtime, RunPromise run);
|
|
36
33
|
};
|
|
37
34
|
|
|
38
|
-
} // namespace
|
|
35
|
+
} // namespace rnwgpu
|