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.
- package/NitroModules.podspec +2 -1
- package/README.md +31 -0
- package/android/CMakeLists.txt +4 -4
- package/android/gradle.properties +1 -1
- package/android/src/main/cpp/JNIOnLoad.cpp +7 -6
- package/android/src/main/java/com/margelo/nitro/HybridObject.kt +0 -11
- package/android/src/main/java/com/margelo/nitro/HybridObjectRegistry.java +2 -13
- package/android/src/main/java/com/margelo/nitro/NitroModulesPackage.java +12 -0
- package/cpp/core/AnyMap.hpp +12 -0
- package/cpp/core/ArrayBuffer.cpp +88 -0
- package/cpp/core/ArrayBuffer.hpp +29 -75
- package/cpp/jsi/JSICache.cpp +1 -3
- package/cpp/jsi/JSIConverter+Promise.hpp +2 -2
- package/cpp/jsi/{Promise.cpp → JSPromise.cpp} +6 -6
- package/cpp/jsi/{Promise.hpp → JSPromise.hpp} +10 -10
- package/cpp/registry/HybridObjectRegistry.cpp +13 -0
- package/cpp/registry/HybridObjectRegistry.hpp +4 -2
- package/cpp/turbomodule/NativeNitroModules.cpp +38 -2
- package/cpp/turbomodule/NativeNitroModules.hpp +2 -0
- package/cpp/utils/NitroDefines.hpp +6 -0
- package/ios/core/ArrayBuffer.swift +51 -0
- package/ios/core/ArrayBufferHolder.hpp +69 -0
- package/ios/core/ClosureWrapper.swift +25 -0
- package/ios/core/Promise.cpp +10 -0
- package/ios/core/Promise.hpp +43 -0
- package/ios/platform/ThreadUtils.cpp +1 -0
- package/lib/NativeNitroModules.d.ts +2 -0
- package/lib/NitroModules.d.ts +9 -1
- package/lib/NitroModules.js +15 -1
- package/lib/commonjs/NativeNitroModules.js.map +1 -1
- package/lib/commonjs/NitroModules.js +15 -1
- package/lib/commonjs/NitroModules.js.map +1 -1
- package/lib/module/NativeNitroModules.js.map +1 -1
- package/lib/module/NitroModules.js +15 -1
- package/lib/module/NitroModules.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/typescript/NativeNitroModules.d.ts +2 -0
- package/lib/typescript/NativeNitroModules.d.ts.map +1 -1
- package/lib/typescript/NitroModules.d.ts +9 -1
- package/lib/typescript/NitroModules.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/NativeNitroModules.ts +2 -0
- package/src/NitroModules.ts +15 -1
- package/lib/typescript/AnyMap.d.ts +0 -17
- package/lib/typescript/HybridObject.d.ts +0 -83
- package/lib/typescript/ModuleNotFoundError.d.ts +0 -7
- package/lib/typescript/NativeNitroModules.web.d.ts +0 -5
- package/lib/typescript/__tests__/index.test.d.ts +0 -1
- package/lib/typescript/index.d.ts +0 -4
package/NitroModules.podspec
CHANGED
|
@@ -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/
|
|
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<T></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<A, B, C, ...></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<A, B, C, ...></code></td>
|
|
150
|
+
<td><code>Variant_A_B_C</code></td>
|
|
143
151
|
</tr>
|
|
144
152
|
<tr>
|
|
145
153
|
<td><code>Record<string, T></code></td>
|
|
146
154
|
<td><code>std::unordered_map<std::string, T></code></td>
|
|
155
|
+
<td><code>Dictionary<String, T></code></td>
|
|
147
156
|
</tr>
|
|
148
157
|
<tr>
|
|
149
158
|
<td><code>T?</code></td>
|
|
150
159
|
<td><code>std::optional<T></code></td>
|
|
160
|
+
<td><code>T?</code></td>
|
|
151
161
|
</tr>
|
|
152
162
|
<tr>
|
|
153
163
|
<td><code>Promise<T></code></td>
|
|
154
164
|
<td><code>std::future<T></code></td>
|
|
165
|
+
<td>❌</td>
|
|
155
166
|
</tr>
|
|
156
167
|
<tr>
|
|
157
168
|
<td><code>(TArgs...) => void</code></td>
|
|
158
169
|
<td><code>std::function<void (TArgs...)></code></td>
|
|
170
|
+
<td><code>@escaping (TArgs...) -> Void</code></td>
|
|
159
171
|
</tr>
|
|
160
172
|
<tr>
|
|
161
173
|
<td><code>(TArgs...) => TReturn</code></td>
|
|
162
174
|
<td><code>std::function<std::future<TReturn> (TArgs...)></code></td>
|
|
175
|
+
<td>❌</td>
|
|
163
176
|
</tr>
|
|
164
177
|
<tr>
|
|
165
178
|
<td><code>{ ... }</code></td>
|
|
166
179
|
<td><code>std::shared_ptr<<a href="./cpp/core/AnyMap.hpp">AnyMap</a>></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<<a href="./cpp/core/ArrayBuffer.hpp">ArrayBuffer</a>></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<<a href="./cpp/core/HybridObject.hpp">HybridObject</a>></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
|
|
package/android/CMakeLists.txt
CHANGED
|
@@ -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(
|
|
9
|
-
"../cpp
|
|
8
|
+
file(GLOB_RECURSE shared_files RELATIVE ${CMAKE_SOURCE_DIR}
|
|
9
|
+
"../cpp/**.cpp"
|
|
10
10
|
)
|
|
11
|
-
file(
|
|
12
|
-
"src/main/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,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
|
-
|
|
11
|
-
|
|
11
|
+
return facebook::jni::initialize(vm, [] {
|
|
12
|
+
// 1. Initialize the Nitro JSI Turbo Module
|
|
13
|
+
RegisterNativeNitroModules::registerNativeNitroModules();
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
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.
|
|
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.
|
|
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
|
package/cpp/core/AnyMap.hpp
CHANGED
|
@@ -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
|
package/cpp/core/ArrayBuffer.hpp
CHANGED
|
@@ -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 =
|
|
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
|
-
|
|
73
|
-
|
|
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,
|
|
80
|
-
|
|
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
|
-
|
|
90
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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;
|
package/cpp/jsi/JSICache.cpp
CHANGED
|
@@ -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
|
|
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 "
|
|
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
|
|
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 "
|
|
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
|
-
|
|
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
|
|
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<
|
|
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
|
|
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
|
|
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
|
-
//
|
|
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
|
-
`
|
|
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
|
|
25
|
+
class JSPromise final {
|
|
26
26
|
public:
|
|
27
|
-
|
|
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<
|
|
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();
|