react-native-onyx 1.0.92 → 1.0.94

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.
@@ -1186,14 +1186,12 @@ function multiSet(data) {
1186
1186
  function applyMerge(existingValue, changes) {
1187
1187
  const lastChange = underscore__WEBPACK_IMPORTED_MODULE_1___default().last(changes);
1188
1188
 
1189
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isArray(existingValue) || underscore__WEBPACK_IMPORTED_MODULE_1___default().isArray(lastChange)) {
1189
+ if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isArray(lastChange)) {
1190
1190
  return lastChange;
1191
1191
  }
1192
1192
 
1193
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject(existingValue) || underscore__WEBPACK_IMPORTED_MODULE_1___default().every(changes, (underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject))) {
1194
- // Object values are merged one after the other
1195
- // lodash adds a small overhead so we don't use it here
1196
- // eslint-disable-next-line prefer-object-spread, rulesdir/prefer-underscore-method
1193
+ if (underscore__WEBPACK_IMPORTED_MODULE_1___default().some(changes, (underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject))) {
1194
+ // Object values are then merged one after the other
1197
1195
  return underscore__WEBPACK_IMPORTED_MODULE_1___default().reduce(changes, (modifiedData, change) => _utils__WEBPACK_IMPORTED_MODULE_9__["default"].fastMerge(modifiedData, change),
1198
1196
  existingValue || {});
1199
1197
  }
@@ -1224,6 +1222,12 @@ function applyMerge(existingValue, changes) {
1224
1222
  * @returns {Promise}
1225
1223
  */
1226
1224
  function merge(key, changes) {
1225
+ // Top-level undefined values are ignored
1226
+ // Therefore we need to prevent adding them to the merge queue
1227
+ if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isUndefined(changes)) {
1228
+ return mergeQueue[key] ? mergeQueuePromise[key] : Promise.resolve();
1229
+ }
1230
+
1227
1231
  // Merge attempts are batched together. The delta should be applied after a single call to get() to prevent a race condition.
1228
1232
  // Using the initial value from storage in subsequent merge attempts will lead to an incorrect final merged value.
1229
1233
  if (mergeQueue[key]) {
@@ -1238,12 +1242,21 @@ function merge(key, changes) {
1238
1242
  // We first only merge the changes, so we can provide these to the native implementation (SQLite uses only delta changes in "JSON_PATCH" to merge)
1239
1243
  let batchedChanges = applyMerge(undefined, mergeQueue[key]);
1240
1244
 
1245
+ if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isNull(batchedChanges)) {
1246
+ return remove(key);
1247
+ }
1248
+
1249
+ // The presence of a `null` in the merge queue instructs us to drop the existing value.
1250
+ // In this case, we can't simply merge the batched changes with the existing value, because then the null in the merge queue would have no effect
1251
+ const shouldOverwriteExistingValue = underscore__WEBPACK_IMPORTED_MODULE_1___default().includes(mergeQueue[key], null);
1252
+
1241
1253
  // Clean up the write queue, so we don't apply these changes again
1242
1254
  delete mergeQueue[key];
1243
1255
  delete mergeQueuePromise[key];
1244
1256
 
1245
1257
  // After that we merge the batched changes with the existing value
1246
- const modifiedData = _utils__WEBPACK_IMPORTED_MODULE_9__["default"].removeNullObjectValues(applyMerge(existingValue, [batchedChanges]));
1258
+ const updatedValue = shouldOverwriteExistingValue ? batchedChanges : applyMerge(existingValue, [batchedChanges]);
1259
+ const modifiedData = _utils__WEBPACK_IMPORTED_MODULE_9__["default"].removeNullObjectValues(updatedValue);
1247
1260
 
1248
1261
  // On native platforms we use SQLite which utilises JSON_PATCH to merge changes.
1249
1262
  // JSON_PATCH generally removes top-level nullish values from the stored object.
@@ -1706,9 +1719,11 @@ class OnyxCache {
1706
1719
  /**
1707
1720
  * @private
1708
1721
  * Captured pending tasks for already running storage methods
1709
- * @type {Record<string, Promise>}
1722
+ * Using a map yields better performance on operations such a delete
1723
+ * https://www.zhenghao.io/posts/object-vs-map
1724
+ * @type {Map<string, Promise>}
1710
1725
  */
1711
- this.pendingPromises = {};
1726
+ this.pendingPromises = new Map();
1712
1727
 
1713
1728
  // bind all public methods to prevent problems with `this`
1714
1729
  underscore__WEBPACK_IMPORTED_MODULE_0___default().bindAll(
@@ -1805,7 +1820,7 @@ class OnyxCache {
1805
1820
  * @returns {*}
1806
1821
  */
1807
1822
  hasPendingTask(taskName) {
1808
- return isDefined(this.pendingPromises[taskName]);
1823
+ return isDefined(this.pendingPromises.get(taskName));
1809
1824
  }
1810
1825
 
1811
1826
  /**
@@ -1817,7 +1832,7 @@ class OnyxCache {
1817
1832
  * @returns {Promise<T>}
1818
1833
  */
1819
1834
  getTaskPromise(taskName) {
1820
- return this.pendingPromises[taskName];
1835
+ return this.pendingPromises.get(taskName);
1821
1836
  }
1822
1837
 
1823
1838
  /**
@@ -1829,11 +1844,13 @@ class OnyxCache {
1829
1844
  * @returns {Promise<T>}
1830
1845
  */
1831
1846
  captureTask(taskName, promise) {
1832
- this.pendingPromises[taskName] = promise.finally(() => {
1833
- delete this.pendingPromises[taskName];
1847
+ const returnPromise = promise.finally(() => {
1848
+ this.pendingPromises.delete(taskName);
1834
1849
  });
1835
1850
 
1836
- return this.pendingPromises[taskName];
1851
+ this.pendingPromises.set(taskName, returnPromise);
1852
+
1853
+ return returnPromise;
1837
1854
  }
1838
1855
 
1839
1856
  /**
@@ -2440,8 +2457,9 @@ function mergeObject(target, source) {
2440
2457
  * @returns {Object|Array}
2441
2458
  */
2442
2459
  function fastMerge(target, source) {
2443
- // lodash adds a small overhead so we don't use it here
2444
- // eslint-disable-next-line rulesdir/prefer-underscore-method
2460
+ // We have to ignore arrays and nullish values here,
2461
+ // otherwise "mergeObject" will throw an error,
2462
+ // because it expects an object as "source"
2445
2463
  if (underscore__WEBPACK_IMPORTED_MODULE_0__.isArray(source) || underscore__WEBPACK_IMPORTED_MODULE_0__.isNull(source) || underscore__WEBPACK_IMPORTED_MODULE_0__.isUndefined(source)) {
2446
2464
  return source;
2447
2465
  }