| 'use strict'; | 
|   | 
| var traverse = require('../../'); | 
|   | 
| function toS(o) { | 
|     return Object.prototype.toString.call(o); | 
| } | 
|   | 
| module.exports = function (a, b) { | 
|     if (arguments.length !== 2) { | 
|         throw new Error('deepEqual requires exactly two objects to compare against'); | 
|     } | 
|   | 
|     var equal = true; | 
|     function notEqual() { | 
|         equal = false; | 
|         // this.stop(); | 
|         return undefined; | 
|     } | 
|   | 
|     var node = b; | 
|   | 
|     traverse(a).forEach(function (y) { // eslint-disable-line consistent-return | 
|   | 
|         // if (node === undefined || node === null) return notEqual(); | 
|   | 
|         if (!this.isRoot) { | 
|             /* | 
|             if (!Object.hasOwnProperty.call(node, this.key)) { | 
|                 return notEqual(); | 
|             } | 
|         */ | 
|             if (typeof node !== 'object') { return notEqual(); } | 
|             node = node[this.key]; | 
|         } | 
|   | 
|         var x = node; | 
|   | 
|         this.post(function () { | 
|             node = x; | 
|         }); | 
|   | 
|         if (this.circular) { | 
|             if (traverse(b).get(this.circular.path) !== x) { notEqual(); } | 
|         } else if (typeof x !== typeof y) { | 
|             notEqual(); | 
|         } else if (x === null || y === null || x === undefined || y === undefined) { | 
|             if (x !== y) { notEqual(); } | 
|         } else if (x.__proto__ !== y.__proto__) { | 
|             notEqual(); | 
|         } else if (x === y) { | 
|             // nop | 
|         } else if (typeof x === 'function') { | 
|             if (x instanceof RegExp) { | 
|                 // both regexps on account of the __proto__ check | 
|                 if (String(x) !== String(y)) { notEqual(); } | 
|             } else if (x !== y) { notEqual(); } | 
|         } else if (typeof x === 'object') { | 
|             if (toS(y) === '[object Arguments]' | 
|             || toS(x) === '[object Arguments]') { | 
|                 if (toS(x) !== toS(y)) { | 
|                     notEqual(); | 
|                 } | 
|             } else if (toS(y) === '[object RegExp]' | 
|             || toS(x) === '[object RegExp]') { | 
|                 if (!x || !y || x.toString() !== y.toString()) { notEqual(); } | 
|             } else if (x instanceof Date || y instanceof Date) { | 
|                 if (!(x instanceof Date) || !(y instanceof Date) | 
|                 || x.getTime() !== y.getTime()) { | 
|                     notEqual(); | 
|                 } | 
|             } else { | 
|                 var kx = Object.keys(x); | 
|                 var ky = Object.keys(y); | 
|                 if (kx.length !== ky.length) { return notEqual(); } | 
|                 for (var i = 0; i < kx.length; i++) { | 
|                     var k = kx[i]; | 
|                     if (!Object.hasOwnProperty.call(y, k)) { | 
|                         notEqual(); | 
|                     } | 
|                 } | 
|             } | 
|         } | 
|     }); | 
|   | 
|     return equal; | 
| }; |