| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 | 
							- 'use strict';
 
- const Types = require('./types');
 
- const internals = {
 
-     mismatched: null
 
- };
 
- module.exports = function (obj, ref, options) {
 
-     options = Object.assign({ prototype: true }, options);
 
-     return !!internals.isDeepEqual(obj, ref, options, []);
 
- };
 
- internals.isDeepEqual = function (obj, ref, options, seen) {
 
-     if (obj === ref) {                                                      // Copied from Deep-eql, copyright(c) 2013 Jake Luer, jake@alogicalparadox.com, MIT Licensed, https://github.com/chaijs/deep-eql
 
-         return obj !== 0 || 1 / obj === 1 / ref;
 
-     }
 
-     const type = typeof obj;
 
-     if (type !== typeof ref) {
 
-         return false;
 
-     }
 
-     if (obj === null ||
 
-         ref === null) {
 
-         return false;
 
-     }
 
-     if (type === 'function') {
 
-         if (!options.deepFunction ||
 
-             obj.toString() !== ref.toString()) {
 
-             return false;
 
-         }
 
-         // Continue as object
 
-     }
 
-     else if (type !== 'object') {
 
-         return obj !== obj && ref !== ref;                                  // NaN
 
-     }
 
-     const instanceType = internals.getSharedType(obj, ref, !!options.prototype);
 
-     switch (instanceType) {
 
-         case Types.buffer:
 
-             return Buffer && Buffer.prototype.equals.call(obj, ref);        // $lab:coverage:ignore$
 
-         case Types.promise:
 
-             return obj === ref;
 
-         case Types.regex:
 
-             return obj.toString() === ref.toString();
 
-         case internals.mismatched:
 
-             return false;
 
-     }
 
-     for (let i = seen.length - 1; i >= 0; --i) {
 
-         if (seen[i].isSame(obj, ref)) {
 
-             return true;                                                    // If previous comparison failed, it would have stopped execution
 
-         }
 
-     }
 
-     seen.push(new internals.SeenEntry(obj, ref));
 
-     try {
 
-         return !!internals.isDeepEqualObj(instanceType, obj, ref, options, seen);
 
-     }
 
-     finally {
 
-         seen.pop();
 
-     }
 
- };
 
- internals.getSharedType = function (obj, ref, checkPrototype) {
 
-     if (checkPrototype) {
 
-         if (Object.getPrototypeOf(obj) !== Object.getPrototypeOf(ref)) {
 
-             return internals.mismatched;
 
-         }
 
-         return Types.getInternalProto(obj);
 
-     }
 
-     const type = Types.getInternalProto(obj);
 
-     if (type !== Types.getInternalProto(ref)) {
 
-         return internals.mismatched;
 
-     }
 
-     return type;
 
- };
 
- internals.valueOf = function (obj) {
 
-     const objValueOf = obj.valueOf;
 
-     if (objValueOf === undefined) {
 
-         return obj;
 
-     }
 
-     try {
 
-         return objValueOf.call(obj);
 
-     }
 
-     catch (err) {
 
-         return err;
 
-     }
 
- };
 
- internals.hasOwnEnumerableProperty = function (obj, key) {
 
-     return Object.prototype.propertyIsEnumerable.call(obj, key);
 
- };
 
- internals.isSetSimpleEqual = function (obj, ref) {
 
-     for (const entry of obj) {
 
-         if (!ref.has(entry)) {
 
-             return false;
 
-         }
 
-     }
 
-     return true;
 
- };
 
