已关闭
fix: 升级react-native-mmkv-storage #12
fix: 升级react-native-mmkv-storage #12
已关闭
houahui创建于 1月30日关闭于 27 天前
共 20 个文件变更+395-82
@@ -8,6 +8,7 @@
8node_modules/8node_modules/
9npm-debug.log9npm-debug.log
10yarn-error.log10yarn-error.log
11+**/.xcode.env.local
11 12
12 13 
13# Xcode14# Xcode
@@ -29,6 +30,8 @@ DerivedData
29*.ipa30*.ipa
30*.xcuserstate31*.xcuserstate
31project.xcworkspace32project.xcworkspace
33+Pods
34+vendor
32 35
33 36 
34# Android/IntelliJ37# Android/IntelliJ
@@ -0,0 +1 @@
1+include/
@@ -591,7 +591,6 @@
591 SKIP_INSTALL = YES;591 SKIP_INSTALL = YES;
592 SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvsimulator appletvos xrsimulator xros";592 SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvsimulator appletvos xrsimulator xros";
593 TARGETED_DEVICE_FAMILY = "1,2,3";593 TARGETED_DEVICE_FAMILY = "1,2,3";
594- SUPPORTS_MACCATALYST = YES;
595 };594 };
596 name = Debug;595 name = Debug;
597 };596 };
@@ -618,7 +617,6 @@
618 SKIP_INSTALL = YES;617 SKIP_INSTALL = YES;
619 SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvsimulator appletvos xrsimulator xros";618 SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvsimulator appletvos xrsimulator xros";
620 TARGETED_DEVICE_FAMILY = "1,2,3";619 TARGETED_DEVICE_FAMILY = "1,2,3";
621- SUPPORTS_MACCATALYST = YES;
622 };620 };
623 name = Release;621 name = Release;
624 };622 };
@@ -337,11 +337,7 @@ void MMKV::close() {
337 SCOPED_LOCK(g_instanceLock);337 SCOPED_LOCK(g_instanceLock);
338 m_lock->lock();338 m_lock->lock();
339 339 
340-#ifndef MMKV_ANDROID
341 auto itr = g_instanceDic->find(m_mmapKey);340 auto itr = g_instanceDic->find(m_mmapKey);
342-#else
343- auto itr = g_instanceDic->find(m_mmapID);
344-#endif
345 if (itr != g_instanceDic->end()) {341 if (itr != g_instanceDic->end()) {
346 g_instanceDic->erase(itr);342 g_instanceDic->erase(itr);
347 }343 }
@@ -779,8 +775,8 @@ void MMKV::shared_lock() {
779}775}
780 776 
781void MMKV::shared_unlock() {777void MMKV::shared_unlock() {
782- m_sharedProcessLock->lock();778+ m_sharedProcessLock->unlock();
783- m_lock->lock();779+ m_lock->unlock();
784}780}
785 781 
786#endif // MMKV_APPLE782#endif // MMKV_APPLE
@@ -1290,8 +1286,14 @@ bool MMKV::backupOneToDirectory(const string &mmapID, const MMKVPath_t &dstDir,
1290 auto dstPath = dstDir + MMKV_PATH_SLASH + encodePath;1286 auto dstPath = dstDir + MMKV_PATH_SLASH + encodePath;
1291 auto mmapKey = mmapedKVKey(mmapID, rootPath);1287 auto mmapKey = mmapedKVKey(mmapID, rootPath);
1292#ifdef MMKV_ANDROID1288#ifdef MMKV_ANDROID
1293- // historically Android mistakenly use mmapKey as mmapID1289+ string srcPath;
1294- auto srcPath = *rootPath + MMKV_PATH_SLASH + encodeFilePath(mmapKey, *rootPath);1290+ auto correctPath = *rootPath + MMKV_PATH_SLASH + encodePath;
1291+ if (srcDir && isFileExist(correctPath)) {
1292+ srcPath = correctPath;
1293+ } else {
1294+ // historically Android mistakenly use mmapKey as mmapID
1295+ srcPath = *rootPath + MMKV_PATH_SLASH + encodeFilePath(mmapKey, *rootPath);
1296+ }
1295#else1297#else
1296 auto srcPath = *rootPath + MMKV_PATH_SLASH + encodePath;1298 auto srcPath = *rootPath + MMKV_PATH_SLASH + encodePath;
1297#endif1299#endif
@@ -1470,8 +1472,14 @@ bool MMKV::restoreOneFromDirectory(const string &mmapID, const MMKVPath_t &srcDi
1470 auto srcPath = srcDir + MMKV_PATH_SLASH + encodePath;1472 auto srcPath = srcDir + MMKV_PATH_SLASH + encodePath;
1471 auto mmapKey = mmapedKVKey(mmapID, rootPath);1473 auto mmapKey = mmapedKVKey(mmapID, rootPath);
1472#ifdef MMKV_ANDROID1474#ifdef MMKV_ANDROID
1473- // historically Android mistakenly use mmapKey as mmapID1475+ string dstPath;
1474- auto dstPath = *rootPath + MMKV_PATH_SLASH + encodeFilePath(mmapKey, *rootPath);1476+ auto correctPath = *rootPath + MMKV_PATH_SLASH + encodePath;
1477+ if (dstDir && isFileExist(correctPath)) {
1478+ dstPath = correctPath;
1479+ } else {
1480+ // historically Android mistakenly use mmapKey as mmapID
1481+ dstPath = *rootPath + MMKV_PATH_SLASH + encodeFilePath(mmapKey, *rootPath);
1482+ }
1475#else1483#else
1476 auto dstPath = *rootPath + MMKV_PATH_SLASH + encodePath;1484 auto dstPath = *rootPath + MMKV_PATH_SLASH + encodePath;
1477#endif1485#endif
@@ -90,20 +90,20 @@ concept MMKV_SUPPORTED_VALUE_TYPE = MMKV_SUPPORTED_PRIMITIVE_VALUE_TYPE<T> || MM
90 90 
91class MMKV {91class MMKV {
92#ifndef MMKV_ANDROID92#ifndef MMKV_ANDROID
93- std::string m_mmapKey;
94 MMKV(const std::string &mmapID, MMKVMode mode, std::string *cryptKey, MMKVPath_t *rootPath, size_t expectedCapacity = 0);93 MMKV(const std::string &mmapID, MMKVMode mode, std::string *cryptKey, MMKVPath_t *rootPath, size_t expectedCapacity = 0);
95#else // defined(MMKV_ANDROID)94#else // defined(MMKV_ANDROID)
96 mmkv::FileLock *m_fileModeLock;95 mmkv::FileLock *m_fileModeLock;
97 mmkv::InterProcessLock *m_sharedProcessModeLock;96 mmkv::InterProcessLock *m_sharedProcessModeLock;
98 mmkv::InterProcessLock *m_exclusiveProcessModeLock;97 mmkv::InterProcessLock *m_exclusiveProcessModeLock;
99 98 
100- MMKV(const std::string &mmapID, int size, MMKVMode mode, std::string *cryptKey, MMKVPath_t *rootPath, size_t expectedCapacity = 0);99+ MMKV(const std::string &mmapID, int size, MMKVMode mode, const std::string *cryptKey, const MMKVPath_t *rootPath, size_t expectedCapacity = 0);
101 100 
102- MMKV(const std::string &mmapID, int ashmemFD, int ashmemMetaFd, std::string *cryptKey = nullptr);101+ MMKV(const std::string &mmapID, int ashmemFD, int ashmemMetaFd, const std::string *cryptKey = nullptr);
103#endif102#endif
104 103 
105 ~MMKV();104 ~MMKV();
106 105 
106+ std::string m_mmapKey;
107 std::string m_mmapID;107 std::string m_mmapID;
108 MMKVPath_t m_path;108 MMKVPath_t m_path;
109 MMKVPath_t m_crcPath;109 MMKVPath_t m_crcPath;
@@ -220,7 +220,7 @@ class MMKV {
220 void notifyContentChanged();220 void notifyContentChanged();
221 221 
222#if defined(MMKV_ANDROID) && !defined(MMKV_DISABLE_CRYPT)222#if defined(MMKV_ANDROID) && !defined(MMKV_DISABLE_CRYPT)
223- void checkReSetCryptKey(int fd, int metaFD, std::string *cryptKey);223+ void checkReSetCryptKey(int fd, int metaFD, const std::string *cryptKey);
224#endif224#endif
225 static bool backupOneToDirectory(const std::string &mmapKey, const MMKVPath_t &dstPath, const MMKVPath_t &srcPath, bool compareFullPath);225 static bool backupOneToDirectory(const std::string &mmapKey, const MMKVPath_t &dstPath, const MMKVPath_t &srcPath, bool compareFullPath);
226 static size_t backupAllToDirectory(const MMKVPath_t &dstDir, const MMKVPath_t &srcDir, bool isInSpecialDir);226 static size_t backupAllToDirectory(const MMKVPath_t &dstDir, const MMKVPath_t &srcDir, bool isInSpecialDir);
@@ -264,11 +264,11 @@ public:
264 static MMKV *mmkvWithID(const std::string &mmapID,264 static MMKV *mmkvWithID(const std::string &mmapID,
265 int size = mmkv::DEFAULT_MMAP_SIZE,265 int size = mmkv::DEFAULT_MMAP_SIZE,
266 MMKVMode mode = MMKV_SINGLE_PROCESS,266 MMKVMode mode = MMKV_SINGLE_PROCESS,
267- std::string *cryptKey = nullptr,267+ const std::string *cryptKey = nullptr,
268- MMKVPath_t *rootPath = nullptr,268+ const MMKVPath_t *rootPath = nullptr,
269 size_t expectedCapacity = 0);269 size_t expectedCapacity = 0);
270 270 
271- static MMKV *mmkvWithAshmemFD(const std::string &mmapID, int fd, int metaFD, std::string *cryptKey = nullptr);271+ static MMKV *mmkvWithAshmemFD(const std::string &mmapID, int fd, int metaFD, const std::string *cryptKey = nullptr);
272 272 
273 int ashmemFD();273 int ashmemFD();
274 274 
@@ -577,5 +577,5 @@ bool MMKV::getVector(MMKVKey_t key, T &result) {
577 577 
578MMKV_NAMESPACE_END578MMKV_NAMESPACE_END
579 579 
580-#endif580+#endif // __cplusplus
581#endif // MMKV_MMKV_H581#endif // MMKV_MMKV_H
@@ -34,7 +34,7 @@
34#include <vector>34#include <vector>
35#include <unordered_map>35#include <unordered_map>
36 36 
37-constexpr auto MMKV_VERSION = "v1.3.9";37+constexpr auto MMKV_VERSION = "v1.3.14";
38 38 
39#ifdef DEBUG39#ifdef DEBUG
40# define MMKV_DEBUG40# define MMKV_DEBUG
@@ -39,8 +39,8 @@ using namespace mmkv;
39extern unordered_map<string, MMKV *> *g_instanceDic;39extern unordered_map<string, MMKV *> *g_instanceDic;
40extern ThreadLock *g_instanceLock;40extern ThreadLock *g_instanceLock;
41 41 
42-MMKV::MMKV(const string &mmapID, int size, MMKVMode mode, string *cryptKey, string *rootPath, size_t expectedCapacity)42+MMKV::MMKV(const string &mmapID, int size, MMKVMode mode, const string *cryptKey, const string *rootPath, size_t expectedCapacity)
43- : m_mmapID((mode & MMKV_BACKUP) ? mmapID : mmapedKVKey(mmapID, rootPath)) // historically Android mistakenly use mmapKey as mmapID43+ : m_mmapID(mmapID)
44 , m_path(mappedKVPathWithID(m_mmapID, mode, rootPath))44 , m_path(mappedKVPathWithID(m_mmapID, mode, rootPath))
45 , m_crcPath(crcPathWithID(m_mmapID, mode, rootPath))45 , m_crcPath(crcPathWithID(m_mmapID, mode, rootPath))
46 , m_dic(nullptr)46 , m_dic(nullptr)
@@ -88,7 +88,7 @@ MMKV::MMKV(const string &mmapID, int size, MMKVMode mode, string *cryptKey, stri
88 }*/88 }*/
89}89}
90 90 
91-MMKV::MMKV(const string &mmapID, int ashmemFD, int ashmemMetaFD, string *cryptKey)91+MMKV::MMKV(const string &mmapID, int ashmemFD, int ashmemMetaFD, const string *cryptKey)
92 : m_mmapID(mmapID)92 : m_mmapID(mmapID)
93 , m_path(mappedKVPathWithID(m_mmapID, MMKV_ASHMEM, nullptr))93 , m_path(mappedKVPathWithID(m_mmapID, MMKV_ASHMEM, nullptr))
94 , m_crcPath(crcPathWithID(m_mmapID, MMKV_ASHMEM, nullptr))94 , m_crcPath(crcPathWithID(m_mmapID, MMKV_ASHMEM, nullptr))
@@ -137,8 +137,8 @@ MMKV::MMKV(const string &mmapID, int ashmemFD, int ashmemMetaFD, string *cryptKe
137 }*/137 }*/
138}138}
139 139 
140-MMKV *MMKV::mmkvWithID(const string &mmapID, int size, MMKVMode mode, string *cryptKey, string *rootPath, size_t expectedCapacity) {140+MMKV *MMKV::mmkvWithID(const string &mmapID, int size, MMKVMode mode, const string *cryptKey, const string *rootPath, size_t expectedCapacity) {
141- if (mmapID.empty()) {141+ if (mmapID.empty() || !g_instanceLock) {
142 return nullptr;142 return nullptr;
143 }143 }
144 SCOPED_LOCK(g_instanceLock);144 SCOPED_LOCK(g_instanceLock);
@@ -157,14 +157,25 @@ MMKV *MMKV::mmkvWithID(const string &mmapID, int size, MMKVMode mode, string *cr
157 }157 }
158 MMKVInfo("prepare to load %s (id %s) from rootPath %zu", mmapID.c_str(), mmapKey.c_str(), rootPath->c_str());158 MMKVInfo("prepare to load %s (id %s) from rootPath %zu", mmapID.c_str(), mmapKey.c_str(), rootPath->c_str());
159 }159 }
160- auto kv = new MMKV(mmapID, size, mode, cryptKey, rootPath, expectedCapacity);160+ 
161+ string realID;
162+ auto correctPath = mappedKVPathWithID(mmapID, mode, rootPath);
163+ if ((mode & MMKV_BACKUP) || (rootPath && isFileExist(correctPath))) {
164+ // it's successfully migrated to the correct path by newer version of MMKV
165+ realID = mmapID;
166+ } else {
167+ // historically Android mistakenly use mmapKey as mmapID
168+ realID = mmapKey;
169+ }
170+ auto kv = new MMKV(realID, size, mode, cryptKey, rootPath, expectedCapacity);
171+ kv->m_mmapKey = mmapKey;
161 (*g_instanceDic)[mmapKey] = kv;172 (*g_instanceDic)[mmapKey] = kv;
162 return kv;173 return kv;
163}174}
164 175 
165-MMKV *MMKV::mmkvWithAshmemFD(const string &mmapID, int fd, int metaFD, string *cryptKey) {176+MMKV *MMKV::mmkvWithAshmemFD(const string &mmapID, int fd, int metaFD, const string *cryptKey) {
166 177 
167- if (fd < 0) {178+ if (fd < 0 || !g_instanceLock) {
168 return nullptr;179 return nullptr;
169 }180 }
170 SCOPED_LOCK(g_instanceLock);181 SCOPED_LOCK(g_instanceLock);
@@ -178,6 +189,7 @@ MMKV *MMKV::mmkvWithAshmemFD(const string &mmapID, int fd, int metaFD, string *c
178 return kv;189 return kv;
179 }190 }
180 auto kv = new MMKV(mmapID, fd, metaFD, cryptKey);191 auto kv = new MMKV(mmapID, fd, metaFD, cryptKey);
192+ kv->m_mmapKey = mmapID;
181 (*g_instanceDic)[mmapID] = kv;193 (*g_instanceDic)[mmapID] = kv;
182 return kv;194 return kv;
183}195}
@@ -191,7 +203,7 @@ int MMKV::ashmemMetaFD() {
191}203}
192 204 
193# ifndef MMKV_DISABLE_CRYPT205# ifndef MMKV_DISABLE_CRYPT
194-void MMKV::checkReSetCryptKey(int fd, int metaFD, string *cryptKey) {206+void MMKV::checkReSetCryptKey(int fd, int metaFD, const string *cryptKey) {
195 SCOPED_LOCK(m_lock);207 SCOPED_LOCK(m_lock);
196 208 
197 checkReSetCryptKey(cryptKey);209 checkReSetCryptKey(cryptKey);
@@ -1526,7 +1526,15 @@ bool MMKV::isFileValid(const string &mmapID, MMKVPath_t *relatePath) {
1526bool MMKV::removeStorage(const std::string &mmapID, MMKVPath_t *relatePath) {1526bool MMKV::removeStorage(const std::string &mmapID, MMKVPath_t *relatePath) {
1527 auto mmapKey = mmapedKVKey(mmapID, relatePath);1527 auto mmapKey = mmapedKVKey(mmapID, relatePath);
1528#ifdef MMKV_ANDROID1528#ifdef MMKV_ANDROID
1529- auto &realID = mmapKey; // historically Android mistakenly use mmapKey as mmapID1529+ std::string realID;
1530+ auto correctPath = mappedKVPathWithID(mmapID, MMKV_SINGLE_PROCESS, relatePath);
1531+ if (relatePath && isFileExist(correctPath)) {
1532+ // it's successfully migrated to the correct path by newer version of MMKV
1533+ realID = mmapID;
1534+ } else {
1535+ // historically Android mistakenly use mmapKey as mmapID
1536+ realID = mmapKey;
1537+ }
1530#else1538#else
1531 auto &realID = mmapID;1539 auto &realID = mmapID;
1532#endif1540#endif
@@ -1700,6 +1708,14 @@ bool MMKV::disableAutoKeyExpire() {
1700 MMKVVector vec;1708 MMKVVector vec;
1701 auto packKeyValue = [&](const MMKVKey_t &key, const MMBuffer &value) {1709 auto packKeyValue = [&](const MMKVKey_t &key, const MMBuffer &value) {
1702 assert(value.length() >= Fixed32Size);1710 assert(value.length() >= Fixed32Size);
1711+ if (value.length() < Fixed32Size) {
1712+#ifdef MMKV_APPLE
1713+ MMKVWarning("key [%@] has invalid value size %u", key, value.length());
1714+#else
1715+ MMKVWarning("key [%s] has invalid value size %u", key.data(), value.length());
1716+#endif
1717+ return;
1718+ }
1703 MMBuffer data(value.length() - Fixed32Size);1719 MMBuffer data(value.length() - Fixed32Size);
1704 auto ptr = (uint8_t *) data.getPtr();1720 auto ptr = (uint8_t *) data.getPtr();
1705 memcpy(ptr, value.getPtr(), value.length() - Fixed32Size);1721 memcpy(ptr, value.getPtr(), value.length() - Fixed32Size);
@@ -1740,6 +1756,13 @@ uint32_t MMKV::getExpireTimeForKey(MMKVKey_t key) {
1740 auto raw = getRawDataForKey(key);1756 auto raw = getRawDataForKey(key);
1741 assert(raw.length() == 0 || raw.length() >= Fixed32Size);1757 assert(raw.length() == 0 || raw.length() >= Fixed32Size);
1742 if (raw.length() < Fixed32Size) {1758 if (raw.length() < Fixed32Size) {
1759+ if (raw.length() != 0) {
1760+#ifdef MMKV_APPLE
1761+ MMKVWarning("key [%@] has invalid value size %u", key, raw.length());
1762+#else
1763+ MMKVWarning("key [%s] has invalid value size %u", key.data(), raw.length());
1764+#endif
1765+ }
1743 return 0;1766 return 0;
1744 }1767 }
1745 auto ptr = (const uint8_t *) raw.getPtr() + raw.length() - Fixed32Size;1768 auto ptr = (const uint8_t *) raw.getPtr() + raw.length() - Fixed32Size;
@@ -1755,6 +1778,13 @@ mmkv::MMBuffer MMKV::getDataWithoutMTimeForKey(MMKVKey_t key) {
1755 auto raw = getRawDataForKey(key);1778 auto raw = getRawDataForKey(key);
1756 assert(raw.length() == 0 || raw.length() >= Fixed32Size);1779 assert(raw.length() == 0 || raw.length() >= Fixed32Size);
1757 if (raw.length() < Fixed32Size) {1780 if (raw.length() < Fixed32Size) {
1781+ if (raw.length() != 0) {
1782+#ifdef MMKV_APPLE
1783+ MMKVWarning("key [%@] has invalid value size %u", key, raw.length());
1784+#else
1785+ MMKVWarning("key [%s] has invalid value size %u", key.data(), raw.length());
1786+#endif
1787+ }
1758 return raw;1788 return raw;
1759 }1789 }
1760 auto newLength = raw.length() - Fixed32Size;1790 auto newLength = raw.length() - Fixed32Size;
@@ -1793,6 +1823,15 @@ size_t MMKV::filterExpiredKeys() {
1793 for (auto itr = m_dicCrypt->begin(); itr != m_dicCrypt->end(); NOOP) {1823 for (auto itr = m_dicCrypt->begin(); itr != m_dicCrypt->end(); NOOP) {
1794 auto &kvHolder = itr->second;1824 auto &kvHolder = itr->second;
1795 assert(kvHolder.realValueSize() >= Fixed32Size);1825 assert(kvHolder.realValueSize() >= Fixed32Size);
1826+ if (kvHolder.realValueSize() < Fixed32Size) {
1827+#ifdef MMKV_APPLE
1828+ MMKVWarning("key [%@] has invalid value size %u", itr->first, kvHolder.realValueSize());
1829+#else
1830+ MMKVWarning("key [%s] has invalid value size %u", itr->first.c_str(), kvHolder.realValueSize());
1831+#endif
1832+ itr++;
1833+ continue;
1834+ }
1796 auto buffer = kvHolder.toMMBuffer(basePtr, m_crypter);1835 auto buffer = kvHolder.toMMBuffer(basePtr, m_crypter);
1797 auto ptr = (uint8_t *) buffer.getPtr();1836 auto ptr = (uint8_t *) buffer.getPtr();
1798 ptr += buffer.length() - Fixed32Size;1837 ptr += buffer.length() - Fixed32Size;
@@ -1817,6 +1856,15 @@ size_t MMKV::filterExpiredKeys() {
1817 for (auto itr = m_dic->begin(); itr != m_dic->end(); NOOP) {1856 for (auto itr = m_dic->begin(); itr != m_dic->end(); NOOP) {
1818 auto &kvHolder = itr->second;1857 auto &kvHolder = itr->second;
1819 assert(kvHolder.valueSize >= Fixed32Size);1858 assert(kvHolder.valueSize >= Fixed32Size);
1859+ if (kvHolder.valueSize < Fixed32Size) {
1860+#ifdef MMKV_APPLE
1861+ MMKVWarning("key [%@] has invalid value size %u", itr->first, kvHolder.valueSize);
1862+#else
1863+ MMKVWarning("key [%s] has invalid value size %u", itr->first.c_str(), kvHolder.valueSize);
1864+#endif
1865+ itr++;
1866+ continue;
1867+ }
1820 auto ptr = basePtr + kvHolder.offset + kvHolder.computedKVSize;1868 auto ptr = basePtr + kvHolder.offset + kvHolder.computedKVSize;
1821 ptr += kvHolder.valueSize - Fixed32Size;1869 ptr += kvHolder.valueSize - Fixed32Size;
1822 auto time = *(const uint32_t *) ptr;1870 auto time = *(const uint32_t *) ptr;
@@ -506,6 +506,13 @@ bool copyFile(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
506 if (copyFileContent(srcPath, tmpFD, false)) {506 if (copyFileContent(srcPath, tmpFD, false)) {
507 MMKVInfo("copyfile [%s] to [%s]", srcPath.c_str(), tmpPath.c_str());507 MMKVInfo("copyfile [%s] to [%s]", srcPath.c_str(), tmpPath.c_str());
508 renamed = tryAtomicRename(tmpPath, dstPath);508 renamed = tryAtomicRename(tmpPath, dstPath);
509+ if (!renamed) {
510+ MMKVInfo("rename fail, try copy file content instead.");
511+ if (copyFileContent(tmpPath, dstPath)) {
512+ renamed = true;
513+ ::unlink(tmpPath.c_str());
514+ }
515+ }
509 if (renamed) {516 if (renamed) {
510 MMKVInfo("copyfile [%s] to [%s] finish.", srcPath.c_str(), dstPath.c_str());517 MMKVInfo("copyfile [%s] to [%s] finish.", srcPath.c_str(), dstPath.c_str());
511 }518 }
@@ -72,6 +72,10 @@ bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
72 MMKVWarning("fail on syscall(SYS_renameat2) [%s] to [%s], %d(%s)", srcPath.c_str(), dstPath.c_str(), errno,72 MMKVWarning("fail on syscall(SYS_renameat2) [%s] to [%s], %d(%s)", srcPath.c_str(), dstPath.c_str(), errno,
73 strerror(errno));73 strerror(errno));
74 }74 }
75+ 
76+ if (renamed && (srcPath != dstPath)) {
77+ ::unlink(srcPath.c_str());
78+ }
75#endif // SYS_renameat2 && !MMKV_OHOS79#endif // SYS_renameat2 && !MMKV_OHOS
76 80 
77 if (!renamed) {81 if (!renamed) {
@@ -81,7 +85,6 @@ bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
81 }85 }
82 }86 }
83 87 
84- ::unlink(srcPath.c_str());
85 return true;88 return true;
86}89}
87 90 
@@ -58,6 +58,9 @@ void tryResetFileProtection(const string &path) {
58namespace mmkv {58namespace mmkv {
59 59 
60bool tryAtomicRename(const char *src, const char *dst) {60bool tryAtomicRename(const char *src, const char *dst) {
61+ if (!src || !dst) {
62+ return false;
63+ }
61 bool renamed = false;64 bool renamed = false;
62 65 
63 // try atomic swap first66 // try atomic swap first
@@ -65,6 +68,9 @@ bool tryAtomicRename(const char *src, const char *dst) {
65 // renameat2() equivalent68 // renameat2() equivalent
66 if (renamex_np(src, dst, RENAME_SWAP) == 0) {69 if (renamex_np(src, dst, RENAME_SWAP) == 0) {
67 renamed = true;70 renamed = true;
71+ if (strcmp(src, dst) != 0) {
72+ ::unlink(src);
73+ }
68 } else if (errno != ENOENT) {74 } else if (errno != ENOENT) {
69 MMKVError("fail to renamex_np %s to %s, %s", src, dst, strerror(errno));75 MMKVError("fail to renamex_np %s to %s, %s", src, dst, strerror(errno));
70 }76 }
@@ -78,8 +84,6 @@ bool tryAtomicRename(const char *src, const char *dst) {
78 }84 }
79 }85 }
80 86 
81- ::unlink(src);
82- 
83 return true;87 return true;
84}88}
85 89 
@@ -97,8 +101,12 @@ bool copyFile(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
97 MMKVInfo("copyfile [%s] to [%s] finish.", srcPath.c_str(), dstPath.c_str());101 MMKVInfo("copyfile [%s] to [%s] finish.", srcPath.c_str(), dstPath.c_str());
98 return true;102 return true;
99 }103 }
104+ 
105+ MMKVInfo("rename fail, try copy file content instead.");
106+ auto ret = copyFileContent(tmpFile.UTF8String, dstPath);
107+ 
100 unlink(tmpFile.UTF8String);108 unlink(tmpFile.UTF8String);
101- return false;109+ return ret;
102}110}
103 111 
104bool copyFileContent(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {112bool copyFileContent(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
@@ -24,13 +24,28 @@
24#include <cstdlib>24#include <cstdlib>
25#include <cstring>25#include <cstring>
26#include <ctime>26#include <ctime>
27+#include "../MMKVLog.h"
28+#include "../MemoryFile.h"
29+ 
30+namespace mmkv {
31+ 
32+// assuming size in [1, 5]
33+uint32_t AESCrypt::randomItemSizeHolder(uint32_t size) {
34+ constexpr uint32_t ItemSizeHolders[] = {0, 0x80, 0x4000, 0x200000, 0x10000000, 0};
35+ auto ItemSizeHolderMin = ItemSizeHolders[size - 1];
36+ auto ItemSizeHolderMax = ItemSizeHolders[size] - 1;
37+ 
38+ srand((unsigned) time(nullptr));
39+ auto result = static_cast<uint32_t>(rand());
40+ result = result % (ItemSizeHolderMax - ItemSizeHolderMin + 1);
41+ result += ItemSizeHolderMin;
42+ return result;
43+}
27 44 
28#ifndef MMKV_DISABLE_CRYPT45#ifndef MMKV_DISABLE_CRYPT
29 46 
30using namespace openssl;47using namespace openssl;
31 48 
32-namespace mmkv {
33- 
34AESCrypt::AESCrypt(const void *key, size_t keyLength, const void *iv, size_t ivLength) {49AESCrypt::AESCrypt(const void *key, size_t keyLength, const void *iv, size_t ivLength) {
35 if (key && keyLength > 0) {50 if (key && keyLength > 0) {
36 memcpy(m_key, key, (keyLength > AES_KEY_LEN) ? AES_KEY_LEN : keyLength);51 memcpy(m_key, key, (keyLength > AES_KEY_LEN) ? AES_KEY_LEN : keyLength);
@@ -102,19 +117,6 @@ void AESCrypt::fillRandomIV(void *vector) {
102 }117 }
103}118}
104 119 
105-// assuming size in [1, 5]
106-uint32_t AESCrypt::randomItemSizeHolder(uint32_t size) {
107- constexpr uint32_t ItemSizeHolders[] = {0, 0x80, 0x4000, 0x200000, 0x10000000, 0};
108- auto ItemSizeHolderMin = ItemSizeHolders[size - 1];
109- auto ItemSizeHolderMax = ItemSizeHolders[size] - 1;
110- 
111- srand((unsigned) time(nullptr));
112- auto result = static_cast<uint32_t>(rand());
113- result = result % (ItemSizeHolderMax - ItemSizeHolderMin + 1);
114- result += ItemSizeHolderMin;
115- return result;
116-}
117- 
118static inline void120static inline void
119Rollback_cfb_decrypt(const uint8_t *input, const uint8_t *output, size_t len, AES_KEY *key, AESCryptStatus &status) {121Rollback_cfb_decrypt(const uint8_t *input, const uint8_t *output, size_t len, AES_KEY *key, AESCryptStatus &status) {
120 auto ivec = status.m_vector;122 auto ivec = status.m_vector;
@@ -174,15 +176,8 @@ AESCrypt AESCrypt::cloneWithStatus(const AESCryptStatus &status) const {
174 return AESCrypt(*this, status);176 return AESCrypt(*this, status);
175}177}
176 178 
177-} // namespace mmkv
178- 
179# ifdef MMKV_DEBUG179# ifdef MMKV_DEBUG
180 180 
181-# include "../MMKVLog.h"
182-# include "../MemoryFile.h"
183- 
184-namespace mmkv {
185- 
186void testRandomPlaceHolder() {181void testRandomPlaceHolder() {
187 for (uint32_t size = 1; size < 6; size++) {182 for (uint32_t size = 1; size < 6; size++) {
188 auto holder = AESCrypt::randomItemSizeHolder(size);183 auto holder = AESCrypt::randomItemSizeHolder(size);
@@ -272,7 +267,7 @@ void AESCrypt::testAESCrypt() {
272 delete[] decryptText;267 delete[] decryptText;
273}268}
274 269 
275-} // namespace mmkv
276- 
277# endif // MMKV_DEBUG270# endif // MMKV_DEBUG
278#endif // MMKV_DISABLE_CRYPT271#endif // MMKV_DISABLE_CRYPT
272+ 
273+} // namespace mmkv
@@ -29,7 +29,10 @@
29#ifdef MMKV_DISABLE_CRYPT29#ifdef MMKV_DISABLE_CRYPT
30 30 
31namespace mmkv {31namespace mmkv {
32-class AESCrypt;32+class AESCrypt {
33+public:
34+ static uint32_t randomItemSizeHolder(uint32_t size);
35+};
33}36}
34 37 
35#else38#else
@@ -1 +1 @@
1-{"version":3,"file":"memoryStore.d.ts","sourceRoot":"","sources":["../../memoryStore.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,MAAM,QAAO,OAMzB,CAAC;AAEF,eAAO,MAAM,IAAI,QAAO,OAqKvB,CAAC"}1+{"version":3,"file":"memoryStore.d.ts","sourceRoot":"","sources":["../../memoryStore.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,MAAM,QAAO,OAMzB,CAAC;AAEF,eAAO,MAAM,IAAI,QAAO,OA4KvB,CAAC"}
@@ -96,7 +96,7 @@ export var mock = function () {
96 if (!MEMORY_STORE[id])96 if (!MEMORY_STORE[id])
97 return undefined;97 return undefined;
98 var value = MEMORY_STORE[id].storage[key];98 var value = MEMORY_STORE[id].storage[key];
99- if (!value)99+ if (typeof value != 'string')
100 return null;100 return null;
101 return value;101 return value;
102 };102 };
@@ -111,7 +111,7 @@ export var mock = function () {
111 if (!MEMORY_STORE[id])111 if (!MEMORY_STORE[id])
112 return undefined;112 return undefined;
113 var value = MEMORY_STORE[id].storage[key];113 var value = MEMORY_STORE[id].storage[key];
114- if (!value)114+ if (typeof value != 'number')
115 return null;115 return null;
116 return value;116 return value;
117 };117 };
@@ -126,7 +126,7 @@ export var mock = function () {
126 if (!MEMORY_STORE[id])126 if (!MEMORY_STORE[id])
127 return undefined;127 return undefined;
128 var value = MEMORY_STORE[id].storage[key];128 var value = MEMORY_STORE[id].storage[key];
129- if (!value)129+ if (typeof value != 'boolean')
130 return null;130 return null;
131 return value;131 return value;
132 };132 };
@@ -165,6 +165,14 @@ export var mock = function () {
165 return undefined;165 return undefined;
166 return Object.keys(MEMORY_STORE[id].storage);166 return Object.keys(MEMORY_STORE[id].storage);
167 };167 };
168+ mmkvJsiModule.removeValuesMMKV = function (keys, id) {
169+ if (!MEMORY_STORE[id])
170+ return undefined;
171+ for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
172+ var key = keys_1[_i];
173+ mmkvJsiModule.removeValueMMKV(key, id);
174+ }
175+ };
168 mmkvJsiModule.setupMMKVInstance('mmkvIdStore');176 mmkvJsiModule.setupMMKVInstance('mmkvIdStore');
169 return true;177 return true;
170};178};
@@ -0,0 +1,201 @@
1+import { MMKVJsiModule, IndexType } from '../src/types/index';
2+ 
3+type MemoryStore = {
4+ [name: string]: {
5+ indexes: {
6+ stringIndex: string[];
7+ boolIndex: string[];
8+ numberIndex: string[];
9+ mapIndex: string[];
10+ arrayIndex: string[];
11+ };
12+ storage: { [name: string]: any };
13+ };
14+};
15+//@ts-ignore
16+const mmkvJsiModule: MMKVJsiModule = global;
17+ 
18+let SECURE_KEYSTORE: { [name: string]: string | null } = {};
19+let MEMORY_STORE: MemoryStore = {};
20+ 
21+export const unmock = (): boolean => {
22+ //@ts-ignore
23+ mmkvJsiModule.getStringMMKV = undefined;
24+ SECURE_KEYSTORE = {};
25+ MEMORY_STORE = {};
26+ return true;
27+};
28+ 
29+export const mock = (): boolean => {
30+ SECURE_KEYSTORE = {};
31+ MEMORY_STORE = {};
32+ mmkvJsiModule.setupMMKVInstance = id => {
33+ MEMORY_STORE[id] = {
34+ indexes: {
35+ stringIndex: [],
36+ boolIndex: [],
37+ numberIndex: [],
38+ mapIndex: [],
39+ arrayIndex: []
40+ },
41+ storage: {}
42+ };
43+ return true;
44+ };
45+ 
46+ //@ts-ignore
47+ mmkvJsiModule.setMMKVServiceName = (alias, serviceName) => {
48+ return serviceName;
49+ };
50+ 
51+ mmkvJsiModule.getSecureKey = alias => {
52+ return SECURE_KEYSTORE[alias];
53+ };
54+ 
55+ mmkvJsiModule.setSecureKey = (alias, key) => {
56+ SECURE_KEYSTORE[alias] = key;
57+ return true;
58+ };
59+ 
60+ mmkvJsiModule.secureKeyExists = alias => {
61+ return Object.keys(SECURE_KEYSTORE).includes(alias);
62+ };
63+ 
64+ mmkvJsiModule.removeSecureKey = alias => {
65+ delete SECURE_KEYSTORE[alias];
66+ return true;
67+ };
68+ 
69+ mmkvJsiModule.clearMMKV = id => {
70+ mmkvJsiModule.setupMMKVInstance(id);
71+ return true;
72+ };
73+ 
74+ mmkvJsiModule.clearMemoryCache = () => {
75+ return true;
76+ };
77+ mmkvJsiModule.decryptMMKV = () => {
78+ return true;
79+ };
80+ 
81+ mmkvJsiModule.encryptMMKV = () => {
82+ return true;
83+ };
84+ 
85+ mmkvJsiModule.containsKeyMMKV = (key, id) => {
86+ if (!MEMORY_STORE[id]) return undefined;
87+ return Object.keys(MEMORY_STORE[id].storage).includes(key);
88+ };
89+ 
90+ mmkvJsiModule.getIndexMMKV = (type, id) => {
91+ if (!MEMORY_STORE[id]) return [];
92+ return MEMORY_STORE[id].indexes[type];
93+ };
94+ 
95+ mmkvJsiModule.removeValueMMKV = (key, id) => {
96+ if (!MEMORY_STORE[id]) return undefined;
97+ delete MEMORY_STORE[id].storage[key];
98+ 
99+ Object.keys(MEMORY_STORE[id].indexes).forEach(indexKey => {
100+ //@ts-ignore
101+ let index: string[] = MEMORY_STORE[id].indexes[indexKey];
102+ if (index.includes(key)) {
103+ index.splice(index.indexOf(key), 1);
104+ }
105+ });
106+ 
107+ return true;
108+ };
109+ 
110+ const updateIndex = (key: string, indexType: IndexType, id: string) => {
111+ let index = MEMORY_STORE[id].indexes[indexType];
112+ if (!index.includes(key)) {
113+ index.push(key);
114+ }
115+ };
116+ 
117+ mmkvJsiModule.setStringMMKV = (key, value, id) => {
118+ if (!MEMORY_STORE[id]) return undefined;
119+ MEMORY_STORE[id].storage[key] = value;
120+ updateIndex(key, 'stringIndex', id);
121+ return true;
122+ };
123+ 
124+ mmkvJsiModule.getStringMMKV = (key, id) => {
125+ if (!MEMORY_STORE[id]) return undefined;
126+ let value = MEMORY_STORE[id].storage[key];
127+ if (typeof value != 'string') return null;
128+ return value;
129+ };
130+ 
131+ mmkvJsiModule.setNumberMMKV = (key, value, id) => {
132+ if (!MEMORY_STORE[id]) return undefined;
133+ MEMORY_STORE[id].storage[key] = value;
134+ updateIndex(key, 'numberIndex', id);
135+ return true;
136+ };
137+ 
138+ mmkvJsiModule.getNumberMMKV = (key, id) => {
139+ if (!MEMORY_STORE[id]) return undefined;
140+ let value = MEMORY_STORE[id].storage[key];
141+ if (typeof value != 'number') return null;
142+ return value;
143+ };
144+ 
145+ mmkvJsiModule.setBoolMMKV = (key, value, id) => {
146+ if (!MEMORY_STORE[id]) return undefined;
147+ MEMORY_STORE[id].storage[key] = value;
148+ updateIndex(key, 'boolIndex', id);
149+ return true;
150+ };
151+ 
152+ mmkvJsiModule.getBoolMMKV = (key, id) => {
153+ if (!MEMORY_STORE[id]) return undefined;
154+ let value = MEMORY_STORE[id].storage[key];
155+ if (typeof value != 'boolean') return null;
156+ return value;
157+ };
158+ 
159+ mmkvJsiModule.setMapMMKV = (key, value, id) => {
160+ if (!MEMORY_STORE[id]) return undefined;
161+ MEMORY_STORE[id].storage[key] = value;
162+ updateIndex(key, 'mapIndex', id);
163+ return true;
164+ };
165+ 
166+ mmkvJsiModule.getMapMMKV = (key, id) => {
167+ if (!MEMORY_STORE[id]) return undefined;
168+ let value = MEMORY_STORE[id].storage[key];
169+ if (!value) return null;
170+ return value;
171+ };
172+ 
173+ mmkvJsiModule.setArrayMMKV = (key, value, id) => {
174+ if (!MEMORY_STORE[id]) return undefined;
175+ MEMORY_STORE[id].storage[key] = value;
176+ updateIndex(key, 'arrayIndex', id);
177+ return true;
178+ };
179+ 
180+ mmkvJsiModule.getArrayMMKV = (key, id) => {
181+ if (!MEMORY_STORE[id]) return undefined;
182+ let value = MEMORY_STORE[id].storage[key];
183+ if (!value) return null;
184+ return value;
185+ };
186+ 
187+ mmkvJsiModule.getAllKeysMMKV = id => {
188+ if (!MEMORY_STORE[id]) return undefined;
189+ return Object.keys(MEMORY_STORE[id].storage);
190+ };
191+ 
192+ mmkvJsiModule.removeValuesMMKV = (keys, id) => {
193+ if (!MEMORY_STORE[id]) return undefined;
194+ for (let key of keys) {
195+ mmkvJsiModule.removeValueMMKV(key, id);
196+ }
197+ };
198+ 
199+ mmkvJsiModule.setupMMKVInstance('mmkvIdStore');
200+ return true;
201+};
@@ -2,12 +2,6 @@ if (!global.__fbBatchedBridgeConfig) {
2 global.__fbBatchedBridgeConfig = {};2 global.__fbBatchedBridgeConfig = {};
3}3}
4 4 
5-if (!global.__turboModuleProxy) {
6- global.__turboModuleProxy = name => {
7- return {};
8- };
9-}
10- 
11require('react-native').NativeModules.MMKVNative = {5require('react-native').NativeModules.MMKVNative = {
12 install: jest.fn(() => true)6 install: jest.fn(() => true)
13};7};
@@ -0,0 +1,25 @@
1+{
2+ "include": ["memoryStore.ts"],
3+ "compilerOptions": {
4+ "baseUrl": "./",
5+ "jsx": "react-native",
6+ "module": "esnext",
7+ "moduleResolution": "node",
8+ "lib": ["es2017"],
9+ "declaration": true,
10+ "declarationMap": true,
11+ "outDir": "dist",
12+ "allowSyntheticDefaultImports": true,
13+ "esModuleInterop": true,
14+ "forceConsistentCasingInFileNames": true,
15+ "noFallthroughCasesInSwitch": true,
16+ "noImplicitReturns": true,
17+ "noUnusedLocals": true,
18+ "noUnusedParameters": true,
19+ "pretty": true,
20+ "resolveJsonModule": true,
21+ "skipLibCheck": true,
22+ "strict": true,
23+ "allowJs": true
24+ }
25+}
@@ -8,9 +8,6 @@
8 "build": "tsc",8 "build": "tsc",
9 "watch": "tsc --watch"9 "watch": "tsc --watch"
10 },10 },
11- "bin": {
12- "mmkv-link": "./autolink/postlink/run.js"
13- },
14 "files": [11 "files": [
15 "jest",12 "jest",
16 "MMKV",13 "MMKV",
@@ -58,21 +55,23 @@
58 "devDependencies": {55 "devDependencies": {
59 "@babel/core": "^7.26.0",56 "@babel/core": "^7.26.0",
60 "@babel/runtime": "^7.26.0",57 "@babel/runtime": "^7.26.0",
61- "@types/react": "18.3.1",58+ "@types/react": "^19.0.0",
62 "@types/react-native": "0.73.0",59 "@types/react-native": "0.73.0",
63- "babel-jest": "^29.6.3",60+ "@react-native-community/cli": "18.0.0",
64- "babel-plugin-module-resolver": "^5.0.0",61+ "@react-native/babel-preset": "0.79.5",
62+ "@react-native/eslint-config": "0.79.5",
63+ "@react-native/metro-config": "0.79.5",
64+ "@react-native/typescript-config": "0.79.5",
65+ "metro": "0.82.0",
65 "jest": "^29.2.1",66 "jest": "^29.2.1",
66- "metro": "0.76.1",67+ "react": "19.0.0",
67- "metro-react-native-babel-preset": "0.76.1",68+ "react-native": "0.79.5",
68- "react": "18.3.1",
69- "react-native": "0.77.1",
70 "typescript": "^5.1.6",69 "typescript": "^5.1.6",
71 "eslint": "^8.57.1",70 "eslint": "^8.57.1",
72 "@react-native-community/eslint-config": "^3.2.0"71 "@react-native-community/eslint-config": "^3.2.0"
73 },72 },
74 "dependencies": {73 "dependencies": {
75- "react-native-mmkv-storage": "0.11.2"74+ "react-native-mmkv-storage": "12.0.1"
76 },75 },
77 "harmony": {76 "harmony": {
78 "alias": "react-native-mmkv-storage"77 "alias": "react-native-mmkv-storage"
@@ -99,7 +99,7 @@ export type MMKVJsiModule = {
99 getBoolMMKV: (key: string, id: string) => boolean | null | undefined;99 getBoolMMKV: (key: string, id: string) => boolean | null | undefined;
100 100 
101 removeValueMMKV: (key: string, id: string) => boolean | undefined;101 removeValueMMKV: (key: string, id: string) => boolean | undefined;
102- removeValuesMMKV: (...keys: string[]) => boolean | undefined;102+ removeValuesMMKV: (keys: string[], id: string) => boolean | undefined;
103 103 
104 getAllKeysMMKV: (id: string) => string[] | undefined;104 getAllKeysMMKV: (id: string) => string[] | undefined;
105 getIndexMMKV: (type: IndexType, id: string) => string[] | undefined;105 getIndexMMKV: (type: IndexType, id: string) => string[] | undefined;