react-native-nitro-modules 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/cpp/core/JArrayBuffer.hpp +1 -2
- package/android/src/main/cpp/core/JPromise.hpp +10 -0
- package/android/src/main/cpp/registry/JHybridObjectRegistry.cpp +1 -1
- package/android/src/main/cpp/utils/JNISharedPtr.hpp +1 -1
- package/android/src/main/java/com/margelo/nitro/core/ArrayBuffer.kt +29 -8
- package/android/src/main/java/com/margelo/nitro/core/HybridObject.kt +1 -1
- package/cpp/core/ArrayBuffer.cpp +16 -1
- package/cpp/core/ArrayBuffer.hpp +20 -1
- package/cpp/core/BoxedHybridObject.cpp +3 -2
- package/cpp/core/HybridObject.cpp +1 -1
- package/cpp/core/Promise.hpp +16 -0
- package/cpp/jsi/JSIConverter+Function.hpp +2 -5
- package/cpp/jsi/JSIConverter+Promise.hpp +2 -2
- package/cpp/prototype/HybridObjectPrototype.hpp +1 -1
- package/cpp/threading/Dispatcher.cpp +7 -0
- package/cpp/utils/NitroDefines.hpp +1 -1
- package/ios/core/ArrayBufferHolder.hpp +3 -3
- package/ios/core/ArrayBufferHolder.swift +98 -10
- package/ios/core/Promise.swift +2 -1
- package/ios/core/PromiseHolder.hpp +1 -1
- package/ios/core/RuntimeError.swift +2 -2
- package/ios/utils/RuntimeError.hpp +2 -2
- package/package.json +1 -2
|
@@ -38,8 +38,7 @@ public:
|
|
|
38
38
|
/**
|
|
39
39
|
* Create a new `JArrayBuffer` that wraps the given `ByteBuffer` from Java.
|
|
40
40
|
*/
|
|
41
|
-
static jni::local_ref<JArrayBuffer::jhybriddata> initHybrid(jni::alias_ref<jhybridobject>
|
|
42
|
-
jni::alias_ref<jni::JByteBuffer> buffer) {
|
|
41
|
+
static jni::local_ref<JArrayBuffer::jhybriddata> initHybrid(jni::alias_ref<jhybridobject>, jni::alias_ref<jni::JByteBuffer> buffer) {
|
|
43
42
|
return makeCxxInstance(buffer);
|
|
44
43
|
}
|
|
45
44
|
|
|
@@ -56,6 +56,16 @@ public:
|
|
|
56
56
|
return newObjectCxxArgs();
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
public:
|
|
60
|
+
~JPromise() override {
|
|
61
|
+
if (_result == nullptr && _error == nullptr) [[unlikely]] {
|
|
62
|
+
jni::ThreadScope::WithClassLoader([&]() {
|
|
63
|
+
std::runtime_error error("Timeouted: JPromise was destroyed!");
|
|
64
|
+
this->reject(jni::getJavaExceptionForCppException(std::make_exception_ptr(error)));
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
59
69
|
public:
|
|
60
70
|
void resolve(jni::alias_ref<jni::JObject> result) {
|
|
61
71
|
std::unique_lock lock(_mutex);
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
namespace margelo::nitro {
|
|
14
14
|
|
|
15
|
-
void JHybridObjectRegistry::registerHybridObjectConstructor(jni::alias_ref<jni::JClass
|
|
15
|
+
void JHybridObjectRegistry::registerHybridObjectConstructor(jni::alias_ref<jni::JClass>, std::string hybridObjectName,
|
|
16
16
|
jni::alias_ref<JHybridObjectInitializer> constructorFn) {
|
|
17
17
|
auto sharedInitializer = jni::make_global(constructorFn);
|
|
18
18
|
HybridObjectRegistry::registerHybridObjectConstructor(
|
|
@@ -107,19 +107,40 @@ class ArrayBuffer {
|
|
|
107
107
|
/**
|
|
108
108
|
* Copy the given `ArrayBuffer` into a new **owning** `ArrayBuffer`.
|
|
109
109
|
*/
|
|
110
|
-
fun
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
110
|
+
fun copy(other: ArrayBuffer): ArrayBuffer {
|
|
111
|
+
val byteBuffer = other.getBuffer(false)
|
|
112
|
+
return copy(byteBuffer)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Copy the given `ByteBuffer` into a new **owning** `ArrayBuffer`.
|
|
117
|
+
*/
|
|
118
|
+
fun copy(byteBuffer: ByteBuffer): ArrayBuffer {
|
|
119
|
+
// 1. Find out size
|
|
120
|
+
byteBuffer.rewind()
|
|
121
|
+
val size = byteBuffer.remaining()
|
|
122
|
+
// 2. Create a new buffer with the same size as the other
|
|
123
|
+
val newBuffer = ByteBuffer.allocateDirect(size)
|
|
116
124
|
// 3. Copy over the source buffer into the new buffer
|
|
117
|
-
newBuffer.put(
|
|
125
|
+
newBuffer.put(byteBuffer)
|
|
118
126
|
// 4. Rewind both buffers again to index 0
|
|
119
127
|
newBuffer.rewind()
|
|
120
|
-
|
|
128
|
+
byteBuffer.rewind()
|
|
121
129
|
// 5. Create a new `ArrayBuffer`
|
|
122
130
|
return ArrayBuffer(newBuffer)
|
|
123
131
|
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Wrap the given `ByteBuffer` in a new **owning** `ArrayBuffer`.
|
|
135
|
+
*/
|
|
136
|
+
fun wrap(byteBuffer: ByteBuffer): ArrayBuffer {
|
|
137
|
+
byteBuffer.rewind()
|
|
138
|
+
return ArrayBuffer(byteBuffer)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@Deprecated("Use copy(...) instead", level = DeprecationLevel.WARNING)
|
|
142
|
+
fun copyOf(other: ArrayBuffer): ArrayBuffer {
|
|
143
|
+
return copy(other)
|
|
144
|
+
}
|
|
124
145
|
}
|
|
125
146
|
}
|
package/cpp/core/ArrayBuffer.cpp
CHANGED
|
@@ -17,10 +17,25 @@ using namespace facebook;
|
|
|
17
17
|
|
|
18
18
|
// 1. ArrayBuffer
|
|
19
19
|
|
|
20
|
-
std::shared_ptr<ArrayBuffer> ArrayBuffer::
|
|
20
|
+
std::shared_ptr<ArrayBuffer> ArrayBuffer::wrap(uint8_t* data, size_t size, DeleteFn&& deleteFunc) {
|
|
21
21
|
return std::make_shared<NativeArrayBuffer>(data, size, std::move(deleteFunc));
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
std::shared_ptr<ArrayBuffer> ArrayBuffer::copy(uint8_t* data, size_t size) {
|
|
25
|
+
uint8_t* copy = new uint8_t[size];
|
|
26
|
+
std::memcpy(copy, data, size);
|
|
27
|
+
return ArrayBuffer::wrap(copy, size, [=]() { delete[] copy; });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
std::shared_ptr<ArrayBuffer> ArrayBuffer::copy(std::vector<uint8_t>& data) {
|
|
31
|
+
return ArrayBuffer::copy(data.data(), data.size());
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
std::shared_ptr<ArrayBuffer> ArrayBuffer::allocate(size_t size) {
|
|
35
|
+
uint8_t* data = new uint8_t[size];
|
|
36
|
+
return ArrayBuffer::wrap(data, size, [=]() { delete[] data; });
|
|
37
|
+
}
|
|
38
|
+
|
|
24
39
|
// 2. NativeArrayBuffer
|
|
25
40
|
|
|
26
41
|
NativeArrayBuffer::NativeArrayBuffer(uint8_t* data, size_t size, DeleteFn&& deleteFunc)
|
package/cpp/core/ArrayBuffer.hpp
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
#include "OwningReference.hpp"
|
|
11
11
|
#include <jsi/jsi.h>
|
|
12
12
|
#include <thread>
|
|
13
|
+
#include <vector>
|
|
13
14
|
|
|
14
15
|
namespace margelo::nitro {
|
|
15
16
|
|
|
@@ -52,7 +53,25 @@ public:
|
|
|
52
53
|
* Create a new `NativeArrayBuffer` that wraps the given data (without copy) of the given size,
|
|
53
54
|
* and calls `deleteFunc` in which `data` should be deleted.
|
|
54
55
|
*/
|
|
55
|
-
static std::shared_ptr<ArrayBuffer>
|
|
56
|
+
static std::shared_ptr<ArrayBuffer> wrap(uint8_t* data, size_t size, DeleteFn&& deleteFunc);
|
|
57
|
+
/**
|
|
58
|
+
* Create a new `NativeArrayBuffer` that copies the given data of the given size
|
|
59
|
+
* into a newly allocated buffer.
|
|
60
|
+
*/
|
|
61
|
+
static std::shared_ptr<ArrayBuffer> copy(uint8_t* data, size_t size);
|
|
62
|
+
/**
|
|
63
|
+
* Create a new `NativeArrayBuffer` that copies the given `std::vector`.
|
|
64
|
+
*/
|
|
65
|
+
static std::shared_ptr<ArrayBuffer> copy(std::vector<uint8_t>& data);
|
|
66
|
+
/**
|
|
67
|
+
* Create a new `NativeArrayBuffer` that allocates a new buffer of the given size.
|
|
68
|
+
*/
|
|
69
|
+
static std::shared_ptr<ArrayBuffer> allocate(size_t size);
|
|
70
|
+
|
|
71
|
+
[[deprecated("Use wrapBuffer(...) instead.")]]
|
|
72
|
+
static std::shared_ptr<ArrayBuffer> makeBuffer(uint8_t* data, size_t size, DeleteFn&& deleteFunc) {
|
|
73
|
+
return ArrayBuffer::wrap(data, size, std::move(deleteFunc));
|
|
74
|
+
}
|
|
56
75
|
};
|
|
57
76
|
|
|
58
77
|
/**
|
|
@@ -19,8 +19,9 @@ jsi::Value BoxedHybridObject::get(jsi::Runtime& runtime, const jsi::PropNameID&
|
|
|
19
19
|
if (name == "unbox") {
|
|
20
20
|
return jsi::Function::createFromHostFunction(
|
|
21
21
|
runtime, jsi::PropNameID::forUtf8(runtime, "unbox"), 0,
|
|
22
|
-
[hybridObject = _hybridObject](jsi::Runtime& runtime, const jsi::Value
|
|
23
|
-
|
|
22
|
+
[hybridObject = _hybridObject](jsi::Runtime& runtime, const jsi::Value&, const jsi::Value*, size_t) -> jsi::Value {
|
|
23
|
+
return hybridObject->toObject(runtime);
|
|
24
|
+
});
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
return jsi::Value::undefined();
|
|
@@ -23,7 +23,7 @@ bool HybridObject::equals(std::shared_ptr<HybridObject> other) {
|
|
|
23
23
|
return this == other.get();
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
jsi::Value HybridObject::disposeRaw(jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value
|
|
26
|
+
jsi::Value HybridObject::disposeRaw(jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value*, size_t) {
|
|
27
27
|
// 1. Dispose any resources - this might be overridden by child classes to perform manual cleanup.
|
|
28
28
|
dispose();
|
|
29
29
|
// 2. Remove the NativeState from `this`
|
package/cpp/core/Promise.hpp
CHANGED
|
@@ -32,6 +32,14 @@ public:
|
|
|
32
32
|
private:
|
|
33
33
|
Promise() {}
|
|
34
34
|
|
|
35
|
+
public:
|
|
36
|
+
~Promise() {
|
|
37
|
+
if (isPending()) [[unlikely]] {
|
|
38
|
+
auto message = std::string("Timeouted: Promise<") + TypeInfo::getFriendlyTypename<TResult>() + "> was destroyed!";
|
|
39
|
+
reject(std::make_exception_ptr(std::runtime_error(message)));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
35
43
|
public:
|
|
36
44
|
/**
|
|
37
45
|
* Creates a new pending Promise that has to be resolved
|
|
@@ -258,6 +266,14 @@ public:
|
|
|
258
266
|
private:
|
|
259
267
|
Promise() {}
|
|
260
268
|
|
|
269
|
+
public:
|
|
270
|
+
~Promise() {
|
|
271
|
+
if (isPending()) [[unlikely]] {
|
|
272
|
+
std::runtime_error error("Timeouted: Promise<void> was destroyed!");
|
|
273
|
+
reject(std::make_exception_ptr(std::move(error)));
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
261
277
|
public:
|
|
262
278
|
static std::shared_ptr<Promise> create() {
|
|
263
279
|
return std::shared_ptr<Promise>(new Promise());
|
|
@@ -68,8 +68,8 @@ struct JSIConverter<std::function<ReturnType(Args...)>> final {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
static inline jsi::Value toJSI(jsi::Runtime& runtime, std::function<ReturnType(Args...)>&& function) {
|
|
71
|
-
jsi::HostFunctionType jsFunction = [function = std::move(function)](jsi::Runtime& runtime, const jsi::Value
|
|
72
|
-
|
|
71
|
+
jsi::HostFunctionType jsFunction = [function = std::move(function)](jsi::Runtime& runtime, const jsi::Value&, const jsi::Value* args,
|
|
72
|
+
size_t count) -> jsi::Value {
|
|
73
73
|
if (count != sizeof...(Args)) [[unlikely]] {
|
|
74
74
|
throw jsi::JSError(runtime, "Function expected " + std::to_string(sizeof...(Args)) + " arguments, but received " +
|
|
75
75
|
std::to_string(count) + "!");
|
|
@@ -95,9 +95,6 @@ struct JSIConverter<std::function<ReturnType(Args...)>> final {
|
|
|
95
95
|
|
|
96
96
|
private:
|
|
97
97
|
static inline ResultingType callJSFunction(jsi::Runtime& runtime, const OwningReference<jsi::Function>& function, const Args&... args) {
|
|
98
|
-
// Throw a lock on the OwningReference<T> so we can guarantee safe access (Hermes GC cannot delete it while `lock` is alive)
|
|
99
|
-
OwningLock<jsi::Function> lock = function.lock();
|
|
100
|
-
|
|
101
98
|
if (!function) {
|
|
102
99
|
if constexpr (std::is_void_v<ResultingType>) {
|
|
103
100
|
// runtime has already been deleted. since this returns void, we can just ignore it being deleted.
|
|
@@ -52,8 +52,8 @@ struct JSIConverter<std::shared_ptr<Promise<TResult>>> final {
|
|
|
52
52
|
if (promise->isPending()) {
|
|
53
53
|
// Get Promise ctor from global
|
|
54
54
|
jsi::Function promiseCtor = runtime.global().getPropertyAsFunction(runtime, "Promise");
|
|
55
|
-
jsi::HostFunctionType executor = [promise](jsi::Runtime& runtime, const jsi::Value
|
|
56
|
-
size_t
|
|
55
|
+
jsi::HostFunctionType executor = [promise](jsi::Runtime& runtime, const jsi::Value&, const jsi::Value* arguments,
|
|
56
|
+
size_t) -> jsi::Value {
|
|
57
57
|
// Add resolver listener
|
|
58
58
|
if constexpr (std::is_void_v<TResult>) {
|
|
59
59
|
// It's resolving to void.
|
|
@@ -79,7 +79,7 @@ protected:
|
|
|
79
79
|
* **Do not conditionally register hybrid methods, getters or setter!**
|
|
80
80
|
*/
|
|
81
81
|
template <typename Derived>
|
|
82
|
-
inline void registerHybrids(Derived*
|
|
82
|
+
inline void registerHybrids(Derived* /* this */, RegisterFn registerFunc) {
|
|
83
83
|
const std::shared_ptr<Prototype>& prototype = _prototypeChain.extendPrototype<Derived>();
|
|
84
84
|
|
|
85
85
|
if (!prototype->hasHybrids()) {
|
|
@@ -35,9 +35,9 @@ public:
|
|
|
35
35
|
* Once the `ArrayBuffer` is no longer in use, the given `deleteFunc` will be called with the given `deleteFuncContext`
|
|
36
36
|
* as an argument. The caller is responsible for deleting `data` once this is called.
|
|
37
37
|
*/
|
|
38
|
-
static ArrayBufferHolder
|
|
38
|
+
static ArrayBufferHolder wrap(uint8_t* _Nonnull data, size_t size, SwiftClosure destroy) {
|
|
39
39
|
std::function<void()> deleteFunc = destroy.getFunction();
|
|
40
|
-
auto arrayBuffer = ArrayBuffer::
|
|
40
|
+
auto arrayBuffer = ArrayBuffer::wrap(data, size, std::move(deleteFunc));
|
|
41
41
|
return ArrayBufferHolder(arrayBuffer);
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -45,7 +45,7 @@ public:
|
|
|
45
45
|
/**
|
|
46
46
|
* Gets the raw bytes the underlying `ArrayBuffer` points to.
|
|
47
47
|
*/
|
|
48
|
-
|
|
48
|
+
uint8_t* _Nonnull getData() const SWIFT_COMPUTED_PROPERTY {
|
|
49
49
|
return _arrayBuffer->data();
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
@@ -15,6 +15,8 @@ import Foundation
|
|
|
15
15
|
*/
|
|
16
16
|
public typealias ArrayBufferHolder = margelo.nitro.ArrayBufferHolder
|
|
17
17
|
|
|
18
|
+
// pragma MARK: Wrap
|
|
19
|
+
|
|
18
20
|
public extension ArrayBufferHolder {
|
|
19
21
|
/**
|
|
20
22
|
* Create a new `ArrayBufferHolder` that wraps the given `data` of the given `size`
|
|
@@ -28,9 +30,27 @@ public extension ArrayBufferHolder {
|
|
|
28
30
|
// Convert escaping Swift closure to a `void*`
|
|
29
31
|
let swiftClosure = SwiftClosure(wrappingClosure: delete)
|
|
30
32
|
// Create ArrayBufferHolder with our wrapped Swift closure to make it callable as a C-function pointer
|
|
31
|
-
return ArrayBufferHolder.
|
|
33
|
+
return ArrayBufferHolder.wrap(data, size, swiftClosure)
|
|
32
34
|
}
|
|
33
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Create a new `ArrayBufferHolder` that wraps the given `data` of the given `size`
|
|
38
|
+
* without performing a copy.
|
|
39
|
+
* When the `ArrayBuffer` is no longer used, `onDelete` will be called, in which
|
|
40
|
+
* you as a caller are responsible for deleting `data`.
|
|
41
|
+
*/
|
|
42
|
+
static func wrap(dataWithoutCopy data: UnsafeMutableRawPointer,
|
|
43
|
+
size: Int,
|
|
44
|
+
onDelete delete: @escaping () -> Void) -> ArrayBufferHolder {
|
|
45
|
+
return ArrayBufferHolder.wrap(dataWithoutCopy: data.assumingMemoryBound(to: UInt8.self),
|
|
46
|
+
size: size,
|
|
47
|
+
onDelete: delete)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// pragma MARK: Allocate
|
|
52
|
+
|
|
53
|
+
public extension ArrayBufferHolder {
|
|
34
54
|
/**
|
|
35
55
|
* Allocate a new buffer of the given `size`.
|
|
36
56
|
* If `initializeToZero` is `true`, all bytes are set to `0`, otherwise they are left untouched.
|
|
@@ -40,24 +60,92 @@ public extension ArrayBufferHolder {
|
|
|
40
60
|
if initializeToZero {
|
|
41
61
|
data.initialize(repeating: 0, count: size)
|
|
42
62
|
}
|
|
43
|
-
|
|
44
63
|
let deleteFunc = SwiftClosure {
|
|
45
64
|
data.deallocate()
|
|
46
65
|
}
|
|
47
|
-
return ArrayBufferHolder.
|
|
66
|
+
return ArrayBufferHolder.wrap(data, size, deleteFunc)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// pragma MARK: Copy
|
|
71
|
+
|
|
72
|
+
public extension ArrayBufferHolder {
|
|
73
|
+
/**
|
|
74
|
+
* Copy the given `UnsafeMutablePointer<UInt8>` into a new **owning** `ArrayBufferHolder`.
|
|
75
|
+
*/
|
|
76
|
+
static func copy(of other: UnsafeMutablePointer<UInt8>,
|
|
77
|
+
size: Int) -> ArrayBufferHolder {
|
|
78
|
+
// 1. Create new `UnsafeMutablePointer<UInt8>`
|
|
79
|
+
let copy = UnsafeMutablePointer<UInt8>.allocate(capacity: size)
|
|
80
|
+
// 2. Copy over data
|
|
81
|
+
copy.initialize(from: other, count: size)
|
|
82
|
+
// 3. Create memory safe destroyer
|
|
83
|
+
let deleteFunc = SwiftClosure {
|
|
84
|
+
copy.deallocate()
|
|
85
|
+
}
|
|
86
|
+
return ArrayBufferHolder.wrap(copy, size, deleteFunc)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Copy the given `UnsafeMutableRawPointer` into a new **owning** `ArrayBufferHolder`.
|
|
91
|
+
*/
|
|
92
|
+
static func copy(of other: UnsafeMutableRawPointer,
|
|
93
|
+
size: Int) -> ArrayBufferHolder {
|
|
94
|
+
return ArrayBufferHolder.copy(of: other.assumingMemoryBound(to: UInt8.self),
|
|
95
|
+
size: size)
|
|
48
96
|
}
|
|
49
97
|
|
|
50
98
|
/**
|
|
51
99
|
* Copy the given `ArrayBufferHolder` into a new **owning** `ArrayBufferHolder`.
|
|
52
100
|
*/
|
|
53
|
-
static func copy(of other:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
data.initialize(from: pointer, count: other.size)
|
|
101
|
+
static func copy(of other: ArrayBufferHolder) -> ArrayBufferHolder {
|
|
102
|
+
return ArrayBufferHolder.copy(of: other.data, size: other.size)
|
|
103
|
+
}
|
|
57
104
|
|
|
58
|
-
|
|
59
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Copy the given `Data` into a new **owning** `ArrayBufferHolder`.
|
|
107
|
+
*/
|
|
108
|
+
static func copy(data: Data) throws -> ArrayBufferHolder {
|
|
109
|
+
// 1. Create new `ArrayBuffer` of same size
|
|
110
|
+
let size = data.count
|
|
111
|
+
let arrayBuffer = ArrayBufferHolder.allocate(size: size)
|
|
112
|
+
// 2. Copy all bytes from `Data` into our new `ArrayBuffer`
|
|
113
|
+
try data.withUnsafeBytes { rawPointer in
|
|
114
|
+
guard let baseAddress = rawPointer.baseAddress else {
|
|
115
|
+
throw RuntimeError.error(withMessage: "Cannot get baseAddress of Data!")
|
|
116
|
+
}
|
|
117
|
+
memcpy(arrayBuffer.data, baseAddress, size)
|
|
118
|
+
}
|
|
119
|
+
return arrayBuffer
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
// pragma MARK: Data
|
|
125
|
+
|
|
126
|
+
public extension ArrayBufferHolder {
|
|
127
|
+
/**
|
|
128
|
+
* Wrap this `ArrayBufferHolder` in a `Data` instance, without performing a copy.
|
|
129
|
+
* - `copyIfNeeded`: If this `ArrayBuffer` is **non-owning**, the foreign
|
|
130
|
+
* data may needs to be copied to be safely used outside of the scope of the caller function.
|
|
131
|
+
* This flag controls that.
|
|
132
|
+
*/
|
|
133
|
+
func toData(copyIfNeeded: Bool) -> Data {
|
|
134
|
+
let shouldCopy = copyIfNeeded && !self.isOwner
|
|
135
|
+
if shouldCopy {
|
|
136
|
+
// COPY DATA
|
|
137
|
+
return Data.init(bytes: self.data, count: self.size)
|
|
138
|
+
} else {
|
|
139
|
+
// WRAP DATA
|
|
140
|
+
// 1. Get the std::shared_ptr<ArrayBuffer>
|
|
141
|
+
var sharedPointer = self.getArrayBuffer()
|
|
142
|
+
// 2. Create a Data object WRAPPING our pointer
|
|
143
|
+
return Data(bytesNoCopy: self.data, count: self.size, deallocator: .custom({ buffer, size in
|
|
144
|
+
// 3. Capture the std::shared_ptr<ArrayBuffer> in the deallocator lambda so it stays alive.
|
|
145
|
+
// As soon as this lambda gets called, the `sharedPointer` gets deleted causing the
|
|
146
|
+
// underlying `ArrayBuffer` to be freed.
|
|
147
|
+
sharedPointer.reset()
|
|
148
|
+
}))
|
|
60
149
|
}
|
|
61
|
-
return ArrayBufferHolder.makeBuffer(data, other.size, deleteFunc)
|
|
62
150
|
}
|
|
63
151
|
}
|
package/ios/core/Promise.swift
CHANGED
|
@@ -37,7 +37,8 @@ public final class Promise<T> {
|
|
|
37
37
|
|
|
38
38
|
deinit {
|
|
39
39
|
if state == nil {
|
|
40
|
-
|
|
40
|
+
let message = "Timeouted: Promise<\(String(describing: T.self))> was destroyed!"
|
|
41
|
+
reject(withError: RuntimeError.error(withMessage: message))
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
|
|
@@ -26,7 +26,7 @@ public enum RuntimeError: Error, CustomStringConvertible {
|
|
|
26
26
|
* Creates a new `RuntimeError` from the given C++ `std::exception`.
|
|
27
27
|
*/
|
|
28
28
|
public static func from(cppError: std.exception_ptr) -> RuntimeError {
|
|
29
|
-
let message = margelo.nitro.
|
|
29
|
+
let message = margelo.nitro.getExceptionMessage(cppError)
|
|
30
30
|
return .error(withMessage: String(message))
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -37,6 +37,6 @@ public extension Error {
|
|
|
37
37
|
*/
|
|
38
38
|
func toCpp() -> std.exception_ptr {
|
|
39
39
|
let message = String(describing: self)
|
|
40
|
-
return margelo.nitro.
|
|
40
|
+
return margelo.nitro.makeException(std.string(message))
|
|
41
41
|
}
|
|
42
42
|
}
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
|
|
14
14
|
namespace margelo::nitro {
|
|
15
15
|
|
|
16
|
-
static inline std::exception_ptr
|
|
16
|
+
static inline std::exception_ptr makeException(const std::string& message) {
|
|
17
17
|
return std::make_exception_ptr(std::runtime_error(message));
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
static inline std::string
|
|
20
|
+
static inline std::string getExceptionMessage(const std::exception_ptr& exception) {
|
|
21
21
|
if (exception == nullptr) [[unlikely]] {
|
|
22
22
|
throw std::runtime_error("Cannot get error message of an empty exception_ptr!");
|
|
23
23
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-nitro-modules",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Insanely fast native C++, Swift or Kotlin modules with a statically compiled binding layer to JSI.",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|
|
@@ -117,7 +117,6 @@
|
|
|
117
117
|
[
|
|
118
118
|
"typescript",
|
|
119
119
|
{
|
|
120
|
-
"tsc": "../../node_modules/.bin/tsc",
|
|
121
120
|
"project": "tsconfig.build.json"
|
|
122
121
|
}
|
|
123
122
|
]
|