react-native-mmkv 2.4.4 → 2.5.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/README.md +8 -0
- package/android/CMakeLists.txt +3 -1
- package/android/src/main/cpp/MmkvHostObject.cpp +55 -1
- package/cpp/TypedArray.cpp +341 -0
- package/cpp/TypedArray.h +175 -0
- package/ios/Mmkv.xcodeproj/project.pbxproj +8 -6
- package/ios/MmkvHostObject.mm +44 -0
- package/lib/commonjs/MMKV.js +5 -0
- package/lib/commonjs/MMKV.js.map +1 -1
- package/lib/commonjs/createMMKV.mock.js +4 -0
- package/lib/commonjs/createMMKV.mock.js.map +1 -1
- package/lib/commonjs/createMMKV.web.js +8 -1
- package/lib/commonjs/createMMKV.web.js.map +1 -1
- package/lib/commonjs/createTextEncoder.js +24 -0
- package/lib/commonjs/createTextEncoder.js.map +1 -0
- package/lib/commonjs/hooks.js +15 -2
- package/lib/commonjs/hooks.js.map +1 -1
- package/lib/module/MMKV.js +5 -0
- package/lib/module/MMKV.js.map +1 -1
- package/lib/module/createMMKV.mock.js +4 -0
- package/lib/module/createMMKV.mock.js.map +1 -1
- package/lib/module/createMMKV.web.js +7 -0
- package/lib/module/createMMKV.web.js.map +1 -1
- package/lib/module/createTextEncoder.js +17 -0
- package/lib/module/createTextEncoder.js.map +1 -0
- package/lib/module/hooks.js +12 -0
- package/lib/module/hooks.js.map +1 -1
- package/lib/typescript/MMKV.d.ts +10 -3
- package/lib/typescript/createTextEncoder.d.ts +1 -0
- package/lib/typescript/hooks.d.ts +11 -0
- package/package.json +2 -1
- package/react-native-mmkv.podspec +2 -1
package/README.md
CHANGED
|
@@ -174,6 +174,14 @@ storage.recrypt('hunter2')
|
|
|
174
174
|
storage.recrypt(undefined)
|
|
175
175
|
```
|
|
176
176
|
|
|
177
|
+
### Buffers
|
|
178
|
+
|
|
179
|
+
```js
|
|
180
|
+
storage.set('someToken', new Uint8Array([1, 100, 255]))
|
|
181
|
+
const buffer = storage.getBuffer('someToken')
|
|
182
|
+
console.log(buffer) // [1, 100, 255]
|
|
183
|
+
```
|
|
184
|
+
|
|
177
185
|
## Testing with Jest
|
|
178
186
|
|
|
179
187
|
A mocked MMKV instance is automatically used when testing with Jest, so you will be able to use `new MMKV()` as per normal in your tests. Refer to [example/test/MMKV.test.ts](example/test/MMKV.test.ts) for an example.
|
package/android/CMakeLists.txt
CHANGED
|
@@ -7,6 +7,7 @@ add_subdirectory(../MMKV/Core core)
|
|
|
7
7
|
|
|
8
8
|
include_directories(
|
|
9
9
|
../MMKV/Core
|
|
10
|
+
../cpp
|
|
10
11
|
"${NODE_MODULES_DIR}/react-native/React"
|
|
11
12
|
"${NODE_MODULES_DIR}/react-native/React/Base"
|
|
12
13
|
"${NODE_MODULES_DIR}/react-native/ReactCommon/jsi"
|
|
@@ -14,7 +15,7 @@ include_directories(
|
|
|
14
15
|
|
|
15
16
|
if(${REACT_NATIVE_VERSION} LESS 66)
|
|
16
17
|
file(
|
|
17
|
-
TO_CMAKE_PATH
|
|
18
|
+
TO_CMAKE_PATH
|
|
18
19
|
"${NODE_MODULES_DIR}/react-native/ReactCommon/jsi/jsi/jsi.cpp"
|
|
19
20
|
INCLUDE_JSI_CPP
|
|
20
21
|
)
|
|
@@ -24,6 +25,7 @@ add_library(reactnativemmkv # <-- Library name
|
|
|
24
25
|
SHARED
|
|
25
26
|
src/main/cpp/cpp-adapter.cpp
|
|
26
27
|
src/main/cpp/MmkvHostObject.cpp
|
|
28
|
+
../cpp/TypedArray.cpp
|
|
27
29
|
${INCLUDE_JSI_CPP} # only on older RN versions
|
|
28
30
|
)
|
|
29
31
|
|
|
@@ -7,9 +7,11 @@
|
|
|
7
7
|
//
|
|
8
8
|
|
|
9
9
|
#include "MmkvHostObject.h"
|
|
10
|
+
#include "TypedArray.h"
|
|
10
11
|
#include <MMKV.h>
|
|
11
12
|
#include <android/log.h>
|
|
12
13
|
#include <string>
|
|
14
|
+
#include <vector>
|
|
13
15
|
|
|
14
16
|
MmkvHostObject::MmkvHostObject(const std::string& instanceId, std::string path, std::string cryptKey) {
|
|
15
17
|
__android_log_print(ANDROID_LOG_INFO, "RNMMKV", "Creating MMKV instance \"%s\"... (Path: %s, Encryption-Key: %s)",
|
|
@@ -65,16 +67,37 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
|
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
auto keyName = arguments[0].getString(runtime).utf8(runtime);
|
|
70
|
+
|
|
68
71
|
if (arguments[1].isBool()) {
|
|
72
|
+
// bool
|
|
69
73
|
instance->set(arguments[1].getBool(), keyName);
|
|
70
74
|
} else if (arguments[1].isNumber()) {
|
|
75
|
+
// number
|
|
71
76
|
instance->set(arguments[1].getNumber(), keyName);
|
|
72
77
|
} else if (arguments[1].isString()) {
|
|
78
|
+
// string
|
|
73
79
|
auto stringValue = arguments[1].getString(runtime).utf8(runtime);
|
|
74
80
|
instance->set(stringValue, keyName);
|
|
81
|
+
} else if (arguments[1].isObject()) {
|
|
82
|
+
// object
|
|
83
|
+
auto object = arguments[1].asObject(runtime);
|
|
84
|
+
if (isTypedArray(runtime, object)) {
|
|
85
|
+
// Uint8Array
|
|
86
|
+
auto typedArray = getTypedArray(runtime, object);
|
|
87
|
+
auto bufferValue = typedArray.getBuffer(runtime);
|
|
88
|
+
mmkv::MMBuffer buffer(bufferValue.data(runtime),
|
|
89
|
+
bufferValue.size(runtime),
|
|
90
|
+
mmkv::MMBufferCopyFlag::MMBufferNoCopy);
|
|
91
|
+
instance->set(buffer, keyName);
|
|
92
|
+
} else {
|
|
93
|
+
// unknown object
|
|
94
|
+
throw jsi::JSError(runtime, "MMKV::set: 'value' argument is an object, but not of type Uint8Array!");
|
|
95
|
+
}
|
|
75
96
|
} else {
|
|
76
|
-
|
|
97
|
+
// unknown type
|
|
98
|
+
throw jsi::JSError(runtime, "MMKV::set: 'value' argument is not of type bool, number, string or buffer!");
|
|
77
99
|
}
|
|
100
|
+
|
|
78
101
|
return jsi::Value::undefined();
|
|
79
102
|
});
|
|
80
103
|
}
|
|
@@ -151,6 +174,37 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
|
|
|
151
174
|
});
|
|
152
175
|
}
|
|
153
176
|
|
|
177
|
+
|
|
178
|
+
if (propName == "getBuffer") {
|
|
179
|
+
// MMKV.getBuffer(key: string)
|
|
180
|
+
return jsi::Function::createFromHostFunction(runtime,
|
|
181
|
+
jsi::PropNameID::forAscii(runtime, funcName),
|
|
182
|
+
1, // key
|
|
183
|
+
[this](jsi::Runtime& runtime,
|
|
184
|
+
const jsi::Value& thisValue,
|
|
185
|
+
const jsi::Value* arguments,
|
|
186
|
+
size_t count) -> jsi::Value {
|
|
187
|
+
if (!arguments[0].isString()) {
|
|
188
|
+
throw jsi::JSError(runtime, "First argument ('key') has to be of type string!");
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
auto keyName = arguments[0].getString(runtime).utf8(runtime);
|
|
192
|
+
mmkv::MMBuffer buffer;
|
|
193
|
+
bool hasValue = instance->getBytes(keyName, buffer);
|
|
194
|
+
if (hasValue) {
|
|
195
|
+
auto length = buffer.length();
|
|
196
|
+
TypedArray<TypedArrayKind::Uint8Array> array(runtime, length);
|
|
197
|
+
auto data = static_cast<const unsigned char*>(buffer.getPtr());
|
|
198
|
+
std::vector<unsigned char> vector(length);
|
|
199
|
+
vector.assign(data, data + length);
|
|
200
|
+
array.update(runtime, vector);
|
|
201
|
+
return array;
|
|
202
|
+
} else {
|
|
203
|
+
return jsi::Value::undefined();
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
154
208
|
if (propName == "contains") {
|
|
155
209
|
// MMKV.contains(key: string)
|
|
156
210
|
return jsi::Function::createFromHostFunction(runtime,
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
//
|
|
2
|
+
// TypedArray.cpp
|
|
3
|
+
// react-native-mmkv
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 11.10.2022.
|
|
6
|
+
// Originally created by Expo (expo-gl)
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#include "TypedArray.h"
|
|
10
|
+
|
|
11
|
+
#include <unordered_map>
|
|
12
|
+
|
|
13
|
+
template <TypedArrayKind T>
|
|
14
|
+
using ContentType = typename typedArrayTypeMap<T>::type;
|
|
15
|
+
|
|
16
|
+
enum class Prop
|
|
17
|
+
{
|
|
18
|
+
Buffer, // "buffer"
|
|
19
|
+
Constructor, // "constructor"
|
|
20
|
+
Name, // "name"
|
|
21
|
+
Proto, // "__proto__"
|
|
22
|
+
Length, // "length"
|
|
23
|
+
ByteLength, // "byteLength"
|
|
24
|
+
ByteOffset, // "offset"
|
|
25
|
+
IsView, // "isView"
|
|
26
|
+
ArrayBuffer, // "ArrayBuffer"
|
|
27
|
+
Int8Array, // "Int8Array"
|
|
28
|
+
Int16Array, // "Int16Array"
|
|
29
|
+
Int32Array, // "Int32Array"
|
|
30
|
+
Uint8Array, // "Uint8Array"
|
|
31
|
+
Uint8ClampedArray, // "Uint8ClampedArray"
|
|
32
|
+
Uint16Array, // "Uint16Array"
|
|
33
|
+
Uint32Array, // "Uint32Array"
|
|
34
|
+
Float32Array, // "Float32Array"
|
|
35
|
+
Float64Array, // "Float64Array"
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
class PropNameIDCache
|
|
39
|
+
{
|
|
40
|
+
public:
|
|
41
|
+
const jsi::PropNameID &get(jsi::Runtime &runtime, Prop prop)
|
|
42
|
+
{
|
|
43
|
+
if (!this->props[prop])
|
|
44
|
+
{
|
|
45
|
+
this->props[prop] = std::make_unique<jsi::PropNameID>(createProp(runtime, prop));
|
|
46
|
+
}
|
|
47
|
+
return *(this->props[prop]);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const jsi::PropNameID &getConstructorNameProp(jsi::Runtime &runtime, TypedArrayKind kind);
|
|
51
|
+
|
|
52
|
+
void invalidate()
|
|
53
|
+
{
|
|
54
|
+
props.erase(props.begin(), props.end());
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private:
|
|
58
|
+
std::unordered_map<Prop, std::unique_ptr<jsi::PropNameID>> props;
|
|
59
|
+
|
|
60
|
+
jsi::PropNameID createProp(jsi::Runtime &runtime, Prop prop);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
PropNameIDCache propNameIDCache;
|
|
64
|
+
|
|
65
|
+
void invalidateJsiPropNameIDCache()
|
|
66
|
+
{
|
|
67
|
+
propNameIDCache.invalidate();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
TypedArrayKind getTypedArrayKindForName(const std::string &name);
|
|
71
|
+
|
|
72
|
+
TypedArrayBase::TypedArrayBase(jsi::Runtime &runtime, size_t size, TypedArrayKind kind)
|
|
73
|
+
: TypedArrayBase(
|
|
74
|
+
runtime,
|
|
75
|
+
runtime.global()
|
|
76
|
+
.getProperty(runtime, propNameIDCache.getConstructorNameProp(runtime, kind))
|
|
77
|
+
.asObject(runtime)
|
|
78
|
+
.asFunction(runtime)
|
|
79
|
+
.callAsConstructor(runtime, {static_cast<double>(size)})
|
|
80
|
+
.asObject(runtime)) {}
|
|
81
|
+
|
|
82
|
+
TypedArrayBase::TypedArrayBase(jsi::Runtime &runtime, const jsi::Object &obj)
|
|
83
|
+
: jsi::Object(jsi::Value(runtime, obj).asObject(runtime)) {}
|
|
84
|
+
|
|
85
|
+
TypedArrayKind TypedArrayBase::getKind(jsi::Runtime &runtime) const
|
|
86
|
+
{
|
|
87
|
+
auto constructorName = this->getProperty(runtime, propNameIDCache.get(runtime, Prop::Constructor))
|
|
88
|
+
.asObject(runtime)
|
|
89
|
+
.getProperty(runtime, propNameIDCache.get(runtime, Prop::Name))
|
|
90
|
+
.asString(runtime)
|
|
91
|
+
.utf8(runtime);
|
|
92
|
+
return getTypedArrayKindForName(constructorName);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
size_t TypedArrayBase::size(jsi::Runtime &runtime) const
|
|
96
|
+
{
|
|
97
|
+
return getProperty(runtime, propNameIDCache.get(runtime, Prop::Length)).asNumber();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
size_t TypedArrayBase::length(jsi::Runtime &runtime) const
|
|
101
|
+
{
|
|
102
|
+
return getProperty(runtime, propNameIDCache.get(runtime, Prop::Length)).asNumber();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
size_t TypedArrayBase::byteLength(jsi::Runtime &runtime) const
|
|
106
|
+
{
|
|
107
|
+
return getProperty(runtime, propNameIDCache.get(runtime, Prop::ByteLength)).asNumber();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
size_t TypedArrayBase::byteOffset(jsi::Runtime &runtime) const
|
|
111
|
+
{
|
|
112
|
+
return getProperty(runtime, propNameIDCache.get(runtime, Prop::ByteOffset)).asNumber();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
bool TypedArrayBase::hasBuffer(jsi::Runtime &runtime) const
|
|
116
|
+
{
|
|
117
|
+
auto buffer = getProperty(runtime, propNameIDCache.get(runtime, Prop::Buffer));
|
|
118
|
+
return buffer.isObject() && buffer.asObject(runtime).isArrayBuffer(runtime);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
std::vector<uint8_t> TypedArrayBase::toVector(jsi::Runtime &runtime)
|
|
122
|
+
{
|
|
123
|
+
auto start =
|
|
124
|
+
reinterpret_cast<uint8_t *>(getBuffer(runtime).data(runtime) + byteOffset(runtime));
|
|
125
|
+
auto end = start + byteLength(runtime);
|
|
126
|
+
return std::vector<uint8_t>(start, end);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
jsi::ArrayBuffer TypedArrayBase::getBuffer(jsi::Runtime &runtime) const
|
|
130
|
+
{
|
|
131
|
+
auto buffer = getProperty(runtime, propNameIDCache.get(runtime, Prop::Buffer));
|
|
132
|
+
if (buffer.isObject() && buffer.asObject(runtime).isArrayBuffer(runtime))
|
|
133
|
+
{
|
|
134
|
+
return buffer.asObject(runtime).getArrayBuffer(runtime);
|
|
135
|
+
}
|
|
136
|
+
else
|
|
137
|
+
{
|
|
138
|
+
throw std::runtime_error("no ArrayBuffer attached");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
bool isTypedArray(jsi::Runtime &runtime, const jsi::Object &jsObj)
|
|
143
|
+
{
|
|
144
|
+
auto jsVal = runtime.global()
|
|
145
|
+
.getProperty(runtime, propNameIDCache.get(runtime, Prop::ArrayBuffer))
|
|
146
|
+
.asObject(runtime)
|
|
147
|
+
.getProperty(runtime, propNameIDCache.get(runtime, Prop::IsView))
|
|
148
|
+
.asObject(runtime)
|
|
149
|
+
.asFunction(runtime)
|
|
150
|
+
.callWithThis(runtime, runtime.global(), {jsi::Value(runtime, jsObj)});
|
|
151
|
+
if (jsVal.isBool())
|
|
152
|
+
{
|
|
153
|
+
return jsVal.getBool();
|
|
154
|
+
}
|
|
155
|
+
else
|
|
156
|
+
{
|
|
157
|
+
throw std::runtime_error("value is not a boolean");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
TypedArrayBase getTypedArray(jsi::Runtime &runtime, const jsi::Object &jsObj)
|
|
162
|
+
{
|
|
163
|
+
auto jsVal = runtime.global()
|
|
164
|
+
.getProperty(runtime, propNameIDCache.get(runtime, Prop::ArrayBuffer))
|
|
165
|
+
.asObject(runtime)
|
|
166
|
+
.getProperty(runtime, propNameIDCache.get(runtime, Prop::IsView))
|
|
167
|
+
.asObject(runtime)
|
|
168
|
+
.asFunction(runtime)
|
|
169
|
+
.callWithThis(runtime, runtime.global(), {jsi::Value(runtime, jsObj)});
|
|
170
|
+
if (jsVal.isBool())
|
|
171
|
+
{
|
|
172
|
+
return TypedArrayBase(runtime, jsObj);
|
|
173
|
+
}
|
|
174
|
+
else
|
|
175
|
+
{
|
|
176
|
+
throw std::runtime_error("value is not a boolean");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
std::vector<uint8_t> arrayBufferToVector(jsi::Runtime &runtime, jsi::Object &jsObj)
|
|
181
|
+
{
|
|
182
|
+
if (!jsObj.isArrayBuffer(runtime))
|
|
183
|
+
{
|
|
184
|
+
throw std::runtime_error("Object is not an ArrayBuffer");
|
|
185
|
+
}
|
|
186
|
+
auto jsArrayBuffer = jsObj.getArrayBuffer(runtime);
|
|
187
|
+
|
|
188
|
+
uint8_t *dataBlock = jsArrayBuffer.data(runtime);
|
|
189
|
+
size_t blockSize =
|
|
190
|
+
jsArrayBuffer.getProperty(runtime, propNameIDCache.get(runtime, Prop::ByteLength)).asNumber();
|
|
191
|
+
return std::vector<uint8_t>(dataBlock, dataBlock + blockSize);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
void arrayBufferUpdate(
|
|
195
|
+
jsi::Runtime &runtime,
|
|
196
|
+
jsi::ArrayBuffer &buffer,
|
|
197
|
+
std::vector<uint8_t> data,
|
|
198
|
+
size_t offset)
|
|
199
|
+
{
|
|
200
|
+
uint8_t *dataBlock = buffer.data(runtime);
|
|
201
|
+
size_t blockSize = buffer.size(runtime);
|
|
202
|
+
if (data.size() > blockSize)
|
|
203
|
+
{
|
|
204
|
+
throw jsi::JSError(runtime, "ArrayBuffer is to small to fit data");
|
|
205
|
+
}
|
|
206
|
+
std::copy(data.begin(), data.end(), dataBlock + offset);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
template <TypedArrayKind T>
|
|
210
|
+
TypedArray<T>::TypedArray(jsi::Runtime &runtime, size_t size) : TypedArrayBase(runtime, size, T){};
|
|
211
|
+
|
|
212
|
+
template <TypedArrayKind T>
|
|
213
|
+
TypedArray<T>::TypedArray(jsi::Runtime &runtime, std::vector<ContentType<T>> data)
|
|
214
|
+
: TypedArrayBase(runtime, data.size(), T)
|
|
215
|
+
{
|
|
216
|
+
update(runtime, data);
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
template <TypedArrayKind T>
|
|
220
|
+
TypedArray<T>::TypedArray(TypedArrayBase &&base) : TypedArrayBase(std::move(base)) {}
|
|
221
|
+
|
|
222
|
+
template <TypedArrayKind T>
|
|
223
|
+
std::vector<ContentType<T>> TypedArray<T>::toVector(jsi::Runtime &runtime)
|
|
224
|
+
{
|
|
225
|
+
auto start =
|
|
226
|
+
reinterpret_cast<ContentType<T> *>(getBuffer(runtime).data(runtime) + byteOffset(runtime));
|
|
227
|
+
auto end = start + size(runtime);
|
|
228
|
+
return std::vector<ContentType<T>>(start, end);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
template <TypedArrayKind T>
|
|
232
|
+
void TypedArray<T>::update(jsi::Runtime &runtime, const std::vector<ContentType<T>> &data)
|
|
233
|
+
{
|
|
234
|
+
if (data.size() != size(runtime))
|
|
235
|
+
{
|
|
236
|
+
throw jsi::JSError(runtime, "TypedArray can only be updated with a vector of the same size");
|
|
237
|
+
}
|
|
238
|
+
uint8_t *rawData = getBuffer(runtime).data(runtime) + byteOffset(runtime);
|
|
239
|
+
std::copy(data.begin(), data.end(), reinterpret_cast<ContentType<T> *>(rawData));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const jsi::PropNameID &PropNameIDCache::getConstructorNameProp(
|
|
243
|
+
jsi::Runtime &runtime,
|
|
244
|
+
TypedArrayKind kind)
|
|
245
|
+
{
|
|
246
|
+
switch (kind)
|
|
247
|
+
{
|
|
248
|
+
case TypedArrayKind::Int8Array:
|
|
249
|
+
return get(runtime, Prop::Int8Array);
|
|
250
|
+
case TypedArrayKind::Int16Array:
|
|
251
|
+
return get(runtime, Prop::Int16Array);
|
|
252
|
+
case TypedArrayKind::Int32Array:
|
|
253
|
+
return get(runtime, Prop::Int32Array);
|
|
254
|
+
case TypedArrayKind::Uint8Array:
|
|
255
|
+
return get(runtime, Prop::Uint8Array);
|
|
256
|
+
case TypedArrayKind::Uint8ClampedArray:
|
|
257
|
+
return get(runtime, Prop::Uint8ClampedArray);
|
|
258
|
+
case TypedArrayKind::Uint16Array:
|
|
259
|
+
return get(runtime, Prop::Uint16Array);
|
|
260
|
+
case TypedArrayKind::Uint32Array:
|
|
261
|
+
return get(runtime, Prop::Uint32Array);
|
|
262
|
+
case TypedArrayKind::Float32Array:
|
|
263
|
+
return get(runtime, Prop::Float32Array);
|
|
264
|
+
case TypedArrayKind::Float64Array:
|
|
265
|
+
return get(runtime, Prop::Float64Array);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
jsi::PropNameID PropNameIDCache::createProp(jsi::Runtime &runtime, Prop prop)
|
|
270
|
+
{
|
|
271
|
+
auto create = [&](const std::string &propName)
|
|
272
|
+
{
|
|
273
|
+
return jsi::PropNameID::forUtf8(runtime, propName);
|
|
274
|
+
};
|
|
275
|
+
switch (prop)
|
|
276
|
+
{
|
|
277
|
+
case Prop::Buffer:
|
|
278
|
+
return create("buffer");
|
|
279
|
+
case Prop::Constructor:
|
|
280
|
+
return create("constructor");
|
|
281
|
+
case Prop::Name:
|
|
282
|
+
return create("name");
|
|
283
|
+
case Prop::Proto:
|
|
284
|
+
return create("__proto__");
|
|
285
|
+
case Prop::Length:
|
|
286
|
+
return create("length");
|
|
287
|
+
case Prop::ByteLength:
|
|
288
|
+
return create("byteLength");
|
|
289
|
+
case Prop::ByteOffset:
|
|
290
|
+
return create("byteOffset");
|
|
291
|
+
case Prop::IsView:
|
|
292
|
+
return create("isView");
|
|
293
|
+
case Prop::ArrayBuffer:
|
|
294
|
+
return create("ArrayBuffer");
|
|
295
|
+
case Prop::Int8Array:
|
|
296
|
+
return create("Int8Array");
|
|
297
|
+
case Prop::Int16Array:
|
|
298
|
+
return create("Int16Array");
|
|
299
|
+
case Prop::Int32Array:
|
|
300
|
+
return create("Int32Array");
|
|
301
|
+
case Prop::Uint8Array:
|
|
302
|
+
return create("Uint8Array");
|
|
303
|
+
case Prop::Uint8ClampedArray:
|
|
304
|
+
return create("Uint8ClampedArray");
|
|
305
|
+
case Prop::Uint16Array:
|
|
306
|
+
return create("Uint16Array");
|
|
307
|
+
case Prop::Uint32Array:
|
|
308
|
+
return create("Uint32Array");
|
|
309
|
+
case Prop::Float32Array:
|
|
310
|
+
return create("Float32Array");
|
|
311
|
+
case Prop::Float64Array:
|
|
312
|
+
return create("Float64Array");
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
std::unordered_map<std::string, TypedArrayKind> nameToKindMap = {
|
|
317
|
+
{"Int8Array", TypedArrayKind::Int8Array},
|
|
318
|
+
{"Int16Array", TypedArrayKind::Int16Array},
|
|
319
|
+
{"Int32Array", TypedArrayKind::Int32Array},
|
|
320
|
+
{"Uint8Array", TypedArrayKind::Uint8Array},
|
|
321
|
+
{"Uint8ClampedArray", TypedArrayKind::Uint8ClampedArray},
|
|
322
|
+
{"Uint16Array", TypedArrayKind::Uint16Array},
|
|
323
|
+
{"Uint32Array", TypedArrayKind::Uint32Array},
|
|
324
|
+
{"Float32Array", TypedArrayKind::Float32Array},
|
|
325
|
+
{"Float64Array", TypedArrayKind::Float64Array},
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
TypedArrayKind getTypedArrayKindForName(const std::string &name)
|
|
329
|
+
{
|
|
330
|
+
return nameToKindMap.at(name);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
template class TypedArray<TypedArrayKind::Int8Array>;
|
|
334
|
+
template class TypedArray<TypedArrayKind::Int16Array>;
|
|
335
|
+
template class TypedArray<TypedArrayKind::Int32Array>;
|
|
336
|
+
template class TypedArray<TypedArrayKind::Uint8Array>;
|
|
337
|
+
template class TypedArray<TypedArrayKind::Uint8ClampedArray>;
|
|
338
|
+
template class TypedArray<TypedArrayKind::Uint16Array>;
|
|
339
|
+
template class TypedArray<TypedArrayKind::Uint32Array>;
|
|
340
|
+
template class TypedArray<TypedArrayKind::Float32Array>;
|
|
341
|
+
template class TypedArray<TypedArrayKind::Float64Array>;
|
package/cpp/TypedArray.h
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
//
|
|
2
|
+
// TypedArray.h
|
|
3
|
+
// react-native-mmkv
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 11.10.2022.
|
|
6
|
+
// Originally created by Expo (expo-gl)
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#pragma once
|
|
10
|
+
|
|
11
|
+
#include <jsi/jsi.h>
|
|
12
|
+
|
|
13
|
+
namespace jsi = facebook::jsi;
|
|
14
|
+
|
|
15
|
+
enum class TypedArrayKind
|
|
16
|
+
{
|
|
17
|
+
Int8Array,
|
|
18
|
+
Int16Array,
|
|
19
|
+
Int32Array,
|
|
20
|
+
Uint8Array,
|
|
21
|
+
Uint8ClampedArray,
|
|
22
|
+
Uint16Array,
|
|
23
|
+
Uint32Array,
|
|
24
|
+
Float32Array,
|
|
25
|
+
Float64Array,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
template <TypedArrayKind T>
|
|
29
|
+
class TypedArray;
|
|
30
|
+
|
|
31
|
+
template <TypedArrayKind T>
|
|
32
|
+
struct typedArrayTypeMap;
|
|
33
|
+
template <>
|
|
34
|
+
struct typedArrayTypeMap<TypedArrayKind::Int8Array>
|
|
35
|
+
{
|
|
36
|
+
typedef int8_t type;
|
|
37
|
+
};
|
|
38
|
+
template <>
|
|
39
|
+
struct typedArrayTypeMap<TypedArrayKind::Int16Array>
|
|
40
|
+
{
|
|
41
|
+
typedef int16_t type;
|
|
42
|
+
};
|
|
43
|
+
template <>
|
|
44
|
+
struct typedArrayTypeMap<TypedArrayKind::Int32Array>
|
|
45
|
+
{
|
|
46
|
+
typedef int32_t type;
|
|
47
|
+
};
|
|
48
|
+
template <>
|
|
49
|
+
struct typedArrayTypeMap<TypedArrayKind::Uint8Array>
|
|
50
|
+
{
|
|
51
|
+
typedef uint8_t type;
|
|
52
|
+
};
|
|
53
|
+
template <>
|
|
54
|
+
struct typedArrayTypeMap<TypedArrayKind::Uint8ClampedArray>
|
|
55
|
+
{
|
|
56
|
+
typedef uint8_t type;
|
|
57
|
+
};
|
|
58
|
+
template <>
|
|
59
|
+
struct typedArrayTypeMap<TypedArrayKind::Uint16Array>
|
|
60
|
+
{
|
|
61
|
+
typedef uint16_t type;
|
|
62
|
+
};
|
|
63
|
+
template <>
|
|
64
|
+
struct typedArrayTypeMap<TypedArrayKind::Uint32Array>
|
|
65
|
+
{
|
|
66
|
+
typedef uint32_t type;
|
|
67
|
+
};
|
|
68
|
+
template <>
|
|
69
|
+
struct typedArrayTypeMap<TypedArrayKind::Float32Array>
|
|
70
|
+
{
|
|
71
|
+
typedef float type;
|
|
72
|
+
};
|
|
73
|
+
template <>
|
|
74
|
+
struct typedArrayTypeMap<TypedArrayKind::Float64Array>
|
|
75
|
+
{
|
|
76
|
+
typedef double type;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
void invalidateJsiPropNameIDCache();
|
|
80
|
+
|
|
81
|
+
class TypedArrayBase : public jsi::Object
|
|
82
|
+
{
|
|
83
|
+
public:
|
|
84
|
+
template <TypedArrayKind T>
|
|
85
|
+
using ContentType = typename typedArrayTypeMap<T>::type;
|
|
86
|
+
|
|
87
|
+
TypedArrayBase(jsi::Runtime &, size_t, TypedArrayKind);
|
|
88
|
+
TypedArrayBase(jsi::Runtime &, const jsi::Object &);
|
|
89
|
+
TypedArrayBase(TypedArrayBase &&) = default;
|
|
90
|
+
TypedArrayBase &operator=(TypedArrayBase &&) = default;
|
|
91
|
+
|
|
92
|
+
TypedArrayKind getKind(jsi::Runtime &runtime) const;
|
|
93
|
+
|
|
94
|
+
template <TypedArrayKind T>
|
|
95
|
+
TypedArray<T> get(jsi::Runtime &runtime) const &;
|
|
96
|
+
template <TypedArrayKind T>
|
|
97
|
+
TypedArray<T> get(jsi::Runtime &runtime) &&;
|
|
98
|
+
template <TypedArrayKind T>
|
|
99
|
+
TypedArray<T> as(jsi::Runtime &runtime) const &;
|
|
100
|
+
template <TypedArrayKind T>
|
|
101
|
+
TypedArray<T> as(jsi::Runtime &runtime) &&;
|
|
102
|
+
|
|
103
|
+
size_t size(jsi::Runtime &runtime) const;
|
|
104
|
+
size_t length(jsi::Runtime &runtime) const;
|
|
105
|
+
size_t byteLength(jsi::Runtime &runtime) const;
|
|
106
|
+
size_t byteOffset(jsi::Runtime &runtime) const;
|
|
107
|
+
bool hasBuffer(jsi::Runtime &runtime) const;
|
|
108
|
+
|
|
109
|
+
std::vector<uint8_t> toVector(jsi::Runtime &runtime);
|
|
110
|
+
jsi::ArrayBuffer getBuffer(jsi::Runtime &runtime) const;
|
|
111
|
+
|
|
112
|
+
private:
|
|
113
|
+
template <TypedArrayKind>
|
|
114
|
+
friend class TypedArray;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
bool isTypedArray(jsi::Runtime &runtime, const jsi::Object &jsObj);
|
|
118
|
+
TypedArrayBase getTypedArray(jsi::Runtime &runtime, const jsi::Object &jsObj);
|
|
119
|
+
|
|
120
|
+
std::vector<uint8_t> arrayBufferToVector(jsi::Runtime &runtime, jsi::Object &jsObj);
|
|
121
|
+
void arrayBufferUpdate(
|
|
122
|
+
jsi::Runtime &runtime,
|
|
123
|
+
jsi::ArrayBuffer &buffer,
|
|
124
|
+
std::vector<uint8_t> data,
|
|
125
|
+
size_t offset);
|
|
126
|
+
|
|
127
|
+
template <TypedArrayKind T>
|
|
128
|
+
class TypedArray : public TypedArrayBase
|
|
129
|
+
{
|
|
130
|
+
public:
|
|
131
|
+
TypedArray(jsi::Runtime &runtime, size_t size);
|
|
132
|
+
TypedArray(jsi::Runtime &runtime, std::vector<ContentType<T>> data);
|
|
133
|
+
TypedArray(TypedArrayBase &&base);
|
|
134
|
+
TypedArray(TypedArray &&) = default;
|
|
135
|
+
TypedArray &operator=(TypedArray &&) = default;
|
|
136
|
+
|
|
137
|
+
std::vector<ContentType<T>> toVector(jsi::Runtime &runtime);
|
|
138
|
+
void update(jsi::Runtime &runtime, const std::vector<ContentType<T>> &data);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
template <TypedArrayKind T>
|
|
142
|
+
TypedArray<T> TypedArrayBase::get(jsi::Runtime &runtime) const &
|
|
143
|
+
{
|
|
144
|
+
assert(getKind(runtime) == T);
|
|
145
|
+
(void)runtime; // when assert is disabled we need to mark this as used
|
|
146
|
+
return TypedArray<T>(jsi::Value(runtime, jsi::Value(runtime, *this).asObject(runtime)));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
template <TypedArrayKind T>
|
|
150
|
+
TypedArray<T> TypedArrayBase::get(jsi::Runtime &runtime) &&
|
|
151
|
+
{
|
|
152
|
+
assert(getKind(runtime) == T);
|
|
153
|
+
(void)runtime; // when assert is disabled we need to mark this as used
|
|
154
|
+
return TypedArray<T>(std::move(*this));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
template <TypedArrayKind T>
|
|
158
|
+
TypedArray<T> TypedArrayBase::as(jsi::Runtime &runtime) const &
|
|
159
|
+
{
|
|
160
|
+
if (getKind(runtime) != T)
|
|
161
|
+
{
|
|
162
|
+
throw jsi::JSError(runtime, "Object is not a TypedArray");
|
|
163
|
+
}
|
|
164
|
+
return get<T>(runtime);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
template <TypedArrayKind T>
|
|
168
|
+
TypedArray<T> TypedArrayBase::as(jsi::Runtime &runtime) &&
|
|
169
|
+
{
|
|
170
|
+
if (getKind(runtime) != T)
|
|
171
|
+
{
|
|
172
|
+
throw jsi::JSError(runtime, "Object is not a TypedArray");
|
|
173
|
+
}
|
|
174
|
+
return std::move(*this).get<T>(runtime);
|
|
175
|
+
}
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
objects = {
|
|
8
8
|
|
|
9
9
|
/* Begin PBXBuildFile section */
|
|
10
|
-
5E555C0D2413F4C50049A1A2 /* Mmkv.mm in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* Mmkv.mm */; };
|
|
11
10
|
B81384EA26E23A8500A8507D /* MmkvHostObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = B81384E926E23A8500A8507D /* MmkvHostObject.mm */; };
|
|
11
|
+
B8A8A9BE28F5797400345076 /* MmkvModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = B8A8A9BD28F5797400345076 /* MmkvModule.mm */; };
|
|
12
12
|
B8CC270225E65597009808A2 /* JSIUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = B8CC270125E65597009808A2 /* JSIUtils.mm */; };
|
|
13
13
|
/* End PBXBuildFile section */
|
|
14
14
|
|
|
@@ -26,10 +26,11 @@
|
|
|
26
26
|
|
|
27
27
|
/* Begin PBXFileReference section */
|
|
28
28
|
134814201AA4EA6300B7C361 /* libMmkv.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMmkv.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
29
|
-
B3E7B5891CC2AC0600A0062D /* Mmkv.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Mmkv.mm; sourceTree = "<group>"; };
|
|
30
29
|
B81384E926E23A8500A8507D /* MmkvHostObject.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MmkvHostObject.mm; sourceTree = "<group>"; };
|
|
31
30
|
B81384EB26E23A8D00A8507D /* MmkvHostObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MmkvHostObject.h; sourceTree = "<group>"; };
|
|
32
|
-
|
|
31
|
+
B8A8A9BC28F5797400345076 /* MmkvModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MmkvModule.h; sourceTree = "<group>"; };
|
|
32
|
+
B8A8A9BD28F5797400345076 /* MmkvModule.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MmkvModule.mm; sourceTree = "<group>"; };
|
|
33
|
+
B8A8A9BF28F5798100345076 /* cpp */ = {isa = PBXFileReference; lastKnownFileType = folder; name = cpp; path = ../cpp; sourceTree = "<group>"; };
|
|
33
34
|
B8CC270125E65597009808A2 /* JSIUtils.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = JSIUtils.mm; sourceTree = "<group>"; };
|
|
34
35
|
B8CC270425E655AD009808A2 /* JSIUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSIUtils.h; sourceTree = "<group>"; };
|
|
35
36
|
/* End PBXFileReference section */
|
|
@@ -60,8 +61,9 @@
|
|
|
60
61
|
B81384E926E23A8500A8507D /* MmkvHostObject.mm */,
|
|
61
62
|
B8CC270425E655AD009808A2 /* JSIUtils.h */,
|
|
62
63
|
B8CC270125E65597009808A2 /* JSIUtils.mm */,
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
B8A8A9BC28F5797400345076 /* MmkvModule.h */,
|
|
65
|
+
B8A8A9BD28F5797400345076 /* MmkvModule.mm */,
|
|
66
|
+
B8A8A9BF28F5798100345076 /* cpp */,
|
|
65
67
|
134814211AA4EA7D00B7C361 /* Products */,
|
|
66
68
|
);
|
|
67
69
|
sourceTree = "<group>";
|
|
@@ -123,8 +125,8 @@
|
|
|
123
125
|
isa = PBXSourcesBuildPhase;
|
|
124
126
|
buildActionMask = 2147483647;
|
|
125
127
|
files = (
|
|
126
|
-
5E555C0D2413F4C50049A1A2 /* Mmkv.mm in Sources */,
|
|
127
128
|
B81384EA26E23A8500A8507D /* MmkvHostObject.mm in Sources */,
|
|
129
|
+
B8A8A9BE28F5797400345076 /* MmkvModule.mm in Sources */,
|
|
128
130
|
B8CC270225E65597009808A2 /* JSIUtils.mm in Sources */,
|
|
129
131
|
);
|
|
130
132
|
runOnlyForDeploymentPostprocessing = 0;
|