diff --git a/packages/ejson/ejson.js b/packages/ejson/ejson.js index c07f8ee8a9..188e06f347 100644 --- a/packages/ejson/ejson.js +++ b/packages/ejson/ejson.js @@ -239,7 +239,6 @@ EJSON.equals = function (a, b, options) { } if (typeof (a.equals) === 'function') return a.equals(b, options); - // fall back to structural equality. if (a instanceof Array) { if (!(b instanceof Array)) return false; @@ -251,25 +250,41 @@ EJSON.equals = function (a, b, options) { } return true; } + // fall back to structural equality of objects + var ret; if (keyOrderSensitive) { - var b_keys = []; - for (var x in b) - b_keys.push(x); - i = 0; - for (var x in a) { - if (i >= b_keys.length) - return false; - if (x !== b_keys[i]) - return false; - if (!EJSON.equals(a[x], b[b_keys[i]], options)) - return false; - i++; - } - if (i !== b_keys.length) + var bKeys = []; + _.each(b, function (val, x) { + bKeys.push(x); + }); + i = 0; + ret = _.all(a, function (val, x) { + if (i >= bKeys.length) { return false; + } + if (x !== bKeys[i]) { + return false; + } + if (!EJSON.equals(val, b[bKeys[i]], options)) { + return false; + } + i++; return true; + }); + return ret && i === bKeys.length; } else { - return _.isEqual(a, b); + i = 0; + ret = _.all(a, function (val, key) { + if (!_.has(b, key)) { + return false; + } + if (!EJSON.equals(val, b[key], options)) { + return false; + } + i++; + return true; + }); + return ret && _.size(b) === i; } }; @@ -300,8 +315,9 @@ EJSON.clone = function (v) { } // handle other objects ret = {}; - for (var key in v) - ret[key] = EJSON.clone(v[key]); + _.each(v, function (value, key) { + ret[key] = EJSON.clone(value); + }); return ret; }; })(); diff --git a/packages/ejson/ejson_test.js b/packages/ejson/ejson_test.js index 3d6859b1b5..4f1e6b6ac6 100644 --- a/packages/ejson/ejson_test.js +++ b/packages/ejson/ejson_test.js @@ -22,6 +22,8 @@ Tinytest.add("ejson - keyOrderSensitive", function (test) { a: {c: 2, b: 1}, d: {f: 4, e: 3} }, {keyOrderSensitive: true})); + test.isFalse(EJSON.equals({a: {}}, {a: {b:2}}, {keyOrderSensitive: true})); + test.isFalse(EJSON.equals({a: {b:2}}, {a: {}}, {keyOrderSensitive: true})); }); Tinytest.add("ejson - nesting and literal", function (test) { @@ -32,6 +34,15 @@ Tinytest.add("ejson - nesting and literal", function (test) { test.equal(obj, roundTrip); }); +Tinytest.add("ejson - some equality tests", function (test) { + test.isTrue(EJSON.equals({a: 1, b: 2, c: 3}, {a: 1, c: 3, b: 2})); + test.isFalse(EJSON.equals({a: 1, b: 2}, {a: 1, c: 3, b: 2})); + test.isFalse(EJSON.equals({a: 1, b: 2, c: 3}, {a: 1, b: 2})); + test.isFalse(EJSON.equals({a: 1, b: 2, c: 3}, {a: 1, c: 3, b: 4})); + test.isFalse(EJSON.equals({a: {}}, {a: {b:2}})); + test.isFalse(EJSON.equals({a: {b:2}}, {a: {}})); +}); + Tinytest.add("ejson - equality and falsiness", function (test) { test.isTrue(EJSON.equals(null, null)); test.isTrue(EJSON.equals(undefined, undefined));