@shopify/react-native-skia 2.4.18 → 2.4.19
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/android/cpp/rnskia-android/RNSkAndroidVideo.cpp +34 -0
- package/android/cpp/rnskia-android/RNSkAndroidVideo.h +3 -0
- package/android/src/main/java/com/shopify/reactnative/skia/RNSkVideo.java +72 -18
- package/apple/RNSkAppleVideo.h +30 -3
- package/apple/RNSkAppleVideo.mm +172 -17
- package/cpp/api/JsiSkApi.h +15 -13
- package/cpp/api/JsiSkHostObjects.h +57 -3
- package/cpp/api/JsiSkImage.h +19 -5
- package/cpp/api/JsiSkPicture.h +19 -5
- package/cpp/api/JsiSkSurface.h +19 -5
- package/cpp/api/JsiVideo.h +15 -2
- package/cpp/api/recorder/Convertor.h +4 -2
- package/cpp/jsi2/EnumMapper.h +49 -34
- package/cpp/jsi2/JSIConverter.h +149 -99
- package/cpp/jsi2/NativeObject.h +23 -25
- package/cpp/jsi2/Promise.cpp +10 -6
- package/cpp/jsi2/Promise.h +9 -7
- package/cpp/rnskia/RNDawnContext.h +3 -8
- package/cpp/rnskia/RNSkManager.cpp +13 -7
- package/cpp/rnskia/RNSkVideo.h +3 -0
- package/cpp/rnwgpu/api/GPUAdapter.cpp +31 -32
- package/cpp/rnwgpu/api/GPUAdapter.h +1 -1
- package/cpp/rnwgpu/api/GPUBuffer.cpp +8 -8
- package/cpp/rnwgpu/api/GPUCommandEncoder.h +4 -4
- package/cpp/rnwgpu/api/GPUDevice.h +12 -12
- package/cpp/rnwgpu/api/GPUQueue.cpp +45 -44
- package/cpp/rnwgpu/api/GPUQueue.h +1 -1
- package/cpp/rnwgpu/api/GPURenderBundleEncoder.h +1 -1
- package/cpp/rnwgpu/api/GPURenderPassEncoder.h +1 -1
- package/cpp/rnwgpu/api/descriptors/GPUBindGroupEntry.h +1 -1
- package/cpp/rnwgpu/api/descriptors/GPUComputePipelineDescriptor.h +1 -1
- package/cpp/rnwgpu/api/descriptors/GPUImageCopyExternalImage.h +7 -6
- package/cpp/rnwgpu/api/descriptors/GPURenderPassDescriptor.h +1 -1
- package/cpp/rnwgpu/api/descriptors/GPURenderPipelineDescriptor.h +1 -1
- package/cpp/rnwgpu/api/descriptors/GPUVertexState.h +1 -1
- package/cpp/rnwgpu/async/AsyncRunner.cpp +2 -1
- package/cpp/rnwgpu/async/AsyncRunner.h +2 -1
- package/lib/commonjs/external/reanimated/useVideo.js +30 -31
- package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
- package/lib/commonjs/renderer/Offscreen.js +1 -0
- package/lib/commonjs/renderer/Offscreen.js.map +1 -1
- package/lib/commonjs/skia/types/Video/Video.d.ts +3 -0
- package/lib/commonjs/skia/types/Video/Video.js.map +1 -1
- package/lib/commonjs/skia/web/JsiVideo.d.ts +3 -0
- package/lib/commonjs/skia/web/JsiVideo.js +9 -0
- package/lib/commonjs/skia/web/JsiVideo.js.map +1 -1
- package/lib/commonjs/sksg/Container.web.js +1 -0
- package/lib/commonjs/sksg/Container.web.js.map +1 -1
- package/lib/commonjs/sksg/HostConfig.js +4 -1
- package/lib/commonjs/sksg/HostConfig.js.map +1 -1
- package/lib/commonjs/sksg/Reconciler.js +6 -6
- package/lib/commonjs/sksg/Reconciler.js.map +1 -1
- package/lib/commonjs/sksg/StaticContainer.js +1 -0
- package/lib/commonjs/sksg/StaticContainer.js.map +1 -1
- package/lib/module/external/reanimated/useVideo.js +30 -31
- package/lib/module/external/reanimated/useVideo.js.map +1 -1
- package/lib/module/renderer/Offscreen.js +1 -0
- package/lib/module/renderer/Offscreen.js.map +1 -1
- package/lib/module/skia/types/Video/Video.d.ts +3 -0
- package/lib/module/skia/types/Video/Video.js.map +1 -1
- package/lib/module/skia/web/JsiVideo.d.ts +3 -0
- package/lib/module/skia/web/JsiVideo.js +9 -0
- package/lib/module/skia/web/JsiVideo.js.map +1 -1
- package/lib/module/sksg/Container.web.js +1 -0
- package/lib/module/sksg/Container.web.js.map +1 -1
- package/lib/module/sksg/HostConfig.js +4 -1
- package/lib/module/sksg/HostConfig.js.map +1 -1
- package/lib/module/sksg/Reconciler.js +6 -6
- package/lib/module/sksg/Reconciler.js.map +1 -1
- package/lib/module/sksg/StaticContainer.js +1 -0
- package/lib/module/sksg/StaticContainer.js.map +1 -1
- package/lib/typescript/lib/commonjs/skia/web/JsiVideo.d.ts +3 -0
- package/lib/typescript/lib/commonjs/sksg/HostConfig.d.ts +2 -0
- package/lib/typescript/lib/module/skia/web/JsiVideo.d.ts +3 -0
- package/lib/typescript/lib/module/sksg/HostConfig.d.ts +2 -0
- package/lib/typescript/src/skia/types/Video/Video.d.ts +3 -0
- package/lib/typescript/src/skia/web/JsiVideo.d.ts +3 -0
- package/package.json +1 -1
- package/src/external/reanimated/useVideo.ts +32 -32
- package/src/renderer/Offscreen.tsx +1 -0
- package/src/skia/types/Video/Video.ts +3 -0
- package/src/skia/web/JsiVideo.ts +12 -0
- package/src/sksg/Container.web.ts +1 -0
- package/src/sksg/HostConfig.ts +4 -0
- package/src/sksg/Reconciler.ts +5 -6
- package/src/sksg/StaticContainer.ts +1 -0
package/cpp/jsi2/JSIConverter.h
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
#include <limits>
|
|
4
|
+
#include <map>
|
|
3
5
|
#include <memory>
|
|
4
|
-
#include <vector>
|
|
5
6
|
#include <string>
|
|
6
|
-
#include <utility>
|
|
7
7
|
#include <type_traits>
|
|
8
|
-
#include <limits>
|
|
9
|
-
#include <variant>
|
|
10
|
-
#include <map>
|
|
11
8
|
#include <unordered_set>
|
|
9
|
+
#include <utility>
|
|
10
|
+
#include <variant>
|
|
11
|
+
#include <vector>
|
|
12
12
|
|
|
13
13
|
#include <jsi/jsi.h>
|
|
14
14
|
|
|
15
|
+
#include "utils/RNSkLog.h"
|
|
16
|
+
|
|
15
17
|
#include "EnumMapper.h"
|
|
16
18
|
#include "Promise.h"
|
|
17
19
|
|
|
@@ -20,7 +22,8 @@
|
|
|
20
22
|
#include "rnwgpu/async/AsyncTaskHandle.h"
|
|
21
23
|
#endif
|
|
22
24
|
|
|
23
|
-
// This number is the maximum integer that can be represented exactly as a
|
|
25
|
+
// This number is the maximum integer that can be represented exactly as a
|
|
26
|
+
// double
|
|
24
27
|
#define MAX_SAFE_INTEGER static_cast<uint64_t>(9007199254740991)
|
|
25
28
|
|
|
26
29
|
#if __has_include(<cxxabi.h>)
|
|
@@ -33,12 +36,14 @@ namespace jsi = facebook::jsi;
|
|
|
33
36
|
|
|
34
37
|
// Unknown type (error)
|
|
35
38
|
template <typename ArgType, typename Enable = void> struct JSIConverter {
|
|
36
|
-
static ArgType fromJSI(jsi::Runtime&, const jsi::Value&, bool outOfBound) {
|
|
37
|
-
static_assert(always_false<ArgType>::value,
|
|
39
|
+
static ArgType fromJSI(jsi::Runtime &, const jsi::Value &, bool outOfBound) {
|
|
40
|
+
static_assert(always_false<ArgType>::value,
|
|
41
|
+
"This type is not supported by the JSIConverter!");
|
|
38
42
|
return ArgType();
|
|
39
43
|
}
|
|
40
|
-
static jsi::Value toJSI(jsi::Runtime&, ArgType) {
|
|
41
|
-
static_assert(always_false<ArgType>::value,
|
|
44
|
+
static jsi::Value toJSI(jsi::Runtime &, ArgType) {
|
|
45
|
+
static_assert(always_false<ArgType>::value,
|
|
46
|
+
"This type is not supported by the JSIConverter!");
|
|
42
47
|
return jsi::Value::undefined();
|
|
43
48
|
}
|
|
44
49
|
|
|
@@ -48,73 +53,77 @@ private:
|
|
|
48
53
|
|
|
49
54
|
// int <> number
|
|
50
55
|
template <> struct JSIConverter<int> {
|
|
51
|
-
static int fromJSI(jsi::Runtime&, const jsi::Value&
|
|
56
|
+
static int fromJSI(jsi::Runtime &, const jsi::Value &arg, bool outOfBound) {
|
|
52
57
|
return static_cast<int>(arg.asNumber());
|
|
53
58
|
}
|
|
54
|
-
static jsi::Value toJSI(jsi::Runtime&, int arg) {
|
|
55
|
-
return jsi::Value(arg);
|
|
56
|
-
}
|
|
59
|
+
static jsi::Value toJSI(jsi::Runtime &, int arg) { return jsi::Value(arg); }
|
|
57
60
|
};
|
|
58
61
|
|
|
59
62
|
// double <> number
|
|
60
63
|
template <> struct JSIConverter<double> {
|
|
61
|
-
static double fromJSI(jsi::Runtime&, const jsi::Value&
|
|
64
|
+
static double fromJSI(jsi::Runtime &, const jsi::Value &arg,
|
|
65
|
+
bool outOfBound) {
|
|
62
66
|
return arg.asNumber();
|
|
63
67
|
}
|
|
64
|
-
static jsi::Value toJSI(jsi::Runtime&, double arg) {
|
|
68
|
+
static jsi::Value toJSI(jsi::Runtime &, double arg) {
|
|
65
69
|
return jsi::Value(arg);
|
|
66
70
|
}
|
|
67
71
|
};
|
|
68
72
|
|
|
69
73
|
// float <> number
|
|
70
74
|
template <> struct JSIConverter<float> {
|
|
71
|
-
static float fromJSI(jsi::Runtime&, const jsi::Value&
|
|
75
|
+
static float fromJSI(jsi::Runtime &, const jsi::Value &arg, bool outOfBound) {
|
|
72
76
|
return static_cast<float>(arg.asNumber());
|
|
73
77
|
}
|
|
74
|
-
static jsi::Value toJSI(jsi::Runtime&, float arg) {
|
|
78
|
+
static jsi::Value toJSI(jsi::Runtime &, float arg) {
|
|
75
79
|
return jsi::Value(static_cast<double>(arg));
|
|
76
80
|
}
|
|
77
81
|
};
|
|
78
82
|
|
|
79
83
|
template <> struct JSIConverter<std::nullptr_t> {
|
|
80
|
-
static std::nullptr_t fromJSI(jsi::Runtime&, const jsi::Value&
|
|
84
|
+
static std::nullptr_t fromJSI(jsi::Runtime &, const jsi::Value &arg,
|
|
85
|
+
bool outOfBound) {
|
|
81
86
|
return nullptr;
|
|
82
87
|
}
|
|
83
|
-
static jsi::Value toJSI(jsi::Runtime&, std::nullptr_t arg) {
|
|
88
|
+
static jsi::Value toJSI(jsi::Runtime &, std::nullptr_t arg) {
|
|
84
89
|
return jsi::Value::null();
|
|
85
90
|
}
|
|
86
91
|
};
|
|
87
92
|
|
|
88
93
|
template <typename T>
|
|
89
|
-
struct JSIConverter<T, std::enable_if_t<!std::is_same_v<T, uint64_t> &&
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
struct JSIConverter<T, std::enable_if_t<!std::is_same_v<T, uint64_t> &&
|
|
95
|
+
std::is_same_v<T, size_t>>> {
|
|
96
|
+
static size_t fromJSI(jsi::Runtime &runtime, const jsi::Value &arg,
|
|
97
|
+
bool outOfBound) {
|
|
98
|
+
if (arg.isNumber()) {
|
|
99
|
+
double value = arg.asNumber();
|
|
100
|
+
return static_cast<size_t>(value);
|
|
101
|
+
} else {
|
|
102
|
+
return arg.asBigInt(runtime).asInt64(runtime);
|
|
103
|
+
}
|
|
97
104
|
}
|
|
98
105
|
|
|
99
|
-
static jsi::Value toJSI(jsi::Runtime&
|
|
106
|
+
static jsi::Value toJSI(jsi::Runtime &runtime, size_t arg) {
|
|
100
107
|
return jsi::Value(static_cast<double>(arg));
|
|
101
108
|
}
|
|
102
109
|
};
|
|
103
110
|
|
|
104
111
|
// uint32_t <> double
|
|
105
112
|
template <> struct JSIConverter<uint32_t> {
|
|
106
|
-
static double fromJSI(jsi::Runtime&
|
|
107
|
-
|
|
108
|
-
|
|
113
|
+
static double fromJSI(jsi::Runtime &runtime, const jsi::Value &arg,
|
|
114
|
+
bool outOfBound) {
|
|
115
|
+
double value = arg.asNumber();
|
|
116
|
+
return static_cast<uint32_t>(value);
|
|
109
117
|
}
|
|
110
|
-
static jsi::Value toJSI(jsi::Runtime&
|
|
111
|
-
|
|
118
|
+
static jsi::Value toJSI(jsi::Runtime &runtime, uint32_t arg) {
|
|
119
|
+
return jsi::Value(static_cast<double>(arg));
|
|
112
120
|
}
|
|
113
121
|
};
|
|
114
122
|
|
|
115
123
|
// uint64_t <> BigInt
|
|
116
124
|
template <> struct JSIConverter<uint64_t> {
|
|
117
|
-
static uint64_t fromJSI(jsi::Runtime&
|
|
125
|
+
static uint64_t fromJSI(jsi::Runtime &runtime, const jsi::Value &arg,
|
|
126
|
+
bool outOfBound) {
|
|
118
127
|
if (arg.isNumber()) {
|
|
119
128
|
double value = arg.asNumber();
|
|
120
129
|
if (value < 0 || value > MAX_SAFE_INTEGER) {
|
|
@@ -126,55 +135,58 @@ template <> struct JSIConverter<uint64_t> {
|
|
|
126
135
|
}
|
|
127
136
|
}
|
|
128
137
|
|
|
129
|
-
static jsi::Value toJSI(jsi::Runtime&
|
|
138
|
+
static jsi::Value toJSI(jsi::Runtime &runtime, uint64_t arg) {
|
|
130
139
|
if (arg <= MAX_SAFE_INTEGER) {
|
|
131
140
|
return jsi::Value(static_cast<double>(arg));
|
|
132
141
|
} else {
|
|
133
|
-
throw jsi::JSError(runtime,
|
|
142
|
+
throw jsi::JSError(runtime,
|
|
143
|
+
"Number too large to be represented as a double");
|
|
134
144
|
}
|
|
135
145
|
}
|
|
136
146
|
};
|
|
137
147
|
|
|
138
148
|
template <> struct JSIConverter<void *> {
|
|
139
|
-
static void*
|
|
149
|
+
static void *fromJSI(jsi::Runtime &runtime, const jsi::Value &arg,
|
|
150
|
+
bool outOfBound) {
|
|
140
151
|
return reinterpret_cast<void *>(arg.asBigInt(runtime).getUint64(runtime));
|
|
141
152
|
}
|
|
142
153
|
|
|
143
|
-
static jsi::Value toJSI(jsi::Runtime&
|
|
154
|
+
static jsi::Value toJSI(jsi::Runtime &runtime, void *arg) {
|
|
144
155
|
return jsi::BigInt::fromUint64(runtime, reinterpret_cast<uint64_t>(arg));
|
|
145
156
|
}
|
|
146
157
|
};
|
|
147
158
|
|
|
148
159
|
// bool <> boolean
|
|
149
160
|
template <> struct JSIConverter<bool> {
|
|
150
|
-
static bool fromJSI(jsi::Runtime&, const jsi::Value&
|
|
161
|
+
static bool fromJSI(jsi::Runtime &, const jsi::Value &arg, bool outOfBound) {
|
|
151
162
|
return arg.asBool();
|
|
152
163
|
}
|
|
153
|
-
static jsi::Value toJSI(jsi::Runtime&, bool arg) {
|
|
154
|
-
return jsi::Value(arg);
|
|
155
|
-
}
|
|
164
|
+
static jsi::Value toJSI(jsi::Runtime &, bool arg) { return jsi::Value(arg); }
|
|
156
165
|
};
|
|
157
166
|
|
|
158
167
|
// std::string <> string
|
|
159
168
|
template <> struct JSIConverter<std::string> {
|
|
160
|
-
static std::string fromJSI(jsi::Runtime&
|
|
169
|
+
static std::string fromJSI(jsi::Runtime &runtime, const jsi::Value &arg,
|
|
170
|
+
bool outOfBound) {
|
|
161
171
|
return arg.asString(runtime).utf8(runtime);
|
|
162
172
|
}
|
|
163
|
-
static jsi::Value toJSI(jsi::Runtime&
|
|
173
|
+
static jsi::Value toJSI(jsi::Runtime &runtime, const std::string &arg) {
|
|
164
174
|
return jsi::String::createFromUtf8(runtime, arg);
|
|
165
175
|
}
|
|
166
176
|
};
|
|
167
177
|
|
|
168
178
|
// std::optional<T> <> T | undefined
|
|
169
179
|
template <typename TInner> struct JSIConverter<std::optional<TInner>> {
|
|
170
|
-
static std::optional<TInner> fromJSI(jsi::Runtime&
|
|
180
|
+
static std::optional<TInner> fromJSI(jsi::Runtime &runtime,
|
|
181
|
+
const jsi::Value &arg, bool outOfBound) {
|
|
171
182
|
if (outOfBound || arg.isUndefined()) {
|
|
172
183
|
return {};
|
|
173
184
|
} else {
|
|
174
185
|
return JSIConverter<TInner>::fromJSI(runtime, std::move(arg), outOfBound);
|
|
175
186
|
}
|
|
176
187
|
}
|
|
177
|
-
static jsi::Value toJSI(jsi::Runtime&
|
|
188
|
+
static jsi::Value toJSI(jsi::Runtime &runtime,
|
|
189
|
+
const std::optional<TInner> &arg) {
|
|
178
190
|
if (arg == std::nullopt) {
|
|
179
191
|
return jsi::Value::undefined();
|
|
180
192
|
} else {
|
|
@@ -184,14 +196,16 @@ template <typename TInner> struct JSIConverter<std::optional<TInner>> {
|
|
|
184
196
|
};
|
|
185
197
|
|
|
186
198
|
// Enum <> Union
|
|
187
|
-
template <typename TEnum>
|
|
188
|
-
|
|
199
|
+
template <typename TEnum>
|
|
200
|
+
struct JSIConverter<TEnum, std::enable_if_t<std::is_enum<TEnum>::value>> {
|
|
201
|
+
static TEnum fromJSI(jsi::Runtime &runtime, const jsi::Value &arg,
|
|
202
|
+
bool outOfBound) {
|
|
189
203
|
std::string string = arg.asString(runtime).utf8(runtime);
|
|
190
204
|
TEnum outEnum;
|
|
191
205
|
EnumMapper::convertJSUnionToEnum(string, &outEnum);
|
|
192
206
|
return outEnum;
|
|
193
207
|
}
|
|
194
|
-
static jsi::Value toJSI(jsi::Runtime&
|
|
208
|
+
static jsi::Value toJSI(jsi::Runtime &runtime, const TEnum &arg) {
|
|
195
209
|
std::string outUnion;
|
|
196
210
|
EnumMapper::convertEnumToJSUnion(arg, &outUnion);
|
|
197
211
|
return jsi::String::createFromUtf8(runtime, outUnion);
|
|
@@ -201,42 +215,53 @@ template <typename TEnum> struct JSIConverter<TEnum, std::enable_if_t<std::is_en
|
|
|
201
215
|
#ifdef SK_GRAPHITE
|
|
202
216
|
// AsyncTaskHandle <> Promise
|
|
203
217
|
template <> struct JSIConverter<rnwgpu::async::AsyncTaskHandle> {
|
|
204
|
-
static rnwgpu::async::AsyncTaskHandle fromJSI(jsi::Runtime
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
+
static rnwgpu::async::AsyncTaskHandle fromJSI(jsi::Runtime &,
|
|
219
|
+
const jsi::Value &, bool) {
|
|
220
|
+
throw std::runtime_error(
|
|
221
|
+
"Cannot convert a Promise to AsyncTaskHandle on the native side.");
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
static jsi::Value toJSI(jsi::Runtime &runtime,
|
|
225
|
+
rnwgpu::async::AsyncTaskHandle &&handle) {
|
|
226
|
+
return rnwgpu::Promise::createPromise(
|
|
227
|
+
runtime, [handle = std::move(handle)](
|
|
228
|
+
jsi::Runtime &runtime,
|
|
229
|
+
std::shared_ptr<rnwgpu::Promise> promise) mutable {
|
|
230
|
+
if (!handle.valid()) {
|
|
231
|
+
promise->resolve(jsi::Value::undefined());
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
handle.attachPromise(promise);
|
|
236
|
+
});
|
|
218
237
|
}
|
|
219
238
|
};
|
|
220
239
|
#endif
|
|
221
240
|
|
|
222
241
|
// std::map<std::string, T> <> Record<string, T>
|
|
223
|
-
template <typename ValueType>
|
|
224
|
-
|
|
242
|
+
template <typename ValueType>
|
|
243
|
+
struct JSIConverter<std::map<std::string, ValueType>> {
|
|
244
|
+
static std::map<std::string, ValueType>
|
|
245
|
+
fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBound) {
|
|
225
246
|
jsi::Object object = arg.asObject(runtime);
|
|
226
247
|
jsi::Array propertyNames = object.getPropertyNames(runtime);
|
|
227
248
|
size_t length = propertyNames.size(runtime);
|
|
228
249
|
|
|
229
250
|
std::map<std::string, ValueType> map;
|
|
230
251
|
for (size_t i = 0; i < length; ++i) {
|
|
231
|
-
std::string key = propertyNames.getValueAtIndex(runtime, i)
|
|
252
|
+
std::string key = propertyNames.getValueAtIndex(runtime, i)
|
|
253
|
+
.asString(runtime)
|
|
254
|
+
.utf8(runtime);
|
|
232
255
|
jsi::Value value = object.getProperty(runtime, key.c_str());
|
|
233
|
-
map.emplace(key,
|
|
256
|
+
map.emplace(key,
|
|
257
|
+
JSIConverter<ValueType>::fromJSI(runtime, value, outOfBound));
|
|
234
258
|
}
|
|
235
259
|
return map;
|
|
236
260
|
}
|
|
237
|
-
static jsi::Value toJSI(jsi::Runtime&
|
|
261
|
+
static jsi::Value toJSI(jsi::Runtime &runtime,
|
|
262
|
+
const std::map<std::string, ValueType> &map) {
|
|
238
263
|
jsi::Object object(runtime);
|
|
239
|
-
for (const auto&
|
|
264
|
+
for (const auto &pair : map) {
|
|
240
265
|
jsi::Value value = JSIConverter<ValueType>::toJSI(runtime, pair.second);
|
|
241
266
|
jsi::String key = jsi::String::createFromUtf8(runtime, pair.first);
|
|
242
267
|
object.setProperty(runtime, key, std::move(value));
|
|
@@ -245,10 +270,10 @@ template <typename ValueType> struct JSIConverter<std::map<std::string, ValueTyp
|
|
|
245
270
|
}
|
|
246
271
|
};
|
|
247
272
|
|
|
248
|
-
|
|
249
273
|
// std::vector<T> <> T[]
|
|
250
274
|
template <typename ElementType> struct JSIConverter<std::vector<ElementType>> {
|
|
251
|
-
static std::vector<ElementType>
|
|
275
|
+
static std::vector<ElementType>
|
|
276
|
+
fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, bool outOfBound) {
|
|
252
277
|
jsi::Array array = arg.asObject(runtime).asArray(runtime);
|
|
253
278
|
size_t length = array.size(runtime);
|
|
254
279
|
|
|
@@ -256,11 +281,13 @@ template <typename ElementType> struct JSIConverter<std::vector<ElementType>> {
|
|
|
256
281
|
vector.reserve(length);
|
|
257
282
|
for (size_t i = 0; i < length; ++i) {
|
|
258
283
|
jsi::Value elementValue = array.getValueAtIndex(runtime, i);
|
|
259
|
-
vector.emplace_back(JSIConverter<ElementType>::fromJSI(
|
|
284
|
+
vector.emplace_back(JSIConverter<ElementType>::fromJSI(
|
|
285
|
+
runtime, elementValue, outOfBound));
|
|
260
286
|
}
|
|
261
287
|
return vector;
|
|
262
288
|
}
|
|
263
|
-
static jsi::Value toJSI(jsi::Runtime&
|
|
289
|
+
static jsi::Value toJSI(jsi::Runtime &runtime,
|
|
290
|
+
const std::vector<ElementType> &vector) {
|
|
264
291
|
jsi::Array array(runtime, vector.size());
|
|
265
292
|
for (size_t i = 0; i < vector.size(); i++) {
|
|
266
293
|
jsi::Value value = JSIConverter<ElementType>::toJSI(runtime, vector[i]);
|
|
@@ -273,9 +300,13 @@ template <typename ElementType> struct JSIConverter<std::vector<ElementType>> {
|
|
|
273
300
|
// NativeState <> {}
|
|
274
301
|
template <typename T> struct is_shared_ptr_to_native_state : std::false_type {};
|
|
275
302
|
|
|
276
|
-
template <typename T>
|
|
303
|
+
template <typename T>
|
|
304
|
+
struct is_shared_ptr_to_native_state<std::shared_ptr<T>>
|
|
305
|
+
: std::is_base_of<jsi::NativeState, T> {};
|
|
277
306
|
|
|
278
|
-
template <typename T>
|
|
307
|
+
template <typename T>
|
|
308
|
+
struct JSIConverter<T,
|
|
309
|
+
std::enable_if_t<is_shared_ptr_to_native_state<T>::value>> {
|
|
279
310
|
using TPointee = typename T::element_type;
|
|
280
311
|
|
|
281
312
|
#if DEBUG
|
|
@@ -283,7 +314,8 @@ template <typename T> struct JSIConverter<T, std::enable_if_t<is_shared_ptr_to_n
|
|
|
283
314
|
std::string name = std::string(typeid(TPointee).name());
|
|
284
315
|
#if __has_include(<cxxabi.h>)
|
|
285
316
|
int status = 0;
|
|
286
|
-
char*
|
|
317
|
+
char *demangled_name =
|
|
318
|
+
abi::__cxa_demangle(name.c_str(), NULL, NULL, &status);
|
|
287
319
|
if (status == 0) {
|
|
288
320
|
name = demangled_name;
|
|
289
321
|
std::free(demangled_name);
|
|
@@ -292,53 +324,71 @@ template <typename T> struct JSIConverter<T, std::enable_if_t<is_shared_ptr_to_n
|
|
|
292
324
|
return name;
|
|
293
325
|
}
|
|
294
326
|
|
|
295
|
-
inline static std::string
|
|
296
|
-
|
|
327
|
+
inline static std::string
|
|
328
|
+
invalidTypeErrorMessage(const std::string &typeDescription,
|
|
329
|
+
const std::string &reason) {
|
|
330
|
+
return "Cannot convert \"" + typeDescription + "\" to NativeState<" +
|
|
331
|
+
getFriendlyTypename() + ">! " + reason;
|
|
297
332
|
}
|
|
298
333
|
#endif
|
|
299
334
|
|
|
300
|
-
static T fromJSI(jsi::Runtime&
|
|
335
|
+
static T fromJSI(jsi::Runtime &runtime, const jsi::Value &arg,
|
|
336
|
+
bool outOfBound) {
|
|
301
337
|
#if DEBUG
|
|
302
338
|
if (arg.isUndefined()) {
|
|
303
339
|
[[unlikely]];
|
|
304
|
-
throw jsi::JSError(
|
|
340
|
+
throw jsi::JSError(
|
|
341
|
+
runtime, invalidTypeErrorMessage("undefined", "It is undefined!"));
|
|
305
342
|
}
|
|
306
343
|
if (!arg.isObject()) {
|
|
307
344
|
[[unlikely]];
|
|
308
345
|
std::string stringRepresentation = arg.toString(runtime).utf8(runtime);
|
|
309
|
-
throw jsi::JSError(runtime,
|
|
346
|
+
throw jsi::JSError(runtime,
|
|
347
|
+
invalidTypeErrorMessage(stringRepresentation,
|
|
348
|
+
"It is not an object!"));
|
|
310
349
|
}
|
|
311
350
|
#endif
|
|
312
351
|
jsi::Object object = arg.getObject(runtime);
|
|
313
352
|
#if DEBUG
|
|
314
|
-
if (!object.hasNativeState<TPointee>(runtime)) {
|
|
315
|
-
|
|
353
|
+
if (!object.hasNativeState<TPointee>(runtime)) [[unlikely]] {
|
|
354
|
+
// Log instead of throwing: hasNativeState<T>() uses dynamic_cast (RTTI)
|
|
355
|
+
// which can return false across shared-library / JSI-runtime boundaries
|
|
356
|
+
// on iOS (duplicate typeinfo symbols in separate .dylib modules).
|
|
357
|
+
// getNativeState<T>() below uses static_pointer_cast and works correctly
|
|
358
|
+
// even when dynamic_cast fails, so this is not a fatal error.
|
|
316
359
|
std::string stringRepresentation = arg.toString(runtime).utf8(runtime);
|
|
317
|
-
|
|
360
|
+
RNSkia::RNSkLogger::logToConsole(
|
|
361
|
+
"NativeState<T> RTTI mismatch for \"%s\" (expected %s) "
|
|
362
|
+
"-- this is likely a false positive from dynamic_cast across JSI "
|
|
363
|
+
"runtime boundaries; continuing with static_pointer_cast.",
|
|
364
|
+
stringRepresentation.c_str(), getFriendlyTypename().c_str());
|
|
318
365
|
}
|
|
319
366
|
#endif
|
|
320
367
|
return object.getNativeState<TPointee>(runtime);
|
|
321
368
|
}
|
|
369
|
+
|
|
322
370
|
private:
|
|
323
371
|
// SFINAE helper to detect if T has a IsNativeObject marker type
|
|
324
372
|
template <typename U, typename = typename U::IsNativeObject>
|
|
325
373
|
static std::true_type hasNativeObjectMarker(int);
|
|
326
|
-
template <typename U>
|
|
327
|
-
static std::false_type hasNativeObjectMarker(...);
|
|
374
|
+
template <typename U> static std::false_type hasNativeObjectMarker(...);
|
|
328
375
|
|
|
329
376
|
// Type trait for detection
|
|
330
|
-
static constexpr bool is_native_object =
|
|
377
|
+
static constexpr bool is_native_object =
|
|
378
|
+
decltype(hasNativeObjectMarker<TPointee>(0))::value;
|
|
331
379
|
|
|
332
380
|
public:
|
|
333
|
-
static jsi::Value toJSI(jsi::Runtime&
|
|
381
|
+
static jsi::Value toJSI(jsi::Runtime &runtime, const T &arg) {
|
|
334
382
|
#if DEBUG
|
|
335
383
|
if (arg == nullptr) {
|
|
336
384
|
[[unlikely]];
|
|
337
|
-
throw jsi::JSError(runtime, "Cannot convert nullptr to NativeState<" +
|
|
385
|
+
throw jsi::JSError(runtime, "Cannot convert nullptr to NativeState<" +
|
|
386
|
+
getFriendlyTypename() + ">!");
|
|
338
387
|
}
|
|
339
388
|
#endif
|
|
340
389
|
// Check if the type is a NativeObject (has IsNativeObject marker)
|
|
341
|
-
// Use TPointee::create() if it's a NativeObject, otherwise fall back to
|
|
390
|
+
// Use TPointee::create() if it's a NativeObject, otherwise fall back to
|
|
391
|
+
// plain setNativeState
|
|
342
392
|
if constexpr (is_native_object) {
|
|
343
393
|
return TPointee::create(runtime, arg);
|
|
344
394
|
} else {
|
|
@@ -349,7 +399,6 @@ public:
|
|
|
349
399
|
}
|
|
350
400
|
};
|
|
351
401
|
|
|
352
|
-
|
|
353
402
|
template <typename O, typename T>
|
|
354
403
|
struct JSIConverter<std::variant<std::vector<T>, std::shared_ptr<O>>> {
|
|
355
404
|
using Target = std::variant<std::vector<T>, std::shared_ptr<O>>;
|
|
@@ -445,21 +494,22 @@ struct JSIConverter<
|
|
|
445
494
|
}
|
|
446
495
|
};
|
|
447
496
|
|
|
448
|
-
template <>
|
|
449
|
-
struct JSIConverter<std::unordered_set<std::string>> {
|
|
497
|
+
template <> struct JSIConverter<std::unordered_set<std::string>> {
|
|
450
498
|
using Target = std::unordered_set<std::string>;
|
|
451
499
|
static Target fromJSI(jsi::Runtime &runtime, const jsi::Value &arg,
|
|
452
500
|
bool outOfBound) {
|
|
453
|
-
throw jsi::JSError(runtime, "JSIConverter<std::unordered_set<std::string
|
|
501
|
+
throw jsi::JSError(runtime, "JSIConverter<std::unordered_set<std::string>>:"
|
|
502
|
+
":fromJSI not implemented");
|
|
454
503
|
}
|
|
455
504
|
|
|
456
505
|
static jsi::Value toJSI(jsi::Runtime &runtime, Target arg) {
|
|
457
|
-
auto setConstructor =
|
|
506
|
+
auto setConstructor =
|
|
507
|
+
runtime.global().getPropertyAsFunction(runtime, "Set");
|
|
458
508
|
auto set = setConstructor.callAsConstructor(runtime).asObject(runtime);
|
|
459
509
|
auto add = set.getPropertyAsFunction(runtime, "add");
|
|
460
|
-
for (const auto&
|
|
461
|
-
|
|
462
|
-
|
|
510
|
+
for (const auto &value : arg) {
|
|
511
|
+
jsi::Value jsiValue = JSIConverter<std::string>::toJSI(runtime, value);
|
|
512
|
+
add.callWithThis(runtime, set, jsiValue);
|
|
463
513
|
}
|
|
464
514
|
return std::move(set);
|
|
465
515
|
}
|
package/cpp/jsi2/NativeObject.h
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
#include <unordered_map>
|
|
15
15
|
#include <utility>
|
|
16
16
|
|
|
17
|
-
#include "jsi/RuntimeAwareCache.h"
|
|
17
|
+
#include "jsi/RuntimeAwareCache.h" // Use Skia's RuntimeAwareCache
|
|
18
18
|
|
|
19
19
|
// Forward declare to avoid circular dependency
|
|
20
20
|
namespace rnwgpu {
|
|
@@ -135,8 +135,7 @@ public:
|
|
|
135
135
|
return jsi::Function::createFromHostFunction(
|
|
136
136
|
runtime, jsi::PropNameID::forUtf8(runtime, "unbox"), 0,
|
|
137
137
|
[this](jsi::Runtime &rt, const jsi::Value & /*thisVal*/,
|
|
138
|
-
const jsi::Value * /*args*/,
|
|
139
|
-
size_t /*count*/) -> jsi::Value {
|
|
138
|
+
const jsi::Value * /*args*/, size_t /*count*/) -> jsi::Value {
|
|
140
139
|
// Try to get the prototype from the global constructor
|
|
141
140
|
auto ctor = rt.global().getProperty(rt, _brand.c_str());
|
|
142
141
|
if (!ctor.isObject()) {
|
|
@@ -154,8 +153,7 @@ public:
|
|
|
154
153
|
auto ctorObj = ctor.getObject(rt);
|
|
155
154
|
auto proto = ctorObj.getProperty(rt, "prototype");
|
|
156
155
|
if (proto.isObject()) {
|
|
157
|
-
auto objectCtor =
|
|
158
|
-
rt.global().getPropertyAsObject(rt, "Object");
|
|
156
|
+
auto objectCtor = rt.global().getPropertyAsObject(rt, "Object");
|
|
159
157
|
auto setPrototypeOf =
|
|
160
158
|
objectCtor.getPropertyAsFunction(rt, "setPrototypeOf");
|
|
161
159
|
setPrototypeOf.call(rt, obj, proto);
|
|
@@ -263,8 +261,7 @@ public:
|
|
|
263
261
|
if (!toStringTag.isUndefined()) {
|
|
264
262
|
// Use Object.defineProperty to set symbol property since setProperty
|
|
265
263
|
// doesn't support symbols directly
|
|
266
|
-
auto objectCtor =
|
|
267
|
-
runtime.global().getPropertyAsObject(runtime, "Object");
|
|
264
|
+
auto objectCtor = runtime.global().getPropertyAsObject(runtime, "Object");
|
|
268
265
|
auto defineProperty =
|
|
269
266
|
objectCtor.getPropertyAsFunction(runtime, "defineProperty");
|
|
270
267
|
jsi::Object descriptor(runtime);
|
|
@@ -292,7 +289,8 @@ public:
|
|
|
292
289
|
* BoxedWebGPUObject::unbox() can install prototypes on secondary runtimes.
|
|
293
290
|
*/
|
|
294
291
|
static void installConstructor(jsi::Runtime &runtime) {
|
|
295
|
-
// Register this class's installer in the registry (only needs to happen
|
|
292
|
+
// Register this class's installer in the registry (only needs to happen
|
|
293
|
+
// once)
|
|
296
294
|
static std::once_flag registryFlag;
|
|
297
295
|
std::call_once(registryFlag, []() {
|
|
298
296
|
NativeObjectRegistry::getInstance().registerInstaller(
|
|
@@ -312,9 +310,9 @@ public:
|
|
|
312
310
|
runtime, jsi::PropNameID::forUtf8(runtime, Derived::CLASS_NAME), 0,
|
|
313
311
|
[](jsi::Runtime &rt, const jsi::Value & /*thisVal*/,
|
|
314
312
|
const jsi::Value * /*args*/, size_t /*count*/) -> jsi::Value {
|
|
315
|
-
throw jsi::JSError(
|
|
316
|
-
|
|
317
|
-
|
|
313
|
+
throw jsi::JSError(rt, std::string("Illegal constructor: ") +
|
|
314
|
+
Derived::CLASS_NAME +
|
|
315
|
+
" objects are created by the WebGPU API");
|
|
318
316
|
});
|
|
319
317
|
|
|
320
318
|
// Set the prototype property on the constructor
|
|
@@ -348,8 +346,7 @@ public:
|
|
|
348
346
|
auto &entry = getPrototypeCache(runtime).get(runtime);
|
|
349
347
|
if (entry.prototype.has_value()) {
|
|
350
348
|
// Use Object.setPrototypeOf to set the prototype
|
|
351
|
-
auto objectCtor =
|
|
352
|
-
runtime.global().getPropertyAsObject(runtime, "Object");
|
|
349
|
+
auto objectCtor = runtime.global().getPropertyAsObject(runtime, "Object");
|
|
353
350
|
auto setPrototypeOf =
|
|
354
351
|
objectCtor.getPropertyAsFunction(runtime, "setPrototypeOf");
|
|
355
352
|
setPrototypeOf.call(runtime, obj, *entry.prototype);
|
|
@@ -483,8 +480,8 @@ protected:
|
|
|
483
480
|
throw jsi::JSError(rt, "Setter requires a value argument");
|
|
484
481
|
}
|
|
485
482
|
auto native = Derived::fromValue(rt, thisVal);
|
|
486
|
-
auto value =
|
|
487
|
-
|
|
483
|
+
auto value = rnwgpu::JSIConverter<std::decay_t<ValueType>>::fromJSI(
|
|
484
|
+
rt, args[0], false);
|
|
488
485
|
(native.get()->*setter)(std::move(value));
|
|
489
486
|
return jsi::Value::undefined();
|
|
490
487
|
});
|
|
@@ -504,8 +501,8 @@ protected:
|
|
|
504
501
|
if (existingDesc.isObject()) {
|
|
505
502
|
auto existingDescObj = existingDesc.getObject(runtime);
|
|
506
503
|
if (existingDescObj.hasProperty(runtime, "get")) {
|
|
507
|
-
descriptor.setProperty(
|
|
508
|
-
|
|
504
|
+
descriptor.setProperty(runtime, "get",
|
|
505
|
+
existingDescObj.getProperty(runtime, "get"));
|
|
509
506
|
}
|
|
510
507
|
}
|
|
511
508
|
descriptor.setProperty(runtime, "set", setterFunc);
|
|
@@ -531,8 +528,8 @@ protected:
|
|
|
531
528
|
const jsi::Value *args, size_t count) -> jsi::Value {
|
|
532
529
|
auto native = Derived::fromValue(rt, thisVal);
|
|
533
530
|
ReturnType result = (native.get()->*getter)();
|
|
534
|
-
return rnwgpu::JSIConverter<std::decay_t<ReturnType>>::toJSI(
|
|
535
|
-
|
|
531
|
+
return rnwgpu::JSIConverter<std::decay_t<ReturnType>>::toJSI(
|
|
532
|
+
rt, std::move(result));
|
|
536
533
|
});
|
|
537
534
|
|
|
538
535
|
auto setterFunc = jsi::Function::createFromHostFunction(
|
|
@@ -544,8 +541,8 @@ protected:
|
|
|
544
541
|
throw jsi::JSError(rt, "Setter requires a value argument");
|
|
545
542
|
}
|
|
546
543
|
auto native = Derived::fromValue(rt, thisVal);
|
|
547
|
-
auto value =
|
|
548
|
-
|
|
544
|
+
auto value = rnwgpu::JSIConverter<std::decay_t<ValueType>>::fromJSI(
|
|
545
|
+
rt, args[0], false);
|
|
549
546
|
(native.get()->*setter)(std::move(value));
|
|
550
547
|
return jsi::Value::undefined();
|
|
551
548
|
});
|
|
@@ -580,10 +577,11 @@ private:
|
|
|
580
577
|
// This requires the method signature to match HostFunction
|
|
581
578
|
return (obj->*method)(runtime, jsi::Value::undefined(), args, count);
|
|
582
579
|
} else {
|
|
583
|
-
ReturnType result =
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
580
|
+
ReturnType result =
|
|
581
|
+
(obj->*method)(rnwgpu::JSIConverter<std::decay_t<Args>>::fromJSI(
|
|
582
|
+
runtime, args[Is], Is >= count)...);
|
|
583
|
+
return rnwgpu::JSIConverter<std::decay_t<ReturnType>>::toJSI(
|
|
584
|
+
runtime, std::move(result));
|
|
587
585
|
}
|
|
588
586
|
}
|
|
589
587
|
};
|
package/cpp/jsi2/Promise.cpp
CHANGED
|
@@ -10,20 +10,24 @@ namespace rnwgpu {
|
|
|
10
10
|
|
|
11
11
|
namespace jsi = facebook::jsi;
|
|
12
12
|
|
|
13
|
-
Promise::Promise(jsi::Runtime&
|
|
14
|
-
|
|
13
|
+
Promise::Promise(jsi::Runtime &runtime, jsi::Function &&resolver,
|
|
14
|
+
jsi::Function &&rejecter)
|
|
15
|
+
: runtime(runtime), _resolver(std::move(resolver)),
|
|
16
|
+
_rejecter(std::move(rejecter)) {}
|
|
15
17
|
|
|
16
|
-
jsi::Value Promise::createPromise(jsi::Runtime&
|
|
18
|
+
jsi::Value Promise::createPromise(jsi::Runtime &runtime, RunPromise run) {
|
|
17
19
|
// Get Promise ctor from global
|
|
18
20
|
auto promiseCtor = runtime.global().getPropertyAsFunction(runtime, "Promise");
|
|
19
21
|
|
|
20
22
|
auto promiseCallback = jsi::Function::createFromHostFunction(
|
|
21
23
|
runtime, jsi::PropNameID::forUtf8(runtime, "PromiseCallback"), 2,
|
|
22
|
-
[=](jsi::Runtime&
|
|
24
|
+
[=](jsi::Runtime &runtime, const jsi::Value &thisValue,
|
|
25
|
+
const jsi::Value *arguments, size_t count) -> jsi::Value {
|
|
23
26
|
// Call function
|
|
24
27
|
auto resolver = arguments[0].asObject(runtime).asFunction(runtime);
|
|
25
28
|
auto rejecter = arguments[1].asObject(runtime).asFunction(runtime);
|
|
26
|
-
auto promise = std::make_shared<Promise>(runtime, std::move(resolver),
|
|
29
|
+
auto promise = std::make_shared<Promise>(runtime, std::move(resolver),
|
|
30
|
+
std::move(rejecter));
|
|
27
31
|
run(runtime, promise);
|
|
28
32
|
|
|
29
33
|
return jsi::Value::undefined();
|
|
@@ -32,7 +36,7 @@ jsi::Value Promise::createPromise(jsi::Runtime& runtime, RunPromise run) {
|
|
|
32
36
|
return promiseCtor.callAsConstructor(runtime, promiseCallback);
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
void Promise::resolve(jsi::Value&&
|
|
39
|
+
void Promise::resolve(jsi::Value &&result) {
|
|
36
40
|
_resolver.call(runtime, std::move(result));
|
|
37
41
|
}
|
|
38
42
|
|