@shopify/react-native-skia 2.4.17 → 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.
Files changed (87) hide show
  1. package/android/cpp/rnskia-android/RNSkAndroidVideo.cpp +34 -0
  2. package/android/cpp/rnskia-android/RNSkAndroidVideo.h +3 -0
  3. package/android/src/main/java/com/shopify/reactnative/skia/RNSkVideo.java +72 -18
  4. package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +7 -7
  5. package/apple/RNSkAppleVideo.h +30 -3
  6. package/apple/RNSkAppleVideo.mm +172 -17
  7. package/cpp/api/JsiSkApi.h +15 -13
  8. package/cpp/api/JsiSkHostObjects.h +57 -3
  9. package/cpp/api/JsiSkImage.h +19 -5
  10. package/cpp/api/JsiSkPicture.h +19 -5
  11. package/cpp/api/JsiSkSurface.h +19 -5
  12. package/cpp/api/JsiVideo.h +15 -2
  13. package/cpp/api/recorder/Convertor.h +4 -2
  14. package/cpp/jsi2/EnumMapper.h +49 -34
  15. package/cpp/jsi2/JSIConverter.h +149 -99
  16. package/cpp/jsi2/NativeObject.h +23 -25
  17. package/cpp/jsi2/Promise.cpp +10 -6
  18. package/cpp/jsi2/Promise.h +9 -7
  19. package/cpp/rnskia/RNDawnContext.h +3 -8
  20. package/cpp/rnskia/RNSkManager.cpp +13 -7
  21. package/cpp/rnskia/RNSkVideo.h +3 -0
  22. package/cpp/rnwgpu/api/GPUAdapter.cpp +31 -32
  23. package/cpp/rnwgpu/api/GPUAdapter.h +1 -1
  24. package/cpp/rnwgpu/api/GPUBuffer.cpp +8 -8
  25. package/cpp/rnwgpu/api/GPUCommandEncoder.h +4 -4
  26. package/cpp/rnwgpu/api/GPUDevice.h +12 -12
  27. package/cpp/rnwgpu/api/GPUQueue.cpp +45 -44
  28. package/cpp/rnwgpu/api/GPUQueue.h +1 -1
  29. package/cpp/rnwgpu/api/GPURenderBundleEncoder.h +1 -1
  30. package/cpp/rnwgpu/api/GPURenderPassEncoder.h +1 -1
  31. package/cpp/rnwgpu/api/descriptors/GPUBindGroupEntry.h +1 -1
  32. package/cpp/rnwgpu/api/descriptors/GPUComputePipelineDescriptor.h +1 -1
  33. package/cpp/rnwgpu/api/descriptors/GPUImageCopyExternalImage.h +7 -6
  34. package/cpp/rnwgpu/api/descriptors/GPURenderPassDescriptor.h +1 -1
  35. package/cpp/rnwgpu/api/descriptors/GPURenderPipelineDescriptor.h +1 -1
  36. package/cpp/rnwgpu/api/descriptors/GPUVertexState.h +1 -1
  37. package/cpp/rnwgpu/async/AsyncRunner.cpp +2 -1
  38. package/cpp/rnwgpu/async/AsyncRunner.h +2 -1
  39. package/lib/commonjs/external/reanimated/useVideo.js +30 -31
  40. package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
  41. package/lib/commonjs/renderer/Offscreen.js +1 -0
  42. package/lib/commonjs/renderer/Offscreen.js.map +1 -1
  43. package/lib/commonjs/skia/types/Video/Video.d.ts +3 -0
  44. package/lib/commonjs/skia/types/Video/Video.js.map +1 -1
  45. package/lib/commonjs/skia/web/JsiVideo.d.ts +3 -0
  46. package/lib/commonjs/skia/web/JsiVideo.js +9 -0
  47. package/lib/commonjs/skia/web/JsiVideo.js.map +1 -1
  48. package/lib/commonjs/sksg/Container.web.js +1 -0
  49. package/lib/commonjs/sksg/Container.web.js.map +1 -1
  50. package/lib/commonjs/sksg/HostConfig.js +4 -1
  51. package/lib/commonjs/sksg/HostConfig.js.map +1 -1
  52. package/lib/commonjs/sksg/Reconciler.js +6 -6
  53. package/lib/commonjs/sksg/Reconciler.js.map +1 -1
  54. package/lib/commonjs/sksg/StaticContainer.js +1 -0
  55. package/lib/commonjs/sksg/StaticContainer.js.map +1 -1
  56. package/lib/module/external/reanimated/useVideo.js +30 -31
  57. package/lib/module/external/reanimated/useVideo.js.map +1 -1
  58. package/lib/module/renderer/Offscreen.js +1 -0
  59. package/lib/module/renderer/Offscreen.js.map +1 -1
  60. package/lib/module/skia/types/Video/Video.d.ts +3 -0
  61. package/lib/module/skia/types/Video/Video.js.map +1 -1
  62. package/lib/module/skia/web/JsiVideo.d.ts +3 -0
  63. package/lib/module/skia/web/JsiVideo.js +9 -0
  64. package/lib/module/skia/web/JsiVideo.js.map +1 -1
  65. package/lib/module/sksg/Container.web.js +1 -0
  66. package/lib/module/sksg/Container.web.js.map +1 -1
  67. package/lib/module/sksg/HostConfig.js +4 -1
  68. package/lib/module/sksg/HostConfig.js.map +1 -1
  69. package/lib/module/sksg/Reconciler.js +6 -6
  70. package/lib/module/sksg/Reconciler.js.map +1 -1
  71. package/lib/module/sksg/StaticContainer.js +1 -0
  72. package/lib/module/sksg/StaticContainer.js.map +1 -1
  73. package/lib/typescript/lib/commonjs/skia/web/JsiVideo.d.ts +3 -0
  74. package/lib/typescript/lib/commonjs/sksg/HostConfig.d.ts +2 -0
  75. package/lib/typescript/lib/module/skia/web/JsiVideo.d.ts +3 -0
  76. package/lib/typescript/lib/module/sksg/HostConfig.d.ts +2 -0
  77. package/lib/typescript/src/skia/types/Video/Video.d.ts +3 -0
  78. package/lib/typescript/src/skia/web/JsiVideo.d.ts +3 -0
  79. package/package.json +1 -1
  80. package/src/external/reanimated/useVideo.ts +32 -32
  81. package/src/renderer/Offscreen.tsx +1 -0
  82. package/src/skia/types/Video/Video.ts +3 -0
  83. package/src/skia/web/JsiVideo.ts +12 -0
  84. package/src/sksg/Container.web.ts +1 -0
  85. package/src/sksg/HostConfig.ts +4 -0
  86. package/src/sksg/Reconciler.ts +5 -6
  87. package/src/sksg/StaticContainer.ts +1 -0
