react-native-mmkv 2.7.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.
Files changed (53) hide show
  1. package/MMKV/Core/Core.xcodeproj/project.pbxproj +15 -19
  2. package/MMKV/Core/Core.xcodeproj/xcshareddata/xcschemes/Core.xcscheme +1 -1
  3. package/MMKV/Core/Core.xcodeproj/xcshareddata/xcschemes/MMKVWatchCore.xcscheme +1 -1
  4. package/MMKV/Core/MMBuffer.cpp +18 -0
  5. package/MMKV/Core/MMBuffer.h +1 -0
  6. package/MMKV/Core/MMKV.cpp +173 -33
  7. package/MMKV/Core/MMKV.h +44 -0
  8. package/MMKV/Core/MMKVMetaInfo.hpp +18 -0
  9. package/MMKV/Core/MMKVPredef.h +2 -2
  10. package/MMKV/Core/MMKV_IO.cpp +477 -68
  11. package/MMKV/Core/MMKV_OSX.cpp +65 -14
  12. package/MMKV/Core/MemoryFile_Win32.cpp +39 -35
  13. package/MMKV/Core/MiniPBCoder.cpp +3 -7
  14. package/MMKV/Core/MiniPBCoder_OSX.cpp +4 -4
  15. package/MMKV/Core/PBUtility.cpp +1 -1
  16. package/MMKV/Core/PBUtility.h +7 -0
  17. package/MMKV/Core/aes/AESCrypt.h +1 -1
  18. package/MMKV/Core/aes/openssl/openssl_aes-armv4.S +4 -0
  19. package/README.md +14 -6
  20. package/android/build.gradle +2 -0
  21. package/android/src/main/AndroidManifest.xml +1 -2
  22. package/android/src/main/cpp/cpp-adapter.cpp +5 -0
  23. package/cpp/TypedArray.cpp +187 -199
  24. package/cpp/TypedArray.h +112 -109
  25. package/ios/JSIUtils.mm +2 -1
  26. package/ios/MmkvModule.mm +12 -7
  27. package/lib/commonjs/MMKV.js +0 -10
  28. package/lib/commonjs/MMKV.js.map +1 -1
  29. package/lib/commonjs/createMMKV.web.js +55 -12
  30. package/lib/commonjs/createMMKV.web.js.map +1 -1
  31. package/lib/commonjs/hooks.js +7 -0
  32. package/lib/commonjs/hooks.js.map +1 -1
  33. package/lib/module/MMKV.js +0 -10
  34. package/lib/module/MMKV.js.map +1 -1
  35. package/lib/module/createMMKV.web.js +55 -12
  36. package/lib/module/createMMKV.web.js.map +1 -1
  37. package/lib/module/hooks.js +7 -0
  38. package/lib/module/hooks.js.map +1 -1
  39. package/lib/typescript/MMKV.d.ts +0 -12
  40. package/lib/typescript/MMKV.d.ts.map +1 -1
  41. package/lib/typescript/createMMKV.web.d.ts.map +1 -1
  42. package/lib/typescript/hooks.d.ts.map +1 -1
  43. package/package.json +15 -10
  44. package/src/MMKV.ts +248 -0
  45. package/src/PlatformChecker.ts +7 -0
  46. package/src/createMMKV.mock.ts +33 -0
  47. package/src/createMMKV.ts +70 -0
  48. package/src/createMMKV.web.ts +119 -0
  49. package/src/createTextEncoder.ts +16 -0
  50. package/src/hooks.ts +232 -0
  51. package/src/index.ts +2 -0
  52. package/MMKV/LICENSE.TXT +0 -193
  53. package/MMKV/README.md +0 -291
