UNPKG

foop

Version:

interfaces that describe their intentions.

162 lines (140 loc) 14.3 kB
// conditionals /* eslint complexity: "OFF" */ // not iterating on empty root /* eslint consistent-return: "OFF" */ // const traverse = require('../traverse') // const get = require('../dot/get') var isObjNotNull = require('../is/objNotNull') var isNull = require('../is/null') var isEmpty = require('../is/empty') var ENV_DEBUG = require('../env/debug') var eqValue = require('./eqValue') /* prettier-ignore */ /** * @name eq * @alias equals * @since 3.0.0 * @version 5.0.0 * @memberOf Traverse * * {@link https://github.com/andrewplummer/Sugar/blob/master/lib/common.js#L668 sugar-equal} * {@link https://github.com/the-grid/finitedomain/blob/master/src/propagator.js#L160 eq-qfox} * {@link https://github.com/jasmine/jasmine.github.io/blob/master/lib/jasmine-1.3.1/jasmine.js#L940 jasmine-equals} * {@link https://github.com/mobxjs/mobx/blob/master/src/utils/utils.ts#L145 mobx-deepequal} * {@link https://github.com/js-data/js-data/blob/v2/src/utils.js#L571 js-data-circular} * {@link https://github.com/js-data/js-data/blob/v2/src/utils.js#L300 js-data-equals} * {@link http://dorey.github.io/JavaScript-Equality-Table/ js-equality-table} * {@link https://github.com/facebook/react/blob/master/src/__mocks__/deepDiffer.js react-deep-differ} * {@link https://github.com/substack/js-traverse/blob/master/test/lib/deep_equal.js traverse-deep-equal} * {@link https://github.com/jashkenas/underscore/blob/master/underscore.js#L1183 underscore-equal} * {@link https://github.com/angular/angular.js/blob/master/src/Angular.js angular-is-equal} * {@link https://lodash.com/docs/4.17.4#isEqual lodash-is-equal} * {@link http://ramdajs.com/docs/#equals ramda-equals} * {@link https://github.com/substack/node-deep-equal node-deep-equal} * {@link https://github.com/facebook/immutable-js/blob/master/src/utils/deepEqual.js immutable-js-deep-equal} * @see {@link mobx-deepequal} * @see {@link js-equality-table} * @see {@link immutable-js-deep-equal} * @see {@link node-deep-equal} * @see {@link ramda-equals} * @see {@link lodash-is-equal} * @see {@link angular-is-equal} * @see {@link underscore-equal} * @see {@link traverse-deep-equal} * @see {@link react-deep-differ} * @see {@link js-data-equals} * @see {@link jasmine-equals} * @see {@link eq-qfox} * @see {@link sugar-equal} * * @param {Traverse} traverse traversejs (scoped, @FIXME @HACK) * @param {*} a compare to b * @param {*} b compare to a * @param {boolean} [loose] compare loosely * @return {boolean} isEqual: a === b * * @extends eqValue * * @example * * eq(1, 1) //=> true * eq(1, '1') //=> false * eq(1, '1', true) //=> true * eq([1], [1]) //=> true * */ module.exports = function (traverse) { return function eq(a, b, loose) { /* istanbul ignore next: dev */ if (ENV_DEBUG) { console.log('\n') } var equal = true var node = b var nodes = [node] var instance = traverse(a) var notEqual = function () { equal = false instance.stop() } /* istanbul ignore next: dev */ if (ENV_DEBUG) { console.log('eq?') } instance.forEach(function(key, y, traverser) { // @NOTE do base comparisons on values that are not actually iteratable // aka, .isRoot if (isNull(key)) { // always-valid state opionion vs always-invalid // so it only returns false when it is !== fosho if (eqValue(node, y, loose) === false) { return notEqual() } else { return } } /* istanbul ignore next: dev */ if (ENV_DEBUG) { console.log('eq: iterating:') } // could use it as a fallback if undefined && y !== undefined // const xyz = get(b, traverser.path.join('.'), b) var x = node // isNotLeafAndIsObj if (isObjNotNull(node) && !isEmpty(node)) { /* istanbul ignore next: dev */ if (ENV_DEBUG) { console.log('is leaf, is not empty node, going deeper') } // so x is our current one, // if node is not empty, use the key, push the value // and when it is empty, and it is not a leaf but has nodes, pop back up x = node[key] nodes.push(x) } // ENV_DEBUG // console.log({[key]: {x, xyz, y, nodes, path: traverser.path.join('.')}}) // for next loop!!! if (!traverser.isLeaf && !isEmpty(nodes)) { /* istanbul ignore next: dev */ if (ENV_DEBUG) { console.log('is not leaf, has nodes stack, pop') } node = nodes.pop() } /* istanbul ignore next: dev */ if (ENV_DEBUG) { console.log({key: key, y: y, x: x, a: a, b: b}) } var eqv = eqValue(x, y, loose) /* istanbul ignore next: dev */ if (ENV_DEBUG) { console.log({eqv: eqv}) } if (eqv === false) { // equal notEqual() } }) // cleanup nodes = undefined node = undefined return equal }; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX2VxLmpzIiwic291cmNlcyI6WyJfZXEuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gY29uZGl0aW9uYWxzXG4vKiBlc2xpbnQgY29tcGxleGl0eTogXCJPRkZcIiAqL1xuXG4vLyBub3QgaXRlcmF0aW5nIG9uIGVtcHR5IHJvb3Rcbi8qIGVzbGludCBjb25zaXN0ZW50LXJldHVybjogXCJPRkZcIiAqL1xuXG4vLyBjb25zdCB0cmF2ZXJzZSA9IHJlcXVpcmUoJy4uL3RyYXZlcnNlJylcbi8vIGNvbnN0IGdldCA9IHJlcXVpcmUoJy4uL2RvdC9nZXQnKVxuY29uc3QgaXNPYmpOb3ROdWxsID0gcmVxdWlyZSgnLi4vaXMvb2JqTm90TnVsbCcpXG5jb25zdCBpc051bGwgPSByZXF1aXJlKCcuLi9pcy9udWxsJylcbmNvbnN0IGlzRW1wdHkgPSByZXF1aXJlKCcuLi9pcy9lbXB0eScpXG5jb25zdCBFTlZfREVCVUcgPSByZXF1aXJlKCcuLi9lbnYvZGVidWcnKVxuY29uc3QgZXFWYWx1ZSA9IHJlcXVpcmUoJy4vZXFWYWx1ZScpXG5cbi8qIHByZXR0aWVyLWlnbm9yZSAqL1xuLyoqXG4gKiBAbmFtZSBlcVxuICogQGFsaWFzIGVxdWFsc1xuICogQHNpbmNlIDMuMC4wXG4gKiBAdmVyc2lvbiA1LjAuMFxuICogQG1lbWJlck9mIFRyYXZlcnNlXG4gKlxuICoge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmRyZXdwbHVtbWVyL1N1Z2FyL2Jsb2IvbWFzdGVyL2xpYi9jb21tb24uanMjTDY2OCBzdWdhci1lcXVhbH1cbiAqIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vdGhlLWdyaWQvZmluaXRlZG9tYWluL2Jsb2IvbWFzdGVyL3NyYy9wcm9wYWdhdG9yLmpzI0wxNjAgZXEtcWZveH1cbiAqIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vamFzbWluZS9qYXNtaW5lLmdpdGh1Yi5pby9ibG9iL21hc3Rlci9saWIvamFzbWluZS0xLjMuMS9qYXNtaW5lLmpzI0w5NDAgamFzbWluZS1lcXVhbHN9XG4gKiB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL21vYnhqcy9tb2J4L2Jsb2IvbWFzdGVyL3NyYy91dGlscy91dGlscy50cyNMMTQ1IG1vYngtZGVlcGVxdWFsfVxuICoge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9qcy1kYXRhL2pzLWRhdGEvYmxvYi92Mi9zcmMvdXRpbHMuanMjTDU3MSBqcy1kYXRhLWNpcmN1bGFyfVxuICoge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9qcy1kYXRhL2pzLWRhdGEvYmxvYi92Mi9zcmMvdXRpbHMuanMjTDMwMCBqcy1kYXRhLWVxdWFsc31cbiAqIHtAbGluayBodHRwOi8vZG9yZXkuZ2l0aHViLmlvL0phdmFTY3JpcHQtRXF1YWxpdHktVGFibGUvIGpzLWVxdWFsaXR5LXRhYmxlfVxuICoge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mYWNlYm9vay9yZWFjdC9ibG9iL21hc3Rlci9zcmMvX19tb2Nrc19fL2RlZXBEaWZmZXIuanMgcmVhY3QtZGVlcC1kaWZmZXJ9XG4gKiB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL3N1YnN0YWNrL2pzLXRyYXZlcnNlL2Jsb2IvbWFzdGVyL3Rlc3QvbGliL2RlZXBfZXF1YWwuanMgdHJhdmVyc2UtZGVlcC1lcXVhbH1cbiAqIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vamFzaGtlbmFzL3VuZGVyc2NvcmUvYmxvYi9tYXN0ZXIvdW5kZXJzY29yZS5qcyNMMTE4MyB1bmRlcnNjb3JlLWVxdWFsfVxuICoge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIuanMvYmxvYi9tYXN0ZXIvc3JjL0FuZ3VsYXIuanMgYW5ndWxhci1pcy1lcXVhbH1cbiAqIHtAbGluayBodHRwczovL2xvZGFzaC5jb20vZG9jcy80LjE3LjQjaXNFcXVhbCBsb2Rhc2gtaXMtZXF1YWx9XG4gKiB7QGxpbmsgaHR0cDovL3JhbWRhanMuY29tL2RvY3MvI2VxdWFscyByYW1kYS1lcXVhbHN9XG4gKiB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL3N1YnN0YWNrL25vZGUtZGVlcC1lcXVhbCBub2RlLWRlZXAtZXF1YWx9XG4gKiB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2ZhY2Vib29rL2ltbXV0YWJsZS1qcy9ibG9iL21hc3Rlci9zcmMvdXRpbHMvZGVlcEVxdWFsLmpzIGltbXV0YWJsZS1qcy1kZWVwLWVxdWFsfVxuICogQHNlZSB7QGxpbmsgbW9ieC1kZWVwZXF1YWx9XG4gKiBAc2VlIHtAbGluayBqcy1lcXVhbGl0eS10YWJsZX1cbiAqIEBzZWUge0BsaW5rIGltbXV0YWJsZS1qcy1kZWVwLWVxdWFsfVxuICogQHNlZSB7QGxpbmsgbm9kZS1kZWVwLWVxdWFsfVxuICogQHNlZSB7QGxpbmsgcmFtZGEtZXF1YWxzfVxuICogQHNlZSB7QGxpbmsgbG9kYXNoLWlzLWVxdWFsfVxuICogQHNlZSB7QGxpbmsgYW5ndWxhci1pcy1lcXVhbH1cbiAqIEBzZWUge0BsaW5rIHVuZGVyc2NvcmUtZXF1YWx9XG4gKiBAc2VlIHtAbGluayB0cmF2ZXJzZS1kZWVwLWVxdWFsfVxuICogQHNlZSB7QGxpbmsgcmVhY3QtZGVlcC1kaWZmZXJ9XG4gKiBAc2VlIHtAbGluayBqcy1kYXRhLWVxdWFsc31cbiAqIEBzZWUge0BsaW5rIGphc21pbmUtZXF1YWxzfVxuICogQHNlZSB7QGxpbmsgZXEtcWZveH1cbiAqIEBzZWUge0BsaW5rIHN1Z2FyLWVxdWFsfVxuICpcbiAqIEBwYXJhbSB7VHJhdmVyc2V9IHRyYXZlcnNlIHRyYXZlcnNlanMgKHNjb3BlZCwgQEZJWE1FIEBIQUNLKVxuICogQHBhcmFtICB7Kn0gYSBjb21wYXJlIHRvIGJcbiAqIEBwYXJhbSAgeyp9IGIgY29tcGFyZSB0byBhXG4gKiBAcGFyYW0gIHtib29sZWFufSBbbG9vc2VdIGNvbXBhcmUgbG9vc2VseVxuICogQHJldHVybiB7Ym9vbGVhbn0gaXNFcXVhbDogYSA9PT0gYlxuICpcbiAqIEBleHRlbmRzIGVxVmFsdWVcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqICAgIGVxKDEsIDEpICAgICAgICAgICAgLy89PiB0cnVlXG4gKiAgICBlcSgxLCAnMScpICAgICAgICAgIC8vPT4gZmFsc2VcbiAqICAgIGVxKDEsICcxJywgdHJ1ZSkgICAgLy89PiB0cnVlXG4gKiAgICBlcShbMV0sIFsxXSkgICAgICAgIC8vPT4gdHJ1ZVxuICpcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSB0cmF2ZXJzZSA9PiBmdW5jdGlvbiBlcShhLCBiLCBsb29zZSkge1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogZGV2ICovXG4gIGlmIChFTlZfREVCVUcpIHtcbiAgICBjb25zb2xlLmxvZygnXFxuJylcbiAgfVxuXG4gIGxldCBlcXVhbCA9IHRydWVcbiAgbGV0IG5vZGUgPSBiXG4gIGxldCBub2RlcyA9IFtub2RlXVxuXG4gIGNvbnN0IGluc3RhbmNlID0gdHJhdmVyc2UoYSlcblxuICBjb25zdCBub3RFcXVhbCA9ICgpID0+IHtcbiAgICBlcXVhbCA9IGZhbHNlXG4gICAgaW5zdGFuY2Uuc3RvcCgpXG4gIH1cblxuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogZGV2ICovXG4gIGlmIChFTlZfREVCVUcpIHtcbiAgICBjb25zb2xlLmxvZygnZXE/JylcbiAgfVxuXG4gIGluc3RhbmNlLmZvckVhY2goZnVuY3Rpb24oa2V5LCB5LCB0cmF2ZXJzZXIpIHtcbiAgICAvLyBATk9URSBkbyBiYXNlIGNvbXBhcmlzb25zIG9uIHZhbHVlcyB0aGF0IGFyZSBub3QgYWN0dWFsbHkgaXRlcmF0YWJsZVxuICAgIC8vIGFrYSwgLmlzUm9vdFxuICAgIGlmIChpc051bGwoa2V5KSkge1xuICAgICAgLy8gYWx3YXlzLXZhbGlkIHN0YXRlIG9waW9uaW9uIHZzIGFsd2F5cy1pbnZhbGlkXG4gICAgICAvLyBzbyBpdCBvbmx5IHJldHVybnMgZmFsc2Ugd2hlbiBpdCBpcyAhPT0gZm9zaG9cbiAgICAgIGlmIChlcVZhbHVlKG5vZGUsIHksIGxvb3NlKSA9PT0gZmFsc2UpIHJldHVybiBub3RFcXVhbCgpXG4gICAgICBlbHNlIHJldHVyblxuICAgIH1cblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXYgKi9cbiAgICBpZiAoRU5WX0RFQlVHKSB7XG4gICAgICBjb25zb2xlLmxvZygnZXE6IGl0ZXJhdGluZzonKVxuICAgIH1cblxuICAgIC8vIGNvdWxkIHVzZSBpdCBhcyBhIGZhbGxiYWNrIGlmIHVuZGVmaW5lZCAmJiB5ICE9PSB1bmRlZmluZWRcbiAgICAvLyBjb25zdCB4eXogPSBnZXQoYiwgdHJhdmVyc2VyLnBhdGguam9pbignLicpLCBiKVxuXG4gICAgbGV0IHggPSBub2RlXG5cbiAgICAvLyBpc05vdExlYWZBbmRJc09ialxuICAgIGlmIChpc09iak5vdE51bGwobm9kZSkgJiYgIWlzRW1wdHkobm9kZSkpIHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXYgKi9cbiAgICAgIGlmIChFTlZfREVCVUcpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ2lzIGxlYWYsIGlzIG5vdCBlbXB0eSBub2RlLCBnb2luZyBkZWVwZXInKVxuICAgICAgfVxuXG4gICAgICAvLyBzbyB4IGlzIG91ciBjdXJyZW50IG9uZSxcbiAgICAgIC8vIGlmIG5vZGUgaXMgbm90IGVtcHR5LCB1c2UgdGhlIGtleSwgcHVzaCB0aGUgdmFsdWVcbiAgICAgIC8vIGFuZCB3aGVuIGl0IGlzIGVtcHR5LCBhbmQgaXQgaXMgbm90IGEgbGVhZiBidXQgaGFzIG5vZGVzLCBwb3AgYmFjayB1cFxuICAgICAgeCA9IG5vZGVba2V5XVxuICAgICAgbm9kZXMucHVzaCh4KVxuICAgIH1cblxuICAgIC8vIEVOVl9ERUJVR1xuICAgIC8vIGNvbnNvbGUubG9nKHtba2V5XToge3gsIHh5eiwgeSwgbm9kZXMsIHBhdGg6IHRyYXZlcnNlci5wYXRoLmpvaW4oJy4nKX19KVxuXG4gICAgLy8gZm9yIG5leHQgbG9vcCEhIVxuICAgIGlmICghdHJhdmVyc2VyLmlzTGVhZiAmJiAhaXNFbXB0eShub2RlcykpIHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXYgKi9cbiAgICAgIGlmIChFTlZfREVCVUcpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ2lzIG5vdCBsZWFmLCBoYXMgbm9kZXMgc3RhY2ssIHBvcCcpXG4gICAgICB9XG4gICAgICBub2RlID0gbm9kZXMucG9wKClcbiAgICB9XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogZGV2ICovXG4gICAgaWYgKEVOVl9ERUJVRykge1xuICAgICAgY29uc29sZS5sb2coe2tleSwgeSwgeCwgYSwgYn0pXG4gICAgfVxuXG4gICAgY29uc3QgZXF2ID0gZXFWYWx1ZSh4LCB5LCBsb29zZSlcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXYgKi9cbiAgICBpZiAoRU5WX0RFQlVHKSB7XG4gICAgICBjb25zb2xlLmxvZyh7ZXF2fSlcbiAgICB9XG5cbiAgICBpZiAoZXF2ID09PSBmYWxzZSkge1xuICAgICAgLy8gZXF1YWxcbiAgICAgIG5vdEVxdWFsKClcbiAgICB9XG4gIH0pXG5cbiAgLy8gY2xlYW51cFxuICBub2RlcyA9IHVuZGVmaW5lZFxuICBub2RlID0gdW5kZWZpbmVkXG5cbiAgcmV0dXJuIGVxdWFsXG59XG4iXSwibmFtZXMiOlsiY29uc3QiLCJsZXQiXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztBQVFBQSxHQUFLLENBQUMsWUFBWSxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQztBQUNoREEsR0FBSyxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDO0FBQ3BDQSxHQUFLLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUM7QUFDdENBLEdBQUssQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQztBQUN6Q0EsR0FBSyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7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