@@ -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 double
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, "This type is not supported by the JSIConverter!");
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, "This type is not supported by the JSIConverter!");
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& arg, bool outOfBound) {
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& arg, bool outOfBound) {
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& arg, bool outOfBound) {
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& arg, bool outOfBound) {
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> && std::is_same_v<T, size_t>>> {
90
- static size_t fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
91
- if (arg.isNumber()) {
92
- double value = arg.asNumber();
93
- return static_cast<size_t>(value);
94
- } else {
95
- return arg.asBigInt(runtime).asInt64(runtime);
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& runtime, size_t arg) {
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& runtime, const jsi::Value& arg, bool outOfBound) {
107
- double value = arg.asNumber();
108
- return static_cast<uint32_t>(value);
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& runtime, uint32_t arg) {
111
- return jsi::Value(static_cast<double>(arg));
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& runtime, const jsi::Value& arg, bool outOfBound) {
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& runtime, uint64_t arg) {
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, "Number too large to be represented as a double");
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* fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
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& runtime, void* arg) {
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& arg, bool outOfBound) {
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& runtime, const jsi::Value& arg, bool outOfBound) {
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& runtime, const std::string& arg) {
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& runtime, const jsi::Value& arg, bool outOfBound) {
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& runtime, const std::optional<TInner>& arg) {
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> struct JSIConverter<TEnum, std::enable_if_t<std::is_enum<TEnum>::value>> {
188
- static TEnum fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
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& runtime, const TEnum& arg) {
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&, const jsi::Value&, bool) {
205
- throw std::runtime_error("Cannot convert a Promise to AsyncTaskHandle on the native side.");
206
- }
207
-
208
- static jsi::Value toJSI(jsi::Runtime& runtime, rnwgpu::async::AsyncTaskHandle&& handle) {
209
- return rnwgpu::Promise::createPromise(runtime, [handle = std::move(handle)](jsi::Runtime& runtime,
210
- std::shared_ptr<rnwgpu::Promise> promise) mutable {
211
- if (!handle.valid()) {
212
- promise->resolve(jsi::Value::undefined());
213
- return;
214
- }
215
-
216
- handle.attachPromise(promise);
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> struct JSIConverter<std::map<std::string, ValueType>> {
224
- static std::map<std::string, ValueType> fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
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).asString(runtime).utf8(runtime);
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, JSIConverter<ValueType>::fromJSI(runtime, value, outOfBound));
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& runtime, const std::map<std::string, ValueType>& map) {
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& pair : map) {
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> fromJSI(jsi::Runtime& runtime, const jsi::Value& arg, bool outOfBound) {
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(runtime, elementValue, outOfBound));
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& runtime, const std::vector<ElementType>& vector) {
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> struct is_shared_ptr_to_native_state<std::shared_ptr<T>> : std::is_base_of<jsi::NativeState, 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> struct JSIConverter<T, std::enable_if_t<is_shared_ptr_to_native_state<T>::value>> {
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* demangled_name = abi::__cxa_demangle(name.c_str(), NULL, NULL, &status);
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 invalidTypeErrorMessage(const std::string& typeDescription, const std::string& reason) {
296
- return "Cannot convert \"" + typeDescription + "\" to NativeState<" + getFriendlyTypename() + ">! " + reason;
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& runtime, const jsi::Value& arg, bool outOfBound) {
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(runtime, invalidTypeErrorMessage("undefined", "It is undefined!"));
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, invalidTypeErrorMessage(stringRepresentation, "It is not an object!"));
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
- [[unlikely]];
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
- throw jsi::JSError(runtime, invalidTypeErrorMessage(stringRepresentation, "It is a different NativeState<T>!"));
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 = decltype(hasNativeObjectMarker<TPointee>(0))::value;
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& runtime, const T& arg) {
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<" + getFriendlyTypename() + ">!");
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 plain setNativeState
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>>::fromJSI not implemented");
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 = runtime.global().getPropertyAsFunction(runtime, "Set");
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& value : arg) {
461
- jsi::Value jsiValue = JSIConverter<std::string>::toJSI(runtime, value);
462
- add.callWithThis(runtime, set, jsiValue);
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
  }
@@ -14,7 +14,7 @@
14
14
  #include <unordered_map>
15
15
  #include <utility>
16
16
 
17
- #include "jsi/RuntimeAwareCache.h" // Use Skia's RuntimeAwareCache
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 once)
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
- rt, std::string("Illegal constructor: ") + Derived::CLASS_NAME +
317
- " objects are created by the WebGPU API");
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
- rnwgpu::JSIConverter<std::decay_t<ValueType>>::fromJSI(rt, args[0], false);
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
- runtime, "get", existingDescObj.getProperty(runtime, "get"));
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(rt,
535
- std::move(result));
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
- rnwgpu::JSIConverter<std::decay_t<ValueType>>::fromJSI(rt, args[0], false);
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 = (obj->*method)(rnwgpu::JSIConverter<std::decay_t<Args>>::fromJSI(
584
- runtime, args[Is], Is >= count)...);
585
- return rnwgpu::JSIConverter<std::decay_t<ReturnType>>::toJSI(runtime,
586
- std::move(result));
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
  };
@@ -10,20 +10,24 @@ namespace rnwgpu {
10
10
 
11
11
  namespace jsi = facebook::jsi;
12
12
 
13
- Promise::Promise(jsi::Runtime& runtime, jsi::Function&& resolver, jsi::Function&& rejecter)
14
- : runtime(runtime), _resolver(std::move(resolver)), _rejecter(std::move(rejecter)) {}
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& runtime, RunPromise run) {
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& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value {
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), std::move(rejecter));
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&& result) {
39
+ void Promise::resolve(jsi::Value &&result) {
36
40
  _resolver.call(runtime, std::move(result));
37
41
  }
38
42