@@ -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
- return setDataForKey(MMBuffer(tmpData, MMBufferNoCopy), key, true);
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
- auto tmp = [NSKeyedArchiver archivedDataWithRootObject:obj];
163
- if (tmp.length > 0) {
164
- return setDataForKey(MMBuffer(tmp, MMBufferNoCopy), key);
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
- @try {
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:[%ws], %d", m_path.c_str(), GetLastError());
73
+ MMKVError("fail to open:[%ls], %d", m_path.c_str(), GetLastError());
74
74
  return false;
75
75
  }
76
- MMKVInfo("open fd[%p], %ws", m_fd, m_path.c_str());
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], %ws", m_fd, m_path.c_str());
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 [%ws], %d", m_path.c_str(), GetLastError());
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 [%ws] to size %zu", m_diskFile.m_path.c_str(), m_size);
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 [%ws] to size %zu", m_diskFile.m_path.c_str(), m_size);
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 [%ws]:%d", m_diskFile.m_path.c_str(), GetLastError());
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 [%ws]:%d", m_diskFile.m_path.c_str(), GetLastError());
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 [%ws], %d", m_diskFile.m_path.c_str(), GetLastError());
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 [%ws], %d", m_diskFile.m_path.c_str(), GetLastError());
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 [%ws] is still valid", m_diskFile.m_path.c_str());
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:%ws, %d", str.c_str(), GetLastError());
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("%ws attribute:%d not a directry", str.c_str(), attribute);
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 %ws: %d", nsFilePath.c_str(), GetLastError());
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 %ws: %d", nsFilePath.c_str(), GetLastError());
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 = CreateFile(szTempFileName, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
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 [%ws], %d", szTempFileName, GetLastError());
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 [%ws] with fd[%p]", szTempFileName, hTempFile);
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 [%ws] to [%ws] failed %d", srcPath.c_str(), dstPath.c_str(), GetLastError());
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 %ws: %d", srcPath.c_str(), GetLastError());
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 %ws to fd[%d] finish", srcPath.c_str(), dstFD);
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 [%ws] to [%ws]", srcPath.c_str(), tmpPath.c_str());
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 [%ws] to [%ws] finish.", srcPath.c_str(), dstPath.c_str());
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 %ws", dstPath.c_str());
475
+ MMKVError("fail to copyfile(): target file %ls", dstPath.c_str());
472
476
  } else {
473
- MMKVInfo("copy content from %ws to [%ws] finish", srcPath.c_str(), dstPath.c_str());
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
  }
@@ -17,7 +17,7 @@
17
17
  * See the License for the specific language governing permissions and
18
18
  * limitations under the License.
19
19
  */
20
-
20
+ #include "MMBuffer.h"
21
21
  #include "PBUtility.h"
22
22
 
