blob: c4b2b42b100836946f1a0aee9b05825f390bc2ec [file] [log] [blame]
'use strict';
var eq = require('./eq')
, isPlainObject = require('./is-plain-object')
, value = require('./valid-value')
, isArray = Array.isArray, keys = Object.keys
, propertyIsEnumerable = Object.prototype.propertyIsEnumerable
, eqArr, eqVal, eqObj;
eqArr = function (a, b, recMap) {
var i, l = a.length;
if (l !== b.length) return false;
for (i = 0; i < l; ++i) {
if (a.hasOwnProperty(i) !== b.hasOwnProperty(i)) return false;
if (!eqVal(a[i], b[i], recMap)) return false;
}
return true;
};
eqObj = function (a, b, recMap) {
var k1 = keys(a), k2 = keys(b);
if (k1.length !== k2.length) return false;
return k1.every(function (key) {
if (!propertyIsEnumerable.call(b, key)) return false;
return eqVal(a[key], b[key], recMap);
});
};
eqVal = function (a, b, recMap) {
var i, eqX, c1, c2;
if (eq(a, b)) return true;
if (isPlainObject(a)) {
if (!isPlainObject(b)) return false;
eqX = eqObj;
} else if (isArray(a) && isArray(b)) {
eqX = eqArr;
} else {
return false;
}
c1 = recMap[0];
c2 = recMap[1];
i = c1.indexOf(a);
if (i !== -1) {
if (c2[i].indexOf(b) !== -1) return true;
} else {
i = c1.push(a) - 1;
c2[i] = [];
}
c2[i].push(b);
return eqX(a, b, recMap);
};
module.exports = function (a, b) {
if (eq(value(a), value(b))) return true;
return eqVal(Object(a), Object(b), [[], []]);
};