react-native-nitro-modules 0.3.0 → 0.4.1

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 (49) hide show
  1. package/NitroModules.podspec +2 -1
  2. package/README.md +31 -0
  3. package/android/CMakeLists.txt +4 -4
  4. package/android/gradle.properties +1 -1
  5. package/android/src/main/cpp/JNIOnLoad.cpp +7 -6
  6. package/android/src/main/java/com/margelo/nitro/HybridObject.kt +0 -11
  7. package/android/src/main/java/com/margelo/nitro/HybridObjectRegistry.java +2 -13
  8. package/android/src/main/java/com/margelo/nitro/NitroModulesPackage.java +12 -0
  9. package/cpp/core/AnyMap.hpp +12 -0
  10. package/cpp/core/ArrayBuffer.cpp +88 -0
  11. package/cpp/core/ArrayBuffer.hpp +29 -75
  12. package/cpp/jsi/JSICache.cpp +1 -3
  13. package/cpp/jsi/JSIConverter+Promise.hpp +2 -2
  14. package/cpp/jsi/{Promise.cpp → JSPromise.cpp} +6 -6
  15. package/cpp/jsi/{Promise.hpp → JSPromise.hpp} +10 -10
  16. package/cpp/registry/HybridObjectRegistry.cpp +13 -0
  17. package/cpp/registry/HybridObjectRegistry.hpp +4 -2
  18. package/cpp/turbomodule/NativeNitroModules.cpp +38 -2
  19. package/cpp/turbomodule/NativeNitroModules.hpp +2 -0
  20. package/cpp/utils/NitroDefines.hpp +6 -0
  21. package/ios/core/ArrayBuffer.swift +51 -0
  22. package/ios/core/ArrayBufferHolder.hpp +69 -0
  23. package/ios/core/ClosureWrapper.swift +25 -0
  24. package/ios/core/Promise.cpp +10 -0
  25. package/ios/core/Promise.hpp +43 -0
  26. package/ios/platform/ThreadUtils.cpp +1 -0
  27. package/lib/NativeNitroModules.d.ts +2 -0
  28. package/lib/NitroModules.d.ts +9 -1
  29. package/lib/NitroModules.js +15 -1
  30. package/lib/commonjs/NativeNitroModules.js.map +1 -1
  31. package/lib/commonjs/NitroModules.js +15 -1
  32. package/lib/commonjs/NitroModules.js.map +1 -1
  33. package/lib/module/NativeNitroModules.js.map +1 -1
  34. package/lib/module/NitroModules.js +15 -1
  35. package/lib/module/NitroModules.js.map +1 -1
  36. package/lib/tsconfig.tsbuildinfo +1 -1
  37. package/lib/typescript/NativeNitroModules.d.ts +2 -0
  38. package/lib/typescript/NativeNitroModules.d.ts.map +1 -1
  39. package/lib/typescript/NitroModules.d.ts +9 -1
  40. package/lib/typescript/NitroModules.d.ts.map +1 -1
  41. package/package.json +1 -1
  42. package/src/NativeNitroModules.ts +2 -0
  43. package/src/NitroModules.ts +15 -1
  44. package/lib/typescript/AnyMap.d.ts +0 -17
  45. package/lib/typescript/HybridObject.d.ts +0 -83
  46. package/lib/typescript/ModuleNotFoundError.d.ts +0 -7
  47. package/lib/typescript/NativeNitroModules.web.d.ts +0 -5
  48. package/lib/typescript/__tests__/index.test.d.ts +0 -1
  49. package/lib/typescript/index.d.ts +0 -4
@@ -37,7 +37,8 @@ Pod::Spec.new do |s|
37
37
  "cpp/utils/NitroHash.hpp",
38
38
  "cpp/utils/NitroDefines.hpp",
39
39
  # Public iOS-specific headers that will be exposed in modulemap (for Swift)
40
- "ios/core/HybridContext.hpp"
40
+ "ios/core/ArrayBufferHolder.hpp",
41
+ "ios/core/HybridContext.hpp",
41
42
  ]
42
43
 
