const compareArrayBufferViews = ( a: ArrayBufferView, b: ArrayBufferView ): boolean => { if (a.byteLength !== b.byteLength) { return false; } const viewA = new Uint8Array(a.buffer, a.byteOffset, a.byteLength); const viewB = new Uint8Array(b.buffer, b.byteOffset, b.byteLength); for (let index = 0; index < viewA.length; index++) { if (viewA[index] !== viewB[index]) { return false; } } return true; }; export const deepEqual = (a: unknown, b: unknown): boolean => { if (a === b) { return true; } if (a && b && typeof a === "object" && typeof b === "object") { if (a.constructor !== b.constructor) { return false; } let i: number | [unknown, unknown]; let length: number; if (Array.isArray(a)) { const bArray = b as unknown[]; length = a.length; if (length !== bArray.length) { return false; } for (i = length; i-- !== 0; ) { if (!deepEqual(a[i], bArray[i])) { return false; } } return true; } if (a instanceof Map && b instanceof Map) { if (a.size !== b.size) { return false; } for (i of a.entries()) { if (!b.has(i[0])) { return false; } } for (i of a.entries()) { if (!deepEqual(i[1], b.get(i[0]))) { return false; } } return true; } if (a instanceof Set && b instanceof Set) { if (a.size !== b.size) { return false; } for (i of a.entries()) { if (!b.has(i[0])) { return false; } } return true; } if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) { return compareArrayBufferViews(a, b); } if (a instanceof RegExp && b instanceof RegExp) { return a.source === b.source && a.flags === b.flags; } if (a.valueOf !== Object.prototype.valueOf) { return a.valueOf() === b.valueOf(); } if (a.toString !== Object.prototype.toString) { return a.toString() === b.toString(); } const aRecord = a as Record; const bRecord = b as Record; const keys = Object.keys(aRecord); length = keys.length; if (length !== Object.keys(bRecord).length) { return false; } for (i = length; i-- !== 0; ) { if (!Object.prototype.hasOwnProperty.call(b, keys[i])) { return false; } } for (i = length; i-- !== 0; ) { const key = keys[i]; if (!deepEqual(aRecord[key], bRecord[key])) { return false; } } return true; } return a !== a && b !== b; };