react-native-nitro-modules 0.22.0 → 0.23.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/build.gradle +1 -1
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/margelo/nitro/views/HybridView.kt +11 -0
- package/cpp/core/ArrayBuffer.cpp +2 -2
- package/cpp/core/ArrayBuffer.hpp +3 -3
- package/cpp/core/HybridFunction.hpp +3 -0
- package/cpp/core/HybridObject.hpp +1 -1
- package/cpp/core/Promise.hpp +3 -3
- package/cpp/jsi/JSICache.cpp +4 -4
- package/cpp/jsi/JSICache.hpp +18 -18
- package/cpp/jsi/JSIConverter+Function.hpp +3 -2
- package/cpp/prototype/HybridObjectPrototype.cpp +2 -2
- package/cpp/prototype/HybridObjectPrototype.hpp +2 -2
- package/cpp/registry/HybridObjectRegistry.cpp +3 -0
- package/cpp/utils/BorrowingReference.hpp +161 -54
- package/cpp/utils/NitroDefines.hpp +1 -11
- package/cpp/utils/OwningLock.hpp +14 -14
- package/cpp/utils/ReferenceState.hpp +40 -0
- package/cpp/utils/WeakReference+Owning.hpp +33 -0
- package/cpp/utils/WeakReference.hpp +102 -0
- package/cpp/views/CachedProp.hpp +3 -3
- package/ios/core/AnyMapHolder.swift +8 -8
- package/ios/turbomodule/NativeNitroModules+NewArch.mm +1 -1
- package/lib/commonjs/index.js +11 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/views/HybridView.js +0 -11
- package/lib/commonjs/views/HybridView.js.map +1 -1
- package/lib/commonjs/views/getHostComponent.js +20 -1
- package/lib/commonjs/views/getHostComponent.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/views/HybridView.js +0 -26
- package/lib/module/views/HybridView.js.map +1 -1
- package/lib/module/views/getHostComponent.js +21 -1
- package/lib/module/views/getHostComponent.js.map +1 -1
- package/lib/tsconfig.build.tsbuildinfo +1 -1
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/views/HybridView.d.ts +89 -16
- package/lib/typescript/views/HybridView.d.ts.map +1 -1
- package/lib/typescript/views/getHostComponent.d.ts +46 -3
- package/lib/typescript/views/getHostComponent.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/index.ts +2 -0
- package/src/views/HybridView.ts +96 -18
- package/src/views/getHostComponent.ts +67 -5
- package/cpp/utils/BorrowingReference+Owning.hpp +0 -36
- package/cpp/utils/OwningReference.hpp +0 -250
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import { Platform, type HostComponent } from 'react-native'
|
|
1
|
+
import { Platform, type HostComponent, type ViewProps } from 'react-native'
|
|
2
2
|
// @ts-expect-error this unfortunately isn't typed or default-exported.
|
|
3
3
|
import * as NativeComponentRegistry from 'react-native/Libraries/NativeComponent/NativeComponentRegistry'
|
|
4
|
+
import type {
|
|
5
|
+
HybridView,
|
|
6
|
+
HybridViewMethods,
|
|
7
|
+
HybridViewProps,
|
|
8
|
+
} from './HybridView'
|
|
4
9
|
|
|
5
10
|
export interface ViewConfig<Props> {
|
|
6
11
|
uiViewClassName: string
|
|
@@ -11,16 +16,73 @@ export interface ViewConfig<Props> {
|
|
|
11
16
|
}
|
|
12
17
|
|
|
13
18
|
/**
|
|
14
|
-
*
|
|
19
|
+
* Represents all default props a Nitro HybridView has.
|
|
15
20
|
*/
|
|
16
|
-
|
|
21
|
+
interface DefaultHybridViewProps<RefType> extends ViewProps {
|
|
22
|
+
/**
|
|
23
|
+
* A `ref` to the {@linkcode HybridObject} this Hybrid View is rendering.
|
|
24
|
+
*
|
|
25
|
+
* The `hybridRef` property expects a stable Ref object received from `useRef` or `createRef`.
|
|
26
|
+
* @example
|
|
27
|
+
* ```jsx
|
|
28
|
+
* function App() {
|
|
29
|
+
* return (
|
|
30
|
+
* <HybridScrollView
|
|
31
|
+
* hybridRef={{ f: (ref) => {
|
|
32
|
+
* ref.current.scrollTo(400)
|
|
33
|
+
* }
|
|
34
|
+
* />
|
|
35
|
+
* )
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
hybridRef?: (ref: RefType) => void
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Due to a React limitation, functions cannot be passed to native directly
|
|
43
|
+
// because RN converts them to booleans (`true`). Nitro knows this and just
|
|
44
|
+
// wraps functions as objects - the original function is stored in `f`.
|
|
45
|
+
type WrapFunctionsInObjects<Props> = {
|
|
46
|
+
[K in keyof Props]: Props[K] extends Function
|
|
47
|
+
? { f: Props[K] }
|
|
48
|
+
: Props[K] extends Function | undefined
|
|
49
|
+
? { f: Props[K] }
|
|
50
|
+
: Props[K]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Represents a React Native view, implemented as a Nitro View, with the given props and methods.
|
|
55
|
+
*
|
|
56
|
+
* @note Every React Native view has a {@linkcode DefaultHybridViewProps.hybridRef hybridRef} which can be used to gain access
|
|
57
|
+
* to the underlying Nitro {@linkcode HybridView}.
|
|
58
|
+
* @note Every function/callback is wrapped as a `{ f: … }` object.
|
|
59
|
+
* @note Every method can be called on the Ref. Including setting properties directly.
|
|
60
|
+
*/
|
|
61
|
+
export type ReactNativeView<
|
|
62
|
+
Props extends HybridViewProps,
|
|
63
|
+
Methods extends HybridViewMethods,
|
|
64
|
+
> = HostComponent<
|
|
65
|
+
WrapFunctionsInObjects<
|
|
66
|
+
DefaultHybridViewProps<HybridView<Props, Methods>> & Props
|
|
67
|
+
>
|
|
68
|
+
>
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Finds and returns a native view (aka "HostComponent") via the given {@linkcode name}.
|
|
72
|
+
*
|
|
73
|
+
* The view is bridged to a native Hybrid Object using Nitro Views.
|
|
74
|
+
*/
|
|
75
|
+
export function getHostComponent<
|
|
76
|
+
Props extends HybridViewProps,
|
|
77
|
+
Methods extends HybridViewMethods,
|
|
78
|
+
>(
|
|
17
79
|
name: string,
|
|
18
80
|
getViewConfig: () => ViewConfig<Props>
|
|
19
|
-
):
|
|
81
|
+
): ReactNativeView<Props, Methods> {
|
|
20
82
|
if (NativeComponentRegistry == null) {
|
|
21
83
|
throw new Error(
|
|
22
84
|
`NativeComponentRegistry is not available on ${Platform.OS}!`
|
|
23
85
|
)
|
|
24
86
|
}
|
|
25
|
-
return NativeComponentRegistry.get
|
|
87
|
+
return NativeComponentRegistry.get(name, getViewConfig)
|
|
26
88
|
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// BorrowingReference+Owning.hpp
|
|
3
|
-
// react-native-nitro
|
|
4
|
-
//
|
|
5
|
-
// Created by Marc Rousavy on 23.06.24.
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
#pragma once
|
|
9
|
-
|
|
10
|
-
#include "OwningReference.hpp"
|
|
11
|
-
|
|
12
|
-
namespace margelo::nitro {
|
|
13
|
-
|
|
14
|
-
template <typename T>
|
|
15
|
-
BorrowingReference<T>::BorrowingReference(const OwningReference<T>& ref) {
|
|
16
|
-
_value = ref._value;
|
|
17
|
-
_isDeleted = ref._isDeleted;
|
|
18
|
-
_strongRefCount = ref._strongRefCount;
|
|
19
|
-
_weakRefCount = ref._weakRefCount;
|
|
20
|
-
_mutex = ref._mutex;
|
|
21
|
-
(*_weakRefCount)++;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
template <typename T>
|
|
25
|
-
OwningReference<T> BorrowingReference<T>::lock() const {
|
|
26
|
-
std::unique_lock lock(*_mutex);
|
|
27
|
-
|
|
28
|
-
if (*_isDeleted) {
|
|
29
|
-
// return nullptr
|
|
30
|
-
return OwningReference<T>();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return OwningReference(*this);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
} // namespace margelo::nitro
|
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// OwningReference.hpp
|
|
3
|
-
// react-native-nitro
|
|
4
|
-
//
|
|
5
|
-
// Created by Marc Rousavy on 23.06.24.
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
#pragma once
|
|
9
|
-
|
|
10
|
-
#include "BorrowingReference.hpp"
|
|
11
|
-
#include "NitroDefines.hpp"
|
|
12
|
-
#include "OwningLock.hpp"
|
|
13
|
-
#include <atomic>
|
|
14
|
-
#include <cstddef>
|
|
15
|
-
#include <mutex>
|
|
16
|
-
|
|
17
|
-
namespace margelo::nitro {
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
An `OwningReference<T>` is a smart-pointer that holds a strong reference to a pointer.
|
|
21
|
-
You can have multiple `OwningReference<T>` instances point to the same pointer, as they internally keep a ref-count.
|
|
22
|
-
As opposed to a `shared_ptr<T>`, an `OwningReference<T>` can also be imperatively manually deleted, even if there
|
|
23
|
-
are multiple strong references still holding onto the pointer.
|
|
24
|
-
|
|
25
|
-
An `OwningReference<T>` can be weakified, which gives the user a `BorrowingReference<T>`.
|
|
26
|
-
A `BorrowingReference<T>` can be locked to get an `OwningReference<T>` again, assuming it has not been deleted yet.
|
|
27
|
-
*/
|
|
28
|
-
template <typename T>
|
|
29
|
-
class OwningReference final {
|
|
30
|
-
public:
|
|
31
|
-
using Pointee = T;
|
|
32
|
-
|
|
33
|
-
public:
|
|
34
|
-
OwningReference() : _value(nullptr), _isDeleted(nullptr), _strongRefCount(nullptr), _weakRefCount(nullptr), _mutex(nullptr) {}
|
|
35
|
-
|
|
36
|
-
explicit OwningReference(T* value)
|
|
37
|
-
: _value(value), _isDeleted(new bool(false)), _strongRefCount(new std::atomic_size_t(1)), _weakRefCount(new std::atomic_size_t(0)),
|
|
38
|
-
_mutex(new std::recursive_mutex()) {}
|
|
39
|
-
|
|
40
|
-
OwningReference(const OwningReference& ref)
|
|
41
|
-
: _value(ref._value), _isDeleted(ref._isDeleted), _strongRefCount(ref._strongRefCount), _weakRefCount(ref._weakRefCount),
|
|
42
|
-
_mutex(ref._mutex) {
|
|
43
|
-
if (_strongRefCount != nullptr) {
|
|
44
|
-
// increment ref count after copy
|
|
45
|
-
(*_strongRefCount)++;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
OwningReference(OwningReference&& ref)
|
|
50
|
-
: _value(ref._value), _isDeleted(ref._isDeleted), _strongRefCount(ref._strongRefCount), _weakRefCount(ref._weakRefCount),
|
|
51
|
-
_mutex(ref._mutex) {
|
|
52
|
-
ref._value = nullptr;
|
|
53
|
-
ref._isDeleted = nullptr;
|
|
54
|
-
ref._strongRefCount = nullptr;
|
|
55
|
-
ref._weakRefCount = nullptr;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
OwningReference& operator=(const OwningReference& ref) {
|
|
59
|
-
if (this == &ref)
|
|
60
|
-
return *this;
|
|
61
|
-
|
|
62
|
-
if (_strongRefCount != nullptr) {
|
|
63
|
-
// destroy previous pointer
|
|
64
|
-
(*_strongRefCount)--;
|
|
65
|
-
maybeDestroy();
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
_value = ref._value;
|
|
69
|
-
_isDeleted = ref._isDeleted;
|
|
70
|
-
_strongRefCount = ref._strongRefCount;
|
|
71
|
-
_weakRefCount = ref._weakRefCount;
|
|
72
|
-
_mutex = ref._mutex;
|
|
73
|
-
if (_strongRefCount != nullptr) {
|
|
74
|
-
// increment new pointer
|
|
75
|
-
(*_strongRefCount)++;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return *this;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
private:
|
|
82
|
-
// BorrowingReference<T> -> OwningReference<T> Lock-constructor
|
|
83
|
-
OwningReference(const BorrowingReference<T>& ref)
|
|
84
|
-
: _value(ref._value), _isDeleted(ref._isDeleted), _strongRefCount(ref._strongRefCount), _weakRefCount(ref._weakRefCount),
|
|
85
|
-
_mutex(ref._mutex) {
|
|
86
|
-
(*_strongRefCount)++;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
private:
|
|
90
|
-
// OwningReference<C> -> OwningReference<T> Cast-constructor
|
|
91
|
-
template <typename OldT>
|
|
92
|
-
OwningReference(T* value, const OwningReference<OldT>& originalRef)
|
|
93
|
-
: _value(value), _isDeleted(originalRef._isDeleted), _strongRefCount(originalRef._strongRefCount),
|
|
94
|
-
_weakRefCount(originalRef._weakRefCount), _mutex(originalRef._mutex) {
|
|
95
|
-
(*_strongRefCount)++;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
template <typename C>
|
|
99
|
-
friend class OwningReference;
|
|
100
|
-
|
|
101
|
-
public:
|
|
102
|
-
~OwningReference() {
|
|
103
|
-
if (_strongRefCount == nullptr) {
|
|
104
|
-
// we are just a dangling nullptr.
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// decrement strong ref count on destroy
|
|
109
|
-
--(*_strongRefCount);
|
|
110
|
-
maybeDestroy();
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
public:
|
|
114
|
-
/**
|
|
115
|
-
Casts this `OwningReference<T>` to a `OwningReference<C>`.
|
|
116
|
-
*/
|
|
117
|
-
template <typename C>
|
|
118
|
-
OwningReference<C> as() {
|
|
119
|
-
return OwningReference<C>(static_cast<C*>(_value), *this);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
public:
|
|
123
|
-
/**
|
|
124
|
-
Creates an `OwningLock<T>` for the given `OwningReference<T>` to guarantee safe
|
|
125
|
-
safe access to `OwningReference<T>`.
|
|
126
|
-
Other threads (e.g. the Hermes garbage collector) cannot delete the `OwningReference<T>`
|
|
127
|
-
as long as the `OwningLock<T>` is still alive.
|
|
128
|
-
*/
|
|
129
|
-
[[nodiscard]]
|
|
130
|
-
OwningLock<T> lock() const {
|
|
131
|
-
return OwningLock<T>(*this);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
Get whether the `OwningReference<T>` is still pointing to a valid value, or not.
|
|
136
|
-
*/
|
|
137
|
-
inline bool hasValue() const {
|
|
138
|
-
return _value != nullptr && !(*_isDeleted);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
Get a borrowing (or "weak") reference to this owning reference
|
|
143
|
-
*/
|
|
144
|
-
[[nodiscard]]
|
|
145
|
-
BorrowingReference<T> weak() const {
|
|
146
|
-
return BorrowingReference(*this);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
Delete and destroy the value this OwningReference is pointing to.
|
|
151
|
-
This can even be called if there are still multiple strong references to the value.
|
|
152
|
-
|
|
153
|
-
This will block as long as one or more `OwningLock<T>`s of this `OwningReference<T>` are still alive.
|
|
154
|
-
*/
|
|
155
|
-
void destroy() {
|
|
156
|
-
std::unique_lock lock(*_mutex);
|
|
157
|
-
|
|
158
|
-
forceDestroy();
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
public:
|
|
162
|
-
explicit inline operator bool() const {
|
|
163
|
-
return hasValue();
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
inline T& operator*() const {
|
|
167
|
-
#ifdef NITRO_DEBUG
|
|
168
|
-
if (!hasValue()) [[unlikely]] {
|
|
169
|
-
throw std::runtime_error("Tried to dereference (*) nullptr OwningReference<T>!");
|
|
170
|
-
}
|
|
171
|
-
#endif
|
|
172
|
-
return *_value;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
inline T* operator->() const {
|
|
176
|
-
#ifdef NITRO_DEBUG
|
|
177
|
-
if (!hasValue()) [[unlikely]] {
|
|
178
|
-
throw std::runtime_error("Tried to dereference (->) nullptr OwningReference<T>!");
|
|
179
|
-
}
|
|
180
|
-
#endif
|
|
181
|
-
return _value;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
inline bool operator==(T* other) const {
|
|
185
|
-
std::unique_lock lock(*_mutex);
|
|
186
|
-
|
|
187
|
-
if (*_isDeleted) {
|
|
188
|
-
return other == nullptr;
|
|
189
|
-
} else {
|
|
190
|
-
return other == _value;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
inline bool operator!=(T* other) const {
|
|
195
|
-
return !(this == other);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
inline bool operator==(const OwningReference<T>& other) const {
|
|
199
|
-
return _value == other._value;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
inline bool operator!=(const OwningReference<T>& other) const {
|
|
203
|
-
return !(this == other);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
private:
|
|
207
|
-
void maybeDestroy() {
|
|
208
|
-
_mutex->lock();
|
|
209
|
-
|
|
210
|
-
if (*_strongRefCount == 0) {
|
|
211
|
-
// after no strong references exist anymore
|
|
212
|
-
forceDestroy();
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (*_strongRefCount == 0 && *_weakRefCount == 0) {
|
|
216
|
-
// free the full memory if there are no more references at all
|
|
217
|
-
delete _isDeleted;
|
|
218
|
-
delete _strongRefCount;
|
|
219
|
-
delete _weakRefCount;
|
|
220
|
-
_mutex->unlock();
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
_mutex->unlock();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
void forceDestroy() {
|
|
228
|
-
if (*_isDeleted) {
|
|
229
|
-
// it has already been destroyed.
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
delete _value;
|
|
233
|
-
*_isDeleted = true;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
public:
|
|
237
|
-
friend class BorrowingReference<T>;
|
|
238
|
-
friend class OwningLock<T>;
|
|
239
|
-
|
|
240
|
-
private:
|
|
241
|
-
T* _value;
|
|
242
|
-
bool* _isDeleted;
|
|
243
|
-
std::atomic_size_t* _strongRefCount;
|
|
244
|
-
std::atomic_size_t* _weakRefCount;
|
|
245
|
-
std::recursive_mutex* _mutex;
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
} // namespace margelo::nitro
|
|
249
|
-
|
|
250
|
-
#include "BorrowingReference+Owning.hpp"
|