react-native-mmkv 2.8.0 → 2.9.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/MMKV/Core/Core.xcodeproj/project.pbxproj +15 -19
- package/MMKV/Core/Core.xcodeproj/xcshareddata/xcschemes/Core.xcscheme +1 -1
- package/MMKV/Core/Core.xcodeproj/xcshareddata/xcschemes/MMKVWatchCore.xcscheme +1 -1
- package/MMKV/Core/MMBuffer.cpp +18 -0
- package/MMKV/Core/MMBuffer.h +1 -0
- package/MMKV/Core/MMKV.cpp +173 -33
- package/MMKV/Core/MMKV.h +44 -0
- package/MMKV/Core/MMKVMetaInfo.hpp +18 -0
- package/MMKV/Core/MMKVPredef.h +2 -2
- package/MMKV/Core/MMKV_IO.cpp +477 -68
- package/MMKV/Core/MMKV_OSX.cpp +65 -14
- package/MMKV/Core/MemoryFile_Win32.cpp +39 -35
- package/MMKV/Core/MiniPBCoder.cpp +3 -7
- package/MMKV/Core/MiniPBCoder_OSX.cpp +4 -4
- package/MMKV/Core/PBUtility.cpp +1 -1
- package/MMKV/Core/PBUtility.h +7 -0
- package/MMKV/Core/aes/AESCrypt.h +1 -1
- package/MMKV/Core/aes/openssl/openssl_aes-armv4.S +4 -0
- package/README.md +12 -3
- package/android/build.gradle +1 -0
- package/android/src/main/AndroidManifest.xml +1 -2
- package/lib/commonjs/createMMKV.web.js +23 -0
- package/lib/commonjs/createMMKV.web.js.map +1 -1
- package/lib/module/createMMKV.web.js +23 -0
- package/lib/module/createMMKV.web.js.map +1 -1
- package/lib/typescript/createMMKV.web.d.ts.map +1 -1
- package/package.json +7 -6
- package/src/MMKV.ts +248 -0
- package/src/PlatformChecker.ts +7 -0
- package/src/createMMKV.mock.ts +33 -0
- package/src/createMMKV.ts +70 -0
- package/src/createMMKV.web.ts +119 -0
- package/src/createTextEncoder.ts +16 -0
- package/src/hooks.ts +232 -0
- package/src/index.ts +2 -0
package/MMKV/Core/MMKV_OSX.cpp
CHANGED
|
@@ -125,7 +125,7 @@ bool MMKV::isInBackground() {
|
|
|
125
125
|
pair<bool, MLockPtr> guardForBackgroundWriting(void *ptr, size_t size) {
|
|
126
126
|
if (g_isInBackground) {
|
|
127
127
|
MLockPtr mlockPtr(ptr, size);
|
|
128
|
-
return make_pair(mlockPtr.isLocked(), move(mlockPtr));
|
|
128
|
+
return make_pair(mlockPtr.isLocked(), std::move(mlockPtr));
|
|
129
129
|
} else {
|
|
130
130
|
return make_pair(true, MLockPtr(nullptr, 0));
|
|
131
131
|
}
|
|
@@ -134,6 +134,10 @@ pair<bool, MLockPtr> guardForBackgroundWriting(void *ptr, size_t size) {
|
|
|
134
134
|
# endif // MMKV_IOS
|
|
135
135
|
|
|
136
136
|
bool MMKV::set(NSObject<NSCoding> *__unsafe_unretained obj, MMKVKey_t key) {
|
|
137
|
+
return set(obj, key, m_expiredInSeconds);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
bool MMKV::set(NSObject<NSCoding> *__unsafe_unretained obj, MMKVKey_t key, uint32_t expireDuration) {
|
|
137
141
|
if (isKeyEmpty(key)) {
|
|
138
142
|
return false;
|
|
139
143
|
}
|
|
@@ -152,22 +156,76 @@ bool MMKV::set(NSObject<NSCoding> *__unsafe_unretained obj, MMKVKey_t key) {
|
|
|
152
156
|
if (tmpData) {
|
|
153
157
|
// delay write the size needed for encoding tmpData
|
|
154
158
|
// avoid memory copying
|
|
155
|
-
|
|
159
|
+
if (likely(!m_enableKeyExpire)) {
|
|
160
|
+
return setDataForKey(MMBuffer(tmpData, MMBufferNoCopy), key, true);
|
|
161
|
+
} else {
|
|
162
|
+
MMBuffer data(tmpData, MMBufferNoCopy);
|
|
163
|
+
if (data.length() > 0) {
|
|
164
|
+
auto tmp = MMBuffer(pbMMBufferSize(data) + Fixed32Size);
|
|
165
|
+
CodedOutputData output(tmp.getPtr(), tmp.length());
|
|
166
|
+
output.writeData(data);
|
|
167
|
+
auto time = (expireDuration != 0) ? getCurrentTimeInSecond() + expireDuration : 0;
|
|
168
|
+
output.writeRawLittleEndian32(UInt32ToInt32(time));
|
|
169
|
+
data = std::move(tmp);
|
|
170
|
+
}
|
|
171
|
+
return setDataForKey(std::move(data), key);
|
|
172
|
+
}
|
|
156
173
|
} else if ([obj isKindOfClass:NSDate.class]) {
|
|
157
174
|
NSDate *oDate = (NSDate *) obj;
|
|
158
175
|
double time = oDate.timeIntervalSince1970;
|
|
159
|
-
return set(time, key);
|
|
176
|
+
return set(time, key, expireDuration);
|
|
160
177
|
} else {
|
|
161
178
|
/*if ([object conformsToProtocol:@protocol(NSCoding)])*/ {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
179
|
+
@try {
|
|
180
|
+
NSError *error = nil;
|
|
181
|
+
auto archived = [NSKeyedArchiver archivedDataWithRootObject:obj requiringSecureCoding:NO error:&error];
|
|
182
|
+
if (error) {
|
|
183
|
+
MMKVError("fail to archive: %@", error);
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
if (archived.length > 0) {
|
|
187
|
+
if (likely(!m_enableKeyExpire)) {
|
|
188
|
+
return setDataForKey(MMBuffer(archived, MMBufferNoCopy), key);
|
|
189
|
+
} else {
|
|
190
|
+
MMBuffer data(archived, MMBufferNoCopy);
|
|
191
|
+
if (data.length() > 0) {
|
|
192
|
+
auto tmp = MMBuffer(pbMMBufferSize(data) + Fixed32Size);
|
|
193
|
+
CodedOutputData output(tmp.getPtr(), tmp.length());
|
|
194
|
+
output.writeData(data);
|
|
195
|
+
auto time = (expireDuration != 0) ? getCurrentTimeInSecond() + expireDuration : 0;
|
|
196
|
+
output.writeRawLittleEndian32(UInt32ToInt32(time));
|
|
197
|
+
data = std::move(tmp);
|
|
198
|
+
}
|
|
199
|
+
return setDataForKey(std::move(data), key);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
} @catch (NSException *exception) {
|
|
203
|
+
MMKVError("exception: %@", exception.reason);
|
|
165
204
|
}
|
|
166
205
|
}
|
|
167
206
|
}
|
|
168
207
|
return false;
|
|
169
208
|
}
|
|
170
209
|
|
|
210
|
+
static id unSecureUnArchiveObjectWithData(NSData *data) {
|
|
211
|
+
@try {
|
|
212
|
+
NSError *error = nil;
|
|
213
|
+
auto unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:&error];
|
|
214
|
+
if (error) {
|
|
215
|
+
MMKVError("fail to init unarchiver %@", error);
|
|
216
|
+
return nil;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
unarchiver.requiresSecureCoding = NO;
|
|
220
|
+
id result = [unarchiver decodeObjectForKey:NSKeyedArchiveRootObjectKey];
|
|
221
|
+
[unarchiver release];
|
|
222
|
+
return result;
|
|
223
|
+
} @catch (NSException *exception) {
|
|
224
|
+
MMKVError("exception: %@", exception.reason);
|
|
225
|
+
}
|
|
226
|
+
return nil;
|
|
227
|
+
}
|
|
228
|
+
|
|
171
229
|
NSObject *MMKV::getObject(MMKVKey_t key, Class cls) {
|
|
172
230
|
if (isKeyEmpty(key) || !cls) {
|
|
173
231
|
return nil;
|
|
@@ -186,12 +244,7 @@ NSObject *MMKV::getObject(MMKVKey_t key, Class cls) {
|
|
|
186
244
|
} else {
|
|
187
245
|
if ([cls conformsToProtocol:@protocol(NSCoding)]) {
|
|
188
246
|
auto tmp = [NSData dataWithBytesNoCopy:data.getPtr() length:data.length() freeWhenDone:NO];
|
|
189
|
-
|
|
190
|
-
id result = [NSKeyedUnarchiver unarchiveObjectWithData:tmp];
|
|
191
|
-
return result;
|
|
192
|
-
} @catch (NSException *exception) {
|
|
193
|
-
MMKVError("%s", exception.reason);
|
|
194
|
-
}
|
|
247
|
+
return unSecureUnArchiveObjectWithData(tmp);
|
|
195
248
|
}
|
|
196
249
|
}
|
|
197
250
|
}
|
|
@@ -200,8 +253,6 @@ NSObject *MMKV::getObject(MMKVKey_t key, Class cls) {
|
|
|
200
253
|
|
|
201
254
|
# ifndef MMKV_DISABLE_CRYPT
|
|
202
255
|
|
|
203
|
-
constexpr uint32_t Fixed32Size = pbFixed32Size();
|
|
204
|
-
|
|
205
256
|
pair<bool, KeyValueHolder>
|
|
206
257
|
MMKV::appendDataWithKey(const MMBuffer &data, MMKVKey_t key, const KeyValueHolderCrypt &kvHolder, bool isDataHolder) {
|
|
207
258
|
if (kvHolder.type != KeyValueHolderType_Offset) {
|
|
@@ -70,20 +70,20 @@ bool File::open() {
|
|
|
70
70
|
m_fd = CreateFile(m_path.c_str(), pair.first, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
|
71
71
|
pair.second, FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
72
72
|
if (!isFileValid()) {
|
|
73
|
-
MMKVError("fail to open:[%
|
|
73
|
+
MMKVError("fail to open:[%ls], %d", m_path.c_str(), GetLastError());
|
|
74
74
|
return false;
|
|
75
75
|
}
|
|
76
|
-
MMKVInfo("open fd[%p], %
|
|
76
|
+
MMKVInfo("open fd[%p], %ls", m_fd, m_path.c_str());
|
|
77
77
|
return true;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
void File::close() {
|
|
81
81
|
if (isFileValid()) {
|
|
82
|
-
MMKVInfo("closing fd[%p], %
|
|
82
|
+
MMKVInfo("closing fd[%p], %ls", m_fd, m_path.c_str());
|
|
83
83
|
if (CloseHandle(m_fd)) {
|
|
84
84
|
m_fd = INVALID_HANDLE_VALUE;
|
|
85
85
|
} else {
|
|
86
|
-
MMKVError("fail to close [%
|
|
86
|
+
MMKVError("fail to close [%ls], %d", m_path.c_str(), GetLastError());
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -117,29 +117,32 @@ bool MemoryFile::truncate(size_t size) {
|
|
|
117
117
|
m_size = ((m_size / DEFAULT_MMAP_SIZE) + 1) * DEFAULT_MMAP_SIZE;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
if (m_ptr) {
|
|
121
|
+
if (!UnmapViewOfFile(m_ptr)) {
|
|
122
|
+
MMKVError("fail to munmap [%ls], %d", m_diskFile.m_path.c_str(), GetLastError());
|
|
123
|
+
}
|
|
124
|
+
m_ptr = nullptr;
|
|
125
|
+
}
|
|
126
|
+
if (m_fileMapping) {
|
|
127
|
+
CloseHandle(m_fileMapping);
|
|
128
|
+
m_fileMapping = nullptr;
|
|
129
|
+
}
|
|
130
|
+
|
|
120
131
|
if (!ftruncate(m_diskFile.getFd(), m_size)) {
|
|
121
|
-
MMKVError("fail to truncate [%
|
|
132
|
+
MMKVError("fail to truncate [%ls] to size %zu", m_diskFile.m_path.c_str(), m_size);
|
|
122
133
|
m_size = oldSize;
|
|
134
|
+
mmap();
|
|
123
135
|
return false;
|
|
124
136
|
}
|
|
125
137
|
if (m_size > oldSize) {
|
|
126
138
|
if (!zeroFillFile(m_diskFile.getFd(), oldSize, m_size - oldSize)) {
|
|
127
|
-
MMKVError("fail to zeroFile [%
|
|
139
|
+
MMKVError("fail to zeroFile [%ls] to size %zu", m_diskFile.m_path.c_str(), m_size);
|
|
128
140
|
m_size = oldSize;
|
|
141
|
+
mmap();
|
|
129
142
|
return false;
|
|
130
143
|
}
|
|
131
144
|
}
|
|
132
145
|
|
|
133
|
-
if (m_ptr) {
|
|
134
|
-
if (!UnmapViewOfFile(m_ptr)) {
|
|
135
|
-
MMKVError("fail to munmap [%ws], %d", m_diskFile.m_path.c_str(), GetLastError());
|
|
136
|
-
}
|
|
137
|
-
m_ptr = nullptr;
|
|
138
|
-
}
|
|
139
|
-
if (m_fileMapping) {
|
|
140
|
-
CloseHandle(m_fileMapping);
|
|
141
|
-
m_fileMapping = nullptr;
|
|
142
|
-
}
|
|
143
146
|
auto ret = mmap();
|
|
144
147
|
if (!ret) {
|
|
145
148
|
doCleanMemoryCache(true);
|
|
@@ -152,13 +155,13 @@ bool MemoryFile::msync(SyncFlag syncFlag) {
|
|
|
152
155
|
if (FlushViewOfFile(m_ptr, m_size)) {
|
|
153
156
|
if (syncFlag == MMKV_SYNC) {
|
|
154
157
|
if (!FlushFileBuffers(m_diskFile.getFd())) {
|
|
155
|
-
MMKVError("fail to FlushFileBuffers [%
|
|
158
|
+
MMKVError("fail to FlushFileBuffers [%ls]:%d", m_diskFile.m_path.c_str(), GetLastError());
|
|
156
159
|
return false;
|
|
157
160
|
}
|
|
158
161
|
}
|
|
159
162
|
return true;
|
|
160
163
|
}
|
|
161
|
-
MMKVError("fail to FlushViewOfFile [%
|
|
164
|
+
MMKVError("fail to FlushViewOfFile [%ls]:%d", m_diskFile.m_path.c_str(), GetLastError());
|
|
162
165
|
return false;
|
|
163
166
|
}
|
|
164
167
|
return false;
|
|
@@ -167,12 +170,12 @@ bool MemoryFile::msync(SyncFlag syncFlag) {
|
|
|
167
170
|
bool MemoryFile::mmap() {
|
|
168
171
|
m_fileMapping = CreateFileMapping(m_diskFile.getFd(), nullptr, PAGE_READWRITE, 0, 0, nullptr);
|
|
169
172
|
if (!m_fileMapping) {
|
|
170
|
-
MMKVError("fail to CreateFileMapping [%
|
|
173
|
+
MMKVError("fail to CreateFileMapping [%ls], %d", m_diskFile.m_path.c_str(), GetLastError());
|
|
171
174
|
return false;
|
|
172
175
|
} else {
|
|
173
176
|
m_ptr = (char *) MapViewOfFile(m_fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
|
174
177
|
if (!m_ptr) {
|
|
175
|
-
MMKVError("fail to mmap [%
|
|
178
|
+
MMKVError("fail to mmap [%ls], %d", m_diskFile.m_path.c_str(), GetLastError());
|
|
176
179
|
return false;
|
|
177
180
|
}
|
|
178
181
|
}
|
|
@@ -182,7 +185,7 @@ bool MemoryFile::mmap() {
|
|
|
182
185
|
|
|
183
186
|
void MemoryFile::reloadFromFile() {
|
|
184
187
|
if (isFileValid()) {
|
|
185
|
-
MMKVWarning("calling reloadFromFile while the cache [%
|
|
188
|
+
MMKVWarning("calling reloadFromFile while the cache [%ls] is still valid", m_diskFile.m_path.c_str());
|
|
186
189
|
assert(0);
|
|
187
190
|
clearMemoryCache();
|
|
188
191
|
}
|
|
@@ -248,12 +251,12 @@ bool mkPath(const MMKVPath_t &str) {
|
|
|
248
251
|
auto attribute = GetFileAttributes(path);
|
|
249
252
|
if (attribute == INVALID_FILE_ATTRIBUTES) {
|
|
250
253
|
if (!CreateDirectory(path, nullptr)) {
|
|
251
|
-
MMKVError("fail to create dir:%
|
|
254
|
+
MMKVError("fail to create dir:%ls, %d", str.c_str(), GetLastError());
|
|
252
255
|
free(path);
|
|
253
256
|
return false;
|
|
254
257
|
}
|
|
255
258
|
} else if (!(attribute & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
256
|
-
MMKVError("%
|
|
259
|
+
MMKVError("%ls attribute:%d not a directry", str.c_str(), attribute);
|
|
257
260
|
free(path);
|
|
258
261
|
return false;
|
|
259
262
|
}
|
|
@@ -279,14 +282,14 @@ MMBuffer *readWholeFile(const MMKVPath_t &nsFilePath) {
|
|
|
279
282
|
if (ReadFile(fd, buffer->getPtr(), fileLength, &readSize, nullptr)) {
|
|
280
283
|
//fileSize = readSize;
|
|
281
284
|
} else {
|
|
282
|
-
MMKVWarning("fail to read %
|
|
285
|
+
MMKVWarning("fail to read %ls: %d", nsFilePath.c_str(), GetLastError());
|
|
283
286
|
delete buffer;
|
|
284
287
|
buffer = nullptr;
|
|
285
288
|
}
|
|
286
289
|
}
|
|
287
290
|
CloseHandle(fd);
|
|
288
291
|
} else {
|
|
289
|
-
MMKVWarning("fail to open %
|
|
292
|
+
MMKVWarning("fail to open %ls: %d", nsFilePath.c_str(), GetLastError());
|
|
290
293
|
}
|
|
291
294
|
return buffer;
|
|
292
295
|
}
|
|
@@ -363,18 +366,19 @@ static pair<MMKVPath_t, MMKVFileHandle_t> createUniqueTempFile(const wchar_t *pr
|
|
|
363
366
|
MMKVError("GetTempFileName failed %d", GetLastError());
|
|
364
367
|
return {L"", INVALID_HANDLE_VALUE};
|
|
365
368
|
}
|
|
366
|
-
auto hTempFile =
|
|
369
|
+
auto hTempFile =
|
|
370
|
+
CreateFile(szTempFileName, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
367
371
|
if (hTempFile == INVALID_HANDLE_VALUE) {
|
|
368
|
-
MMKVError("fail to create unique temp file [%
|
|
372
|
+
MMKVError("fail to create unique temp file [%ls], %d", szTempFileName, GetLastError());
|
|
369
373
|
return {L"", INVALID_HANDLE_VALUE};
|
|
370
374
|
}
|
|
371
|
-
MMKVDebug("create unique temp file [%
|
|
375
|
+
MMKVDebug("create unique temp file [%ls] with fd[%p]", szTempFileName, hTempFile);
|
|
372
376
|
return {MMKVPath_t(szTempFileName), hTempFile};
|
|
373
377
|
}
|
|
374
378
|
|
|
375
379
|
bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
|
|
376
380
|
if (MoveFileEx(srcPath.c_str(), dstPath.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) == 0) {
|
|
377
|
-
MMKVError("MoveFileEx [%
|
|
381
|
+
MMKVError("MoveFileEx [%ls] to [%ls] failed %d", srcPath.c_str(), dstPath.c_str(), GetLastError());
|
|
378
382
|
return false;
|
|
379
383
|
}
|
|
380
384
|
return true;
|
|
@@ -401,7 +405,7 @@ bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD, bool nee
|
|
|
401
405
|
while (true) {
|
|
402
406
|
DWORD sizeRead = 0;
|
|
403
407
|
if (!ReadFile(srcFile.getFd(), buffer, bufferSize, &sizeRead, nullptr)) {
|
|
404
|
-
MMKVError("fail to read %
|
|
408
|
+
MMKVError("fail to read %ls: %d", srcPath.c_str(), GetLastError());
|
|
405
409
|
goto errorOut;
|
|
406
410
|
}
|
|
407
411
|
|
|
@@ -426,7 +430,7 @@ bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD, bool nee
|
|
|
426
430
|
}
|
|
427
431
|
|
|
428
432
|
ret = true;
|
|
429
|
-
MMKVInfo("copy content from %
|
|
433
|
+
MMKVInfo("copy content from %ls to fd[%d] finish", srcPath.c_str(), dstFD);
|
|
430
434
|
|
|
431
435
|
errorOut:
|
|
432
436
|
free(buffer);
|
|
@@ -445,11 +449,11 @@ bool copyFile(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
|
|
|
445
449
|
|
|
446
450
|
bool renamed = false;
|
|
447
451
|
if (copyFileContent(srcPath, tmpFD, false)) {
|
|
448
|
-
MMKVInfo("copyed file [%
|
|
452
|
+
MMKVInfo("copyed file [%ls] to [%ls]", srcPath.c_str(), tmpPath.c_str());
|
|
449
453
|
CloseHandle(tmpFD);
|
|
450
454
|
renamed = tryAtomicRename(tmpPath.c_str(), dstPath.c_str());
|
|
451
455
|
if (renamed) {
|
|
452
|
-
MMKVInfo("copyfile [%
|
|
456
|
+
MMKVInfo("copyfile [%ls] to [%ls] finish.", srcPath.c_str(), dstPath.c_str());
|
|
453
457
|
}
|
|
454
458
|
} else {
|
|
455
459
|
CloseHandle(tmpFD);
|
|
@@ -468,9 +472,9 @@ bool copyFileContent(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
|
|
|
468
472
|
}
|
|
469
473
|
auto ret = copyFileContent(srcPath, dstFile.getFd(), false);
|
|
470
474
|
if (!ret) {
|
|
471
|
-
MMKVError("fail to copyfile(): target file %
|
|
475
|
+
MMKVError("fail to copyfile(): target file %ls", dstPath.c_str());
|
|
472
476
|
} else {
|
|
473
|
-
MMKVInfo("copy content from %
|
|
477
|
+
MMKVInfo("copy content from %ls to [%ls] finish", srcPath.c_str(), dstPath.c_str());
|
|
474
478
|
}
|
|
475
479
|
return ret;
|
|
476
480
|
}
|
|
@@ -127,8 +127,6 @@ size_t MiniPBCoder::prepareObjectForEncode(const MMBuffer &buffer) {
|
|
|
127
127
|
return index;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
#ifndef MMKV_DISABLE_CRYPT
|
|
131
|
-
|
|
132
130
|
size_t MiniPBCoder::prepareObjectForEncode(const MMKVVector &vec) {
|
|
133
131
|
m_encodeItems->push_back(PBEncodeItem());
|
|
134
132
|
PBEncodeItem *encodeItem = &(m_encodeItems->back());
|
|
@@ -167,8 +165,6 @@ size_t MiniPBCoder::prepareObjectForEncode(const MMKVVector &vec) {
|
|
|
167
165
|
return index;
|
|
168
166
|
}
|
|
169
167
|
|
|
170
|
-
#endif // MMKV_DISABLE_CRYPT
|
|
171
|
-
|
|
172
168
|
MMBuffer MiniPBCoder::writePreparedItems(size_t index) {
|
|
173
169
|
PBEncodeItem *oItem = (index < m_encodeItems->size()) ? &(*m_encodeItems)[index] : nullptr;
|
|
174
170
|
if (oItem && oItem->compiledSize > 0) {
|
|
@@ -240,7 +236,7 @@ vector<string> MiniPBCoder::decodeOneVector() {
|
|
|
240
236
|
|
|
241
237
|
while (!m_inputData->isAtEnd()) {
|
|
242
238
|
auto value = m_inputData->readString();
|
|
243
|
-
v.push_back(move(value));
|
|
239
|
+
v.push_back(std::move(value));
|
|
244
240
|
}
|
|
245
241
|
|
|
246
242
|
return v;
|
|
@@ -259,7 +255,7 @@ void MiniPBCoder::decodeOneMap(MMKVMap &dic, size_t position, bool greedy) {
|
|
|
259
255
|
if (key.length() > 0) {
|
|
260
256
|
m_inputData->readData(kvHolder);
|
|
261
257
|
if (kvHolder.valueSize > 0) {
|
|
262
|
-
dictionary[key] = move(kvHolder);
|
|
258
|
+
dictionary[key] = std::move(kvHolder);
|
|
263
259
|
} else {
|
|
264
260
|
auto itr = dictionary.find(key);
|
|
265
261
|
if (itr != dictionary.end()) {
|
|
@@ -302,7 +298,7 @@ void MiniPBCoder::decodeOneMap(MMKVMapCrypt &dic, size_t position, bool greedy)
|
|
|
302
298
|
if (key.length() > 0) {
|
|
303
299
|
m_inputDataDecrpt->readData(kvHolder);
|
|
304
300
|
if (kvHolder.realValueSize() > 0) {
|
|
305
|
-
dictionary[key] = move(kvHolder);
|
|
301
|
+
dictionary[key] = std::move(kvHolder);
|
|
306
302
|
} else {
|
|
307
303
|
auto itr = dictionary.find(key);
|
|
308
304
|
if (itr != dictionary.end()) {
|
|
@@ -90,7 +90,7 @@ void MiniPBCoder::decodeOneMap(MMKVMap &dic, size_t position, bool greedy) {
|
|
|
90
90
|
auto itr = dictionary.find(key);
|
|
91
91
|
if (itr != dictionary.end()) {
|
|
92
92
|
if (kvHolder.valueSize > 0) {
|
|
93
|
-
itr->second = move(kvHolder);
|
|
93
|
+
itr->second = std::move(kvHolder);
|
|
94
94
|
} else {
|
|
95
95
|
auto oldKey = itr->first;
|
|
96
96
|
dictionary.erase(itr);
|
|
@@ -98,7 +98,7 @@ void MiniPBCoder::decodeOneMap(MMKVMap &dic, size_t position, bool greedy) {
|
|
|
98
98
|
}
|
|
99
99
|
} else {
|
|
100
100
|
if (kvHolder.valueSize > 0) {
|
|
101
|
-
dictionary.emplace(key, move(kvHolder));
|
|
101
|
+
dictionary.emplace(key, std::move(kvHolder));
|
|
102
102
|
[key retain];
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -143,7 +143,7 @@ void MiniPBCoder::decodeOneMap(MMKVMapCrypt &dic, size_t position, bool greedy)
|
|
|
143
143
|
auto itr = dictionary.find(key);
|
|
144
144
|
if (itr != dictionary.end()) {
|
|
145
145
|
if (kvHolder.realValueSize() > 0) {
|
|
146
|
-
itr->second = move(kvHolder);
|
|
146
|
+
itr->second = std::move(kvHolder);
|
|
147
147
|
} else {
|
|
148
148
|
auto oldKey = itr->first;
|
|
149
149
|
dictionary.erase(itr);
|
|
@@ -151,7 +151,7 @@ void MiniPBCoder::decodeOneMap(MMKVMapCrypt &dic, size_t position, bool greedy)
|
|
|
151
151
|
}
|
|
152
152
|
} else {
|
|
153
153
|
if (kvHolder.realValueSize() > 0) {
|
|
154
|
-
dictionary.emplace(key, move(kvHolder));
|
|
154
|
+
dictionary.emplace(key, std::move(kvHolder));
|
|
155
155
|
[key retain];
|
|
156
156
|
}
|
|
157
157
|
}
|
package/MMKV/Core/PBUtility.cpp
CHANGED
package/MMKV/Core/PBUtility.h
CHANGED
|
@@ -147,6 +147,13 @@ static inline uint32_t pbUInt32Size(uint32_t value) {
|
|
|
147
147
|
return pbRawVarint32Size(value);
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
static inline uint32_t pbMMBufferSize(const MMBuffer &data) {
|
|
151
|
+
auto valueLength = static_cast<uint32_t>(data.length());
|
|
152
|
+
return valueLength + pbUInt32Size(valueLength);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
constexpr uint32_t Fixed32Size = pbFixed32Size();
|
|
156
|
+
|
|
150
157
|
} // namespace mmkv
|
|
151
158
|
|
|
152
159
|
#endif
|
package/MMKV/Core/aes/AESCrypt.h
CHANGED
|
@@ -161,6 +161,7 @@ AES_Te:
|
|
|
161
161
|
|
|
162
162
|
/* void openssl_aes_arm_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
|
|
163
163
|
*/
|
|
164
|
+
.type openssl_aes_arm_encrypt, %function
|
|
164
165
|
#ifndef __linux__
|
|
165
166
|
.globl _openssl_aes_arm_encrypt
|
|
166
167
|
#ifdef __thumb2__
|
|
@@ -422,6 +423,7 @@ Lenc_loop:
|
|
|
422
423
|
ldr pc,[sp],#4 // pop and return
|
|
423
424
|
|
|
424
425
|
|
|
426
|
+
.type openssl_aes_arm_set_encrypt_key, %function
|
|
425
427
|
#ifndef __linux__
|
|
426
428
|
.globl _openssl_aes_arm_set_encrypt_key
|
|
427
429
|
#ifdef __thumb2__
|
|
@@ -735,6 +737,7 @@ Labrt:
|
|
|
735
737
|
.word 0xe12fff1e // interoperable with Thumb ISA:-)
|
|
736
738
|
#endif
|
|
737
739
|
|
|
740
|
+
.type openssl_aes_arm_set_decrypt_key, %function
|
|
738
741
|
#ifndef __linux__
|
|
739
742
|
.globl _openssl_aes_arm_set_decrypt_key
|
|
740
743
|
#ifdef __thumb2__
|
|
@@ -954,6 +957,7 @@ AES_Td:
|
|
|
954
957
|
.byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
|
|
955
958
|
|
|
956
959
|
|
|
960
|
+
.type openssl_aes_arm_decrypt, %function
|
|
957
961
|
// void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
|
|
958
962
|
#ifndef __linux__
|
|
959
963
|
.globl _openssl_aes_arm_decrypt
|
package/README.md
CHANGED
|
@@ -76,8 +76,8 @@ cd ios && pod install
|
|
|
76
76
|
### Expo
|
|
77
77
|
|
|
78
78
|
```sh
|
|
79
|
-
expo install react-native-mmkv
|
|
80
|
-
expo prebuild
|
|
79
|
+
npx expo install react-native-mmkv
|
|
80
|
+
npx expo prebuild
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
## Usage
|
|
@@ -192,6 +192,7 @@ A mocked MMKV instance is automatically used when testing with Jest, so you will
|
|
|
192
192
|
* [Value-change Listeners](./docs/LISTENERS.md)
|
|
193
193
|
* [Migrate from AsyncStorage](./docs/MIGRATE_FROM_ASYNC_STORAGE.md)
|
|
194
194
|
* [Using MMKV with redux-persist](./docs/WRAPPER_REDUX.md)
|
|
195
|
+
* [Using MMKV with recoil](./docs/WRAPPER_RECOIL.md)
|
|
195
196
|
* [Using MMKV with mobx-persist-storage](./docs/WRAPPER_MOBX.md)
|
|
196
197
|
* [Using MMKV with mobx-persist](./docs/WRAPPER_MOBXPERSIST.md)
|
|
197
198
|
* [Using MMKV with zustand persist-middleware](./docs/WRAPPER_ZUSTAND_PERSIST_MIDDLEWARE.md)
|
|
@@ -199,14 +200,22 @@ A mocked MMKV instance is automatically used when testing with Jest, so you will
|
|
|
199
200
|
* [Using MMKV with react-query](./docs/WRAPPER_REACT_QUERY.md)
|
|
200
201
|
* [How is this library different from **react-native-mmkv-storage**?](https://github.com/mrousavy/react-native-mmkv/issues/100#issuecomment-886477361)
|
|
201
202
|
|
|
203
|
+
## LocalStorage and In-Memory Storage (Web)
|
|
204
|
+
|
|
205
|
+
If a user chooses to disable LocalStorage in their browser, the library will automatically provide a limited in-memory storage as an alternative. However, this in-memory storage won't persist data, and users may experience data loss if they refresh the page or close their browser. To optimize user experience, consider implementing a suitable solution within your app to address this scenario.
|
|
206
|
+
|
|
202
207
|
## Limitations
|
|
203
208
|
|
|
204
209
|
As the library uses JSI for synchronous native methods access, remote debugging (e.g. with Chrome) is no longer possible. Instead, you should use [Flipper](https://fbflipper.com).
|
|
205
210
|
|
|
206
|
-
|
|
211
|
+
### Flipper
|
|
207
212
|
|
|
208
213
|
Use [flipper-plugin-react-native-mmkv](https://github.com/muchobien/flipper-plugin-react-native-mmkv) to debug your MMKV storage using Flipper. You can also simply `console.log` an MMKV instance.
|
|
209
214
|
|
|
215
|
+
### Reactotron
|
|
216
|
+
|
|
217
|
+
Use [reactotron-react-native-mmkv](https://www.npmjs.com/package/reactotron-react-native-mmkv) to automatically log writes to your MMKV storage using Reactotron. [See the docs for how to setup this plugin with Reactotron.](https://www.npmjs.com/package/reactotron-react-native-mmkv)
|
|
218
|
+
|
|
210
219
|
## Adopting at scale
|
|
211
220
|
|
|
212
221
|
react-native-mmkv is provided _as is_, I work on it in my free time.
|
package/android/build.gradle
CHANGED
|
@@ -7,7 +7,17 @@ exports.createMMKV = void 0;
|
|
|
7
7
|
var _createTextEncoder = require("./createTextEncoder");
|
|
8
8
|
var _window$document;
|
|
9
9
|
const canUseDOM = typeof window !== 'undefined' && ((_window$document = window.document) === null || _window$document === void 0 ? void 0 : _window$document.createElement) != null;
|
|
10
|
+
const hasAccessToLocalStorage = () => {
|
|
11
|
+
try {
|
|
12
|
+
// throws ACCESS_DENIED error
|
|
13
|
+
window.localStorage;
|
|
14
|
+
return true;
|
|
15
|
+
} catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
10
19
|
const KEY_WILDCARD = '\\';
|
|
20
|
+
const inMemoryStorage = new Map();
|
|
11
21
|
const createMMKV = config => {
|
|
12
22
|
if (config.encryptionKey != null) {
|
|
13
23
|
throw new Error("MMKV: 'encryptionKey' is not supported on Web!");
|
|
@@ -15,11 +25,24 @@ const createMMKV = config => {
|
|
|
15
25
|
if (config.path != null) {
|
|
16
26
|
throw new Error("MMKV: 'path' is not supported on Web!");
|
|
17
27
|
}
|
|
28
|
+
if (!hasAccessToLocalStorage()) {
|
|
29
|
+
console.warn('MMKV: LocalStorage has been disabled. Your experience will be limited to in-memory storage!');
|
|
30
|
+
}
|
|
18
31
|
const storage = () => {
|
|
19
32
|
var _global, _window;
|
|
20
33
|
if (!canUseDOM) {
|
|
21
34
|
throw new Error('Tried to access storage on the server. Did you forget to call this in useEffect?');
|
|
22
35
|
}
|
|
36
|
+
if (!hasAccessToLocalStorage()) {
|
|
37
|
+
return {
|
|
38
|
+
getItem: key => inMemoryStorage.get(key) ?? null,
|
|
39
|
+
setItem: (key, value) => inMemoryStorage.set(key, value),
|
|
40
|
+
removeItem: key => inMemoryStorage.delete(key),
|
|
41
|
+
clear: () => inMemoryStorage.clear(),
|
|
42
|
+
length: inMemoryStorage.size,
|
|
43
|
+
key: index => Object.keys(inMemoryStorage).at(index) ?? null
|
|
44
|
+
};
|
|
45
|
+
}
|
|
23
46
|
const domStorage = ((_global = global) === null || _global === void 0 ? void 0 : _global.localStorage) ?? ((_window = window) === null || _window === void 0 ? void 0 : _window.localStorage) ?? localStorage;
|
|
24
47
|
if (domStorage == null) {
|
|
25
48
|
throw new Error(`Could not find 'localStorage' instance!`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["canUseDOM","window","document","createElement","KEY_WILDCARD","createMMKV","config","encryptionKey","Error","path","storage","
|
|
1
|
+
{"version":3,"names":["canUseDOM","window","document","createElement","hasAccessToLocalStorage","localStorage","KEY_WILDCARD","inMemoryStorage","Map","createMMKV","config","encryptionKey","Error","path","console","warn","storage","getItem","key","get","setItem","value","set","removeItem","delete","clear","length","size","index","Object","keys","at","domStorage","global","textEncoder","createTextEncoder","id","includes","keyPrefix","prefixedKey","clearAll","startsWith","toString","getString","undefined","getNumber","Number","getBoolean","getBuffer","encode","getAllKeys","filter","contains","recrypt"],"sourceRoot":"../../src","sources":["createMMKV.web.ts"],"mappings":"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"}
|
|
@@ -3,7 +3,17 @@ var _window$document;
|
|
|
3
3
|
|
|
4
4
|
import { createTextEncoder } from './createTextEncoder';
|
|
5
5
|
const canUseDOM = typeof window !== 'undefined' && ((_window$document = window.document) === null || _window$document === void 0 ? void 0 : _window$document.createElement) != null;
|
|
6
|
+
const hasAccessToLocalStorage = () => {
|
|
7
|
+
try {
|
|
8
|
+
// throws ACCESS_DENIED error
|
|
9
|
+
window.localStorage;
|
|
10
|
+
return true;
|
|
11
|
+
} catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
6
15
|
const KEY_WILDCARD = '\\';
|
|
16
|
+
const inMemoryStorage = new Map();
|
|
7
17
|
export const createMMKV = config => {
|
|
8
18
|
if (config.encryptionKey != null) {
|
|
9
19
|
throw new Error("MMKV: 'encryptionKey' is not supported on Web!");
|
|
@@ -11,11 +21,24 @@ export const createMMKV = config => {
|
|
|
11
21
|
if (config.path != null) {
|
|
12
22
|
throw new Error("MMKV: 'path' is not supported on Web!");
|
|
13
23
|
}
|
|
24
|
+
if (!hasAccessToLocalStorage()) {
|
|
25
|
+
console.warn('MMKV: LocalStorage has been disabled. Your experience will be limited to in-memory storage!');
|
|
26
|
+
}
|
|
14
27
|
const storage = () => {
|
|
15
28
|
var _global, _window;
|
|
16
29
|
if (!canUseDOM) {
|
|
17
30
|
throw new Error('Tried to access storage on the server. Did you forget to call this in useEffect?');
|
|
18
31
|
}
|
|
32
|
+
if (!hasAccessToLocalStorage()) {
|
|
33
|
+
return {
|
|
34
|
+
getItem: key => inMemoryStorage.get(key) ?? null,
|
|
35
|
+
setItem: (key, value) => inMemoryStorage.set(key, value),
|
|
36
|
+
removeItem: key => inMemoryStorage.delete(key),
|
|
37
|
+
clear: () => inMemoryStorage.clear(),
|
|
38
|
+
length: inMemoryStorage.size,
|
|
39
|
+
key: index => Object.keys(inMemoryStorage).at(index) ?? null
|
|
40
|
+
};
|
|
41
|
+
}
|
|
19
42
|
const domStorage = ((_global = global) === null || _global === void 0 ? void 0 : _global.localStorage) ?? ((_window = window) === null || _window === void 0 ? void 0 : _window.localStorage) ?? localStorage;
|
|
20
43
|
if (domStorage == null) {
|
|
21
44
|
throw new Error(`Could not find 'localStorage' instance!`);
|