react-native-nitro-modules 0.30.0 → 0.30.2
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/java/com/margelo/nitro/NitroModules.kt +50 -42
- package/android/src/main/java/com/margelo/nitro/NitroModulesPackage.kt +26 -22
- package/android/src/main/java/com/margelo/nitro/core/AnyMap.kt +44 -7
- package/android/src/main/java/com/margelo/nitro/core/AnyValue.kt +145 -139
- package/android/src/main/java/com/margelo/nitro/core/ArrayBuffer.kt +162 -154
- package/android/src/main/java/com/margelo/nitro/core/HybridObject.kt +51 -51
- package/android/src/main/java/com/margelo/nitro/core/Promise.kt +9 -1
- package/android/src/main/java/com/margelo/nitro/utils/HardwareBuffer+updateFrom.kt +1 -2
- package/android/src/main/java/com/margelo/nitro/utils/HardwareBufferUtils.kt +33 -26
- package/android/src/main/java/com/margelo/nitro/views/HybridView.kt +20 -19
- package/cpp/jsi/{JSIConverter+HybridObject.hpp → JSIConverter+NativeState.hpp} +19 -13
- package/cpp/jsi/JSIConverter.hpp +1 -1
- package/cpp/threading/Dispatcher.cpp +16 -13
- package/cpp/utils/NitroDefines.hpp +1 -1
- package/ios/core/AnyMap.swift +12 -17
- package/ios/core/ArrayBuffer.swift +45 -36
- package/ios/core/HybridObject.swift +4 -6
- package/ios/core/Promise.swift +23 -25
- package/ios/core/RuntimeError.swift +6 -8
- package/ios/utils/Date+fromChrono.swift +4 -4
- package/ios/utils/SwiftClosure.swift +12 -16
- package/ios/views/HybridView.swift +30 -32
- package/lib/commonjs/turbomodule/NativeNitroModules.js +17 -0
- package/lib/commonjs/turbomodule/NativeNitroModules.js.map +1 -1
- package/lib/module/turbomodule/NativeNitroModules.js +17 -0
- package/lib/module/turbomodule/NativeNitroModules.js.map +1 -1
- package/lib/tsconfig.build.tsbuildinfo +1 -1
- package/lib/typescript/turbomodule/NativeNitroModules.d.ts +1 -0
- package/lib/typescript/turbomodule/NativeNitroModules.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/turbomodule/NativeNitroModules.ts +19 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
package com.margelo.nitro.core
|
|
2
2
|
|
|
3
|
-
import androidx.annotation.Keep
|
|
4
3
|
import android.hardware.HardwareBuffer
|
|
5
4
|
import android.os.Build
|
|
5
|
+
import androidx.annotation.Keep
|
|
6
6
|
import androidx.annotation.RequiresApi
|
|
7
7
|
import com.facebook.jni.HybridData
|
|
8
8
|
import com.facebook.proguard.annotations.DoNotStrip
|
|
@@ -23,185 +23,193 @@ typealias BoxedHardwareBuffer = Any
|
|
|
23
23
|
@Keep
|
|
24
24
|
@DoNotStrip
|
|
25
25
|
class ArrayBuffer {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Holds the native C++ instance of the `ArrayBuffer`.
|
|
28
|
+
*/
|
|
29
|
+
private val mHybridData: HybridData
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Whether this `ArrayBuffer` is an **owning-**, or a **non-owning-** `ArrayBuffer`.
|
|
33
|
+
* - **Owning** ArrayBuffers can safely be held in memory for longer, and accessed at any point.
|
|
34
|
+
* - **Non-owning** ArrayBuffers can not be held in memory for longer, and can only be safely
|
|
35
|
+
* accessed within the synchronous function's scope (aka on the JS Thread). Once you switch Threads,
|
|
36
|
+
* data access is not safe anymore. If you need to access data longer, copy the data.
|
|
37
|
+
*/
|
|
38
|
+
val isOwner: Boolean
|
|
39
|
+
get() = getIsOwner()
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Whether this `ArrayBuffer` is holding a `ByteBuffer`, or not.
|
|
43
|
+
* - If the `ArrayBuffer` holds a `ByteBuffer`, `getBuffer(false)` can safely be called to
|
|
44
|
+
* get shared access to the underlying data, without performing any copies.
|
|
45
|
+
* - If the `ArrayBuffer` doesn't hold a `ByteBuffer`, it can still be accessed via `getBuffer(false)`,
|
|
46
|
+
* but the returned `ByteBuffer` is only valid as long as it's parent `ArrayBuffer` is alive.
|
|
47
|
+
*/
|
|
48
|
+
val isByteBuffer: Boolean
|
|
49
|
+
get() = getIsByteBuffer()
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Whether this `ArrayBuffer` is holding a `HardwareBuffer`, or not.
|
|
53
|
+
* - If the `ArrayBuffer` holds a `HardwareBuffer`, `getHardwareBuffer()` can safely be called without copy.
|
|
54
|
+
* - If the `ArrayBuffer` doesn't hold a `HardwareBuffer`, `getHardwareBuffer()` will throw.
|
|
55
|
+
* You will need to call `getByteBuffer(copyIfNeeded)` instead.
|
|
56
|
+
*/
|
|
57
|
+
val isHardwareBuffer: Boolean
|
|
58
|
+
get() = getIsHardwareBuffer()
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get the size of bytes in this `ArrayBuffer`.
|
|
62
|
+
*/
|
|
63
|
+
val size: Int
|
|
64
|
+
get() = getBufferSize()
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get a `ByteBuffer` that holds- or wraps- the underlying data.
|
|
68
|
+
* - If this `ArrayBuffer` has been created from Kotlin/Java, it is already holding a
|
|
69
|
+
* `ByteBuffer` (`isByteBuffer == true`). In this case, the returned buffer is safe to access,
|
|
70
|
+
* even after the `ArrayBuffer` has already been destroyed in JS.
|
|
71
|
+
* - If this `ArrayBuffer` has been created elsewhere (C++/JS), it is not holding a
|
|
72
|
+
* `ByteBuffer` (`isByteBuffer == false`). In this case, the returned buffer will either be a copy
|
|
73
|
+
* of the data (`copyIfNeeded == true`), or just wrapping the data (`copyIfNeeded == false`).
|
|
74
|
+
*
|
|
75
|
+
* @param copyIfNeeded If this `ArrayBuffer` is not holding a `ByteBuffer` (`isByteBuffer == false`),
|
|
76
|
+
* the foreign data needs to be either _wrapped_, or _copied_ to be represented as a `ByteBuffer`.
|
|
77
|
+
* This flag controls that behaviour.
|
|
78
|
+
*/
|
|
79
|
+
fun getBuffer(copyIfNeeded: Boolean): ByteBuffer {
|
|
80
|
+
return getByteBuffer(copyIfNeeded)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get the underlying `HardwareBuffer` if this `ArrayBuffer` was created with one.
|
|
85
|
+
* @throws Error if this `ArrayBuffer` was not created with a `HardwareBuffer`.
|
|
86
|
+
*/
|
|
87
|
+
@RequiresApi(Build.VERSION_CODES.O)
|
|
88
|
+
fun getHardwareBuffer(): HardwareBuffer {
|
|
89
|
+
val boxed = getHardwareBufferBoxed()
|
|
90
|
+
return boxed as HardwareBuffer
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Create a new **owning-** `ArrayBuffer` that holds the given `ByteBuffer`.
|
|
95
|
+
* The `ByteBuffer` needs to remain valid for as long as the `ArrayBuffer` is alive.
|
|
96
|
+
*/
|
|
97
|
+
constructor(byteBuffer: ByteBuffer) {
|
|
98
|
+
if (!byteBuffer.isDirect) {
|
|
99
|
+
throw Error(
|
|
100
|
+
"ArrayBuffers can only be created from direct ByteBuffers, " +
|
|
101
|
+
"and the given ByteBuffer is not direct!",
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
mHybridData = initHybrid(byteBuffer)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Create a new **owning-** `ArrayBuffer` that holds the given `HardwareBuffer`.
|
|
109
|
+
* The `HardwareBuffer` needs to remain valid for as long as the `ArrayBuffer` is alive.
|
|
110
|
+
*/
|
|
111
|
+
@RequiresApi(Build.VERSION_CODES.O)
|
|
112
|
+
constructor(hardwareBuffer: HardwareBuffer) {
|
|
113
|
+
if (hardwareBuffer.isClosed) {
|
|
114
|
+
throw Error("Cannot create ArrayBuffer from an already-closed HardwareBuffer!")
|
|
115
|
+
}
|
|
116
|
+
mHybridData = initHybridBoxedHardwareBuffer(hardwareBuffer)
|
|
117
|
+
}
|
|
30
118
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
119
|
+
/**
|
|
120
|
+
* Create a new **non-owning-** `ArrayBuffer` that holds foreign data, potentially coming from JS.
|
|
121
|
+
*/
|
|
122
|
+
@Suppress("unused")
|
|
123
|
+
@Keep
|
|
124
|
+
@DoNotStrip
|
|
125
|
+
private constructor(hybridData: HybridData) {
|
|
126
|
+
mHybridData = hybridData
|
|
127
|
+
}
|
|
40
128
|
|
|
41
|
-
|
|
42
|
-
* Whether this `ArrayBuffer` is holding a `ByteBuffer`, or not.
|
|
43
|
-
* - If the `ArrayBuffer` holds a `ByteBuffer`, `getBuffer(false)` can safely be called to
|
|
44
|
-
* get shared access to the underlying data, without performing any copies.
|
|
45
|
-
* - If the `ArrayBuffer` doesn't hold a `ByteBuffer`, it can still be accessed via `getBuffer(false)`,
|
|
46
|
-
* but the returned `ByteBuffer` is only valid as long as it's parent `ArrayBuffer` is alive.
|
|
47
|
-
*/
|
|
48
|
-
val isByteBuffer: Boolean
|
|
49
|
-
get() = getIsByteBuffer()
|
|
129
|
+
private external fun initHybrid(buffer: ByteBuffer): HybridData
|
|
50
130
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
* - If the `ArrayBuffer` holds a `HardwareBuffer`, `getHardwareBuffer()` can safely be called without copy.
|
|
54
|
-
* - If the `ArrayBuffer` doesn't hold a `HardwareBuffer`, `getHardwareBuffer()` will throw.
|
|
55
|
-
* You will need to call `getByteBuffer(copyIfNeeded)` instead.
|
|
56
|
-
*/
|
|
57
|
-
val isHardwareBuffer: Boolean
|
|
58
|
-
get() = getIsHardwareBuffer()
|
|
131
|
+
@RequiresApi(Build.VERSION_CODES.O)
|
|
132
|
+
private external fun initHybridBoxedHardwareBuffer(hardwareBufferBoxed: BoxedHardwareBuffer): HybridData
|
|
59
133
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
134
|
+
private external fun getByteBuffer(copyIfNeeded: Boolean): ByteBuffer
|
|
135
|
+
|
|
136
|
+
private external fun getHardwareBufferBoxed(): BoxedHardwareBuffer
|
|
137
|
+
|
|
138
|
+
@FastNative
|
|
139
|
+
private external fun getIsOwner(): Boolean
|
|
140
|
+
|
|
141
|
+
@FastNative
|
|
142
|
+
private external fun getIsByteBuffer(): Boolean
|
|
65
143
|
|
|
144
|
+
@FastNative
|
|
145
|
+
private external fun getIsHardwareBuffer(): Boolean
|
|
146
|
+
|
|
147
|
+
@FastNative
|
|
148
|
+
private external fun getBufferSize(): Int
|
|
149
|
+
|
|
150
|
+
companion object {
|
|
66
151
|
/**
|
|
67
|
-
*
|
|
68
|
-
* - If this `ArrayBuffer` has been created from Kotlin/Java, it is already holding a
|
|
69
|
-
* `ByteBuffer` (`isByteBuffer == true`). In this case, the returned buffer is safe to access,
|
|
70
|
-
* even after the `ArrayBuffer` has already been destroyed in JS.
|
|
71
|
-
* - If this `ArrayBuffer` has been created elsewhere (C++/JS), it is not holding a
|
|
72
|
-
* `ByteBuffer` (`isByteBuffer == false`). In this case, the returned buffer will either be a copy
|
|
73
|
-
* of the data (`copyIfNeeded == true`), or just wrapping the data (`copyIfNeeded == false`).
|
|
74
|
-
*
|
|
75
|
-
* @param copyIfNeeded If this `ArrayBuffer` is not holding a `ByteBuffer` (`isByteBuffer == false`),
|
|
76
|
-
* the foreign data needs to be either _wrapped_, or _copied_ to be represented as a `ByteBuffer`.
|
|
77
|
-
* This flag controls that behaviour.
|
|
152
|
+
* Allocate a new `ArrayBuffer` with the given [size].
|
|
78
153
|
*/
|
|
79
|
-
fun
|
|
80
|
-
|
|
154
|
+
fun allocate(size: Int): ArrayBuffer {
|
|
155
|
+
val buffer = ByteBuffer.allocateDirect(size)
|
|
156
|
+
return ArrayBuffer(buffer)
|
|
81
157
|
}
|
|
82
158
|
|
|
83
159
|
/**
|
|
84
|
-
*
|
|
85
|
-
* @throws Error if this `ArrayBuffer` was not created with a `HardwareBuffer`.
|
|
160
|
+
* Copy the given `ArrayBuffer` into a new **owning** `ArrayBuffer`.
|
|
86
161
|
*/
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
val
|
|
90
|
-
return
|
|
162
|
+
fun copy(other: ArrayBuffer): ArrayBuffer {
|
|
163
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && other.isHardwareBuffer) {
|
|
164
|
+
val hardwareBuffer = other.getHardwareBuffer()
|
|
165
|
+
return copy(hardwareBuffer)
|
|
166
|
+
} else {
|
|
167
|
+
val byteBuffer = other.getBuffer(false)
|
|
168
|
+
return copy(byteBuffer)
|
|
169
|
+
}
|
|
91
170
|
}
|
|
92
171
|
|
|
93
172
|
/**
|
|
94
|
-
*
|
|
95
|
-
* The `ByteBuffer` needs to remain valid for as long as the `ArrayBuffer` is alive.
|
|
173
|
+
* Copy the given `ByteBuffer` into a new **owning** `ArrayBuffer`.
|
|
96
174
|
*/
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
175
|
+
fun copy(byteBuffer: ByteBuffer): ArrayBuffer {
|
|
176
|
+
// 1. Find out size
|
|
177
|
+
byteBuffer.rewind()
|
|
178
|
+
val size = byteBuffer.remaining()
|
|
179
|
+
// 2. Create a new buffer with the same size as the other
|
|
180
|
+
val newBuffer = ByteBuffer.allocateDirect(size)
|
|
181
|
+
// 3. Copy over the source buffer into the new buffer
|
|
182
|
+
newBuffer.put(byteBuffer)
|
|
183
|
+
// 4. Rewind both buffers again to index 0
|
|
184
|
+
newBuffer.rewind()
|
|
185
|
+
byteBuffer.rewind()
|
|
186
|
+
// 5. Create a new `ArrayBuffer`
|
|
187
|
+
return ArrayBuffer(newBuffer)
|
|
103
188
|
}
|
|
104
189
|
|
|
105
190
|
/**
|
|
106
|
-
*
|
|
107
|
-
* The `HardwareBuffer` needs to remain valid for as long as the `ArrayBuffer` is alive.
|
|
191
|
+
* Copy the given `HardwareBuffer` into a new **owning** `ArrayBuffer`.
|
|
108
192
|
*/
|
|
109
193
|
@RequiresApi(Build.VERSION_CODES.O)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
mHybridData = initHybridBoxedHardwareBuffer(hardwareBuffer)
|
|
194
|
+
fun copy(hardwareBuffer: HardwareBuffer): ArrayBuffer {
|
|
195
|
+
val copy = HardwareBufferUtils.copyHardwareBuffer(hardwareBuffer)
|
|
196
|
+
return ArrayBuffer(copy)
|
|
115
197
|
}
|
|
116
198
|
|
|
117
199
|
/**
|
|
118
|
-
*
|
|
200
|
+
* Wrap the given `ByteBuffer` in a new **owning** `ArrayBuffer`.
|
|
119
201
|
*/
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
private constructor(hybridData: HybridData) {
|
|
124
|
-
mHybridData = hybridData
|
|
202
|
+
fun wrap(byteBuffer: ByteBuffer): ArrayBuffer {
|
|
203
|
+
byteBuffer.rewind()
|
|
204
|
+
return ArrayBuffer(byteBuffer)
|
|
125
205
|
}
|
|
126
206
|
|
|
127
|
-
|
|
207
|
+
/**
|
|
208
|
+
* Wrap the given `HardwareBuffer` in a new **owning** `ArrayBuffer`.
|
|
209
|
+
*/
|
|
128
210
|
@RequiresApi(Build.VERSION_CODES.O)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
private external fun getByteBuffer(copyIfNeeded: Boolean): ByteBuffer
|
|
132
|
-
private external fun getHardwareBufferBoxed(): BoxedHardwareBuffer
|
|
133
|
-
|
|
134
|
-
@FastNative
|
|
135
|
-
private external fun getIsOwner(): Boolean
|
|
136
|
-
@FastNative
|
|
137
|
-
private external fun getIsByteBuffer(): Boolean
|
|
138
|
-
@FastNative
|
|
139
|
-
private external fun getIsHardwareBuffer(): Boolean
|
|
140
|
-
@FastNative
|
|
141
|
-
private external fun getBufferSize(): Int
|
|
142
|
-
|
|
143
|
-
companion object {
|
|
144
|
-
/**
|
|
145
|
-
* Allocate a new `ArrayBuffer` with the given [size].
|
|
146
|
-
*/
|
|
147
|
-
fun allocate(size: Int): ArrayBuffer {
|
|
148
|
-
val buffer = ByteBuffer.allocateDirect(size)
|
|
149
|
-
return ArrayBuffer(buffer)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Copy the given `ArrayBuffer` into a new **owning** `ArrayBuffer`.
|
|
154
|
-
*/
|
|
155
|
-
fun copy(other: ArrayBuffer): ArrayBuffer {
|
|
156
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && other.isHardwareBuffer) {
|
|
157
|
-
val hardwareBuffer = other.getHardwareBuffer()
|
|
158
|
-
return copy(hardwareBuffer)
|
|
159
|
-
} else {
|
|
160
|
-
val byteBuffer = other.getBuffer(false)
|
|
161
|
-
return copy(byteBuffer)
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Copy the given `ByteBuffer` into a new **owning** `ArrayBuffer`.
|
|
167
|
-
*/
|
|
168
|
-
fun copy(byteBuffer: ByteBuffer): ArrayBuffer {
|
|
169
|
-
// 1. Find out size
|
|
170
|
-
byteBuffer.rewind()
|
|
171
|
-
val size = byteBuffer.remaining()
|
|
172
|
-
// 2. Create a new buffer with the same size as the other
|
|
173
|
-
val newBuffer = ByteBuffer.allocateDirect(size)
|
|
174
|
-
// 3. Copy over the source buffer into the new buffer
|
|
175
|
-
newBuffer.put(byteBuffer)
|
|
176
|
-
// 4. Rewind both buffers again to index 0
|
|
177
|
-
newBuffer.rewind()
|
|
178
|
-
byteBuffer.rewind()
|
|
179
|
-
// 5. Create a new `ArrayBuffer`
|
|
180
|
-
return ArrayBuffer(newBuffer)
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Copy the given `HardwareBuffer` into a new **owning** `ArrayBuffer`.
|
|
184
|
-
*/
|
|
185
|
-
@RequiresApi(Build.VERSION_CODES.O)
|
|
186
|
-
fun copy(hardwareBuffer: HardwareBuffer): ArrayBuffer {
|
|
187
|
-
val copy = HardwareBufferUtils.copyHardwareBuffer(hardwareBuffer)
|
|
188
|
-
return ArrayBuffer(copy)
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Wrap the given `ByteBuffer` in a new **owning** `ArrayBuffer`.
|
|
193
|
-
*/
|
|
194
|
-
fun wrap(byteBuffer: ByteBuffer): ArrayBuffer {
|
|
195
|
-
byteBuffer.rewind()
|
|
196
|
-
return ArrayBuffer(byteBuffer)
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Wrap the given `HardwareBuffer` in a new **owning** `ArrayBuffer`.
|
|
201
|
-
*/
|
|
202
|
-
@RequiresApi(Build.VERSION_CODES.O)
|
|
203
|
-
fun wrap(hardwareBuffer: HardwareBuffer): ArrayBuffer {
|
|
204
|
-
return ArrayBuffer(hardwareBuffer)
|
|
205
|
-
}
|
|
211
|
+
fun wrap(hardwareBuffer: HardwareBuffer): ArrayBuffer {
|
|
212
|
+
return ArrayBuffer(hardwareBuffer)
|
|
206
213
|
}
|
|
214
|
+
}
|
|
207
215
|
}
|
|
@@ -10,58 +10,58 @@ import com.facebook.proguard.annotations.DoNotStrip
|
|
|
10
10
|
@Keep
|
|
11
11
|
@DoNotStrip
|
|
12
12
|
abstract class HybridObject {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Get the memory size of the Kotlin instance (plus any external heap allocations),
|
|
15
|
+
* in bytes.
|
|
16
|
+
*
|
|
17
|
+
* Override this to allow tracking heap allocations such as buffers or images,
|
|
18
|
+
* which will help the JS GC be more efficient in deleting large unused objects.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```kotlin
|
|
22
|
+
* override val memorySize: ULong
|
|
23
|
+
* get() {
|
|
24
|
+
* val imageSize = this.bitmap.bytesPerRow * this.bitmap.height
|
|
25
|
+
* return imageSize
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
@get:DoNotStrip
|
|
30
|
+
@get:Keep
|
|
31
|
+
open val memorySize: Long
|
|
32
|
+
get() = 0L
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Eagerly- (and manually-) dispose all native resources this `HybridObject` holds.
|
|
36
|
+
* This method can only be manually called from JS using `dispose()`.
|
|
37
|
+
*
|
|
38
|
+
* If this method is never manually called, a `HybridObject` is expected to disposes it's
|
|
39
|
+
* resources as usual via the object's destructor (`~HybridObject()`, `deinit` or `finalize()`).
|
|
40
|
+
*
|
|
41
|
+
* By default, this method does nothing. It can be overridden to perform actual disposing/cleanup
|
|
42
|
+
* if required.
|
|
43
|
+
* This method must not throw.
|
|
44
|
+
*/
|
|
45
|
+
@DoNotStrip
|
|
46
|
+
@Keep
|
|
47
|
+
open fun dispose() { }
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Holds the native C++ instance.
|
|
51
|
+
* In `HybridObject`, the C++ instance is a sub-class of `JHybridObject`, such as one of it's specs.
|
|
52
|
+
* This is `null`, until `updateNative(..)` is called.
|
|
53
|
+
*/
|
|
54
|
+
private var mHybridData: HybridData? = null
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
56
|
+
/**
|
|
57
|
+
* If `HybridObject` is subclassed, the sub-class needs to create it's own `HybridData`
|
|
58
|
+
* with a C++ `jni::HybridClass` representing the subclass directly.
|
|
59
|
+
* Then, that `HybridData` must be passed upwards to `HybridObject` using `updateNative(..)`.
|
|
60
|
+
*
|
|
61
|
+
* This must happen for each sub/base class in the whole inheritance chain to ensure
|
|
62
|
+
* overrides and type-erasure works as expected.
|
|
63
|
+
*/
|
|
64
|
+
protected open fun updateNative(hybridData: HybridData) {
|
|
65
|
+
mHybridData = hybridData
|
|
66
|
+
}
|
|
67
67
|
}
|
|
@@ -96,9 +96,13 @@ class Promise<T> {
|
|
|
96
96
|
|
|
97
97
|
// C++ functions
|
|
98
98
|
private external fun nativeResolve(result: Any)
|
|
99
|
+
|
|
99
100
|
private external fun nativeReject(error: Throwable)
|
|
101
|
+
|
|
100
102
|
private external fun addOnResolvedListener(callback: OnResolvedCallback)
|
|
103
|
+
|
|
101
104
|
private external fun addOnRejectedListener(callback: OnRejectedCallback)
|
|
105
|
+
|
|
102
106
|
private external fun initHybrid(): HybridData
|
|
103
107
|
|
|
104
108
|
// Nested callbacks - need to be JavaClasses so we can access them with JNI
|
|
@@ -110,6 +114,7 @@ class Promise<T> {
|
|
|
110
114
|
@DoNotStrip
|
|
111
115
|
fun onResolved(result: Any)
|
|
112
116
|
}
|
|
117
|
+
|
|
113
118
|
@Keep
|
|
114
119
|
@DoNotStrip
|
|
115
120
|
private fun interface OnRejectedCallback {
|
|
@@ -131,7 +136,10 @@ class Promise<T> {
|
|
|
131
136
|
* When the suspending function returns, the Promise gets resolved. If the suspending
|
|
132
137
|
* function throws, the Promise gets rejected.
|
|
133
138
|
*/
|
|
134
|
-
fun <T> async(
|
|
139
|
+
fun <T> async(
|
|
140
|
+
scope: CoroutineScope = defaultScope,
|
|
141
|
+
run: suspend () -> T,
|
|
142
|
+
): Promise<T> {
|
|
135
143
|
val promise = Promise<T>()
|
|
136
144
|
scope.launch {
|
|
137
145
|
try {
|
|
@@ -10,6 +10,5 @@ import androidx.annotation.RequiresApi
|
|
|
10
10
|
*/
|
|
11
11
|
@RequiresApi(Build.VERSION_CODES.O)
|
|
12
12
|
fun HardwareBuffer.updateFrom(hardwareBuffer: HardwareBuffer) {
|
|
13
|
-
|
|
13
|
+
HardwareBufferUtils.copyHardwareBuffer(hardwareBuffer, this)
|
|
14
14
|
}
|
|
15
|
-
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
package com.margelo.nitro.utils
|
|
2
2
|
|
|
3
|
-
import androidx.annotation.Keep
|
|
4
|
-
import com.facebook.proguard.annotations.DoNotStrip
|
|
5
3
|
import android.hardware.HardwareBuffer
|
|
6
4
|
import android.os.Build
|
|
5
|
+
import androidx.annotation.Keep
|
|
7
6
|
import androidx.annotation.RequiresApi
|
|
7
|
+
import com.facebook.proguard.annotations.DoNotStrip
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* HardwareBuffers are special types in JNI (`AHardwareBuffer*`)
|
|
@@ -16,31 +16,38 @@ typealias BoxedHardwareBuffer = Any
|
|
|
16
16
|
@Keep
|
|
17
17
|
@DoNotStrip
|
|
18
18
|
class HardwareBufferUtils {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
companion object {
|
|
20
|
+
@JvmStatic
|
|
21
|
+
@RequiresApi(Build.VERSION_CODES.O)
|
|
22
|
+
private external fun copyHardwareBuffer(sourceHardwareBuffer: BoxedHardwareBuffer): BoxedHardwareBuffer
|
|
23
|
+
|
|
24
|
+
@JvmStatic
|
|
25
|
+
@RequiresApi(Build.VERSION_CODES.O)
|
|
26
|
+
private external fun copyHardwareBuffer(
|
|
27
|
+
sourceHardwareBuffer: BoxedHardwareBuffer,
|
|
28
|
+
destinationHardwareBuffer: BoxedHardwareBuffer,
|
|
29
|
+
)
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Copies the given [[hardwareBuffer]] into a new, identically shaped [[HardwareBuffer]].
|
|
33
|
+
*/
|
|
34
|
+
@Throws
|
|
35
|
+
@RequiresApi(Build.VERSION_CODES.O)
|
|
36
|
+
fun copyHardwareBuffer(hardwareBuffer: HardwareBuffer): HardwareBuffer {
|
|
37
|
+
val resultBoxed = copyHardwareBuffer(hardwareBuffer as Any)
|
|
38
|
+
return resultBoxed as HardwareBuffer
|
|
39
|
+
}
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Copies the given [[source]] [[HardwareBuffer]] into the given [[destination]] [[HardwareBuffer]].
|
|
43
|
+
*/
|
|
44
|
+
@Throws
|
|
45
|
+
@RequiresApi(Build.VERSION_CODES.O)
|
|
46
|
+
fun copyHardwareBuffer(
|
|
47
|
+
source: HardwareBuffer,
|
|
48
|
+
destination: HardwareBuffer,
|
|
49
|
+
) {
|
|
50
|
+
copyHardwareBuffer(source as Any, destination as Any)
|
|
45
51
|
}
|
|
52
|
+
}
|
|
46
53
|
}
|
|
@@ -11,24 +11,25 @@ import com.margelo.nitro.core.HybridObject
|
|
|
11
11
|
*/
|
|
12
12
|
@Keep
|
|
13
13
|
@DoNotStrip
|
|
14
|
-
abstract class HybridView: HybridObject() {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
abstract class HybridView : HybridObject() {
|
|
15
|
+
/**
|
|
16
|
+
* Get the `UIView` this HybridView is holding.
|
|
17
|
+
*
|
|
18
|
+
* This value should not change during the lifetime of this `HybridView`.
|
|
19
|
+
*/
|
|
20
|
+
@get:DoNotStrip
|
|
21
|
+
@get:Keep
|
|
22
|
+
abstract val view: View
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Called right before updating props.
|
|
26
|
+
* React props are updated in a single batch/transaction.
|
|
27
|
+
*/
|
|
28
|
+
open fun beforeUpdate() { /* noop */ }
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Called right after updating props.
|
|
32
|
+
* React props are updated in a single batch/transaction.
|
|
33
|
+
*/
|
|
34
|
+
open fun afterUpdate() { /* noop */ }
|
|
34
35
|
}
|