UNPKG

typhonjs-object-util

Version:
886 lines (752 loc) 35.1 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _freeze = require('babel-runtime/core-js/object/freeze'); var _freeze2 = _interopRequireDefault(_freeze); var _set = require('babel-runtime/core-js/set'); var _set2 = _interopRequireDefault(_set); var _stringify = require('babel-runtime/core-js/json/stringify'); var _stringify2 = _interopRequireDefault(_stringify); var _keys = require('babel-runtime/core-js/object/keys'); var _keys2 = _interopRequireDefault(_keys); var _getIterator2 = require('babel-runtime/core-js/get-iterator'); var _getIterator3 = _interopRequireDefault(_getIterator2); var _isInteger = require('babel-runtime/core-js/number/is-integer'); var _isInteger2 = _interopRequireDefault(_isInteger); var _typeof2 = require('babel-runtime/helpers/typeof'); var _typeof3 = _interopRequireDefault(_typeof2); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); exports.onPluginLoad = onPluginLoad; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Provides common object manipulation utilities including depth traversal, obtaining accessors, safely setting values / * equality tests, and validation. * * Support for typhonjs-plugin-manager is enabled. */ var ObjectUtil = function () { function ObjectUtil() { (0, _classCallCheck3.default)(this, ObjectUtil); } (0, _createClass3.default)(ObjectUtil, null, [{ key: 'deepFreeze', /** * Freezes all entries traversed that are objects including entries in arrays. * * @param {object|Array} data - An object or array. * * @param {string[]} skipFreezeKeys - An array of strings indicating keys of objects to not freeze. * * @returns {object|Array} */ value: function deepFreeze(data) { var skipFreezeKeys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; /* istanbul ignore if */ if ((typeof data === 'undefined' ? 'undefined' : (0, _typeof3.default)(data)) !== 'object') { throw new TypeError('\'data\' is not an \'object\'.'); } /* istanbul ignore if */ if (!Array.isArray(skipFreezeKeys)) { throw new TypeError('\'skipFreezeKeys\' is not an \'array\'.'); } return _deepFreeze(data, skipFreezeKeys); } /** * Performs a naive depth traversal of an object / array. The data structure _must not_ have circular references. * The result of the callback function is used to modify in place the given data. * * @param {object|Array} data - An object or array. * * @param {function} func - A callback function to process leaf values in children arrays or object members. * * @param {boolean} modify - If true then the result of the callback function is used to modify in place * the given data. * * @returns {*} */ }, { key: 'depthTraverse', value: function depthTraverse(data, func) { var modify = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; /* istanbul ignore if */ if ((typeof data === 'undefined' ? 'undefined' : (0, _typeof3.default)(data)) !== 'object') { throw new TypeError('\'data\' is not an \'object\'.'); } /* istanbul ignore if */ if (typeof func !== 'function') { throw new TypeError('\'func\' is not a \'function\'.'); } return _depthTraverse(data, func, modify); } /** * Returns a list of accessor keys by traversing the given object. * * @param {object} data - An object to traverse for accessor keys. * * @returns {Array} */ }, { key: 'getAccessorList', value: function getAccessorList(data) { if ((typeof data === 'undefined' ? 'undefined' : (0, _typeof3.default)(data)) !== 'object') { throw new TypeError('getAccessorList error: \'data\' is not an \'object\'.'); } return _getAccessorList(data); } /** * Provides a way to safely access an objects data / entries given an accessor string which describes the * entries to walk. To access deeper entries into the object format the accessor string with `.` between entries * to walk. * * @param {object} data - An object to access entry data. * * @param {string} accessor - A string describing the entries to access. * * @param {*} defaultValue - (Optional) A default value to return if an entry for accessor is not found. * * @returns {*} */ }, { key: 'safeAccess', value: function safeAccess(data, accessor) { var defaultValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : void 0; if ((typeof data === 'undefined' ? 'undefined' : (0, _typeof3.default)(data)) !== 'object') { return defaultValue; } if (typeof accessor !== 'string') { return defaultValue; } var access = accessor.split('.'); // Walk through the given object by the accessor indexes. for (var cntr = 0; cntr < access.length; cntr++) { // If the next level of object access is undefined or null then return the empty string. if (typeof data[access[cntr]] === 'undefined' || data[access[cntr]] === null) { return defaultValue; } data = data[access[cntr]]; } return data; } /** * Provides a way to safely batch set an objects data / entries given an array of accessor strings which describe the * entries to walk. To access deeper entries into the object format the accessor string with `.` between entries * to walk. If value is an object the accessor will be used to access a target value from `value` which is * subsequently set to `data` by the given operation. If `value` is not an object it will be used as the target * value to set across all accessors. * * @param {object} data - An object to access entry data. * * @param {Array<string>} accessors - A string describing the entries to access. * * @param {object|*} value - A new value to set if an entry for accessor is found. * * @param {string} [operation='set'] - Operation to perform including: 'add', 'div', 'mult', 'set', * 'set-undefined', 'sub'. * * @param {object|*} [defaultAccessValue=0] - A new value to set if an entry for accessor is found. * * * @param {boolean} [createMissing=true] - If true missing accessor entries will be created as objects * automatically. */ }, { key: 'safeBatchSet', value: function safeBatchSet(data, accessors, value) { var operation = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'set'; var defaultAccessValue = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0; var createMissing = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true; if ((typeof data === 'undefined' ? 'undefined' : (0, _typeof3.default)(data)) !== 'object') { throw new TypeError('safeBatchSet Error: \'data\' is not an \'object\'.'); } if (!Array.isArray(accessors)) { throw new TypeError('safeBatchSet Error: \'accessors\' is not an \'array\'.'); } if ((typeof value === 'undefined' ? 'undefined' : (0, _typeof3.default)(value)) === 'object') { accessors.forEach(function (accessor) { var targetValue = ObjectUtil.safeAccess(value, accessor, defaultAccessValue); ObjectUtil.safeSet(data, accessor, targetValue, operation, createMissing); }); } else { accessors.forEach(function (accessor) { ObjectUtil.safeSet(data, accessor, value, operation, createMissing); }); } } /** * Compares a source object and values of entries against a target object. If the entries in the source object match * the target object then `true` is returned otherwise `false`. If either object is undefined or null then false * is returned. * * @param {object} source - Source object. * * @param {object} target - Target object. * * @returns {boolean} */ }, { key: 'safeEqual', value: function safeEqual(source, target) { if (typeof source === 'undefined' || source === null || typeof target === 'undefined' || target === null) { return false; } var sourceAccessors = ObjectUtil.getAccessorList(source); for (var cntr = 0; cntr < sourceAccessors.length; cntr++) { var accessor = sourceAccessors[cntr]; var sourceObjectValue = ObjectUtil.safeAccess(source, accessor); var targetObjectValue = ObjectUtil.safeAccess(target, accessor); if (sourceObjectValue !== targetObjectValue) { return false; } } return true; } /** * Provides a way to safely set an objects data / entries given an accessor string which describes the * entries to walk. To access deeper entries into the object format the accessor string with `.` between entries * to walk. * * @param {object} data - An object to access entry data. * * @param {string} accessor - A string describing the entries to access. * * @param {*} value - A new value to set if an entry for accessor is found. * * @param {string} [operation='set'] - Operation to perform including: 'add', 'div', 'mult', 'set', * 'set-undefined', 'sub'. * * @param {boolean} [createMissing=true] - If true missing accessor entries will be created as objects * automatically. * * @returns {boolean} True if successful. */ }, { key: 'safeSet', value: function safeSet(data, accessor, value) { var operation = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'set'; var createMissing = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; if ((typeof data === 'undefined' ? 'undefined' : (0, _typeof3.default)(data)) !== 'object') { throw new TypeError('safeSet Error: \'data\' is not an \'object\'.'); } if (typeof accessor !== 'string') { throw new TypeError('safeSet Error: \'accessor\' is not a \'string\'.'); } var access = accessor.split('.'); // Walk through the given object by the accessor indexes. for (var cntr = 0; cntr < access.length; cntr++) { // If data is an array perform validation that the accessor is a positive integer otherwise quit. if (Array.isArray(data)) { var number = +access[cntr]; if (!(0, _isInteger2.default)(number) || number < 0) { return false; } } if (cntr === access.length - 1) { switch (operation) { case 'add': data[access[cntr]] += value; break; case 'div': data[access[cntr]] /= value; break; case 'mult': data[access[cntr]] *= value; break; case 'set': data[access[cntr]] = value; break; case 'set-undefined': if (typeof data[access[cntr]] === 'undefined') { data[access[cntr]] = value; } break; case 'sub': data[access[cntr]] -= value; break; } } else { // If createMissing is true and the next level of object access is undefined then create a new object entry. if (createMissing && typeof data[access[cntr]] === 'undefined') { data[access[cntr]] = {}; } // Abort if the next level is null or not an object and containing a value. if (data[access[cntr]] === null || (0, _typeof3.default)(data[access[cntr]]) !== 'object') { return false; } data = data[access[cntr]]; } } return true; } /** * Performs bulk setting of values to the given data object. * * @param {object} data - The data object to set data. * * @param {object<string, *>} accessorValues - Object of accessor keys to values to set. * * @param {string} [operation='set'] - Operation to perform including: 'add', 'div', 'mult', 'set', 'sub'; * default (`set`). * * @param {boolean} [createMissing=true] - If true missing accessor entries will be created as objects * automatically. */ }, { key: 'safeSetAll', value: function safeSetAll(data, accessorValues) { var operation = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'set'; var createMissing = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; if ((typeof data === 'undefined' ? 'undefined' : (0, _typeof3.default)(data)) !== 'object') { throw new TypeError('\'data\' is not an \'object\'.'); } if ((typeof accessorValues === 'undefined' ? 'undefined' : (0, _typeof3.default)(accessorValues)) !== 'object') { throw new TypeError('\'accessorValues\' is not an \'object\'.'); } var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = (0, _getIterator3.default)((0, _keys2.default)(accessorValues)), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var accessor = _step.value; if (!accessorValues.hasOwnProperty(accessor)) { continue; } ObjectUtil.safeSet(data, accessor, accessorValues[accessor], operation, createMissing); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } /** * Performs bulk validation of data given an object, `validationData`, which describes all entries to test. * * @param {object} data - The data object to test. * * @param {object<string, ValidationEntry>} validationData - Key is the accessor / value is a validation entry. * * @param {string} [dataName='data'] - Optional name of data. * * @returns {boolean} True if validation passes otherwise an exception is thrown. */ }, { key: 'validate', value: function validate(data) { var validationData = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var dataName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'data'; if ((typeof data === 'undefined' ? 'undefined' : (0, _typeof3.default)(data)) !== 'object') { throw new TypeError('\'' + dataName + '\' is not an \'object\'.'); } if ((typeof validationData === 'undefined' ? 'undefined' : (0, _typeof3.default)(validationData)) !== 'object') { throw new TypeError('\'validationData\' is not an \'object\'.'); } var result = void 0; var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = (0, _getIterator3.default)((0, _keys2.default)(validationData)), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var key = _step2.value; if (!validationData.hasOwnProperty(key)) { continue; } var entry = validationData[key]; switch (entry.test) { case 'array': result = ObjectUtil.validateArray(data, key, entry, dataName); break; case 'entry': result = ObjectUtil.validateEntry(data, key, entry, dataName); break; case 'entry|array': result = ObjectUtil.validateEntryOrArray(data, key, entry, dataName); break; } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } return result; } // TODO: add docs after upgrading to latest WebStorm / better object destructuring support. // /** // * Validates all array entries against potential type and expected tests. // * // * @param {object} data - The data object to test. // * // * @param {string} accessor - A string describing the entries to access. // * // * @param {string} [type] - Tests with a typeof check. // * // * @param {function|Set<*>} [expected] - Optional function or set of expected values to test against. // * // * @param {string} [message] - Optional message to include. // * // * @param {boolean} [required] - When false if the accessor is missing validation is skipped. // * // * @param {boolean} [error=true] - When true and error is thrown otherwise a boolean is returned. // * // * @param {string} [dataName='data'] - Optional name of data. // * // * @returns {boolean} True if validation passes otherwise an exception is thrown. // */ }, { key: 'validateArray', value: function validateArray(data, accessor) { var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, _ref$type = _ref.type, type = _ref$type === undefined ? void 0 : _ref$type, _ref$expected = _ref.expected, expected = _ref$expected === undefined ? void 0 : _ref$expected, _ref$message = _ref.message, message = _ref$message === undefined ? void 0 : _ref$message, _ref$required = _ref.required, required = _ref$required === undefined ? true : _ref$required, _ref$error = _ref.error, error = _ref$error === undefined ? true : _ref$error; var dataName = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'data'; var dataArray = ObjectUtil.safeAccess(data, accessor); // A non-required entry is missing so return without validation. if (!required && typeof dataArray === 'undefined') { return true; } if (!Array.isArray(dataArray)) { if (error) { throw _validateError(TypeError, '\'' + dataName + '.' + accessor + '\' is not an \'array\'.'); } else { return false; } } if (typeof type === 'string') { for (var cntr = 0; cntr < dataArray.length; cntr++) { if (!((0, _typeof3.default)(dataArray[cntr]) === type)) { if (error) { var dataEntryString = (0, _typeof3.default)(dataArray[cntr]) === 'object' ? (0, _stringify2.default)(dataArray[cntr]) : dataArray[cntr]; throw _validateError(TypeError, '\'' + dataName + '.' + accessor + '[' + cntr + ']\': \'' + dataEntryString + '\' is not a \'' + type + '\'.'); } else { return false; } } } } // If expected is a function then test all array entries against the test function. If expected is a Set then // test all array entries for inclusion in the set. Otherwise if expected is a string then test that all array // entries as a `typeof` test against expected. if (Array.isArray(expected)) { for (var _cntr = 0; _cntr < dataArray.length; _cntr++) { if (expected.indexOf(dataArray[_cntr]) < 0) { if (error) { var _dataEntryString = (0, _typeof3.default)(dataArray[_cntr]) === 'object' ? (0, _stringify2.default)(dataArray[_cntr]) : dataArray[_cntr]; throw _validateError(Error, '\'' + dataName + '.' + accessor + '[' + _cntr + ']\': \'' + _dataEntryString + '\' is not an expected value: ' + (0, _stringify2.default)(expected) + '.'); } else { return false; } } } } else if (expected instanceof _set2.default) { for (var _cntr2 = 0; _cntr2 < dataArray.length; _cntr2++) { if (!expected.has(dataArray[_cntr2])) { if (error) { var _dataEntryString2 = (0, _typeof3.default)(dataArray[_cntr2]) === 'object' ? (0, _stringify2.default)(dataArray[_cntr2]) : dataArray[_cntr2]; throw _validateError(Error, '\'' + dataName + '.' + accessor + '[' + _cntr2 + ']\': \'' + _dataEntryString2 + '\' is not an expected value: ' + (0, _stringify2.default)(expected) + '.'); } else { return false; } } } } else if (typeof expected === 'function') { for (var _cntr3 = 0; _cntr3 < dataArray.length; _cntr3++) { try { var result = expected(dataArray[_cntr3]); if (typeof result === 'undefined' || !result) { throw new Error(message); } } catch (err) { if (error) { var _dataEntryString3 = (0, _typeof3.default)(dataArray[_cntr3]) === 'object' ? (0, _stringify2.default)(dataArray[_cntr3]) : dataArray[_cntr3]; throw _validateError(Error, '\'' + dataName + '.' + accessor + '[' + _cntr3 + ']\': \'' + _dataEntryString3 + '\' failed validation: ' + err.message + '.'); } else { return false; } } } } return true; } // TODO: add docs after upgrading to latest WebStorm / better object destructuring support. // /** // * Validates data entry with a typeof check and potentially tests against the values in any given expected set. // * // * @param {object} data - The object data to validate. // * // * @param {string} accessor - A string describing the entries to access. // * // * @param {string} [type] - Tests with a typeof check. // * // * @param {function|Set<*>} [expected] - Optional function or set of expected values to test against. // * // * @param {string} [message] - Optional message to include. // * // * @param {boolean} [required=true] - When false if the accessor is missing validation is skipped. // * // * @param {boolean} [error=true] - When true and error is thrown otherwise a boolean is returned. // * // * @param {string} [dataName='data'] - Optional name of data. // * // * @returns {boolean} True if validation passes otherwise an exception is thrown. // */ }, { key: 'validateEntry', value: function validateEntry(data, accessor) { var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, _ref2$type = _ref2.type, type = _ref2$type === undefined ? void 0 : _ref2$type, _ref2$expected = _ref2.expected, expected = _ref2$expected === undefined ? void 0 : _ref2$expected, _ref2$message = _ref2.message, message = _ref2$message === undefined ? void 0 : _ref2$message, _ref2$required = _ref2.required, required = _ref2$required === undefined ? true : _ref2$required, _ref2$error = _ref2.error, error = _ref2$error === undefined ? true : _ref2$error; var dataName = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'data'; var dataEntry = ObjectUtil.safeAccess(data, accessor); // A non-required entry is missing so return without validation. if (!required && typeof dataEntry === 'undefined') { return true; } if (type && (typeof dataEntry === 'undefined' ? 'undefined' : (0, _typeof3.default)(dataEntry)) !== type) { if (error) { throw _validateError(TypeError, '\'' + dataName + '.' + accessor + '\' is not a \'' + type + '\'.'); } else { return false; } } if (expected instanceof _set2.default && !expected.has(dataEntry) || Array.isArray(expected) && expected.indexOf(dataEntry) < 0) { if (error) { var dataEntryString = (typeof dataEntry === 'undefined' ? 'undefined' : (0, _typeof3.default)(dataEntry)) === 'object' ? (0, _stringify2.default)(dataEntry) : dataEntry; throw _validateError(Error, '\'' + dataName + '.' + accessor + '\': \'' + dataEntryString + '\' is not an expected value: ' + (0, _stringify2.default)(expected) + '.'); } else { return false; } } else if (typeof expected === 'function') { try { var result = expected(dataEntry); if (typeof result === 'undefined' || !result) { throw new Error(message); } } catch (err) { if (error) { var _dataEntryString4 = (typeof dataEntry === 'undefined' ? 'undefined' : (0, _typeof3.default)(dataEntry)) === 'object' ? (0, _stringify2.default)(dataEntry) : dataEntry; throw _validateError(Error, '\'' + dataName + '.' + accessor + '\': \'' + _dataEntryString4 + '\' failed to validate: ' + err.message + '.'); } else { return false; } } } return true; } /** * Dispatches validation of data entry to string or array validation depending on data entry type. * * @param {object} data - The data object to test. * * @param {string} accessor - A string describing the entries to access. * * @param {ValidationEntry} [entry] - A validation entry. * * @param {string} [dataName='data'] - Optional name of data. * * @returns {boolean} True if validation passes otherwise an exception is thrown. */ }, { key: 'validateEntryOrArray', value: function validateEntryOrArray(data, accessor, entry) { var dataName = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'data'; var dataEntry = ObjectUtil.safeAccess(data, accessor); var result = void 0; if (Array.isArray(dataEntry)) { result = ObjectUtil.validateArray(data, accessor, entry, dataName); } else { result = ObjectUtil.validateEntry(data, accessor, entry, dataName); } return result; } }]); return ObjectUtil; }(); /** * Wires up ObjectUtil on the plugin eventbus. The following event bindings are available: * * `typhonjs:object:util:deep:freeze`: Invokes `deepFreeze`. * `typhonjs:object:util:depth:traverse`: Invokes `depthTraverse`. * `typhonjs:object:util:get:accessor:list`: Invokes `getAccessorList`. * `typhonjs:object:util:safe:access`: Invokes `safeAccess`. * `typhonjs:object:util:safe:batch:set`: Invokes `safeBatchSet`. * `typhonjs:object:util:safe:equal`: Invokes `safeEqual`. * `typhonjs:object:util:safe:set`: Invokes `safeSet`. * `typhonjs:object:util:safe:set:all`: Invokes `safeSetAll`. * `typhonjs:object:util:validate`: Invokes `validate`. * `typhonjs:object:util:validate:array`: Invokes `validateArray`. * `typhonjs:object:util:validate:entry`: Invokes `validateEntry`. * `typhonjs:object:util:validate:entry|array`: Invokes `validateEntryOrArray`. * * @param {PluginEvent} ev - The plugin event. * @ignore */ exports.default = ObjectUtil; function onPluginLoad(ev) { var eventbus = ev.eventbus; eventbus.on('typhonjs:object:util:deep:freeze', ObjectUtil.deepFreeze, ObjectUtil); eventbus.on('typhonjs:object:util:depth:traverse', ObjectUtil.depthTraverse, ObjectUtil); eventbus.on('typhonjs:object:util:get:accessor:list', ObjectUtil.getAccessorList, ObjectUtil); eventbus.on('typhonjs:object:util:safe:access', ObjectUtil.safeAccess, ObjectUtil); eventbus.on('typhonjs:object:util:safe:batch:set', ObjectUtil.safeBatchSet, ObjectUtil); eventbus.on('typhonjs:object:util:safe:equal', ObjectUtil.safeEqual, ObjectUtil); eventbus.on('typhonjs:object:util:safe:set', ObjectUtil.safeSet, ObjectUtil); eventbus.on('typhonjs:object:util:safe:set:all', ObjectUtil.safeSetAll, ObjectUtil); eventbus.on('typhonjs:object:util:validate', ObjectUtil.validate, ObjectUtil); eventbus.on('typhonjs:object:util:validate:array', ObjectUtil.validateArray, ObjectUtil); eventbus.on('typhonjs:object:util:validate:entry', ObjectUtil.validateEntry, ObjectUtil); eventbus.on('typhonjs:object:util:validate:entry|array', ObjectUtil.validateEntryOrArray, ObjectUtil); } // Module private --------------------------------------------------------------------------------------------------- /** * Private implementation of depth traversal. * * @param {object|Array} data - An object or array. * * @param {string[]} skipFreezeKeys - An array of strings indicating keys of objects to not freeze. * * @returns {*} * @ignore * @private */ function _deepFreeze(data, skipFreezeKeys) { if (Array.isArray(data)) { for (var cntr = 0; cntr < data.length; cntr++) { _deepFreeze(data[cntr], skipFreezeKeys); } } else if ((typeof data === 'undefined' ? 'undefined' : (0, _typeof3.default)(data)) === 'object') { for (var key in data) { if (data.hasOwnProperty(key) && skipFreezeKeys.indexOf(key) === -1) { _deepFreeze(data[key], skipFreezeKeys); } } } return (0, _freeze2.default)(data); } /** * Private implementation of depth traversal. * * @param {object|Array} data - An object or array. * * @param {function} func - A callback function to process leaf values in children arrays or object members. * * @param {boolean} modify - If true then the result of the callback function is used to modify in place * the given data. * @returns {*} * @ignore * @private */ function _depthTraverse(data, func, modify) { if (modify) { if (Array.isArray(data)) { for (var cntr = 0; cntr < data.length; cntr++) { data[cntr] = _depthTraverse(data[cntr], func, modify); } } else if ((typeof data === 'undefined' ? 'undefined' : (0, _typeof3.default)(data)) === 'object') { for (var key in data) { if (data.hasOwnProperty(key)) { data[key] = _depthTraverse(data[key], func, modify); } } } else { data = func(data); } } else { if (Array.isArray(data)) { for (var _cntr4 = 0; _cntr4 < data.length; _cntr4++) { _depthTraverse(data[_cntr4], func, modify); } } else if ((typeof data === 'undefined' ? 'undefined' : (0, _typeof3.default)(data)) === 'object') { for (var _key in data) { if (data.hasOwnProperty(_key)) { _depthTraverse(data[_key], func, modify); } } } else { func(data); } } return data; } /** * Private implementation of `getAccessorList`. * * @param {object} data - An object to traverse. * * @returns {Array} * @ignore * @private */ function _getAccessorList(data) { var accessors = []; var _loop = function _loop(key) { if (data.hasOwnProperty(key)) { if ((0, _typeof3.default)(data[key]) === 'object') { var childKeys = _getAccessorList(data[key]); childKeys.forEach(function (childKey) { accessors.push(Array.isArray(childKey) ? key + '.' + childKey.join('.') : key + '.' + childKey); }); } else { accessors.push(key); } } }; for (var key in data) { _loop(key); } return accessors; } /** * Creates a new error of type `clazz` adding the field `_objectValidateError` set to true. * * @param {Error} clazz - Error class to instantiate. * * @param {string} message - An error message. * * @returns {*} * @ignore * @private */ function _validateError(clazz) { var message = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : void 0; var error = new clazz(message); error._objectValidateError = true; return error; }