- internals.isDeepEqualObj = function (instanceType, obj, ref, options, seen) {
 
-     const { isDeepEqual, valueOf, hasOwnEnumerableProperty } = internals;
 
-     const { keys, getOwnPropertySymbols } = Object;
 
-     if (instanceType === Types.array) {
 
-         if (options.part) {
 
-             // Check if any index match any other index
 
-             for (const objValue of obj) {
 
-                 for (const refValue of ref) {
 
-                     if (isDeepEqual(objValue, refValue, options, seen)) {
 
-                         return true;
 
-                     }
 
-                 }
 
-             }
 
-         }
 
-         else {
 
-             if (obj.length !== ref.length) {
 
-                 return false;
 
-             }
 
-             for (let i = 0; i < obj.length; ++i) {
 
-                 if (!isDeepEqual(obj[i], ref[i], options, seen)) {
 
-                     return false;
 
-                 }
 
-             }
 
-             return true;
 
-         }
 
-     }
 
-     else if (instanceType === Types.set) {
 
-         if (obj.size !== ref.size) {
 
-             return false;
 
-         }
 
-         if (!internals.isSetSimpleEqual(obj, ref)) {
 
-             // Check for deep equality
 
-             const ref2 = new Set(ref);
 
-             for (const objEntry of obj) {
 
-                 if (ref2.delete(objEntry)) {
 
-                     continue;
 
-                 }
 
-                 let found = false;
 
-                 for (const refEntry of ref2) {
 
-                     if (isDeepEqual(objEntry, refEntry, options, seen)) {
 
-                         ref2.delete(refEntry);
 
-                         found = true;
 
-                         break;
 
-                     }
 
-                 }
 
-                 if (!found) {
 
-                     return false;
 
-                 }
 
-             }
 
-         }
 
-     }
 
-     else if (instanceType === Types.map) {
 
-         if (obj.size !== ref.size) {
 
-             return false;
 
-         }
 
-         for (const [key, value] of obj) {
 
-             if (value === undefined && !ref.has(key)) {
 
-                 return false;
 
-             }
 
-             if (!isDeepEqual(value, ref.get(key), options, seen)) {
 
-                 return false;
 
-             }
 
-         }
 
-     }
 
-     else if (instanceType === Types.error) {
 
-         // Always check name and message
 
-         if (obj.name !== ref.name ||
 
-             obj.message !== ref.message) {
 
-             return false;
 
-         }
 
-     }
 
-     // Check .valueOf()
 
-     const valueOfObj = valueOf(obj);
 
-     const valueOfRef = valueOf(ref);
 
-     if ((obj !== valueOfObj || ref !== valueOfRef) &&
 
-         !isDeepEqual(valueOfObj, valueOfRef, options, seen)) {
 
-         return false;
 
-     }
 
-     // Check properties
 
-     const objKeys = keys(obj);
 
-     if (!options.part &&
 
-         objKeys.length !== keys(ref).length &&
 
-         !options.skip) {
 
-         return false;
 
-     }
 
-     let skipped = 0;
 
-     for (const key of objKeys) {
 
-         if (options.skip &&
 
-             options.skip.includes(key)) {
 
-             if (ref[key] === undefined) {
 
-                 ++skipped;
 
-             }
 
-             continue;
 
-         }
 
-         if (!hasOwnEnumerableProperty(ref, key)) {
 
-             return false;
 
-         }
 
-         if (!isDeepEqual(obj[key], ref[key], options, seen)) {
 
-             return false;
 
-         }
 
-     }
 
-     if (!options.part &&
 
-         objKeys.length - skipped !== keys(ref).length) {
 
-         return false;
 
-     }
 
-     // Check symbols
 
-     if (options.symbols !== false) {                                // Defaults to true
 
-         const objSymbols = getOwnPropertySymbols(obj);
 
-         const refSymbols = new Set(getOwnPropertySymbols(ref));
 
-         for (const key of objSymbols) {
 
-             if (!options.skip ||
 
-                 !options.skip.includes(key)) {
 
-                 if (hasOwnEnumerableProperty(obj, key)) {
 
-                     if (!hasOwnEnumerableProperty(ref, key)) {
 
-                         return false;
 
-                     }
 
-                     if (!isDeepEqual(obj[key], ref[key], options, seen)) {
 
-                         return false;
 
-                     }
 
-                 }
 
-                 else if (hasOwnEnumerableProperty(ref, key)) {
 
-                     return false;
 
-                 }
 
-             }
 
-             refSymbols.delete(key);
 
-         }
 
-         for (const key of refSymbols) {
 
-             if (hasOwnEnumerableProperty(ref, key)) {
 
-                 return false;
 
-             }
 
-         }
 
-     }
 
-     return true;
 
- };
 
- internals.SeenEntry = class {
 
-     constructor(obj, ref) {
 
-         this.obj = obj;
 
-         this.ref = ref;
 
-     }
 
-     isSame(obj, ref) {
 
-         return this.obj === obj && this.ref === ref;
 
-     }
 
- };
 
 
  |