react-native-onyx 1.0.18 → 1.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -319,6 +319,9 @@ Sample output of `Onyx.printMetrics()`
319
319
  | 1.17sec | 2.20sec | 1.03sec | currentURL, / |
320
320
  ```
321
321
 
322
+ # Debug mode
323
+
324
+ It can be useful to log why Onyx is calling `setState()` on a particular React component so that we can understand which key changed, what changed about the value, and the connected component that ultimately rendered as a result. When used correctly this can help isolate problem areas and unnecessary renders in the code. To enable this feature, pass `debugSetState: true` to the config and grep JS console logs for `[Onyx-Debug]`.
322
325
 
323
326
  # Development
324
327
 
@@ -1,13 +1,13 @@
1
1
  (function webpackUniversalModuleDefinition(root, factory) {
2
2
  if(typeof exports === 'object' && typeof module === 'object')
3
- module.exports = factory(require("underscore"), require("expensify-common/lib/str"), require("lodash/get"), require("localforage"), require("lodash/mergeWith"), require("react"));
3
+ module.exports = factory(require("underscore"), require("expensify-common/lib/str"), require("lodash/get"), require("localforage"), require("lodash/transform"), require("react"));
4
4
  else if(typeof define === 'function' && define.amd)
5
- define(["underscore", "expensify-common/lib/str", "lodash/get", "localforage", "lodash/mergeWith", "react"], factory);
5
+ define(["underscore", "expensify-common/lib/str", "lodash/get", "localforage", "lodash/transform", "react"], factory);
6
6
  else if(typeof exports === 'object')
7
- exports["react-native-onyx/web"] = factory(require("underscore"), require("expensify-common/lib/str"), require("lodash/get"), require("localforage"), require("lodash/mergeWith"), require("react"));
7
+ exports["react-native-onyx/web"] = factory(require("underscore"), require("expensify-common/lib/str"), require("lodash/get"), require("localforage"), require("lodash/transform"), require("react"));
8
8
  else
9
- root["react-native-onyx/web"] = factory(root["underscore"], root["expensify-common/lib/str"], root["lodash/get"], root["localforage"], root["lodash/mergeWith"], root["react"]);
10
- })(self, (__WEBPACK_EXTERNAL_MODULE_underscore__, __WEBPACK_EXTERNAL_MODULE_expensify_common_lib_str__, __WEBPACK_EXTERNAL_MODULE_lodash_get__, __WEBPACK_EXTERNAL_MODULE_localforage__, __WEBPACK_EXTERNAL_MODULE_lodash_mergeWith__, __WEBPACK_EXTERNAL_MODULE_react__) => {
9
+ root["react-native-onyx/web"] = factory(root["underscore"], root["expensify-common/lib/str"], root["lodash/get"], root["localforage"], root["lodash/transform"], root["react"]);
10
+ })(self, (__WEBPACK_EXTERNAL_MODULE_underscore__, __WEBPACK_EXTERNAL_MODULE_expensify_common_lib_str__, __WEBPACK_EXTERNAL_MODULE_lodash_get__, __WEBPACK_EXTERNAL_MODULE_localforage__, __WEBPACK_EXTERNAL_MODULE_lodash_transform__, __WEBPACK_EXTERNAL_MODULE_react__) => {
11
11
  return /******/ (() => { // webpackBootstrap
12
12
  /******/ var __webpack_modules__ = ({
13
13
 
@@ -497,7 +497,8 @@ var _storage = _interopRequireDefault(__webpack_require__(/*! ./storage */ "./li
497
497
  var Logger = _interopRequireWildcard(__webpack_require__(/*! ./Logger */ "./lib/Logger.js"));
498
498
  var _OnyxCache = _interopRequireDefault(__webpack_require__(/*! ./OnyxCache */ "./lib/OnyxCache.js"));
499
499
  var _createDeferredTask = _interopRequireDefault(__webpack_require__(/*! ./createDeferredTask */ "./lib/createDeferredTask.js"));
500
- var _mergeWithCustomized = _interopRequireDefault(__webpack_require__(/*! ./mergeWithCustomized */ "./lib/mergeWithCustomized.js"));function _getRequireWildcardCache(nodeInterop) {if (typeof WeakMap !== "function") return null;var cacheBabelInterop = new WeakMap();var cacheNodeInterop = new WeakMap();return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) {return nodeInterop ? cacheNodeInterop : cacheBabelInterop;})(nodeInterop);}function _interopRequireWildcard(obj, nodeInterop) {if (!nodeInterop && obj && obj.__esModule) {return obj;}if (obj === null || typeof obj !== "object" && typeof obj !== "function") {return { default: obj };}var cache = _getRequireWildcardCache(nodeInterop);if (cache && cache.has(obj)) {return cache.get(obj);}var newObj = {};var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;for (var key in obj) {if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;if (desc && (desc.get || desc.set)) {Object.defineProperty(newObj, key, desc);} else {newObj[key] = obj[key];}}}newObj.default = obj;if (cache) {cache.set(obj, newObj);}return newObj;} /* eslint-disable no-continue */
500
+ var _fastMerge = _interopRequireDefault(__webpack_require__(/*! ./fastMerge */ "./lib/fastMerge.js"));
501
+ var PerformanceUtils = _interopRequireWildcard(__webpack_require__(/*! ./metrics/PerformanceUtils */ "./lib/metrics/PerformanceUtils.js"));function _getRequireWildcardCache(nodeInterop) {if (typeof WeakMap !== "function") return null;var cacheBabelInterop = new WeakMap();var cacheNodeInterop = new WeakMap();return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) {return nodeInterop ? cacheNodeInterop : cacheBabelInterop;})(nodeInterop);}function _interopRequireWildcard(obj, nodeInterop) {if (!nodeInterop && obj && obj.__esModule) {return obj;}if (obj === null || typeof obj !== "object" && typeof obj !== "function") {return { default: obj };}var cache = _getRequireWildcardCache(nodeInterop);if (cache && cache.has(obj)) {return cache.get(obj);}var newObj = {};var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;for (var key in obj) {if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;if (desc && (desc.get || desc.set)) {Object.defineProperty(newObj, key, desc);} else {newObj[key] = obj[key];}}}newObj.default = obj;if (cache) {cache.set(obj, newObj);}return newObj;} /* eslint-disable no-continue */
501
502
 
502
503
  // Keeps track of the last connectionID that was used so we can keep incrementing it
503
504
  var lastConnectionID = 0;
@@ -814,12 +815,13 @@ function keysChanged(collectionKey, partialCollection) {
814
815
  if (isSubscribedToCollectionKey) {
815
816
  subscriber.withOnyxInstance.setState(function (prevState) {
816
817
  var finalCollection = _underscore.default.clone(prevState[subscriber.statePropertyName] || {});
817
-
818
818
  var dataKeys = _underscore.default.keys(partialCollection);
819
819
  for (var _j = 0; _j < dataKeys.length; _j++) {
820
820
  var _dataKey = dataKeys[_j];
821
821
  finalCollection[_dataKey] = cachedCollection[_dataKey];
822
822
  }
823
+
824
+ PerformanceUtils.logSetStateCall(subscriber, prevState[subscriber.statePropertyName], finalCollection, 'keysChanged', collectionKey);
823
825
  return (0, _defineProperty2.default)({},
824
826
  subscriber.statePropertyName, finalCollection);
825
827
 
@@ -836,9 +838,18 @@ function keysChanged(collectionKey, partialCollection) {
836
838
  return "continue";
837
839
  }
838
840
 
839
- subscriber.withOnyxInstance.setState((0, _defineProperty2.default)({},
840
- subscriber.statePropertyName, cachedCollection[subscriber.key]));
841
+ subscriber.withOnyxInstance.setState(function (prevState) {
842
+ var data = cachedCollection[subscriber.key];
843
+ var previousData = prevState[subscriber.statePropertyName];
844
+ if (data === previousData) {
845
+ return null;
846
+ }
847
+
848
+ PerformanceUtils.logSetStateCall(subscriber, previousData, data, 'keysChanged', collectionKey);
849
+ return (0, _defineProperty2.default)({},
850
+ subscriber.statePropertyName, data);
841
851
 
852
+ });
842
853
  }
843
854
  }};for (var i = stateMappingKeys.length; i--;) {var _ret = _loop(i);if (_ret === "continue") continue;
844
855
  }
@@ -888,20 +899,30 @@ function keyChanged(key, data) {
888
899
  if (isCollectionKey(subscriber.key)) {
889
900
  subscriber.withOnyxInstance.setState(function (prevState) {
890
901
  var collection = prevState[subscriber.statePropertyName] || {};
891
- return (0, _defineProperty2.default)({},
892
- subscriber.statePropertyName, (0, _extends3.default)({},
902
+ var newCollection = (0, _extends3.default)({},
893
903
  collection, (0, _defineProperty2.default)({},
894
- key, data)));
904
+ key, data));
895
905
 
906
+ PerformanceUtils.logSetStateCall(subscriber, collection, newCollection, 'keyChanged', key);
907
+ return (0, _defineProperty2.default)({},
908
+ subscriber.statePropertyName, newCollection);
896
909
 
897
910
  });
898
911
  return "continue";
899
912
  }
900
913
 
901
914
  // If we did not match on a collection key then we just set the new data to the state property
902
- subscriber.withOnyxInstance.setState((0, _defineProperty2.default)({},
903
- subscriber.statePropertyName, data));
915
+ subscriber.withOnyxInstance.setState(function (prevState) {
916
+ var previousData = prevState[subscriber.statePropertyName];
917
+ if (previousData === data) {
918
+ return null;
919
+ }
920
+
921
+ PerformanceUtils.logSetStateCall(subscriber, previousData, data, 'keyChanged', key);
922
+ return (0, _defineProperty2.default)({},
923
+ subscriber.statePropertyName, data);
904
924
 
925
+ });
905
926
  return "continue";
906
927
  }
907
928
 
@@ -930,6 +951,7 @@ function sendDataToConnection(config, val, matchedKey) {
930
951
  }
931
952
 
932
953
  if (config.withOnyxInstance) {
954
+ PerformanceUtils.logSetStateCall(config, null, val, 'sendDataToConnection');
933
955
  config.withOnyxInstance.setWithOnyxState(config.statePropertyName, val);
934
956
  } else if (_underscore.default.isFunction(config.callback)) {
935
957
  config.callback(val, matchedKey);
@@ -1252,7 +1274,9 @@ function applyMerge(key, data) {
1252
1274
  if (_underscore.default.isObject(data) || _underscore.default.every(mergeValues, _underscore.default.isObject)) {
1253
1275
  // Object values are merged one after the other
1254
1276
  return _underscore.default.reduce(mergeValues, function (modifiedData, mergeValue) {
1255
- var newData = (0, _mergeWithCustomized.default)({}, modifiedData, mergeValue);
1277
+ // lodash adds a small overhead so we don't use it here
1278
+ // eslint-disable-next-line prefer-object-spread, rulesdir/prefer-underscore-method
1279
+ var newData = (0, _extends3.default)({}, (0, _fastMerge.default)(modifiedData, mergeValue));
1256
1280
 
1257
1281
  // We will also delete any object keys that are undefined or null.
1258
1282
  // Deleting keys is not supported by AsyncStorage so we do it this way.
@@ -1323,7 +1347,7 @@ function initializeWithDefaultKeyStates() {
1323
1347
  then(function (pairs) {
1324
1348
  var asObject = _underscore.default.object(pairs);
1325
1349
 
1326
- var merged = (0, _mergeWithCustomized.default)(asObject, defaultKeyStates);
1350
+ var merged = (0, _fastMerge.default)(asObject, defaultKeyStates);
1327
1351
  _OnyxCache.default.merge(merged);
1328
1352
  _underscore.default.each(merged, function (val, key) {return keyChanged(key, val);});
1329
1353
  });
@@ -1430,7 +1454,7 @@ function mergeCollection(collectionKey, collection) {
1430
1454
  */
1431
1455
  function update(data) {
1432
1456
  // First, validate the Onyx object is in the format we expect
1433
- _underscore.default.each(data, function (_ref3) {var onyxMethod = _ref3.onyxMethod,key = _ref3.key;
1457
+ _underscore.default.each(data, function (_ref5) {var onyxMethod = _ref5.onyxMethod,key = _ref5.key;
1434
1458
  if (!_underscore.default.contains(['clear', 'set', 'merge', 'mergecollection'], onyxMethod)) {
1435
1459
  throw new Error("Invalid onyxMethod " + onyxMethod + " in Onyx update.");
1436
1460
  }
@@ -1439,7 +1463,7 @@ function update(data) {
1439
1463
  }
1440
1464
  });
1441
1465
 
1442
- _underscore.default.each(data, function (_ref4) {var onyxMethod = _ref4.onyxMethod,key = _ref4.key,value = _ref4.value;
1466
+ _underscore.default.each(data, function (_ref6) {var onyxMethod = _ref6.onyxMethod,key = _ref6.key,value = _ref6.value;
1443
1467
  switch (onyxMethod) {
1444
1468
  case 'set':
1445
1469
  set(key, value);
@@ -1477,6 +1501,7 @@ function update(data) {
1477
1501
  * of Onyx running in different tabs/windows. Defaults to true for platforms that support local storage (web/desktop)
1478
1502
  * @param {String[]} [option.keysToDisableSyncEvents=[]] Contains keys for which
1479
1503
  * we want to disable sync event across tabs.
1504
+ * @param {Boolean} [options.debugSetState] Enables debugging setState() calls to connected components.
1480
1505
  * @example
1481
1506
  * Onyx.init({
1482
1507
  * keys: ONYXKEYS,
@@ -1493,13 +1518,18 @@ function init()
1493
1518
 
1494
1519
 
1495
1520
 
1496
- {var _ref5 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},_ref5$keys = _ref5.keys,keys = _ref5$keys === void 0 ? {} : _ref5$keys,_ref5$initialKeyState = _ref5.initialKeyStates,initialKeyStates = _ref5$initialKeyState === void 0 ? {} : _ref5$initialKeyState,_ref5$safeEvictionKey = _ref5.safeEvictionKeys,safeEvictionKeys = _ref5$safeEvictionKey === void 0 ? [] : _ref5$safeEvictionKey,_ref5$maxCachedKeysCo = _ref5.maxCachedKeysCount,maxCachedKeysCount = _ref5$maxCachedKeysCo === void 0 ? 1000 : _ref5$maxCachedKeysCo,_ref5$captureMetrics = _ref5.captureMetrics,captureMetrics = _ref5$captureMetrics === void 0 ? false : _ref5$captureMetrics,_ref5$shouldSyncMulti = _ref5.shouldSyncMultipleInstances,shouldSyncMultipleInstances = _ref5$shouldSyncMulti === void 0 ? Boolean(__webpack_require__.g.localStorage) : _ref5$shouldSyncMulti,_ref5$keysToDisableSy = _ref5.keysToDisableSyncEvents,keysToDisableSyncEvents = _ref5$keysToDisableSy === void 0 ? [] : _ref5$keysToDisableSy;
1521
+
1522
+ {var _ref7 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},_ref7$keys = _ref7.keys,keys = _ref7$keys === void 0 ? {} : _ref7$keys,_ref7$initialKeyState = _ref7.initialKeyStates,initialKeyStates = _ref7$initialKeyState === void 0 ? {} : _ref7$initialKeyState,_ref7$safeEvictionKey = _ref7.safeEvictionKeys,safeEvictionKeys = _ref7$safeEvictionKey === void 0 ? [] : _ref7$safeEvictionKey,_ref7$maxCachedKeysCo = _ref7.maxCachedKeysCount,maxCachedKeysCount = _ref7$maxCachedKeysCo === void 0 ? 1000 : _ref7$maxCachedKeysCo,_ref7$captureMetrics = _ref7.captureMetrics,captureMetrics = _ref7$captureMetrics === void 0 ? false : _ref7$captureMetrics,_ref7$shouldSyncMulti = _ref7.shouldSyncMultipleInstances,shouldSyncMultipleInstances = _ref7$shouldSyncMulti === void 0 ? Boolean(__webpack_require__.g.localStorage) : _ref7$shouldSyncMulti,_ref7$keysToDisableSy = _ref7.keysToDisableSyncEvents,keysToDisableSyncEvents = _ref7$keysToDisableSy === void 0 ? [] : _ref7$keysToDisableSy,_ref7$debugSetState = _ref7.debugSetState,debugSetState = _ref7$debugSetState === void 0 ? false : _ref7$debugSetState;
1497
1523
  if (captureMetrics) {
1498
1524
  // The code here is only bundled and applied when the captureMetrics is set
1499
1525
  // eslint-disable-next-line no-use-before-define
1500
1526
  applyDecorators();
1501
1527
  }
1502
1528
 
1529
+ if (debugSetState) {
1530
+ PerformanceUtils.setShouldDebugSetState(true);
1531
+ }
1532
+
1503
1533
  if (maxCachedKeysCount > 0) {
1504
1534
  _OnyxCache.default.setRecentKeysLimit(maxCachedKeysCount);
1505
1535
  }
@@ -1592,8 +1622,8 @@ Onyx;exports["default"] = _default;
1592
1622
  \**************************/
1593
1623
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1594
1624
 
1595
- var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "./node_modules/@babel/runtime/helpers/interopRequireDefault.js");Object.defineProperty(exports, "__esModule", ({ value: true }));exports["default"] = void 0;var _toConsumableArray2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/toConsumableArray */ "./node_modules/@babel/runtime/helpers/toConsumableArray.js"));var _classCallCheck2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/classCallCheck */ "./node_modules/@babel/runtime/helpers/classCallCheck.js"));var _createClass2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/createClass */ "./node_modules/@babel/runtime/helpers/createClass.js"));var _underscore = _interopRequireDefault(__webpack_require__(/*! underscore */ "underscore"));
1596
- var _mergeWithCustomized = _interopRequireDefault(__webpack_require__(/*! ./mergeWithCustomized */ "./lib/mergeWithCustomized.js"));
1625
+ var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "./node_modules/@babel/runtime/helpers/interopRequireDefault.js");Object.defineProperty(exports, "__esModule", ({ value: true }));exports["default"] = void 0;var _toConsumableArray2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/toConsumableArray */ "./node_modules/@babel/runtime/helpers/toConsumableArray.js"));var _extends2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/extends */ "./node_modules/@babel/runtime/helpers/extends.js"));var _classCallCheck2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/classCallCheck */ "./node_modules/@babel/runtime/helpers/classCallCheck.js"));var _createClass2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/createClass */ "./node_modules/@babel/runtime/helpers/createClass.js"));var _underscore = _interopRequireDefault(__webpack_require__(/*! underscore */ "underscore"));
1626
+ var _fastMerge = _interopRequireDefault(__webpack_require__(/*! ./fastMerge */ "./lib/fastMerge.js"));
1597
1627
 
1598
1628
  var isDefined = _underscore.default.negate(_underscore.default.isUndefined);
1599
1629
 
@@ -1704,7 +1734,9 @@ OnyxCache = /*#__PURE__*/function () {
1704
1734
  * @param {Record<string, *>} data - a map of (cache) key - values
1705
1735
  */ }, { key: "merge", value: function merge(
1706
1736
  data) {var _this = this;
1707
- this.storageMap = (0, _mergeWithCustomized.default)({}, this.storageMap, data);
1737
+ // lodash adds a small overhead so we don't use it here
1738
+ // eslint-disable-next-line prefer-object-spread, rulesdir/prefer-underscore-method
1739
+ this.storageMap = (0, _extends2.default)({}, (0, _fastMerge.default)(this.storageMap, data));
1708
1740
 
1709
1741
  var storageKeys = this.getAllKeys();
1710
1742
  var mergedKeys = _underscore.default.keys(data);
@@ -1875,38 +1907,150 @@ function createDeferredTask() {
1875
1907
 
1876
1908
  /***/ }),
1877
1909
 
1878
- /***/ "./lib/mergeWithCustomized.js":
1879
- /*!************************************!*\
1880
- !*** ./lib/mergeWithCustomized.js ***!
1881
- \************************************/
1882
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1910
+ /***/ "./lib/fastMerge.js":
1911
+ /*!**************************!*\
1912
+ !*** ./lib/fastMerge.js ***!
1913
+ \**************************/
1914
+ /***/ ((__unused_webpack_module, exports) => {
1883
1915
 
1884
- var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "./node_modules/@babel/runtime/helpers/interopRequireDefault.js");Object.defineProperty(exports, "__esModule", ({ value: true }));exports["default"] = void 0;var _mergeWith = _interopRequireDefault(__webpack_require__(/*! lodash/mergeWith */ "lodash/mergeWith"));
1916
+ Object.defineProperty(exports, "__esModule", ({ value: true }));exports["default"] = void 0; // Mostly copied from https://medium.com/@lubaka.a/how-to-remove-lodash-performance-improvement-b306669ad0e1
1885
1917
 
1886
1918
  /**
1887
- * When merging 2 objects into onyx that contain an array, we want to completely replace the array instead of the default
1888
- * behavior which is to merge each item by its index.
1889
- * ie:
1890
- * merge({a: [1]}, {a: [2,3]}):
1891
- * - In the default implementation would produce {a:[1,3]}
1892
- * - With this function would produce: {a: [2,3]}
1893
- * @param {*} objValue
1894
- * @param {*} srcValue
1895
- * @return {*}
1896
- */
1897
- // eslint-disable-next-line rulesdir/prefer-early-return
1898
- function customizerForMergeWith(objValue, srcValue) {
1919
+ * @param {mixed} val
1920
+ * @returns {boolean}
1921
+ */
1922
+ function isMergeableObject(val) {
1923
+ var nonNullObject = val != null ? typeof val === 'object' : false;
1924
+ return nonNullObject &&
1925
+ Object.prototype.toString.call(val) !== '[object RegExp]' &&
1926
+ Object.prototype.toString.call(val) !== '[object Date]';
1927
+ }
1928
+
1929
+ /**
1930
+ * @param {Object} target
1931
+ * @param {Object} source
1932
+ * @returns {Object}
1933
+ */
1934
+ function mergeObject(target, source) {
1935
+ var destination = {};
1936
+ if (isMergeableObject(target)) {
1937
+ // lodash adds a small overhead so we don't use it here
1938
+ // eslint-disable-next-line rulesdir/prefer-underscore-method
1939
+ var targetKeys = Object.keys(target);
1940
+ for (var i = 0; i < targetKeys.length; ++i) {
1941
+ var key = targetKeys[i];
1942
+ destination[key] = target[key];
1943
+ }
1944
+ }
1945
+
1946
+ // lodash adds a small overhead so we don't use it here
1899
1947
  // eslint-disable-next-line rulesdir/prefer-underscore-method
1900
- if (Array.isArray(objValue)) {
1901
- return srcValue;
1948
+ var sourceKeys = Object.keys(source);
1949
+ for (var _i = 0; _i < sourceKeys.length; ++_i) {
1950
+ var _key = sourceKeys[_i];
1951
+ if (source[_key] === undefined) {
1952
+ // eslint-disable-next-line no-continue
1953
+ continue;
1954
+ }
1955
+ if (!isMergeableObject(source[_key]) || !target[_key]) {
1956
+ destination[_key] = source[_key];
1957
+ } else {
1958
+ // eslint-disable-next-line no-use-before-define
1959
+ destination[_key] = fastMerge(target[_key], source[_key]);
1960
+ }
1902
1961
  }
1962
+
1963
+ return destination;
1903
1964
  }
1904
1965
 
1905
- function mergeWithCustomized() {for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {args[_key] = arguments[_key];}
1906
- return _mergeWith.default.apply(void 0, args.concat([customizerForMergeWith]));
1966
+ /**
1967
+ * @param {Object|Array} target
1968
+ * @param {Object|Array} source
1969
+ * @returns {Object|Array}
1970
+ */
1971
+ function fastMerge(target, source) {
1972
+ // lodash adds a small overhead so we don't use it here
1973
+ // eslint-disable-next-line rulesdir/prefer-underscore-method
1974
+ var array = Array.isArray(source);
1975
+ if (array) {
1976
+ return source;
1977
+ }
1978
+ return mergeObject(target, source);
1907
1979
  }var _default =
1908
1980
 
1909
- mergeWithCustomized;exports["default"] = _default;
1981
+ fastMerge;exports["default"] = _default;
1982
+
1983
+ /***/ }),
1984
+
1985
+ /***/ "./lib/metrics/PerformanceUtils.js":
1986
+ /*!*****************************************!*\
1987
+ !*** ./lib/metrics/PerformanceUtils.js ***!
1988
+ \*****************************************/
1989
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1990
+
1991
+ var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "./node_modules/@babel/runtime/helpers/interopRequireDefault.js");Object.defineProperty(exports, "__esModule", ({ value: true }));exports.logSetStateCall = logSetStateCall;exports.setShouldDebugSetState = setShouldDebugSetState;var _transform = _interopRequireDefault(__webpack_require__(/*! lodash/transform */ "lodash/transform"));
1992
+ var _underscore = _interopRequireDefault(__webpack_require__(/*! underscore */ "underscore"));
1993
+
1994
+ var debugSetState = false;
1995
+
1996
+ /**
1997
+ * @param {Boolean} debug
1998
+ */
1999
+ function setShouldDebugSetState(debug) {
2000
+ debugSetState = debug;
2001
+ }
2002
+
2003
+ /**
2004
+ * Deep diff between two objects. Useful for figuring out what changed about an object from one render to the next so
2005
+ * that state and props updates can be optimized.
2006
+ *
2007
+ * @param {Object} object
2008
+ * @param {Object} base
2009
+ * @return {Object}
2010
+ */
2011
+ function diffObject(object, base) {
2012
+ function changes(obj, comparisonObject) {
2013
+ return (0, _transform.default)(obj, function (result, value, key) {
2014
+ if (_underscore.default.isEqual(value, comparisonObject[key])) {
2015
+ return;
2016
+ }
2017
+
2018
+ // eslint-disable-next-line no-param-reassign
2019
+ result[key] = _underscore.default.isObject(value) && _underscore.default.isObject(comparisonObject[key]) ?
2020
+ changes(value, comparisonObject[key]) :
2021
+ value;
2022
+ });
2023
+ }
2024
+ return changes(object, base);
2025
+ }
2026
+
2027
+ /**
2028
+ * Provide insights into why a setState() call occurred by diffing the before and after values.
2029
+ *
2030
+ * @param {Object} mapping
2031
+ * @param {*} previousValue
2032
+ * @param {*} newValue
2033
+ * @param {String} caller
2034
+ * @param {String} [keyThatChanged]
2035
+ */
2036
+ function logSetStateCall(mapping, previousValue, newValue, caller, keyThatChanged) {
2037
+ if (!debugSetState) {
2038
+ return;
2039
+ }
2040
+
2041
+ var logParams = {};
2042
+ if (keyThatChanged) {
2043
+ logParams.keyThatChanged = keyThatChanged;
2044
+ }
2045
+ if (_underscore.default.isObject(newValue) && _underscore.default.isObject(previousValue)) {
2046
+ logParams.difference = diffObject(previousValue, newValue);
2047
+ } else {
2048
+ logParams.previousValue = previousValue;
2049
+ logParams.newValue = newValue;
2050
+ }
2051
+
2052
+ console.debug("[Onyx-Debug] " + mapping.displayName + " setState() called. Subscribed to key '" + mapping.key + "' (" + caller + ")", logParams);
2053
+ }
1910
2054
 
1911
2055
  /***/ }),
1912
2056
 
@@ -2008,7 +2152,7 @@ _WebStorage.default;exports["default"] = _default;
2008
2152
  \**********************************************/
2009
2153
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
2010
2154
 
2011
- var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "./node_modules/@babel/runtime/helpers/interopRequireDefault.js");Object.defineProperty(exports, "__esModule", ({ value: true }));exports["default"] = void 0;var _slicedToArray2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/slicedToArray */ "./node_modules/@babel/runtime/helpers/slicedToArray.js"));
2155
+ var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "./node_modules/@babel/runtime/helpers/interopRequireDefault.js");Object.defineProperty(exports, "__esModule", ({ value: true }));exports["default"] = void 0;var _slicedToArray2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/slicedToArray */ "./node_modules/@babel/runtime/helpers/slicedToArray.js"));var _extends2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/extends */ "./node_modules/@babel/runtime/helpers/extends.js"));
2012
2156
 
2013
2157
 
2014
2158
 
@@ -2017,7 +2161,7 @@ var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/inte
2017
2161
  var _localforage = _interopRequireDefault(__webpack_require__(/*! localforage */ "localforage"));
2018
2162
  var _underscore = _interopRequireDefault(__webpack_require__(/*! underscore */ "underscore"));
2019
2163
  var _SyncQueue = _interopRequireDefault(__webpack_require__(/*! ../../SyncQueue */ "./lib/SyncQueue.js"));
2020
- var _mergeWithCustomized = _interopRequireDefault(__webpack_require__(/*! ../../mergeWithCustomized */ "./lib/mergeWithCustomized.js")); /**
2164
+ var _fastMerge = _interopRequireDefault(__webpack_require__(/*! ../../fastMerge */ "./lib/fastMerge.js")); /**
2021
2165
  * @file
2022
2166
  * The storage provider based on localforage allows us to store most anything in its
2023
2167
  * natural form in the underlying DB without having to stringify or de-stringify it
@@ -2033,8 +2177,11 @@ var provider = {
2033
2177
  if (shouldMerge) {
2034
2178
  return _localforage.default.getItem(key).
2035
2179
  then(function (existingValue) {
2036
- var newValue = _underscore.default.isObject(existingValue) ?
2037
- (0, _mergeWithCustomized.default)({}, existingValue, value) :
2180
+ var newValue = _underscore.default.isObject(existingValue)
2181
+
2182
+ // lodash adds a small overhead so we don't use it here
2183
+ // eslint-disable-next-line prefer-object-spread, rulesdir/prefer-underscore-method
2184
+ ? (0, _extends2.default)({}, (0, _fastMerge.default)(existingValue, value)) :
2038
2185
  value;
2039
2186
  return _localforage.default.setItem(key, newValue);
2040
2187
  });
@@ -2155,8 +2302,8 @@ function _default(mapOnyxToState) {var _this = this;
2155
2302
  omit(function (config) {return config.initWithStoredValues === false;}).
2156
2303
  keys().
2157
2304
  value();
2158
-
2159
- return function (WrappedComponent) {var
2305
+ return function (WrappedComponent) {
2306
+ var displayName = getDisplayName(WrappedComponent);var
2160
2307
  withOnyx = /*#__PURE__*/function (_React$Component) {(0, _inherits2.default)(withOnyx, _React$Component);var _super = _createSuper(withOnyx);
2161
2308
  function withOnyx(props) {var _this2;(0, _classCallCheck2.default)(this, withOnyx);
2162
2309
  _this2 = _super.call(this, props);
@@ -2281,7 +2428,8 @@ function _default(mapOnyxToState) {var _this = this;
2281
2428
  mapping, {
2282
2429
  key: key,
2283
2430
  statePropertyName: statePropertyName,
2284
- withOnyxInstance: this }));
2431
+ withOnyxInstance: this,
2432
+ displayName: displayName }));
2285
2433
 
2286
2434
  } }, { key: "render", value: function render()
2287
2435
 
@@ -2305,7 +2453,7 @@ function _default(mapOnyxToState) {var _this = this;
2305
2453
  , (0, _extends2.default)({}, propsToPass,
2306
2454
 
2307
2455
  stateToPass, {
2308
- ref: this.props.forwardedRef, __self: this, __source: { fileName: _jsxFileName, lineNumber: 173, columnNumber: 21 } })));
2456
+ ref: this.props.forwardedRef, __self: this, __source: { fileName: _jsxFileName, lineNumber: 174, columnNumber: 21 } })));
2309
2457
 
2310
2458
 
2311
2459
  } }]);return withOnyx;}(_react.default.Component);
@@ -2320,11 +2468,11 @@ function _default(mapOnyxToState) {var _this = this;
2320
2468
  withOnyx.defaultProps = {
2321
2469
  forwardedRef: undefined };
2322
2470
 
2323
- withOnyx.displayName = "withOnyx(" + getDisplayName(WrappedComponent) + ")";
2471
+ withOnyx.displayName = "withOnyx(" + displayName + ")";
2324
2472
  return _react.default.forwardRef(function (props, ref) {
2325
2473
  var Component = withOnyx;
2326
2474
  // eslint-disable-next-line react/jsx-props-no-spreading
2327
- return /*#__PURE__*/_react.default.createElement(Component, (0, _extends2.default)({}, props, { forwardedRef: ref, __self: _this, __source: { fileName: _jsxFileName, lineNumber: 197, columnNumber: 20 } }));
2475
+ return /*#__PURE__*/_react.default.createElement(Component, (0, _extends2.default)({}, props, { forwardedRef: ref, __self: _this, __source: { fileName: _jsxFileName, lineNumber: 198, columnNumber: 20 } }));
2328
2476
  });
2329
2477
  };
2330
2478
  }
@@ -3436,14 +3584,14 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_lodash_get__;
3436
3584
 
3437
3585
  /***/ }),
3438
3586
 
3439
- /***/ "lodash/mergeWith":
3587
+ /***/ "lodash/transform":
3440
3588
  /*!***********************************!*\
3441
- !*** external "lodash/mergeWith" ***!
3589
+ !*** external "lodash/transform" ***!
3442
3590
  \***********************************/
3443
3591
  /***/ ((module) => {
3444
3592
 
3445
3593
  "use strict";
3446
- module.exports = __WEBPACK_EXTERNAL_MODULE_lodash_mergeWith__;
3594
+ module.exports = __WEBPACK_EXTERNAL_MODULE_lodash_transform__;
3447
3595
 
3448
3596
  /***/ }),
3449
3597