23
23
  namespace mmkv {
@@ -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
@@ -22,7 +22,7 @@
22
22
  #define AES_CRYPT_H_
23
23
  #ifdef __cplusplus
24
24
 
25
- #include "MMKVPredef.h"
25
+ #include "../MMKVPredef.h"
26
26
  #include <cstddef>
27
27
 
28
28
  #ifdef MMKV_DISABLE_CRYPT
@@ -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
@@ -104,8 +104,7 @@ import { MMKV } from 'react-native-mmkv'
104
104
  export const storage = new MMKV({
105
105
  id: `user-${userId}-storage`,
106
106
  path: `${USER_DIRECTORY}/storage`,
107
- encryptionKey: 'hunter2',
108
- fastWrites: true
107
+ encryptionKey: 'hunter2'
109
108
  })
110
109
  ```
111
110
 
@@ -116,7 +115,6 @@ The following values can be configured:
116
115
  * `id`: The MMKV instance's ID. If you want to use multiple instances, use different IDs. For example, you can separate the global app's storage and a logged-in user's storage. (required if `path` or `encryptionKey` fields are specified, otherwise defaults to: `'mmkv.default'`)
117
116
  * `path`: The MMKV instance's root path. By default, MMKV stores file inside `$(Documents)/mmkv/`. You can customize MMKV's root directory on MMKV initialization (documentation: [iOS](https://github.com/Tencent/MMKV/wiki/iOS_advance#customize-location) / [Android](https://github.com/Tencent/MMKV/wiki/android_advance#customize-location))
118
117
  * `encryptionKey`: The MMKV instance's encryption/decryption key. By default, MMKV stores all key-values in plain text on file, relying on iOS's/Android's sandbox to make sure the file is encrypted. Should you worry about information leaking, you can choose to encrypt MMKV. (documentation: [iOS](https://github.com/Tencent/MMKV/wiki/iOS_advance#encryption) / [Android](https://github.com/Tencent/MMKV/wiki/android_advance#encryption))
119
- * `fastWrites`: Configure fast writes for MMKV. When set to `true`, all calls to `set(..)` do not overwrite the previous value to avoid storage resizing, this speeds up write speed. Only enable this if you use a small MMKV storage, as this uses more RAM.
120
118
 
121
119
  ### Set
122
120
 
@@ -194,20 +192,30 @@ A mocked MMKV instance is automatically used when testing with Jest, so you will
194
192
  * [Value-change Listeners](./docs/LISTENERS.md)
195
193
  * [Migrate from AsyncStorage](./docs/MIGRATE_FROM_ASYNC_STORAGE.md)
196
194
  * [Using MMKV with redux-persist](./docs/WRAPPER_REDUX.md)
195
+ * [Using MMKV with recoil](./docs/WRAPPER_RECOIL.md)
197
196
  * [Using MMKV with mobx-persist-storage](./docs/WRAPPER_MOBX.md)
198
197
  * [Using MMKV with mobx-persist](./docs/WRAPPER_MOBXPERSIST.md)
199
198
  * [Using MMKV with zustand persist-middleware](./docs/WRAPPER_ZUSTAND_PERSIST_MIDDLEWARE.md)
200
199
  * [Using MMKV with jotai](./docs/WRAPPER_JOTAI.md)
200
+ * [Using MMKV with react-query](./docs/WRAPPER_REACT_QUERY.md)
201
201
  * [How is this library different from **react-native-mmkv-storage**?](https://github.com/mrousavy/react-native-mmkv/issues/100#issuecomment-886477361)
202
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
+
203
207
  ## Limitations
204
208
 
205
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).
206
210
 
207
- ## Debugging
211
+ ### Flipper
208
212
 
209
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.
210
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
+
211
219
  ## Adopting at scale
212
220
 
213
221
  react-native-mmkv is provided _as is_, I work on it in my free time.
@@ -46,6 +46,7 @@ repositories {
46
46
  }
47
47
 
48
48
  android {
49
+ namespace = "com.reactnativemmkv"
49
50
  compileSdkVersion safeExtGet("compileSdkVersion", 28)
50
51
 
51
52
  // Used to override the NDK path/version on internal CI or by allowing
@@ -92,6 +93,7 @@ android {
92
93
  "META-INF",
93
94
  "META-INF/**",
94
95
  "**/libjsi.so",
96
+ "**/libc++_shared.so"
95
97
  ]
96
98
  }
97
99
  }
@@ -1,4 +1,3 @@
1
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
- package="com.reactnativemmkv">
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
2
 
4
3
  </manifest>
@@ -2,6 +2,7 @@
2
2
  #include <jsi/jsi.h>
3
3
  #include <MMKV.h>
4
4
  #include "MmkvHostObject.h"
5
+ #include "TypedArray.h"
5
6
 
6
7
  using namespace facebook;
7
8
 
@@ -32,6 +33,10 @@ void install(jsi::Runtime& jsiRuntime) {
32
33
  return jsi::Object::createFromHostObject(runtime, instance);
33
34
  });
34
35
  jsiRuntime.global().setProperty(jsiRuntime, "mmkvCreateNewInstance", std::move(mmkvCreateNewInstance));
36
+
37
+ // Adds the PropNameIDCache object to the Runtime. If the Runtime gets destroyed, the Object gets destroyed and the cache gets invalidated.
38
+ auto propNameIdCache = std::make_shared<InvalidateCacheOnDestroy>(jsiRuntime);
39
+ jsiRuntime.global().setProperty(jsiRuntime, "mmkvArrayBufferPropNameIdCache", jsi::Object::createFromHostObject(jsiRuntime, propNameIdCache));
35
40
  }
36
41
 
37
42
  std::string jstringToStdString(JNIEnv *env, jstring jStr) {