var traverse = require('../../'); module.exports = function (a, b) { if (arguments.length !== 2) { throw new Error( 'deepEqual requires exactly two objects to compare against' ); } var equal = true; var node = b; traverse(a).forEach(function (y) { var notEqual = (function () { equal = false; //this.stop(); return undefined; }).bind(this); //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; }); var toS = function (o) { return Object.prototype.toString.call(o); }; 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 (x.toString() != y.toString()) 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; };