react-native-nitro-modules 0.18.2 → 0.20.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/NitroModules.podspec +2 -0
- package/README.md +3 -3
- package/android/src/main/cpp/core/JPromise.hpp +4 -2
- package/android/src/main/cpp/registry/JHybridObjectRegistry.cpp +17 -14
- package/android/src/main/cpp/turbomodule/JNitroModules.cpp +0 -2
- package/android/src/main/cpp/turbomodule/JNitroModules.hpp +1 -1
- package/android/src/main/java/com/margelo/nitro/core/HybridObject.kt +1 -1
- package/cpp/core/AnyMap.hpp +2 -1
- package/cpp/core/HybridFunction.hpp +8 -0
- package/cpp/core/HybridObject.hpp +2 -2
- package/cpp/core/Promise.hpp +19 -32
- package/cpp/jsi/JSIConverter+Exception.hpp +6 -0
- package/cpp/jsi/JSIConverter+Function.hpp +21 -14
- package/cpp/jsi/JSIConverter+Future.hpp +5 -4
- package/cpp/templates/PromiseType.hpp +32 -0
- package/cpp/threading/Dispatcher.hpp +9 -10
- package/cpp/utils/NitroDefines.hpp +13 -14
- package/cpp/utils/TypeInfo.hpp +1 -1
- package/ios/core/ArrayBufferHolder.hpp +1 -1
- package/ios/core/ArrayBufferHolder.swift +1 -1
- package/ios/core/HybridContext.hpp +2 -1
- package/ios/core/HybridObjectSpec.swift +3 -18
- package/ios/core/Promise.swift +10 -10
- package/ios/core/PromiseHolder.hpp +93 -0
- package/ios/utils/MemoryHelper.swift +21 -0
- package/ios/utils/Result.hpp +193 -0
- package/ios/utils/SwiftClosure.hpp +4 -4
- package/ios/utils/SwiftClosure.swift +3 -4
- package/lib/commonjs/Constructor.js +1 -1
- package/lib/module/Constructor.js +1 -1
- package/lib/tsconfig.build.tsbuildinfo +1 -1
- package/lib/typescript/Constructor.d.ts +1 -1
- package/package.json +4 -4
- package/src/Constructor.ts +1 -1
|
@@ -11,17 +11,6 @@ import Foundation
|
|
|
11
11
|
* A base protocol for all Swift-based Hybrid Objects.
|
|
12
12
|
*/
|
|
13
13
|
public protocol HybridObjectSpec: AnyObject {
|
|
14
|
-
/**
|
|
15
|
-
* Holds the C++ HybridObject and it's context.
|
|
16
|
-
* Use the default initializer in your implementation, C++ will set and get this value.
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```swift
|
|
20
|
-
* var hybridContext = margelo.nitro.HybridContext()
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
var hybridContext: margelo.nitro.HybridContext { get set }
|
|
24
|
-
|
|
25
14
|
/**
|
|
26
15
|
* Get the memory size of the Swift instance (plus any external heap allocations),
|
|
27
16
|
* in bytes.
|
|
@@ -33,7 +22,7 @@ public protocol HybridObjectSpec: AnyObject {
|
|
|
33
22
|
* ```swift
|
|
34
23
|
* var memorySize: Int {
|
|
35
24
|
* let imageSize = self.uiImage.bytesPerRow * self.uiImage.height
|
|
36
|
-
* return
|
|
25
|
+
* return imageSize
|
|
37
26
|
* }
|
|
38
27
|
* ```
|
|
39
28
|
*/
|
|
@@ -41,12 +30,8 @@ public protocol HybridObjectSpec: AnyObject {
|
|
|
41
30
|
}
|
|
42
31
|
|
|
43
32
|
public extension HybridObjectSpec {
|
|
44
|
-
|
|
45
|
-
* Get the memory size of the given instance.
|
|
46
|
-
* This only accounts for stack allocated member variables,
|
|
47
|
-
* not for externally allocated heap allocations like images or buffers.
|
|
48
|
-
*/
|
|
33
|
+
@available(*, deprecated, message: "getSizeOf(...) will now be default-computed. Please remove getSizeOf() from your code.")
|
|
49
34
|
func getSizeOf<T: AnyObject>(_ instance: T) -> Int {
|
|
50
|
-
return
|
|
35
|
+
return 0
|
|
51
36
|
}
|
|
52
37
|
}
|
package/ios/core/Promise.swift
CHANGED
|
@@ -17,16 +17,16 @@ import Foundation
|
|
|
17
17
|
* - `Promise<T>.rejected(withError:)` - Creates a new already rejected Promise.
|
|
18
18
|
* - `Promise<T>()` - Creates a new Promise with fully manual control over the `resolve(..)`/`reject(..)` functions.
|
|
19
19
|
*/
|
|
20
|
-
public class Promise<T> {
|
|
20
|
+
public final class Promise<T> {
|
|
21
21
|
private enum State {
|
|
22
22
|
case result(T)
|
|
23
23
|
case error(Error)
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
private var state: State?
|
|
27
27
|
private var onResolvedListeners: [(T) -> Void] = []
|
|
28
28
|
private var onRejectedListeners: [(Error) -> Void] = []
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
/**
|
|
31
31
|
* Create a new pending Promise.
|
|
32
32
|
* It can (and must) be resolved **or** rejected later.
|
|
@@ -34,13 +34,13 @@ public class Promise<T> {
|
|
|
34
34
|
public init() {
|
|
35
35
|
state = nil
|
|
36
36
|
}
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
deinit {
|
|
39
39
|
if state == nil {
|
|
40
40
|
print("⚠️ Promise<\(String(describing: T.self))> got destroyed, but was never resolved or rejected! It is probably left hanging in JS now.")
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
/**
|
|
45
45
|
* Resolves this `Promise<T>` with the given `T` and notifies all listeners.
|
|
46
46
|
*/
|
|
@@ -51,7 +51,7 @@ public class Promise<T> {
|
|
|
51
51
|
state = .result(result)
|
|
52
52
|
onResolvedListeners.forEach { listener in listener(result) }
|
|
53
53
|
}
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
/**
|
|
56
56
|
* Rejects this `Promise<T>` with the given `Error` and notifies all listeners.
|
|
57
57
|
*/
|
|
@@ -76,7 +76,7 @@ extension Promise {
|
|
|
76
76
|
promise.state = .result(result)
|
|
77
77
|
return promise
|
|
78
78
|
}
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
/**
|
|
81
81
|
* Create a new `Promise<T>` already rejected with the given `Error`.
|
|
82
82
|
*/
|
|
@@ -85,7 +85,7 @@ extension Promise {
|
|
|
85
85
|
promise.state = .error(error)
|
|
86
86
|
return promise
|
|
87
87
|
}
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
/**
|
|
90
90
|
* Create a new `Promise<T>` that runs the given `async` code in a `Task`.
|
|
91
91
|
* This does not necessarily run the code in a different Thread, but supports Swift's `async`/`await`.
|
|
@@ -103,7 +103,7 @@ extension Promise {
|
|
|
103
103
|
}
|
|
104
104
|
return promise
|
|
105
105
|
}
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
/**
|
|
108
108
|
* Create a new `Promise<T>` that runs the given `run` function on a parallel Thread/`DispatchQueue`.
|
|
109
109
|
*/
|
|
@@ -142,7 +142,7 @@ extension Promise {
|
|
|
142
142
|
}
|
|
143
143
|
return self
|
|
144
144
|
}
|
|
145
|
-
|
|
145
|
+
|
|
146
146
|
/**
|
|
147
147
|
* Add an error continuation listener to this `Promise<T>`.
|
|
148
148
|
* Once the `Promise<T>` rejects, the `onRejectedListener` will be called with the error.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ArrayBufferHolder.hpp
|
|
3
|
+
// react-native-nitro
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 14.08.24.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include "NitroDefines.hpp"
|
|
11
|
+
#include "Promise.hpp"
|
|
12
|
+
#include <exception>
|
|
13
|
+
#include <memory>
|
|
14
|
+
#include <type_traits>
|
|
15
|
+
|
|
16
|
+
namespace margelo::nitro {
|
|
17
|
+
|
|
18
|
+
using namespace facebook;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Holds instances of `std::shared_ptr<Promise<T>>`.
|
|
22
|
+
* The reason this exists is for performance optimizations, as well as easier listeners for Swift.
|
|
23
|
+
*/
|
|
24
|
+
template <typename T>
|
|
25
|
+
class PromiseHolder final {
|
|
26
|
+
public:
|
|
27
|
+
PromiseHolder(const std::shared_ptr<Promise<T>>& promise) : _promise(promise) {}
|
|
28
|
+
PromiseHolder(std::shared_ptr<Promise<T>>&& promise) : _promise(std::move(promise)) {}
|
|
29
|
+
|
|
30
|
+
public:
|
|
31
|
+
static PromiseHolder<T> create() {
|
|
32
|
+
return PromiseHolder<T>(Promise<T>::create());
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public:
|
|
36
|
+
void resolve(T value) const {
|
|
37
|
+
_promise->resolve(std::move(value));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
void reject(const std::exception_ptr& exception) const {
|
|
41
|
+
_promise->reject(exception);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public:
|
|
45
|
+
void addOnResolvedListener(std::function<void(const T&)> onResolved) const {
|
|
46
|
+
_promise->addOnResolvedListener([onResolved = std::move(onResolved)](const T& result) { onResolved(result); });
|
|
47
|
+
}
|
|
48
|
+
void addOnResolvedListenerCopy(std::function<void(T)> onResolved) const {
|
|
49
|
+
_promise->addOnResolvedListener([onResolved = std::move(onResolved)](const T& result) { onResolved(result); });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
void addOnRejectedListener(std::function<void(const std::exception_ptr&)> onRejected) const {
|
|
53
|
+
_promise->addOnRejectedListener([onRejected = std::move(onRejected)](const std::exception_ptr& error) { onRejected(error); });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private:
|
|
57
|
+
std::shared_ptr<Promise<T>> _promise;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
template <>
|
|
61
|
+
class PromiseHolder<void> final {
|
|
62
|
+
public:
|
|
63
|
+
PromiseHolder(const std::shared_ptr<Promise<void>>& promise) : _promise(promise) {}
|
|
64
|
+
PromiseHolder(std::shared_ptr<Promise<void>>&& promise) : _promise(std::move(promise)) {}
|
|
65
|
+
|
|
66
|
+
public:
|
|
67
|
+
static PromiseHolder<void> create() {
|
|
68
|
+
return PromiseHolder<void>(Promise<void>::create());
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public:
|
|
72
|
+
void resolve() const {
|
|
73
|
+
_promise->resolve();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
void reject(const std::exception_ptr& exception) const {
|
|
77
|
+
_promise->reject(exception);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public:
|
|
81
|
+
void addOnResolvedListener(std::function<void()> onResolved) const {
|
|
82
|
+
_promise->addOnResolvedListener([onResolved = std::move(onResolved)]() { onResolved(); });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
void addOnRejectedListener(std::function<void(const std::exception_ptr&)> onRejected) const {
|
|
86
|
+
_promise->addOnRejectedListener([onRejected = std::move(onRejected)](const std::exception_ptr& error) { onRejected(error); });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private:
|
|
90
|
+
std::shared_ptr<Promise<void>> _promise;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
} // namespace margelo::nitro
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//
|
|
2
|
+
// MemoryHelper.swift
|
|
3
|
+
// NitroModules
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 17.12.2024.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
public final class MemoryHelper {
|
|
11
|
+
/**
|
|
12
|
+
* Get the amount of memory that was allocated using a `malloc`-like allocator
|
|
13
|
+
* for the given instance, in bytes.
|
|
14
|
+
* When allocating resources differently (e.g. GPU buffers, or `UIImage`) you
|
|
15
|
+
* should add their byte sizes to the result of this function to get an object's
|
|
16
|
+
* total memory footprint.
|
|
17
|
+
*/
|
|
18
|
+
public static func getSizeOf(_ instance: AnyObject) -> Int {
|
|
19
|
+
return malloc_size(Unmanaged.passUnretained(instance).toOpaque())
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <exception>
|
|
4
|
+
#include <new>
|
|
5
|
+
#include <type_traits>
|
|
6
|
+
#include <utility>
|
|
7
|
+
|
|
8
|
+
namespace margelo::nitro {
|
|
9
|
+
|
|
10
|
+
// TODO: Remove this whole Result wrapping system once Swift errors can be caught in C++.
|
|
11
|
+
// See https://github.com/swiftlang/swift/issues/75290
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Represents a Result from a function. It's either a value (`T`), or an error (`std::exception_ptr`).
|
|
15
|
+
*/
|
|
16
|
+
template <typename T>
|
|
17
|
+
class Result {
|
|
18
|
+
public:
|
|
19
|
+
// Constructors
|
|
20
|
+
Result(const Result& other) : _hasError(other._hasError) {
|
|
21
|
+
if (_hasError) {
|
|
22
|
+
new (&_error) std::exception_ptr(other._error);
|
|
23
|
+
} else {
|
|
24
|
+
new (&_storage) T(other.value());
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Result(Result&& other) noexcept(std::is_nothrow_move_constructible<T>::value) : _hasError(other._hasError) {
|
|
29
|
+
if (_hasError) {
|
|
30
|
+
new (&_error) std::exception_ptr(std::move(other._error));
|
|
31
|
+
} else {
|
|
32
|
+
new (&_storage) T(std::move(other.value()));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
~Result() {
|
|
37
|
+
destroy();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
Result& operator=(const Result& other) {
|
|
41
|
+
if (this == &other)
|
|
42
|
+
return *this;
|
|
43
|
+
destroy();
|
|
44
|
+
_hasError = other._hasError;
|
|
45
|
+
if (_hasError) {
|
|
46
|
+
new (&_error) std::exception_ptr(other._error);
|
|
47
|
+
} else {
|
|
48
|
+
new (&_storage) T(other.value());
|
|
49
|
+
}
|
|
50
|
+
return *this;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
Result& operator=(Result&& other) noexcept(std::is_nothrow_move_constructible<T>::value) {
|
|
54
|
+
if (this == &other)
|
|
55
|
+
return *this;
|
|
56
|
+
destroy();
|
|
57
|
+
_hasError = other._hasError;
|
|
58
|
+
if (_hasError) {
|
|
59
|
+
new (&_error) std::exception_ptr(std::move(other._error));
|
|
60
|
+
} else {
|
|
61
|
+
new (&_storage) T(std::move(other.value()));
|
|
62
|
+
}
|
|
63
|
+
return *this;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Static factories
|
|
67
|
+
static Result withValue(const T& value) {
|
|
68
|
+
return Result(value);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static Result withValue(T&& value) {
|
|
72
|
+
return Result(std::move(value));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static Result withError(std::exception_ptr eptr) {
|
|
76
|
+
return Result(eptr);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Accessors
|
|
80
|
+
bool hasValue() const noexcept {
|
|
81
|
+
return !_hasError;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
bool hasError() const noexcept {
|
|
85
|
+
return _hasError;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const T& value() const {
|
|
89
|
+
assert(!_hasError && "Result<T> does not hold a value!");
|
|
90
|
+
return *reinterpret_cast<const T*>(&_storage);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
T& value() {
|
|
94
|
+
assert(!_hasError && "Result<T> does not hold a value!");
|
|
95
|
+
return *reinterpret_cast<T*>(&_storage);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
std::exception_ptr error() const {
|
|
99
|
+
assert(_hasError && "Result<T> does not hold an error!");
|
|
100
|
+
return _error;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private:
|
|
104
|
+
// Private constructors
|
|
105
|
+
explicit Result(const T& value) : _hasError(false) {
|
|
106
|
+
new (&_storage) T(value);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
explicit Result(T&& value) : _hasError(false) {
|
|
110
|
+
new (&_storage) T(std::move(value));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
explicit Result(std::exception_ptr eptr) : _hasError(true) {
|
|
114
|
+
new (&_error) std::exception_ptr(eptr);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
void destroy() {
|
|
118
|
+
if (_hasError) {
|
|
119
|
+
reinterpret_cast<std::exception_ptr*>(&_error)->~exception_ptr();
|
|
120
|
+
} else {
|
|
121
|
+
reinterpret_cast<T*>(&_storage)->~T();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private:
|
|
126
|
+
bool _hasError;
|
|
127
|
+
union {
|
|
128
|
+
typename std::aligned_storage<sizeof(T), alignof(T)>::type _storage;
|
|
129
|
+
std::exception_ptr _error;
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// Specialization for void
|
|
134
|
+
template <>
|
|
135
|
+
class Result<void> {
|
|
136
|
+
public:
|
|
137
|
+
// Constructors
|
|
138
|
+
Result(const Result& other) : _hasError(other._hasError), _error(other._error) {}
|
|
139
|
+
|
|
140
|
+
Result(Result&& other) noexcept : _hasError(other._hasError), _error(std::move(other._error)) {}
|
|
141
|
+
|
|
142
|
+
Result& operator=(const Result& other) {
|
|
143
|
+
if (this == &other)
|
|
144
|
+
return *this;
|
|
145
|
+
_hasError = other._hasError;
|
|
146
|
+
if (_hasError) {
|
|
147
|
+
_error = other._error;
|
|
148
|
+
}
|
|
149
|
+
return *this;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
Result& operator=(Result&& other) noexcept {
|
|
153
|
+
if (this == &other)
|
|
154
|
+
return *this;
|
|
155
|
+
_hasError = other._hasError;
|
|
156
|
+
if (_hasError) {
|
|
157
|
+
_error = std::move(other._error);
|
|
158
|
+
}
|
|
159
|
+
return *this;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Static factories
|
|
163
|
+
static Result withValue() {
|
|
164
|
+
return Result();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
static Result withError(std::exception_ptr eptr) {
|
|
168
|
+
return Result(eptr);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
bool hasValue() const noexcept {
|
|
172
|
+
return !_hasError;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
bool hasError() const noexcept {
|
|
176
|
+
return _hasError;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
std::exception_ptr error() const {
|
|
180
|
+
assert(_hasError && "Result<void> does not hold an error!");
|
|
181
|
+
return _error;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
private:
|
|
185
|
+
explicit Result() : _hasError(false), _error(nullptr) {}
|
|
186
|
+
explicit Result(std::exception_ptr error) : _hasError(true), _error(error) {}
|
|
187
|
+
|
|
188
|
+
private:
|
|
189
|
+
bool _hasError;
|
|
190
|
+
std::exception_ptr _error;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
} // namespace margelo::nitro
|
|
@@ -21,14 +21,14 @@ namespace margelo::nitro {
|
|
|
21
21
|
*/
|
|
22
22
|
struct SwiftClosure final {
|
|
23
23
|
public:
|
|
24
|
-
using CallFn = void(void*);
|
|
25
|
-
using DeleteFn = void(void*);
|
|
24
|
+
using CallFn = void(void* _Nonnull);
|
|
25
|
+
using DeleteFn = void(void* _Nonnull);
|
|
26
26
|
|
|
27
27
|
private:
|
|
28
28
|
std::function<void()> _function;
|
|
29
29
|
|
|
30
30
|
public:
|
|
31
|
-
explicit SwiftClosure(void* context, CallFn* call, DeleteFn* destroy) {
|
|
31
|
+
explicit SwiftClosure(void* _Nonnull context, CallFn* _Nonnull call, DeleteFn* _Nonnull destroy) {
|
|
32
32
|
// Create a std::shared_ptr of the `void* context` which calls `destroy`
|
|
33
33
|
// once no references of it exist anymore.
|
|
34
34
|
// Since the std::function captures this std::shared_ptr, it can now be
|
|
@@ -37,7 +37,7 @@ public:
|
|
|
37
37
|
std::shared_ptr<void> sharedContext(context, destroy);
|
|
38
38
|
// Create a std::function that captures `sharedContext`.
|
|
39
39
|
// Once it gets destroyed, `destroy()` gets called.
|
|
40
|
-
_function = [sharedContext, call]() {
|
|
40
|
+
_function = [sharedContext = std::move(sharedContext), call]() {
|
|
41
41
|
// Call the actual Swift closure.
|
|
42
42
|
call(sharedContext.get());
|
|
43
43
|
};
|
|
@@ -39,16 +39,15 @@ public extension SwiftClosure {
|
|
|
39
39
|
let context = Unmanaged.passRetained(ClosureWrapper(closure: closure)).toOpaque()
|
|
40
40
|
|
|
41
41
|
// Create a C-style Function Pointer, which calls the actual Swift closure.
|
|
42
|
-
|
|
42
|
+
func call(context: UnsafeMutableRawPointer) {
|
|
43
43
|
// Unwrap context from void* to closure again. We are assuming that it has not been deleted yet.
|
|
44
|
-
let closure = Unmanaged<ClosureWrapper>.fromOpaque(context
|
|
44
|
+
let closure = Unmanaged<ClosureWrapper>.fromOpaque(context).takeUnretainedValue()
|
|
45
45
|
// Call it!
|
|
46
46
|
closure.invoke()
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// Create a C-style Function Pointer, which deletes the `ClosureWrapper`.
|
|
50
|
-
|
|
51
|
-
guard let context else { return }
|
|
50
|
+
func destroy(context: UnsafeMutableRawPointer) {
|
|
52
51
|
// Release the void* holding our `ClosureWrapper`
|
|
53
52
|
Unmanaged<ClosureWrapper>.fromOpaque(context).release()
|
|
54
53
|
}
|
|
@@ -10,7 +10,7 @@ const cache = new Map();
|
|
|
10
10
|
/**
|
|
11
11
|
* Get a constructor function for the given `HybridObject` {@linkcode T}.
|
|
12
12
|
* @param name The name of the `HybridObject` under which it was registered at.
|
|
13
|
-
* @returns
|
|
13
|
+
* @returns A constructor that creates instances of {@linkcode T}
|
|
14
14
|
* @example
|
|
15
15
|
* ```ts
|
|
16
16
|
* export const HybridImage = getHybridObjectConstructor<Image>('Image')
|
|
@@ -6,7 +6,7 @@ const cache = new Map();
|
|
|
6
6
|
/**
|
|
7
7
|
* Get a constructor function for the given `HybridObject` {@linkcode T}.
|
|
8
8
|
* @param name The name of the `HybridObject` under which it was registered at.
|
|
9
|
-
* @returns
|
|
9
|
+
* @returns A constructor that creates instances of {@linkcode T}
|
|
10
10
|
* @example
|
|
11
11
|
* ```ts
|
|
12
12
|
* export const HybridImage = getHybridObjectConstructor<Image>('Image')
|