43
44
  s.pod_target_xcconfig = {
package/README.md CHANGED
@@ -111,67 +111,98 @@ The following C++ / JS types are supported out of the box:
111
111
  <tr>
112
112
  <th>JS Type</th>
113
113
  <th>C++ Type</th>
114
+ <th>Swift Type</th>
114
115
  </tr>
115
116
 
116
117
  <tr>
117
118
  <td><code>number</code></td>
118
119
  <td><code>double</code> / <code>int</code> / <code>float</code></td>
120
+ <td><code>Double</code> / <code>Int</code> / <code>Float</code></td>
119
121
  </tr>
120
122
  <tr>
121
123
  <td><code>boolean</code></td>
122
124
  <td><code>bool</code></td>
125
+ <td><code>Bool</code></td>
123
126
  </tr>
124
127
  <tr>
125
128
  <td><code>string</code></td>
126
129
  <td><code>std::string</code></td>
130
+ <td><code>String</code></td>
127
131
  </tr>
128
132
  <tr>
129
133
  <td><code>bigint</code></td>
130
134
  <td><code>int64_t</code> / <code>uint64_t</code></td>
135
+ <td><code>Int64</code> / <code>UInt64</code></td>
131
136
  </tr>
132
137
  <tr>
133
138
  <td><code>T[]</code></td>
134
139
  <td><code>std::vector&lt;T&gt;</code></td>
140
+ <td><code>[T]</code></td>
135
141
  </tr>
136
142
  <tr>
137
143
  <td><code>[A, B, C, ...]</code></td>
138
144
  <td><code>std::tuple&lt;A, B, C, ...&gt;</code></td>
145
+ <td><code>(A, B, C)</code></td>
139
146
  </tr>
140
147
  <tr>
141
148
  <td><code>A | B | C | ...</code></td>
142
149
  <td><code>std::variant&lt;A, B, C, ...&gt;</code></td>
150
+ <td><code>Variant_A_B_C</code></td>
143
151
  </tr>
144
152
  <tr>
145
153
  <td><code>Record&lt;string, T&gt;</code></td>
146
154
  <td><code>std::unordered_map&lt;std::string, T&gt;</code></td>
155
+ <td><code>Dictionary&lt;String, T&gt;</code></td>
147
156
  </tr>
148
157
  <tr>
149
158
  <td><code>T?</code></td>
150
159
  <td><code>std::optional&lt;T&gt;</code></td>
160
+ <td><code>T?</code></td>
151
161
  </tr>
152
162
  <tr>
153
163
  <td><code>Promise&lt;T&gt;</code></td>
154
164
  <td><code>std::future&lt;T&gt;</code></td>
165
+ <td>❌</td>
155
166
  </tr>
156
167
  <tr>
157
168
  <td><code>(TArgs...) =&gt; void</code></td>
158
169
  <td><code>std::function&lt;void (TArgs...)&gt;</code></td>
170
+ <td><code>@escaping (TArgs...) -&gt; Void</code></td>
159
171
  </tr>
160
172
  <tr>
161
173
  <td><code>(TArgs...) =&gt; TReturn</code></td>
162
174
  <td><code>std::function&lt;std::future&lt;TReturn&gt; (TArgs...)&gt;</code></td>
175
+ <td>❌</td>
163
176
  </tr>
164
177
  <tr>
165
178
  <td><code>{ ... }</code></td>
166
179
  <td><code>std::shared_ptr&lt;<a href="./cpp/core/AnyMap.hpp">AnyMap</a>&gt;</code></td>
180
+ <td>❌</td>
167
181
  </tr>
168
182
  <tr>
169
183
  <td><code>ArrayBuffer</code></td>
170
184
  <td><code>std::shared_ptr&lt;<a href="./cpp/core/ArrayBuffer.hpp">ArrayBuffer</a>&gt;</code></td>
185
+ <td><code><a href="./ios/core/ArrayBufferHolder.hpp">ArrayBufferHolder</a></code></td>
171
186
  </tr>
172
187
  <tr>
173
188
  <td><code><a href="./src/HybridObject.ts">HybridObject</a></code></td>
174
189
  <td><code>std::shared_ptr&lt;<a href="./cpp/core/HybridObject.hpp">HybridObject</a>&gt;</code></td>
190
+ <td><code><a href="./ios/core/HybridObjectSpec.swift">HybridObjectSpec</a></code></td>
191
+ </tr>
192
+ <tr>
193
+ <td>..any <code>interface</code></td>
194
+ <td><code>T</code></td>
195
+ <td><code>T</code></td>
196
+ </tr>
197
+ <tr>
198
+ <td>..any <code>enum</code></td>
199
+ <td><code>T</code></td>
200
+ <td><code>T</code></td>
201
+ </tr>
202
+ <tr>
203
+ <td>..any <code>union</code></td>
204
+ <td><code>T</code></td>
205
+ <td><code>T</code></td>
175
206
  </tr>
176
207
  </table>
177
208
 
@@ -5,11 +5,11 @@ set (CMAKE_VERBOSE_MAKEFILE ON)
5
5
  set (CMAKE_CXX_STANDARD 20)
6
6
 
7
7
  # Find all C++ files (shared and platform specifics)
8
- file(GLOB shared_files
9
- "../cpp/**/*.cpp"
8
+ file(GLOB_RECURSE shared_files RELATIVE ${CMAKE_SOURCE_DIR}
9
+ "../cpp/**.cpp"
10
10
  )
11
- file(GLOB android_files
12
- "src/main/cpp/**/*.cpp"
11
+ file(GLOB_RECURSE android_files RELATIVE ${CMAKE_SOURCE_DIR}
12
+ "src/main/cpp/**.cpp"
13
13
  )
14
14
 
15
15
  # Create library "NitroModules" and add all C++ files to it
@@ -2,4 +2,4 @@ Nitro_kotlinVersion=1.7.0
2
2
  Nitro_minSdkVersion=21
3
3
  Nitro_targetSdkVersion=31
4
4
  Nitro_compileSdkVersion=31
5
- Nitro_ndkversion=21.4.7075529
5
+ Nitro_ndkVersion=21.4.7075529
@@ -2,16 +2,17 @@
2
2
 
3
3
  #include "JHybridObjectRegistry.hpp"
4
4
  #include "RegisterNativeNitroModules.hpp"
5
+ #include <fbjni/fbjni.h>
5
6
  #include <jni.h>
6
7
 
7
8
  using namespace margelo::nitro;
8
9
 
9
10
  JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
10
- // 1. Initialize the Nitro JSI Turbo Module
11
- RegisterNativeNitroModules::registerNativeNitroModules();
11
+ return facebook::jni::initialize(vm, [] {
12
+ // 1. Initialize the Nitro JSI Turbo Module
13
+ RegisterNativeNitroModules::registerNativeNitroModules();
12
14
 
13
- // 2. Initialize all Java bindings
14
- JHybridObjectRegistry::registerNatives();
15
-
16
- return JNI_VERSION_1_2;
15
+ // 2. Initialize all Java bindings
16
+ JHybridObjectRegistry::registerNatives();
17
+ });
17
18
  }
@@ -1,6 +1,5 @@
1
1
  package com.margelo.nitro
2
2
 
3
- import android.util.Log
4
3
  import androidx.annotation.Keep
5
4
  import com.facebook.jni.HybridData
6
5
  import com.facebook.proguard.annotations.DoNotStrip
@@ -47,15 +46,5 @@ abstract class HybridObject {
47
46
 
48
47
  companion object {
49
48
  private const val TAG = "HybridObject"
50
- init {
51
- try {
52
- Log.i(TAG, "Loading NitroModules C++ library...")
53
- System.loadLibrary("NitroModules")
54
- Log.i(TAG, "Successfully loaded NitroModules C++ library!")
55
- } catch (e: Error) {
56
- Log.e(TAG, "Failed to load NitroModules C++ library! Is it properly installed and linked?", e)
57
- throw e
58
- }
59
- }
60
49
  }
61
50
  }
@@ -1,30 +1,19 @@
1
1
  package com.margelo.nitro;
2
2
 
3
- import android.util.Log;
4
-
5
3
  import java.util.function.Supplier;
6
4
 
7
5
  /**
8
6
  * A registry that holds initializers for HybridObjects.
9
- * This will be used to initialize them from JS using `NitroModules.get<T>(name)`.
7
+ * This will be used to initialize them from JS using `NitroModules.createHybridObject<T>(name)`.
10
8
  * @noinspection JavaJniMissingFunction
11
9
  */
12
10
  public class HybridObjectRegistry {
13
11
  /**
14
12
  * Registers the given HybridObject in the `HybridObjectRegistry`.
15
13
  * It will be uniquely identified via it's `hybridObjectName`, and can be initialized from
16
- * JS using `NitroModules.get<T>(name)` - which will call the `constructorFn` here.
14
+ * JS using `NitroModules.createHybridObject<T>(name)` - which will call the `constructorFn` here.
17
15
  */
18
16
  public static native void registerHybridObjectConstructor(String hybridObjectName, HybridObjectInitializer initializer);
19
17
 
20
18
  private static final String TAG = "HybridObjectRegistry";
21
- static {
22
- Log.i(TAG, "Loading native NitroModules C++ library...");
23
- try {
24
- System.loadLibrary("NitroModules");
25
- Log.i(TAG, "Successfully loaded native NitroModules C++ library!");
26
- } catch (Throwable e) {
27
- Log.e(TAG, "Failed to load native NitroModules C++ library!", e);
28
- }
29
- }
30
19
  }
@@ -1,5 +1,6 @@
1
1
  package com.margelo.nitro;
2
2
 
3
+ import android.util.Log;
3
4
  import androidx.annotation.Nullable;
4
5
 
5
6
  import com.facebook.react.bridge.NativeModule;
@@ -10,6 +11,17 @@ import com.facebook.react.TurboReactPackage;
10
11
  import java.util.HashMap;
11
12
 
12
13
  public class NitroModulesPackage extends TurboReactPackage {
14
+ private static final String TAG = "NitroModules";
15
+ static {
16
+ try {
17
+ Log.i(TAG, "Loading NitroModules C++ library...");
18
+ System.loadLibrary("NitroModules");
19
+ Log.i(TAG, "Successfully loaded NitroModules C++ library!");
20
+ } catch (Throwable e) {
21
+ Log.e(TAG, "Failed to load NitroModules C++ library! Is it properly installed and linked?", e);
22
+ throw e;
23
+ }
24
+ }
13
25
 
14
26
  @Nullable
15
27
  @Override
@@ -40,6 +40,12 @@ public:
40
40
  * Create a new instance of AnyMap.
41
41
  */
42
42
  explicit AnyMap() {}
43
+ /**
44
+ * Create a new instance of AnyMap with the given amount of spaces pre-allocated.
45
+ */
46
+ explicit AnyMap(size_t size) {
47
+ _map.reserve(size);
48
+ }
43
49
 
44
50
  public:
45
51
  /**
@@ -48,6 +54,12 @@ public:
48
54
  static std::shared_ptr<AnyMap> make() {
49
55
  return std::make_shared<AnyMap>();
50
56
  }
57
+ /**
58
+ * Create a new shared_ptr instance of AnyMap with the given amount of spaces pre-allocated.
59
+ */
60
+ static std::shared_ptr<AnyMap> make(size_t size) {
61
+ return std::make_shared<AnyMap>(size);
62
+ }
51
63
 
52
64
  public:
53
65
  /**
@@ -0,0 +1,88 @@
1
+ //
2
+ // ArrayBuffer.cpp
3
+ // react-native-nitro
4
+ //
5
+ // Created by Marc Rousavy on 14.07.24.
6
+ //
7
+
8
+ #include "ArrayBuffer.hpp"
9
+ #include "OwningReference.hpp"
10
+ #include <functional>
11
+ #include <jsi/jsi.h>
12
+ #include <thread>
13
+
14
+ namespace margelo::nitro {
15
+
16
+ using namespace facebook;
17
+
18
+ // 1. ArrayBuffer
19
+
20
+ std::shared_ptr<ArrayBuffer> ArrayBuffer::makeBuffer(uint8_t* data, size_t size, DeleteFn deleteFunc, void* deleteFuncContext) {
21
+ return std::make_shared<NativeArrayBuffer>(data, size, deleteFunc, deleteFuncContext);
22
+ }
23
+
24
+ // 2. NativeArrayBuffer
25
+
26
+ NativeArrayBuffer::NativeArrayBuffer(uint8_t* data, size_t size, DeleteFn deleteFunc, void* deleteFuncContext)
27
+ : ArrayBuffer(), _data(data), _size(size), _deleteFunc(deleteFunc), _deleteFuncContext(deleteFuncContext) {}
28
+
29
+ NativeArrayBuffer::~NativeArrayBuffer() {
30
+ if (_deleteFunc != nullptr) {
31
+ _deleteFunc(_deleteFuncContext);
32
+ }
33
+ }
34
+
35
+ uint8_t* NativeArrayBuffer::data() {
36
+ return _data;
37
+ }
38
+
39
+ size_t NativeArrayBuffer::size() const {
40
+ return _size;
41
+ }
42
+
43
+ bool NativeArrayBuffer::isOwner() const noexcept {
44
+ return _deleteFunc != nullptr;
45
+ }
46
+
47
+ // 3. JSArrayBuffer
48
+
49
+ JSArrayBuffer::JSArrayBuffer(jsi::Runtime* runtime, OwningReference<jsi::ArrayBuffer> jsReference)
50
+ : ArrayBuffer(), _runtime(runtime), _jsReference(jsReference), _initialThreadId(std::this_thread::get_id()) {}
51
+
52
+ JSArrayBuffer::~JSArrayBuffer() {}
53
+
54
+ uint8_t* JSArrayBuffer::data() {
55
+ if (_initialThreadId != std::this_thread::get_id()) [[unlikely]] {
56
+ throw std::runtime_error("`data()` can only be accessed synchronously on the JS Thread! "
57
+ "If you want to access it elsewhere, copy it first.");
58
+ }
59
+
60
+ OwningLock<jsi::ArrayBuffer> lock = _jsReference.lock();
61
+ if (!_jsReference) [[unlikely]] {
62
+ // JS Part has been deleted - data is now nullptr.
63
+ return nullptr;
64
+ }
65
+ // JS Part is still alive - we can assume that the jsi::Runtime is safe to access here too.
66
+ return _jsReference->data(*_runtime);
67
+ }
68
+
69
+ size_t JSArrayBuffer::size() const {
70
+ if (_initialThreadId != std::this_thread::get_id()) [[unlikely]] {
71
+ throw std::runtime_error("`size()` can only be accessed synchronously on the JS Thread! "
72
+ "If you want to access it elsewhere, copy it first.");
73
+ }
74
+
75
+ OwningLock<jsi::ArrayBuffer> lock = _jsReference.lock();
76
+ if (!_jsReference) [[unlikely]] {
77
+ // JS Part has been deleted - size is now 0.
78
+ return 0;
79
+ }
80
+ // JS Part is still alive - we can assume that the jsi::Runtime is safe to access here too.
81
+ return _jsReference->size(*_runtime);
82
+ }
83
+
84
+ bool JSArrayBuffer::isOwner() const noexcept {
85
+ return false;
86
+ }
87
+
88
+ } // namespace margelo::nitro
@@ -8,7 +8,6 @@
8
8
  #pragma once
9
9
 
10
10
  #include "OwningReference.hpp"
11
- #include <functional>
12
11
  #include <jsi/jsi.h>
13
12
  #include <thread>
14
13
 
@@ -16,9 +15,7 @@ namespace margelo::nitro {
16
15
 
17
16
  using namespace facebook;
18
17
 
19
- using DeleteFn = std::function<void(uint8_t*)>;
20
-
21
- static DeleteFn defaultDeleteFn = [](uint8_t* buffer) { delete[] buffer; };
18
+ using DeleteFn = void (*)(void* context);
22
19
 
23
20
  /**
24
21
  * Represents a raw byte buffer that can be read from-, and
@@ -36,12 +33,6 @@ static DeleteFn defaultDeleteFn = [](uint8_t* buffer) { delete[] buffer; };
36
33
  * When this `ArrayBuffer` gets deleted, the memory will not be freed explicitly, as someone else owns it.
37
34
  */
38
35
  class ArrayBuffer : public jsi::MutableBuffer {
39
- public:
40
- ArrayBuffer() = default;
41
- ArrayBuffer(const ArrayBuffer&) = delete;
42
- ArrayBuffer(ArrayBuffer&&) = delete;
43
- virtual ~ArrayBuffer() = default;
44
-
45
36
  public:
46
37
  /**
47
38
  * Returns whether this `ArrayBuffer` is actually owning the data,
@@ -49,6 +40,12 @@ public:
49
40
  * memory that we didn't allocate, or from JS - which can be deleted at any point).
50
41
  */
51
42
  virtual bool isOwner() const noexcept = 0;
43
+
44
+ /**
45
+ * Create a new `NativeArrayBuffer` that wraps the given data (without copy) of the given size,
46
+ * and calls `deleteFunc` with the given `deleteFuncContext` as a parameter in which `data` should be deleted.
47
+ */
48
+ static std::shared_ptr<ArrayBuffer> makeBuffer(uint8_t* data, size_t size, DeleteFn deleteFunc, void* deleteFuncContext);
52
49
  };
53
50
 
54
51
  /**
@@ -62,46 +59,31 @@ public:
62
59
  *
63
60
  * It is safe to access `data()` and `size()` from any Thread, but there are no synchronization/mutexes implemented by default.
64
61
  */
65
- class NativeArrayBuffer : public ArrayBuffer {
62
+ class NativeArrayBuffer final : public ArrayBuffer {
66
63
  public:
67
64
  /**
68
65
  * Create a new **owning** `ArrayBuffer`.
69
66
  * The `ArrayBuffer` can be kept in memory, as C++ owns the data
70
- * and will only delete it once this `ArrayBuffer` gets deleted
71
- */
72
- NativeArrayBuffer(uint8_t* data, size_t size, DeleteFn&& deleteFunc)
73
- : ArrayBuffer(), _data(data), _size(size), _deleteFunc(std::move(deleteFunc)) {}
74
- /**
75
- * Create a new `ArrayBuffer`.
76
- * If `destroyOnDeletion` is `true`, the `ArrayBuffer` is **owning**, otherwise it is **non-owning**.
77
- * The `ArrayBuffer` can only be safely kept in memory if it is owning (`isOwning()`).
67
+ * and will only delete it once this `ArrayBuffer` gets deleted.
68
+ *
69
+ * Once this `ArrayBuffer` goes out of scope, `deleteFunc` will be called.
70
+ * The caller is responsible for deleting the memory (`data` and `deleteFuncContext`) here.
78
71
  */
79
- NativeArrayBuffer(uint8_t* data, size_t size, bool destroyOnDeletion) : ArrayBuffer(), _data(data), _size(size) {
80
- _deleteFunc = destroyOnDeletion ? defaultDeleteFn : nullptr;
81
- }
82
-
83
- ~NativeArrayBuffer() {
84
- if (_deleteFunc != nullptr) {
85
- _deleteFunc(_data);
86
- }
87
- }
72
+ NativeArrayBuffer(uint8_t* data, size_t size, DeleteFn deleteFunc, void* deleteFuncContext);
73
+ ~NativeArrayBuffer();
88
74
 
89
- uint8_t* data() override {
90
- return _data;
91
- }
92
-
93
- size_t size() const override {
94
- return _size;
95
- }
75
+ public:
76
+ uint8_t* data() override;
77
+ size_t size() const override;
78
+ bool isOwner() const noexcept override;
96
79
 
97
- bool isOwner() const noexcept override {
98
- return _deleteFunc != nullptr;
99
- }
80
+ double something();
100
81
 
101
82
  private:
102
83
  uint8_t* _data;
103
84
  size_t _size;
104
85
  DeleteFn _deleteFunc;
86
+ void* _deleteFuncContext;
105
87
  };
106
88
 
107
89
  /**
@@ -115,52 +97,24 @@ private:
115
97
  *
116
98
  * If the JS ArrayBuffer (or it's JS Runtime) have already been deleted, `data()` returns `nullptr`.
117
99
  */
118
- class JSArrayBuffer : public ArrayBuffer {
100
+ class JSArrayBuffer final : public ArrayBuffer {
119
101
  public:
120
- explicit JSArrayBuffer(jsi::Runtime* runtime, OwningReference<jsi::ArrayBuffer> jsReference)
121
- : ArrayBuffer(), _runtime(runtime), _jsReference(jsReference), _initialThreadId(std::this_thread::get_id()) {}
122
- ~JSArrayBuffer() {}
102
+ explicit JSArrayBuffer(jsi::Runtime* runtime, OwningReference<jsi::ArrayBuffer> jsReference);
103
+ ~JSArrayBuffer();
123
104
 
124
105
  public:
125
106
  /**
126
107
  * Gets the data this `ArrayBuffer` points to, or `nullptr` if it has already been deleted.
127
108
  */
128
- uint8_t* data() override {
129
- if (_initialThreadId != std::this_thread::get_id()) [[unlikely]] {
130
- throw std::runtime_error("`data()` can only be accessed synchronously on the JS Thread! "
131
- "If you want to access it elsewhere, copy it first.");
132
- }
133
-
134
- OwningLock<jsi::ArrayBuffer> lock = _jsReference.lock();
135
- if (!_jsReference) [[unlikely]] {
136
- // JS Part has been deleted - data is now nullptr.
137
- return nullptr;
138
- }
139
- // JS Part is still alive - we can assume that the jsi::Runtime is safe to access here too.
140
- return _jsReference->data(*_runtime);
141
- }
142
-
109
+ uint8_t* data() override;
143
110
  /**
144
111
  * Gets the size of the data this `ArrayBuffer` points to, or `0` if it has already been deleted.
145
112
  */
146
- size_t size() const override {
147
- if (_initialThreadId != std::this_thread::get_id()) [[unlikely]] {
148
- throw std::runtime_error("`size()` can only be accessed synchronously on the JS Thread! "
149
- "If you want to access it elsewhere, copy it first.");
150
- }
151
-
152
- OwningLock<jsi::ArrayBuffer> lock = _jsReference.lock();
153
- if (!_jsReference) [[unlikely]] {
154
- // JS Part has been deleted - size is now 0.
155
- return 0;
156
- }
157
- // JS Part is still alive - we can assume that the jsi::Runtime is safe to access here too.
158
- return _jsReference->size(*_runtime);
159
- }
160
-
161
- bool isOwner() const noexcept override {
162
- return false;
163
- }
113
+ size_t size() const override;
114
+ /**
115
+ * Returns `false` for JS-based ArrayBuffers.
116
+ */
117
+ bool isOwner() const noexcept override;
164
118
 
165
119
  private:
166
120
  jsi::Runtime* _runtime;
@@ -8,8 +8,6 @@
8
8
  #include "JSICache.hpp"
9
9
  #include "JSIHelpers.hpp"
10
10
 
11
- #define DOUBLE_CHECK_GLOBAL_CACHE 1
12
-
13
11
  namespace margelo::nitro {
14
12
 
15
13
  static constexpr auto CACHE_PROP_NAME = "__nitroModulesJSICache";
@@ -48,7 +46,7 @@ JSICacheReference JSICache::getOrCreateCache(jsi::Runtime& runtime) {
48
46
  Logger::log(TAG, "JSICache was created, but it is no longer strong!");
49
47
  }
50
48
 
51
- #if DOUBLE_CHECK_GLOBAL_CACHE
49
+ #if DEBUG
52
50
  if (runtime.global().hasProperty(runtime, CACHE_PROP_NAME)) [[unlikely]] {
53
51
  throw std::runtime_error("The Runtime \"" + getRuntimeId(runtime) + "\" already has a global cache! (\"" + CACHE_PROP_NAME + "\")");
54
52
  }
@@ -16,7 +16,7 @@ struct JSIConverter;
16
16
  #include "JSIConverter.hpp"
17
17
 
18
18
  #include "Dispatcher.hpp"
19
- #include "Promise.hpp"
19
+ #include "JSPromise.hpp"
20
20
  #include "ThreadPool.hpp"
21
21
  #include "TypeInfo.hpp"
22
22
  #include <future>
@@ -38,7 +38,7 @@ struct JSIConverter<std::future<TResult>> {
38
38
  std::shared_ptr<Dispatcher> strongDispatcher = Dispatcher::getRuntimeGlobalDispatcher(runtime);
39
39
  std::weak_ptr<Dispatcher> weakDispatcher = strongDispatcher;
40
40
 
41
- return Promise::createPromise(runtime, [sharedFuture, weakDispatcher](jsi::Runtime& runtime, std::shared_ptr<Promise> promise) {
41
+ return JSPromise::createPromise(runtime, [sharedFuture, weakDispatcher](jsi::Runtime& runtime, std::shared_ptr<JSPromise> promise) {
42
42
  // Spawn new async thread to synchronously wait for the `future<T>` to complete
43
43
  std::shared_ptr<ThreadPool> pool = ThreadPool::getSharedPool();
44
44
  pool->run([promise, &runtime, weakDispatcher, sharedFuture]() {
@@ -1,4 +1,4 @@
1
- #include "Promise.hpp"
1
+ #include "JSPromise.hpp"
2
2
  #include "JSICache.hpp"
3
3
  #include "NitroLogger.hpp"
4
4
  #include <jsi/jsi.h>
@@ -7,13 +7,13 @@ namespace margelo::nitro {
7
7
 
8
8
  using namespace facebook;
9
9
 
10
- Promise::Promise(jsi::Runtime& runtime, jsi::Function&& resolver, jsi::Function&& rejecter) {
10
+ JSPromise::JSPromise(jsi::Runtime& runtime, jsi::Function&& resolver, jsi::Function&& rejecter) {
11
11
  auto functionCache = JSICache::getOrCreateCache(runtime);
12
12
  _resolver = functionCache.makeShared(std::move(resolver));
13
13
  _rejecter = functionCache.makeShared(std::move(rejecter));
14
14
  }
15
15
 
16
- jsi::Value Promise::createPromise(jsi::Runtime& runtime, RunPromise&& run) {
16
+ jsi::Value JSPromise::createPromise(jsi::Runtime& runtime, RunPromise&& run) {
17
17
  // Get Promise ctor from global
18
18
  auto promiseCtor = runtime.global().getPropertyAsFunction(runtime, "Promise");
19
19
 
@@ -24,7 +24,7 @@ jsi::Value Promise::createPromise(jsi::Runtime& runtime, RunPromise&& run) {
24
24
  auto resolver = arguments[0].getObject(runtime).getFunction(runtime);
25
25
  auto rejecter = arguments[1].getObject(runtime).getFunction(runtime);
26
26
  // Create `Promise` type that wraps the JSI callbacks
27
- auto promise = std::make_shared<Promise>(runtime, std::move(resolver), std::move(rejecter));
27
+ auto promise = std::make_shared<JSPromise>(runtime, std::move(resolver), std::move(rejecter));
28
28
  // Call `run` callback
29
29
  run(runtime, promise);
30
30
 
@@ -34,7 +34,7 @@ jsi::Value Promise::createPromise(jsi::Runtime& runtime, RunPromise&& run) {
34
34
  return promiseCtor.callAsConstructor(runtime, promiseCallback);
35
35
  }
36
36
 
37
- void Promise::resolve(jsi::Runtime& runtime, jsi::Value&& result) {
37
+ void JSPromise::resolve(jsi::Runtime& runtime, jsi::Value&& result) {
38
38
  OwningLock<jsi::Function> lock = _resolver.lock();
39
39
 
40
40
  if (!_resolver) {
@@ -44,7 +44,7 @@ void Promise::resolve(jsi::Runtime& runtime, jsi::Value&& result) {
44
44
  _resolver->call(runtime, std::move(result));
45
45
  }
46
46
 
47
- void Promise::reject(jsi::Runtime& runtime, std::string message) {
47
+ void JSPromise::reject(jsi::Runtime& runtime, std::string message) {
48
48
  OwningLock<jsi::Function> lock = _rejecter.lock();
49
49
 
50
50
  if (!_rejecter) {
@@ -1,5 +1,5 @@
1
1
  //
2
- // Promise.hpp
2
+ // JSPromise.hpp
3
3
  // react-native-filament
4
4
  //
5
5
  // Created by Marc Rousavy on 11.03.24.
@@ -17,14 +17,14 @@ namespace margelo::nitro {
17
17
  using namespace facebook;
18
18
 
19
19
  /**
20
- Represents a JS Promise.
21
-
22
- `Promise` is not thread-safe: It has to be resolved/rejected
23
- on the same thread and Runtime as it was created on.
20
+ * Represents a JS Promise.
21
+ *
22
+ * `JSPromise` is not thread-safe: It has to be resolved/rejected
23
+ * on the same thread and Runtime as it was created on.
24
24
  */
25
- class Promise final {
25
+ class JSPromise final {
26
26
  public:
27
- Promise(jsi::Runtime& runtime, jsi::Function&& resolver, jsi::Function&& rejecter);
27
+ JSPromise(jsi::Runtime& runtime, jsi::Function&& resolver, jsi::Function&& rejecter);
28
28
 
29
29
  /**
30
30
  Resolve the Promise with the given `jsi::Value`.
@@ -43,10 +43,10 @@ private:
43
43
  static constexpr auto TAG = "Promise";
44
44
 
45
45
  public:
46
- using RunPromise = std::function<void(jsi::Runtime& runtime, std::shared_ptr<Promise> promise)>;
46
+ using RunPromise = std::function<void(jsi::Runtime& runtime, std::shared_ptr<JSPromise> promise)>;
47
47
  /**
48
- Create a new Promise using the JS `Promise` constructor and runs the given `run` function.
49
- The resulting Promise should be returned to JS so it can be awaited.
48
+ * Create a new Promise using the JS `Promise` constructor and runs the given `run` function.
49
+ * The resulting Promise should be returned to JS so it can be awaited.
50
50
  */
51
51
  static jsi::Value createPromise(jsi::Runtime& runtime, RunPromise&& run);
52
52
  };
@@ -15,6 +15,19 @@ std::unordered_map<std::string, HybridObjectRegistry::HybridObjectConstructorFn>
15
15
  return _constructorsMap;
16
16
  }
17
17
 
18
+ bool HybridObjectRegistry::hasHybridObject(const std::string& name) {
19
+ return getRegistry().contains(name);
20
+ }
21
+
22
+ std::vector<std::string> HybridObjectRegistry::getAllHybridObjectNames() {
23
+ std::vector<std::string> keys;
24
+ keys.reserve(getRegistry().size());
25
+ for (const auto& entry : getRegistry()) {
26
+ keys.push_back(entry.first);
27
+ }
28
+ return keys;
29
+ }
30
+
18
31
  void HybridObjectRegistry::registerHybridObjectConstructor(const std::string& hybridObjectName, HybridObjectConstructorFn&& constructorFn) {
19
32
  Logger::log(TAG, "Registering HybridObject \"%s\"...", hybridObjectName);
20
33
  auto& map = HybridObjectRegistry::getRegistry();