react-native-wgpu 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +31 -0
- package/android/CMakeLists.txt +74 -0
- package/android/build.gradle +166 -0
- package/android/cpp/cpp-adapter.cpp +12 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/AndroidManifestNew.xml +2 -0
- package/android/src/main/java/com/webgpu/WebGPUModule.java +39 -0
- package/android/src/main/java/com/webgpu/WebGPUView.java +24 -0
- package/android/src/main/java/com/webgpu/WebGPUViewManager.java +31 -0
- package/android/src/main/java/com/webgpu/WebGPUViewPackage.java +26 -0
- package/android/src/newarch/WgpuViewManagerSpec.java +24 -0
- package/android/src/oldarch/WebGPUViewManagerSpec.java +11 -0
- package/cpp/Logger.h +82 -0
- package/cpp/dawn/dawn_proc_table.h +308 -0
- package/cpp/dawn/webgpu.h +4201 -0
- package/cpp/dawn/webgpu_cpp.h +8985 -0
- package/cpp/dawn/webgpu_cpp_print.h +2460 -0
- package/cpp/dawn/wire/client/webgpu.h +339 -0
- package/cpp/dawn/wire/client/webgpu_cpp.h +9140 -0
- package/cpp/jsi/RNFEnumMapper.h +49 -0
- package/cpp/jsi/RNFHybridObject.cpp +145 -0
- package/cpp/jsi/RNFHybridObject.h +162 -0
- package/cpp/jsi/RNFJSIConverter.h +412 -0
- package/cpp/jsi/RNFJSIHelper.h +49 -0
- package/cpp/jsi/RNFPointerHolder.h +95 -0
- package/cpp/jsi/RNFPromise.cpp +45 -0
- package/cpp/jsi/RNFPromise.h +38 -0
- package/cpp/jsi/RNFRuntimeCache.cpp +57 -0
- package/cpp/jsi/RNFRuntimeCache.h +79 -0
- package/cpp/jsi/RNFWorkletRuntimeCollector.h +43 -0
- package/cpp/jsi/RNFWorkletRuntimeRegistry.cpp +11 -0
- package/cpp/jsi/RNFWorkletRuntimeRegistry.h +44 -0
- package/cpp/rnwgpu/MutableBuffer.h +48 -0
- package/cpp/rnwgpu/RNWebGPUManager.cpp +60 -0
- package/cpp/rnwgpu/RNWebGPUManager.h +30 -0
- package/cpp/rnwgpu/api/GPU.cpp +40 -0
- package/cpp/rnwgpu/api/GPU.h +43 -0
- package/cpp/rnwgpu/api/GPUAdapter.cpp +33 -0
- package/cpp/rnwgpu/api/GPUAdapter.h +40 -0
- package/cpp/rnwgpu/api/GPUAdapterInfo.h +33 -0
- package/cpp/rnwgpu/api/GPUBindGroup.h +38 -0
- package/cpp/rnwgpu/api/GPUBindGroupLayout.h +39 -0
- package/cpp/rnwgpu/api/GPUBuffer.cpp +16 -0
- package/cpp/rnwgpu/api/GPUBuffer.h +44 -0
- package/cpp/rnwgpu/api/GPUCanvasContext.h +33 -0
- package/cpp/rnwgpu/api/GPUCommandBuffer.h +38 -0
- package/cpp/rnwgpu/api/GPUCommandEncoder.h +38 -0
- package/cpp/rnwgpu/api/GPUCompilationInfo.h +33 -0
- package/cpp/rnwgpu/api/GPUCompilationMessage.h +33 -0
- package/cpp/rnwgpu/api/GPUComputePassEncoder.h +40 -0
- package/cpp/rnwgpu/api/GPUComputePipeline.h +39 -0
- package/cpp/rnwgpu/api/GPUDevice.cpp +12 -0
- package/cpp/rnwgpu/api/GPUDevice.h +45 -0
- package/cpp/rnwgpu/api/GPUDeviceLostInfo.h +33 -0
- package/cpp/rnwgpu/api/GPUExternalTexture.h +39 -0
- package/cpp/rnwgpu/api/GPUPipelineLayout.h +38 -0
- package/cpp/rnwgpu/api/GPUQuerySet.h +38 -0
- package/cpp/rnwgpu/api/GPUQueue.h +38 -0
- package/cpp/rnwgpu/api/GPURenderBundle.h +38 -0
- package/cpp/rnwgpu/api/GPURenderBundleEncoder.h +40 -0
- package/cpp/rnwgpu/api/GPURenderPassEncoder.h +40 -0
- package/cpp/rnwgpu/api/GPURenderPipeline.h +38 -0
- package/cpp/rnwgpu/api/GPUSampler.h +38 -0
- package/cpp/rnwgpu/api/GPUShaderModule.h +38 -0
- package/cpp/rnwgpu/api/GPUSupportedLimits.h +33 -0
- package/cpp/rnwgpu/api/GPUTexture.h +38 -0
- package/cpp/rnwgpu/api/GPUTextureView.h +38 -0
- package/cpp/rnwgpu/api/GPUUncapturedErrorEvent.h +33 -0
- package/cpp/rnwgpu/api/descriptors/GPUBindGroupDescriptor.h +81 -0
- package/cpp/rnwgpu/api/descriptors/GPUBindGroupEntry.h +67 -0
- package/cpp/rnwgpu/api/descriptors/GPUBindGroupLayoutDescriptor.h +69 -0
- package/cpp/rnwgpu/api/descriptors/GPUBindGroupLayoutEntry.h +95 -0
- package/cpp/rnwgpu/api/descriptors/GPUBlendComponent.h +56 -0
- package/cpp/rnwgpu/api/descriptors/GPUBlendState.h +65 -0
- package/cpp/rnwgpu/api/descriptors/GPUBufferBinding.h +72 -0
- package/cpp/rnwgpu/api/descriptors/GPUBufferBindingLayout.h +62 -0
- package/cpp/rnwgpu/api/descriptors/GPUBufferDescriptor.h +85 -0
- package/cpp/rnwgpu/api/descriptors/GPUBufferUsage.h +43 -0
- package/cpp/rnwgpu/api/descriptors/GPUCanvasConfiguration.h +93 -0
- package/cpp/rnwgpu/api/descriptors/GPUColorDict.h +81 -0
- package/cpp/rnwgpu/api/descriptors/GPUColorTargetState.h +69 -0
- package/cpp/rnwgpu/api/descriptors/GPUColorWrite.h +31 -0
- package/cpp/rnwgpu/api/descriptors/GPUComputePassDescriptor.h +62 -0
- package/cpp/rnwgpu/api/descriptors/GPUComputePassTimestampWrites.h +80 -0
- package/cpp/rnwgpu/api/descriptors/GPUComputePipelineDescriptor.h +82 -0
- package/cpp/rnwgpu/api/descriptors/GPUDepthStencilState.h +126 -0
- package/cpp/rnwgpu/api/descriptors/GPUDeviceDescriptor.h +69 -0
- package/cpp/rnwgpu/api/descriptors/GPUExtent3DDict.h +76 -0
- package/cpp/rnwgpu/api/descriptors/GPUExtent3DDictStrict.h +91 -0
- package/cpp/rnwgpu/api/descriptors/GPUExternalTextureBindingLayout.h +44 -0
- package/cpp/rnwgpu/api/descriptors/GPUExternalTextureDescriptor.h +75 -0
- package/cpp/rnwgpu/api/descriptors/GPUFragmentState.h +85 -0
- package/cpp/rnwgpu/api/descriptors/GPUImageCopyBuffer.h +83 -0
- package/cpp/rnwgpu/api/descriptors/GPUImageCopyExternalImage.h +66 -0
- package/cpp/rnwgpu/api/descriptors/GPUImageCopyTexture.h +74 -0
- package/cpp/rnwgpu/api/descriptors/GPUImageCopyTextureTagged.h +88 -0
- package/cpp/rnwgpu/api/descriptors/GPUImageDataLayout.h +70 -0
- package/cpp/rnwgpu/api/descriptors/GPUMapMode.h +25 -0
- package/cpp/rnwgpu/api/descriptors/GPUMultisampleState.h +68 -0
- package/cpp/rnwgpu/api/descriptors/GPUOrigin2DDict.h +61 -0
- package/cpp/rnwgpu/api/descriptors/GPUOrigin2DDictStrict.h +75 -0
- package/cpp/rnwgpu/api/descriptors/GPUOrigin3DDict.h +71 -0
- package/cpp/rnwgpu/api/descriptors/GPUPipelineErrorInit.h +54 -0
- package/cpp/rnwgpu/api/descriptors/GPUPipelineLayoutDescriptor.h +72 -0
- package/cpp/rnwgpu/api/descriptors/GPUPrimitiveState.h +66 -0
- package/cpp/rnwgpu/api/descriptors/GPUProgrammableStage.h +72 -0
- package/cpp/rnwgpu/api/descriptors/GPUQuerySetDescriptor.h +81 -0
- package/cpp/rnwgpu/api/descriptors/GPURenderBundleEncoderDescriptor.h +102 -0
- package/cpp/rnwgpu/api/descriptors/GPURenderPassColorAttachment.h +105 -0
- package/cpp/rnwgpu/api/descriptors/GPURenderPassDepthStencilAttachment.h +118 -0
- package/cpp/rnwgpu/api/descriptors/GPURenderPassDescriptor.h +100 -0
- package/cpp/rnwgpu/api/descriptors/GPURenderPassLayout.h +83 -0
- package/cpp/rnwgpu/api/descriptors/GPURenderPassTimestampWrites.h +80 -0
- package/cpp/rnwgpu/api/descriptors/GPURenderPipelineDescriptor.h +104 -0
- package/cpp/rnwgpu/api/descriptors/GPURequestAdapterOptions.h +56 -0
- package/cpp/rnwgpu/api/descriptors/GPUSamplerBindingLayout.h +48 -0
- package/cpp/rnwgpu/api/descriptors/GPUSamplerDescriptor.h +116 -0
- package/cpp/rnwgpu/api/descriptors/GPUShaderModuleCompilationHint.h +64 -0
- package/cpp/rnwgpu/api/descriptors/GPUShaderModuleDescriptor.h +88 -0
- package/cpp/rnwgpu/api/descriptors/GPUShaderStage.h +27 -0
- package/cpp/rnwgpu/api/descriptors/GPUStencilFaceState.h +61 -0
- package/cpp/rnwgpu/api/descriptors/GPUStorageTextureBindingLayout.h +67 -0
- package/cpp/rnwgpu/api/descriptors/GPUTextureBindingLayout.h +58 -0
- package/cpp/rnwgpu/api/descriptors/GPUTextureDescriptor.h +123 -0
- package/cpp/rnwgpu/api/descriptors/GPUTextureUsage.h +40 -0
- package/cpp/rnwgpu/api/descriptors/GPUTextureViewDescriptor.h +113 -0
- package/cpp/rnwgpu/api/descriptors/GPUUncapturedErrorEventInit.h +71 -0
- package/cpp/rnwgpu/api/descriptors/GPUVertexAttribute.h +80 -0
- package/cpp/rnwgpu/api/descriptors/GPUVertexBufferLayout.h +73 -0
- package/cpp/rnwgpu/api/descriptors/GPUVertexState.h +77 -0
- package/cpp/rnwgpu/api/descriptors/Unions.h +1645 -0
- package/cpp/webgpu/webgpu.h +33 -0
- package/cpp/webgpu/webgpu_cpp.h +33 -0
- package/cpp/webgpu/webgpu_cpp_chained_struct.h +55 -0
- package/cpp/webgpu/webgpu_enum_class_bitmasks.h +161 -0
- package/ios/RNFAppleLogger.mm +22 -0
- package/ios/Utils.h +5 -0
- package/ios/Utils.m +26 -0
- package/ios/WebGPUModule.h +18 -0
- package/ios/WebGPUModule.mm +77 -0
- package/ios/WebGPUView.h +15 -0
- package/ios/WebGPUView.mm +58 -0
- package/ios/WebGPUViewManager.mm +21 -0
- package/lib/commonjs/WebGPUNativeModule.js +10 -0
- package/lib/commonjs/WebGPUNativeModule.js.map +1 -0
- package/lib/commonjs/WebGPUViewNativeComponent.js +11 -0
- package/lib/commonjs/WebGPUViewNativeComponent.js.map +1 -0
- package/lib/commonjs/index.js +45 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/WebGPUNativeModule.js +4 -0
- package/lib/module/WebGPUNativeModule.js.map +1 -0
- package/lib/module/WebGPUViewNativeComponent.js +4 -0
- package/lib/module/WebGPUViewNativeComponent.js.map +1 -0
- package/lib/module/index.js +9 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/babel.config.d.ts +2 -0
- package/lib/typescript/babel.config.d.ts.map +1 -0
- package/lib/typescript/jest.config.d.ts +5 -0
- package/lib/typescript/jest.config.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/WebGPUNativeModule.d.ts +5 -0
- package/lib/typescript/lib/commonjs/WebGPUNativeModule.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/WebGPUViewNativeComponent.d.ts +4 -0
- package/lib/typescript/lib/commonjs/WebGPUViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/index.d.ts +5 -0
- package/lib/typescript/lib/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/lib/module/WebGPUNativeModule.d.ts +3 -0
- package/lib/typescript/lib/module/WebGPUNativeModule.d.ts.map +1 -0
- package/lib/typescript/lib/module/WebGPUViewNativeComponent.d.ts +4 -0
- package/lib/typescript/lib/module/WebGPUViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/lib/module/index.d.ts +5 -0
- package/lib/typescript/lib/module/index.d.ts.map +1 -0
- package/lib/typescript/scripts/build/copy-artifacts.d.ts +2 -0
- package/lib/typescript/scripts/build/copy-artifacts.d.ts.map +1 -0
- package/lib/typescript/scripts/build/dawn.d.ts +2 -0
- package/lib/typescript/scripts/build/dawn.d.ts.map +1 -0
- package/lib/typescript/scripts/build/util.d.ts +13 -0
- package/lib/typescript/scripts/build/util.d.ts.map +1 -0
- package/lib/typescript/scripts/codegen/codegen.d.ts +2 -0
- package/lib/typescript/scripts/codegen/codegen.d.ts.map +1 -0
- package/lib/typescript/scripts/codegen/model/dawn.d.ts +2 -0
- package/lib/typescript/scripts/codegen/model/dawn.d.ts.map +1 -0
- package/lib/typescript/scripts/codegen/model/model.d.ts +8 -0
- package/lib/typescript/scripts/codegen/model/model.d.ts.map +1 -0
- package/lib/typescript/scripts/codegen/templates/Descriptor.d.ts +4 -0
- package/lib/typescript/scripts/codegen/templates/Descriptor.d.ts.map +1 -0
- package/lib/typescript/scripts/codegen/templates/Enum.d.ts +3 -0
- package/lib/typescript/scripts/codegen/templates/Enum.d.ts.map +1 -0
- package/lib/typescript/scripts/codegen/templates/HybridObject.d.ts +3 -0
- package/lib/typescript/scripts/codegen/templates/HybridObject.d.ts.map +1 -0
- package/lib/typescript/scripts/codegen/templates/Unions.d.ts +6 -0
- package/lib/typescript/scripts/codegen/templates/Unions.d.ts.map +1 -0
- package/lib/typescript/scripts/codegen/templates/common.d.ts +9 -0
- package/lib/typescript/scripts/codegen/templates/common.d.ts.map +1 -0
- package/lib/typescript/scripts/codegen/util.d.ts +2 -0
- package/lib/typescript/scripts/codegen/util.d.ts.map +1 -0
- package/lib/typescript/src/WebGPUNativeModule.d.ts +7 -0
- package/lib/typescript/src/WebGPUNativeModule.d.ts.map +1 -0
- package/lib/typescript/src/WebGPUViewNativeComponent.d.ts +8 -0
- package/lib/typescript/src/WebGPUViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +9 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +120 -0
- package/react-native-webgpu.podspec +56 -0
- package/src/WebGPUNativeModule.ts +9 -0
- package/src/WebGPUViewNativeComponent.ts +9 -0
- package/src/index.tsx +13 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Created by Marc Rousavy on 21.02.24.
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
#pragma once
|
|
6
|
+
|
|
7
|
+
#include "RNFEnumMapper.h"
|
|
8
|
+
#include "RNFHybridObject.h"
|
|
9
|
+
#include "RNFJSIHelper.h"
|
|
10
|
+
#include "RNFPromise.h"
|
|
11
|
+
#include "RNFWorkletRuntimeRegistry.h"
|
|
12
|
+
#include <jsi/jsi.h>
|
|
13
|
+
#include <memory>
|
|
14
|
+
#include <array>
|
|
15
|
+
#include <future>
|
|
16
|
+
#include <vector>
|
|
17
|
+
#include <string>
|
|
18
|
+
#include <utility>
|
|
19
|
+
#include <type_traits>
|
|
20
|
+
#include <unordered_map>
|
|
21
|
+
|
|
22
|
+
#if __has_include(<cxxabi.h>)
|
|
23
|
+
#include <cxxabi.h>
|
|
24
|
+
#endif
|
|
25
|
+
|
|
26
|
+
namespace margelo {
|
|
27
|
+
|
|
28
|
+
namespace jsi = facebook::jsi;
|
|
29
|
+
|
|
30
|
+
// Unknown type (error)
|
|
31
|
+
template <typename ArgType, typename Enable = void> struct JSIConverter {
|
|
32
|
+
static ArgType fromJSI(jsi::Runtime&, const jsi::Value&, bool outOfBound) {
|
|
33
|
+
static_assert(always_false<ArgType>::value, "This type is not supported by the JSIConverter!");
|
|
34
|
+
return ArgType();
|
|
35
|
+
}
|
|
36
|
+
static jsi::Value toJSI(jsi::Runtime&, ArgType) {
|
|
37
|
+
static_assert(always_false<ArgType>::value, "This type is not supported by the JSIConverter!");
|
|
38
|
+
return jsi::Value::undefined();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private:
|
|
42
|
+
template <typename> struct always_false : std::false_type {};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// int <> number
|
|
46
|
+
template <> struct JSIConverter<int> {
|
|
47
|
+
static int fromJSI(jsi::Runtime&, const jsi::Value& arg, bool outOfBound) {
|
|
48
|
+
return static_cast<int>(arg.asNumber());
|
|
49
|
+
}
|
|
50
|
+
static jsi::Value toJSI(jsi::Runtime&, int arg) {
|
|
51
|
+
return jsi::Value(arg);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// double <> number
|
|
56
|
+
template <> struct JSIConverter<double> {
|
|
57
|
+
static double fromJSI(jsi::Runtime&, const jsi::Value& arg, bool outOfBound) {
|
|
58
|
+
return arg.asNumber();
|
|
59
|
+
}
|
|
60
|
+
static jsi::Value toJSI(jsi::Runtime&, double arg) {
|
|
61
|
+
return jsi::Value(arg);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// float <> number
|
|
66
|
+
template <> struct JSIConverter<float> {
|
|
67
|
+
static float fromJSI(jsi::Runtime&, const jsi::Value& arg, bool outOfBound) {
|
|
68
|
+
return static_cast<float>(arg.asNumber());
|
|
69
|
+
}
|
|
70
|
+
static jsi::Value toJSI(jsi::Runtime&, float arg) {
|
|
71
|
+
return jsi::Value(static_cast<double>(arg));
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// uint64_t <> BigInt
|
|
76
|
+
template <> struct JSIConverter<uint64_t> {
|
|
77
|
+
static double fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
|
|
78
|
+
return arg.asBigInt(runtime).asUint64(runtime);
|
|
79
|
+
}
|
|
80
|
+
static jsi::Value toJSI(jsi::Runtime& runtime, uint64_t arg) {
|
|
81
|
+
return jsi::BigInt::fromUint64(runtime, arg);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// int64_t <> BigInt
|
|
86
|
+
template <> struct JSIConverter<int64_t> {
|
|
87
|
+
static double fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
|
|
88
|
+
return arg.asBigInt(runtime).asInt64(runtime);
|
|
89
|
+
}
|
|
90
|
+
static jsi::Value toJSI(jsi::Runtime& runtime, int64_t arg) {
|
|
91
|
+
return jsi::BigInt::fromInt64(runtime, arg);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
// bool <> boolean
|
|
97
|
+
template <> struct JSIConverter<bool> {
|
|
98
|
+
static bool fromJSI(jsi::Runtime&, const jsi::Value& arg, bool outOfBound) {
|
|
99
|
+
return arg.asBool();
|
|
100
|
+
}
|
|
101
|
+
static jsi::Value toJSI(jsi::Runtime&, bool arg) {
|
|
102
|
+
return jsi::Value(arg);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// std::string <> string
|
|
107
|
+
template <> struct JSIConverter<std::string> {
|
|
108
|
+
static std::string fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
|
|
109
|
+
return arg.asString(runtime).utf8(runtime);
|
|
110
|
+
}
|
|
111
|
+
static jsi::Value toJSI(jsi::Runtime& runtime, const std::string& arg) {
|
|
112
|
+
return jsi::String::createFromUtf8(runtime, arg);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// std::optional<T> <> T | undefined
|
|
117
|
+
template <typename TInner> struct JSIConverter<std::optional<TInner>> {
|
|
118
|
+
static std::optional<TInner> fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
|
|
119
|
+
if (outOfBound || arg.isUndefined()) {
|
|
120
|
+
return {};
|
|
121
|
+
} else {
|
|
122
|
+
return JSIConverter<TInner>::fromJSI(runtime, std::move(arg), outOfBound);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
static jsi::Value toJSI(jsi::Runtime& runtime, const std::optional<TInner>& arg) {
|
|
126
|
+
if (arg == std::nullopt) {
|
|
127
|
+
return jsi::Value::undefined();
|
|
128
|
+
} else {
|
|
129
|
+
return JSIConverter<TInner>::toJSI(runtime, arg.value());
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Enum <> Union
|
|
135
|
+
template <typename TEnum> struct JSIConverter<TEnum, std::enable_if_t<std::is_enum<TEnum>::value>> {
|
|
136
|
+
static TEnum fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
|
|
137
|
+
std::string string = arg.asString(runtime).utf8(runtime);
|
|
138
|
+
TEnum outEnum;
|
|
139
|
+
EnumMapper::convertJSUnionToEnum(string, &outEnum);
|
|
140
|
+
return outEnum;
|
|
141
|
+
}
|
|
142
|
+
static jsi::Value toJSI(jsi::Runtime& runtime, const TEnum& arg) {
|
|
143
|
+
std::string outUnion;
|
|
144
|
+
EnumMapper::convertEnumToJSUnion(arg, &outUnion);
|
|
145
|
+
return jsi::String::createFromUtf8(runtime, outUnion);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// std::future<T> <> Promise<T>
|
|
150
|
+
template <typename TResult> struct JSIConverter<std::future<TResult>> {
|
|
151
|
+
static std::future<TResult> fromJSI(jsi::Runtime&, const jsi::Value&, bool outOfBound) {
|
|
152
|
+
throw std::runtime_error("Promise cannot be converted to a native type - it needs to be awaited first!");
|
|
153
|
+
}
|
|
154
|
+
static jsi::Value toJSI(jsi::Runtime& runtime, std::future<TResult>&& arg) {
|
|
155
|
+
auto sharedFuture = std::make_shared<std::future<TResult>>(std::move(arg));
|
|
156
|
+
return Promise::createPromise(runtime, [sharedFuture = std::move(sharedFuture)](jsi::Runtime& runtime,
|
|
157
|
+
std::shared_ptr<Promise> promise) {
|
|
158
|
+
try {
|
|
159
|
+
// wait until the future completes.
|
|
160
|
+
sharedFuture->wait();
|
|
161
|
+
|
|
162
|
+
if constexpr (std::is_same_v<TResult, void>) {
|
|
163
|
+
// it's returning void, just return undefined to JS
|
|
164
|
+
sharedFuture->get();
|
|
165
|
+
promise->resolve(jsi::Value::undefined());
|
|
166
|
+
} else {
|
|
167
|
+
// it's returning a custom type, convert it to a jsi::Value
|
|
168
|
+
TResult result = sharedFuture->get();
|
|
169
|
+
jsi::Value jsResult = JSIConverter<TResult>::toJSI(runtime, result);
|
|
170
|
+
promise->resolve(std::move(jsResult));
|
|
171
|
+
}
|
|
172
|
+
} catch (const std::exception& exception) {
|
|
173
|
+
// the async function threw an error, reject the promise
|
|
174
|
+
std::string what = exception.what();
|
|
175
|
+
promise->reject(what);
|
|
176
|
+
} catch (...) {
|
|
177
|
+
// the async function threw a non-std error, try getting it
|
|
178
|
+
#if __has_include(<cxxabi.h>)
|
|
179
|
+
std::string name = __cxxabiv1::__cxa_current_exception_type()->name();
|
|
180
|
+
#else
|
|
181
|
+
std::string name = "<unknown>";
|
|
182
|
+
#endif
|
|
183
|
+
promise->reject("Unknown non-std exception: " + name);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// This lambda owns the promise shared pointer, and we need to call its
|
|
187
|
+
// destructor correctly here - ensuring it's properly handled.
|
|
188
|
+
promise = nullptr;
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
// [](Args...) -> T {} <> (Args...) => T
|
|
195
|
+
template <typename ReturnType, typename... Args> struct JSIConverter<std::function<ReturnType(Args...)>> {
|
|
196
|
+
static std::function<ReturnType(Args...)> fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
|
|
197
|
+
jsi::Function function = arg.asObject(runtime).asFunction(runtime);
|
|
198
|
+
|
|
199
|
+
std::shared_ptr<jsi::Function> sharedFunction = JSIHelper::createSharedJsiFunction(runtime, std::move(function));
|
|
200
|
+
return [&runtime, sharedFunction, outOfBound](Args... args) -> ReturnType {
|
|
201
|
+
jsi::Value result = sharedFunction->call(runtime, JSIConverter<std::decay_t<Args>>::toJSI(runtime, args)...);
|
|
202
|
+
if constexpr (std::is_same_v<ReturnType, void>) {
|
|
203
|
+
// it is a void function (returns undefined)
|
|
204
|
+
return;
|
|
205
|
+
} else {
|
|
206
|
+
// it returns a custom type, parse it from the JSI value.
|
|
207
|
+
return JSIConverter<ReturnType>::fromJSI(runtime, std::move(result), outOfBound);
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
template <size_t... Is>
|
|
213
|
+
static jsi::Value callHybridFunction(const std::function<ReturnType(Args...)>& function, jsi::Runtime& runtime, const jsi::Value* args,
|
|
214
|
+
std::index_sequence<Is...>, size_t count) {
|
|
215
|
+
if constexpr (std::is_same_v<ReturnType, void>) {
|
|
216
|
+
// it is a void function (will return undefined in JS)
|
|
217
|
+
function(JSIConverter<std::decay_t<Args>>::fromJSI(runtime, args[Is], Is >= count)...);
|
|
218
|
+
return jsi::Value::undefined();
|
|
219
|
+
} else {
|
|
220
|
+
// it is a custom type, parse it to a JS value
|
|
221
|
+
ReturnType result = function(JSIConverter<std::decay_t<Args>>::fromJSI(runtime, args[Is], Is >= count)...);
|
|
222
|
+
return JSIConverter<ReturnType>::toJSI(runtime, result);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
static jsi::Value toJSI(jsi::Runtime& runtime, const std::function<ReturnType(Args...)>& function) {
|
|
226
|
+
jsi::HostFunctionType jsFunction = [function = std::move(function)](jsi::Runtime& runtime, const jsi::Value& thisValue,
|
|
227
|
+
const jsi::Value* args, size_t count) -> jsi::Value {
|
|
228
|
+
if (count != sizeof...(Args)) {
|
|
229
|
+
[[unlikely]];
|
|
230
|
+
throw jsi::JSError(runtime, "Function expected " + std::to_string(sizeof...(Args)) + " arguments, but received " +
|
|
231
|
+
std::to_string(count) + "!");
|
|
232
|
+
}
|
|
233
|
+
return callHybridFunction(function, runtime, args, std::index_sequence_for<Args...>{}, count);
|
|
234
|
+
};
|
|
235
|
+
return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "hostFunction"), sizeof...(Args), jsFunction);
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// std::vector<T> <> T[]
|
|
240
|
+
template <typename ElementType> struct JSIConverter<std::vector<ElementType>> {
|
|
241
|
+
static std::vector<ElementType> fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
|
|
242
|
+
jsi::Array array = arg.asObject(runtime).asArray(runtime);
|
|
243
|
+
size_t length = array.size(runtime);
|
|
244
|
+
|
|
245
|
+
std::vector<ElementType> vector;
|
|
246
|
+
vector.reserve(length);
|
|
247
|
+
for (size_t i = 0; i < length; ++i) {
|
|
248
|
+
jsi::Value elementValue = array.getValueAtIndex(runtime, i);
|
|
249
|
+
vector.emplace_back(JSIConverter<ElementType>::fromJSI(runtime, elementValue, outOfBound));
|
|
250
|
+
}
|
|
251
|
+
return vector;
|
|
252
|
+
}
|
|
253
|
+
static jsi::Value toJSI(jsi::Runtime& runtime, const std::vector<ElementType>& vector) {
|
|
254
|
+
jsi::Array array(runtime, vector.size());
|
|
255
|
+
for (size_t i = 0; i < vector.size(); i++) {
|
|
256
|
+
jsi::Value value = JSIConverter<ElementType>::toJSI(runtime, vector[i]);
|
|
257
|
+
array.setValueAtIndex(runtime, i, std::move(value));
|
|
258
|
+
}
|
|
259
|
+
return array;
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
// std::unordered_map<std::string, T> <> Record<string, T>
|
|
264
|
+
template <typename ValueType> struct JSIConverter<std::unordered_map<std::string, ValueType>> {
|
|
265
|
+
static std::unordered_map<std::string, ValueType> fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
|
|
266
|
+
jsi::Object object = arg.asObject(runtime);
|
|
267
|
+
jsi::Array propertyNames = object.getPropertyNames(runtime);
|
|
268
|
+
size_t length = propertyNames.size(runtime);
|
|
269
|
+
|
|
270
|
+
std::unordered_map<std::string, ValueType> map;
|
|
271
|
+
map.reserve(length);
|
|
272
|
+
for (size_t i = 0; i < length; ++i) {
|
|
273
|
+
std::string key = propertyNames.getValueAtIndex(runtime, i).asString(runtime).utf8(runtime);
|
|
274
|
+
jsi::Value value = object.getProperty(runtime, key.c_str());
|
|
275
|
+
map.emplace(key, JSIConverter<ValueType>::fromJSI(runtime, value, outOfBound));
|
|
276
|
+
}
|
|
277
|
+
return map;
|
|
278
|
+
}
|
|
279
|
+
static jsi::Value toJSI(jsi::Runtime& runtime, const std::unordered_map<std::string, ValueType>& map) {
|
|
280
|
+
jsi::Object object(runtime);
|
|
281
|
+
for (const auto& pair : map) {
|
|
282
|
+
jsi::Value value = JSIConverter<ValueType>::toJSI(runtime, pair.second);
|
|
283
|
+
jsi::String key = jsi::String::createFromUtf8(runtime, pair.first);
|
|
284
|
+
object.setProperty(runtime, key, std::move(value));
|
|
285
|
+
}
|
|
286
|
+
return object;
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
// HybridObject <> {}
|
|
291
|
+
template <typename T> struct is_shared_ptr_to_host_object : std::false_type {};
|
|
292
|
+
|
|
293
|
+
template <typename T> struct is_shared_ptr_to_host_object<std::shared_ptr<T>> : std::is_base_of<jsi::HostObject, T> {};
|
|
294
|
+
|
|
295
|
+
template <typename T> struct JSIConverter<T, std::enable_if_t<is_shared_ptr_to_host_object<T>::value>> {
|
|
296
|
+
using TPointee = typename T::element_type;
|
|
297
|
+
|
|
298
|
+
#if DEBUG
|
|
299
|
+
inline static std::string getFriendlyTypename() {
|
|
300
|
+
std::string name = std::string(typeid(TPointee).name());
|
|
301
|
+
#if __has_include(<cxxabi.h>)
|
|
302
|
+
int status = 0;
|
|
303
|
+
char* demangled_name = abi::__cxa_demangle(name.c_str(), NULL, NULL, &status);
|
|
304
|
+
if (status == 0) {
|
|
305
|
+
name = demangled_name;
|
|
306
|
+
std::free(demangled_name);
|
|
307
|
+
}
|
|
308
|
+
#endif
|
|
309
|
+
return name;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
inline static std::string invalidTypeErrorMessage(const std::string& typeDescription, const std::string& reason) {
|
|
313
|
+
return "Cannot convert \"" + typeDescription + "\" to HostObject<" + getFriendlyTypename() + ">! " + reason;
|
|
314
|
+
}
|
|
315
|
+
#endif
|
|
316
|
+
|
|
317
|
+
static T fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
|
|
318
|
+
#if DEBUG
|
|
319
|
+
if (arg.isUndefined()) {
|
|
320
|
+
[[unlikely]];
|
|
321
|
+
throw jsi::JSError(runtime, invalidTypeErrorMessage("undefined", "It is undefined!"));
|
|
322
|
+
}
|
|
323
|
+
if (!arg.isObject()) {
|
|
324
|
+
[[unlikely]];
|
|
325
|
+
std::string stringRepresentation = arg.toString(runtime).utf8(runtime);
|
|
326
|
+
throw jsi::JSError(runtime, invalidTypeErrorMessage(stringRepresentation, "It is not an object!"));
|
|
327
|
+
}
|
|
328
|
+
#endif
|
|
329
|
+
jsi::Object object = arg.getObject(runtime);
|
|
330
|
+
#if DEBUG
|
|
331
|
+
if (!object.isHostObject<TPointee>(runtime)) {
|
|
332
|
+
[[unlikely]];
|
|
333
|
+
std::string stringRepresentation = arg.toString(runtime).utf8(runtime);
|
|
334
|
+
throw jsi::JSError(runtime, invalidTypeErrorMessage(stringRepresentation, "It is a different HostObject<T>!"));
|
|
335
|
+
}
|
|
336
|
+
#endif
|
|
337
|
+
return object.getHostObject<TPointee>(runtime);
|
|
338
|
+
}
|
|
339
|
+
static jsi::Value toJSI(jsi::Runtime& runtime, const T& arg) {
|
|
340
|
+
#if DEBUG
|
|
341
|
+
if (arg == nullptr) {
|
|
342
|
+
[[unlikely]];
|
|
343
|
+
throw jsi::JSError(runtime, "Cannot convert nullptr to HostObject<" + getFriendlyTypename() + ">!");
|
|
344
|
+
}
|
|
345
|
+
#endif
|
|
346
|
+
return jsi::Object::createFromHostObject(runtime, arg);
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
// NativeState <> {}
|
|
351
|
+
template <typename T> struct is_shared_ptr_to_native_state : std::false_type {};
|
|
352
|
+
|
|
353
|
+
template <typename T> struct is_shared_ptr_to_native_state<std::shared_ptr<T>> : std::is_base_of<jsi::NativeState, T> {};
|
|
354
|
+
|
|
355
|
+
template <typename T> struct JSIConverter<T, std::enable_if_t<is_shared_ptr_to_native_state<T>::value>> {
|
|
356
|
+
using TPointee = typename T::element_type;
|
|
357
|
+
|
|
358
|
+
#if DEBUG
|
|
359
|
+
inline static std::string getFriendlyTypename() {
|
|
360
|
+
std::string name = std::string(typeid(TPointee).name());
|
|
361
|
+
#if __has_include(<cxxabi.h>)
|
|
362
|
+
int status = 0;
|
|
363
|
+
char* demangled_name = abi::__cxa_demangle(name.c_str(), NULL, NULL, &status);
|
|
364
|
+
if (status == 0) {
|
|
365
|
+
name = demangled_name;
|
|
366
|
+
std::free(demangled_name);
|
|
367
|
+
}
|
|
368
|
+
#endif
|
|
369
|
+
return name;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
inline static std::string invalidTypeErrorMessage(const std::string& typeDescription, const std::string& reason) {
|
|
373
|
+
return "Cannot convert \"" + typeDescription + "\" to NativeState<" + getFriendlyTypename() + ">! " + reason;
|
|
374
|
+
}
|
|
375
|
+
#endif
|
|
376
|
+
|
|
377
|
+
static T fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
|
|
378
|
+
#if DEBUG
|
|
379
|
+
if (arg.isUndefined()) {
|
|
380
|
+
[[unlikely]];
|
|
381
|
+
throw jsi::JSError(runtime, invalidTypeErrorMessage("undefined", "It is undefined!"));
|
|
382
|
+
}
|
|
383
|
+
if (!arg.isObject()) {
|
|
384
|
+
[[unlikely]];
|
|
385
|
+
std::string stringRepresentation = arg.toString(runtime).utf8(runtime);
|
|
386
|
+
throw jsi::JSError(runtime, invalidTypeErrorMessage(stringRepresentation, "It is not an object!"));
|
|
387
|
+
}
|
|
388
|
+
#endif
|
|
389
|
+
jsi::Object object = arg.getObject(runtime);
|
|
390
|
+
#if DEBUG
|
|
391
|
+
if (!object.hasNativeState<TPointee>(runtime)) {
|
|
392
|
+
[[unlikely]];
|
|
393
|
+
std::string stringRepresentation = arg.toString(runtime).utf8(runtime);
|
|
394
|
+
throw jsi::JSError(runtime, invalidTypeErrorMessage(stringRepresentation, "It is a different NativeState<T>!"));
|
|
395
|
+
}
|
|
396
|
+
#endif
|
|
397
|
+
return object.getNativeState<TPointee>(runtime);
|
|
398
|
+
}
|
|
399
|
+
static jsi::Value toJSI(jsi::Runtime& runtime, const T& arg) {
|
|
400
|
+
#if DEBUG
|
|
401
|
+
if (arg == nullptr) {
|
|
402
|
+
[[unlikely]];
|
|
403
|
+
throw jsi::JSError(runtime, "Cannot convert nullptr to HostObject<" + getFriendlyTypename() + ">!");
|
|
404
|
+
}
|
|
405
|
+
#endif
|
|
406
|
+
jsi::Object object(runtime);
|
|
407
|
+
object.setNativeState(runtime, arg);
|
|
408
|
+
return object;
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
} // namespace margelo
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Created by Hanno Gödecke on 15.05.24.
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
#pragma once
|
|
6
|
+
|
|
7
|
+
#include "RNFWorkletRuntimeRegistry.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
|
+
std::shared_ptr<jsi::Function> sharedFunction(new jsi::Function(std::move(function)), [&runtime](jsi::Function* ptr) {
|
|
24
|
+
if (RNFWorkletRuntimeRegistry::isRuntimeAlive(&runtime)) {
|
|
25
|
+
// Only delete the jsi::Function when the runtime it created is still alive.
|
|
26
|
+
// Otherwise leak memory. We do this on purpose, as sometimes we would keep
|
|
27
|
+
// references to JSI objects past the lifetime of its runtime (e.g.,
|
|
28
|
+
// shared values references from the RN VM holds reference to JSI objects
|
|
29
|
+
// on the UI runtime). When the runtime is terminated, the orphaned JSI
|
|
30
|
+
// objects would crash the app when their destructors are called, because
|
|
31
|
+
// they call into a memory that's managed by the terminated runtime. We
|
|
32
|
+
// accept the tradeoff of leaking memory here, as it has a limited impact.
|
|
33
|
+
// This scenario can only occur when the React instance is torn down which
|
|
34
|
+
// happens in development mode during app reloads, or in production when
|
|
35
|
+
// the app is being shut down gracefully by the system. An alternative
|
|
36
|
+
// solution would require us to keep track of all JSI values that are in
|
|
37
|
+
// use which would require additional data structure and compute spent on
|
|
38
|
+
// bookkeeping that only for the sake of destroying the values in time
|
|
39
|
+
// before the runtime is terminated. Note that the underlying memory that
|
|
40
|
+
// jsi::Value refers to is managed by the VM and gets freed along with the
|
|
41
|
+
// runtime.
|
|
42
|
+
delete ptr;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return sharedFunction;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
} // namespace margelo
|
|
@@ -0,0 +1,95 @@
|
|
|
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
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Created by Marc Rousavy on 22.02.24.
|
|
3
|
+
//
|
|
4
|
+
#include "RNFPromise.h"
|
|
5
|
+
#include <future>
|
|
6
|
+
#include <jsi/jsi.h>
|
|
7
|
+
#include <utility>
|
|
8
|
+
#include <vector>
|
|
9
|
+
|
|
10
|
+
namespace margelo {
|
|
11
|
+
|
|
12
|
+
namespace jsi = facebook::jsi;
|
|
13
|
+
|
|
14
|
+
Promise::Promise(jsi::Runtime& runtime, jsi::Function&& resolver, jsi::Function&& rejecter)
|
|
15
|
+
: runtime(runtime), _resolver(std::move(resolver)), _rejecter(std::move(rejecter)) {}
|
|
16
|
+
|
|
17
|
+
jsi::Value Promise::createPromise(jsi::Runtime& runtime, RunPromise run) {
|
|
18
|
+
// Get Promise ctor from global
|
|
19
|
+
auto promiseCtor = runtime.global().getPropertyAsFunction(runtime, "Promise");
|
|
20
|
+
|
|
21
|
+
auto promiseCallback = jsi::Function::createFromHostFunction(
|
|
22
|
+
runtime, jsi::PropNameID::forUtf8(runtime, "PromiseCallback"), 2,
|
|
23
|
+
[=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value {
|
|
24
|
+
// Call function
|
|
25
|
+
auto resolver = arguments[0].asObject(runtime).asFunction(runtime);
|
|
26
|
+
auto rejecter = arguments[1].asObject(runtime).asFunction(runtime);
|
|
27
|
+
auto promise = std::make_shared<Promise>(runtime, std::move(resolver), std::move(rejecter));
|
|
28
|
+
run(runtime, promise);
|
|
29
|
+
|
|
30
|
+
return jsi::Value::undefined();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return promiseCtor.callAsConstructor(runtime, promiseCallback);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void Promise::resolve(jsi::Value&& result) {
|
|
37
|
+
_resolver.call(runtime, std::move(result));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
void Promise::reject(std::string message) {
|
|
41
|
+
jsi::JSError error(runtime, message);
|
|
42
|
+
_rejecter.call(runtime, error.value());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
} // namespace margelo
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Created by Marc Rousavy on 22.02.24.
|
|
3
|
+
//
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include <jsi/jsi.h>
|
|
7
|
+
#include <utility>
|
|
8
|
+
#include <vector>
|
|
9
|
+
#include <string>
|
|
10
|
+
#include <memory>
|
|
11
|
+
|
|
12
|
+
namespace margelo {
|
|
13
|
+
|
|
14
|
+
namespace jsi = facebook::jsi;
|
|
15
|
+
|
|
16
|
+
class Promise {
|
|
17
|
+
public:
|
|
18
|
+
Promise(jsi::Runtime& runtime, jsi::Function&& resolver, jsi::Function&& rejecter);
|
|
19
|
+
|
|
20
|
+
void resolve(jsi::Value&& result);
|
|
21
|
+
void reject(std::string error);
|
|
22
|
+
|
|
23
|
+
public:
|
|
24
|
+
jsi::Runtime& runtime;
|
|
25
|
+
|
|
26
|
+
private:
|
|
27
|
+
jsi::Function _resolver;
|
|
28
|
+
jsi::Function _rejecter;
|
|
29
|
+
|
|
30
|
+
public:
|
|
31
|
+
using RunPromise = std::function<void(jsi::Runtime& runtime, std::shared_ptr<Promise> promise)>;
|
|
32
|
+
/**
|
|
33
|
+
Create a new Promise and runs the given `run` function.
|
|
34
|
+
*/
|
|
35
|
+
static jsi::Value createPromise(jsi::Runtime& runtime, RunPromise run);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
} // namespace margelo
|