| 'use strict';
|
|
|
| |
| |
| |
| |
|
|
|
|
| var type = require('type-detect');
|
| function FakeMap() {
|
| this._key = 'chai/deep-eql__' + Math.random() + Date.now();
|
| }
|
|
|
| FakeMap.prototype = {
|
| get: function get(key) {
|
| return key[this._key];
|
| },
|
| set: function set(key, value) {
|
| if (Object.isExtensible(key)) {
|
| Object.defineProperty(key, this._key, {
|
| value: value,
|
| configurable: true,
|
| });
|
| }
|
| },
|
| };
|
|
|
| var MemoizeMap = typeof WeakMap === 'function' ? WeakMap : FakeMap;
|
| |
| |
| |
| |
| |
| |
| |
|
|
| function memoizeCompare(leftHandOperand, rightHandOperand, memoizeMap) {
|
|
|
| if (!memoizeMap || isPrimitive(leftHandOperand) || isPrimitive(rightHandOperand)) {
|
| return null;
|
| }
|
| var leftHandMap = memoizeMap.get(leftHandOperand);
|
| if (leftHandMap) {
|
| var result = leftHandMap.get(rightHandOperand);
|
| if (typeof result === 'boolean') {
|
| return result;
|
| }
|
| }
|
| return null;
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
| function memoizeSet(leftHandOperand, rightHandOperand, memoizeMap, result) {
|
|
|
| if (!memoizeMap || isPrimitive(leftHandOperand) || isPrimitive(rightHandOperand)) {
|
| return;
|
| }
|
| var leftHandMap = memoizeMap.get(leftHandOperand);
|
| if (leftHandMap) {
|
| leftHandMap.set(rightHandOperand, result);
|
| } else {
|
| leftHandMap = new MemoizeMap();
|
| leftHandMap.set(rightHandOperand, result);
|
| memoizeMap.set(leftHandOperand, leftHandMap);
|
| }
|
| }
|
|
|
| |
| |
|
|
|
|
| module.exports = deepEqual;
|
| module.exports.MemoizeMap = MemoizeMap;
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| function deepEqual(leftHandOperand, rightHandOperand, options) {
|
|
|
| if (options && options.comparator) {
|
| return extensiveDeepEqual(leftHandOperand, rightHandOperand, options);
|
| }
|
|
|
| var simpleResult = simpleEqual(leftHandOperand, rightHandOperand);
|
| if (simpleResult !== null) {
|
| return simpleResult;
|
| }
|
|
|
|
|
| return extensiveDeepEqual(leftHandOperand, rightHandOperand, options);
|
| }
|
|
|
| |
| |
| |
| |
| |
|
|
| function simpleEqual(leftHandOperand, rightHandOperand) {
|
|
|
| if (leftHandOperand === rightHandOperand) {
|
|
|
| return leftHandOperand !== 0 || 1 / leftHandOperand === 1 / rightHandOperand;
|
| }
|
|
|
|
|
| if (
|
| leftHandOperand !== leftHandOperand &&
|
| rightHandOperand !== rightHandOperand
|
| ) {
|
| return true;
|
| }
|
|
|
|
|
|
|
| if (isPrimitive(leftHandOperand) || isPrimitive(rightHandOperand)) {
|
|
|
| return false;
|
| }
|
| return null;
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| function extensiveDeepEqual(leftHandOperand, rightHandOperand, options) {
|
| options = options || {};
|
| options.memoize = options.memoize === false ? false : options.memoize || new MemoizeMap();
|
| var comparator = options && options.comparator;
|
|
|
|
|
| var memoizeResultLeft = memoizeCompare(leftHandOperand, rightHandOperand, options.memoize);
|
| if (memoizeResultLeft !== null) {
|
| return memoizeResultLeft;
|
| }
|
| var memoizeResultRight = memoizeCompare(rightHandOperand, leftHandOperand, options.memoize);
|
| if (memoizeResultRight !== null) {
|
| return memoizeResultRight;
|
| }
|
|
|
|
|
| if (comparator) {
|
| var comparatorResult = comparator(leftHandOperand, rightHandOperand);
|
|
|
| if (comparatorResult === false || comparatorResult === true) {
|
| memoizeSet(leftHandOperand, rightHandOperand, options.memoize, comparatorResult);
|
| return comparatorResult;
|
| }
|
|
|
|
|
| var simpleResult = simpleEqual(leftHandOperand, rightHandOperand);
|
| if (simpleResult !== null) {
|
|
|
| return simpleResult;
|
| }
|
| }
|
|
|
| var leftHandType = type(leftHandOperand);
|
| if (leftHandType !== type(rightHandOperand)) {
|
| memoizeSet(leftHandOperand, rightHandOperand, options.memoize, false);
|
| return false;
|
| }
|
|
|
|
|
| memoizeSet(leftHandOperand, rightHandOperand, options.memoize, true);
|
|
|
| var result = extensiveDeepEqualByType(leftHandOperand, rightHandOperand, leftHandType, options);
|
| memoizeSet(leftHandOperand, rightHandOperand, options.memoize, result);
|
| return result;
|
| }
|
|
|
| function extensiveDeepEqualByType(leftHandOperand, rightHandOperand, leftHandType, options) {
|
| switch (leftHandType) {
|
| case 'String':
|
| case 'Number':
|
| case 'Boolean':
|
| case 'Date':
|
|
|
| return deepEqual(leftHandOperand.valueOf(), rightHandOperand.valueOf());
|
| case 'Promise':
|
| case 'Symbol':
|
| case 'function':
|
| case 'WeakMap':
|
| case 'WeakSet':
|
| return leftHandOperand === rightHandOperand;
|
| case 'Error':
|
| return keysEqual(leftHandOperand, rightHandOperand, [ 'name', 'message', 'code' ], options);
|
| case 'Arguments':
|
| case 'Int8Array':
|
| case 'Uint8Array':
|
| case 'Uint8ClampedArray':
|
| case 'Int16Array':
|
| case 'Uint16Array':
|
| case 'Int32Array':
|
| case 'Uint32Array':
|
| case 'Float32Array':
|
| case 'Float64Array':
|
| case 'Array':
|
| return iterableEqual(leftHandOperand, rightHandOperand, options);
|
| case 'RegExp':
|
| return regexpEqual(leftHandOperand, rightHandOperand);
|
| case 'Generator':
|
| return generatorEqual(leftHandOperand, rightHandOperand, options);
|
| case 'DataView':
|
| return iterableEqual(new Uint8Array(leftHandOperand.buffer), new Uint8Array(rightHandOperand.buffer), options);
|
| case 'ArrayBuffer':
|
| return iterableEqual(new Uint8Array(leftHandOperand), new Uint8Array(rightHandOperand), options);
|
| case 'Set':
|
| return entriesEqual(leftHandOperand, rightHandOperand, options);
|
| case 'Map':
|
| return entriesEqual(leftHandOperand, rightHandOperand, options);
|
| case 'Temporal.PlainDate':
|
| case 'Temporal.PlainTime':
|
| case 'Temporal.PlainDateTime':
|
| case 'Temporal.Instant':
|
| case 'Temporal.ZonedDateTime':
|
| case 'Temporal.PlainYearMonth':
|
| case 'Temporal.PlainMonthDay':
|
| return leftHandOperand.equals(rightHandOperand);
|
| case 'Temporal.Duration':
|
| return leftHandOperand.total('nanoseconds') === rightHandOperand.total('nanoseconds');
|
| case 'Temporal.TimeZone':
|
| case 'Temporal.Calendar':
|
| return leftHandOperand.toString() === rightHandOperand.toString();
|
| default:
|
| return objectEqual(leftHandOperand, rightHandOperand, options);
|
| }
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
|
|
|
|
| function regexpEqual(leftHandOperand, rightHandOperand) {
|
| return leftHandOperand.toString() === rightHandOperand.toString();
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| function entriesEqual(leftHandOperand, rightHandOperand, options) {
|
| try {
|
|
|
| if (leftHandOperand.size !== rightHandOperand.size) {
|
| return false;
|
| }
|
| if (leftHandOperand.size === 0) {
|
| return true;
|
| }
|
| } catch (sizeError) {
|
|
|
| return false;
|
| }
|
| var leftHandItems = [];
|
| var rightHandItems = [];
|
| leftHandOperand.forEach(function gatherEntries(key, value) {
|
| leftHandItems.push([ key, value ]);
|
| });
|
| rightHandOperand.forEach(function gatherEntries(key, value) {
|
| rightHandItems.push([ key, value ]);
|
| });
|
| return iterableEqual(leftHandItems.sort(), rightHandItems.sort(), options);
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| function iterableEqual(leftHandOperand, rightHandOperand, options) {
|
| var length = leftHandOperand.length;
|
| if (length !== rightHandOperand.length) {
|
| return false;
|
| }
|
| if (length === 0) {
|
| return true;
|
| }
|
| var index = -1;
|
| while (++index < length) {
|
| if (deepEqual(leftHandOperand[index], rightHandOperand[index], options) === false) {
|
| return false;
|
| }
|
| }
|
| return true;
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| function generatorEqual(leftHandOperand, rightHandOperand, options) {
|
| return iterableEqual(getGeneratorEntries(leftHandOperand), getGeneratorEntries(rightHandOperand), options);
|
| }
|
|
|
| |
| |
| |
| |
| |
|
|
| function hasIteratorFunction(target) {
|
| return typeof Symbol !== 'undefined' &&
|
| typeof target === 'object' &&
|
| typeof Symbol.iterator !== 'undefined' &&
|
| typeof target[Symbol.iterator] === 'function';
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
|
|
| function getIteratorEntries(target) {
|
| if (hasIteratorFunction(target)) {
|
| try {
|
| return getGeneratorEntries(target[Symbol.iterator]());
|
| } catch (iteratorError) {
|
| return [];
|
| }
|
| }
|
| return [];
|
| }
|
|
|
| |
| |
| |
| |
| |
|
|
| function getGeneratorEntries(generator) {
|
| var generatorResult = generator.next();
|
| var accumulator = [ generatorResult.value ];
|
| while (generatorResult.done === false) {
|
| generatorResult = generator.next();
|
| accumulator.push(generatorResult.value);
|
| }
|
| return accumulator;
|
| }
|
|
|
| |
| |
| |
| |
| |
|
|
| function getEnumerableKeys(target) {
|
| var keys = [];
|
| for (var key in target) {
|
| keys.push(key);
|
| }
|
| return keys;
|
| }
|
|
|
| function getEnumerableSymbols(target) {
|
| var keys = [];
|
| var allKeys = Object.getOwnPropertySymbols(target);
|
| for (var i = 0; i < allKeys.length; i += 1) {
|
| var key = allKeys[i];
|
| if (Object.getOwnPropertyDescriptor(target, key).enumerable) {
|
| keys.push(key);
|
| }
|
| }
|
| return keys;
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| function keysEqual(leftHandOperand, rightHandOperand, keys, options) {
|
| var length = keys.length;
|
| if (length === 0) {
|
| return true;
|
| }
|
| for (var i = 0; i < length; i += 1) {
|
| if (deepEqual(leftHandOperand[keys[i]], rightHandOperand[keys[i]], options) === false) {
|
| return false;
|
| }
|
| }
|
| return true;
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| function objectEqual(leftHandOperand, rightHandOperand, options) {
|
| var leftHandKeys = getEnumerableKeys(leftHandOperand);
|
| var rightHandKeys = getEnumerableKeys(rightHandOperand);
|
| var leftHandSymbols = getEnumerableSymbols(leftHandOperand);
|
| var rightHandSymbols = getEnumerableSymbols(rightHandOperand);
|
| leftHandKeys = leftHandKeys.concat(leftHandSymbols);
|
| rightHandKeys = rightHandKeys.concat(rightHandSymbols);
|
|
|
| if (leftHandKeys.length && leftHandKeys.length === rightHandKeys.length) {
|
| if (iterableEqual(mapSymbols(leftHandKeys).sort(), mapSymbols(rightHandKeys).sort()) === false) {
|
| return false;
|
| }
|
| return keysEqual(leftHandOperand, rightHandOperand, leftHandKeys, options);
|
| }
|
|
|
| var leftHandEntries = getIteratorEntries(leftHandOperand);
|
| var rightHandEntries = getIteratorEntries(rightHandOperand);
|
| if (leftHandEntries.length && leftHandEntries.length === rightHandEntries.length) {
|
| leftHandEntries.sort();
|
| rightHandEntries.sort();
|
| return iterableEqual(leftHandEntries, rightHandEntries, options);
|
| }
|
|
|
| if (leftHandKeys.length === 0 &&
|
| leftHandEntries.length === 0 &&
|
| rightHandKeys.length === 0 &&
|
| rightHandEntries.length === 0) {
|
| return true;
|
| }
|
|
|
| return false;
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| function isPrimitive(value) {
|
| return value === null || typeof value !== 'object';
|
| }
|
|
|
| function mapSymbols(arr) {
|
| return arr.map(function mapSymbol(entry) {
|
| if (typeof entry === 'symbol') {
|
| return entry.toString();
|
| }
|
|
|
| return entry;
|
| });
|
| }
|
|
|