Skip to content

Commit

Permalink
Merge pull request #5 from twada/circular-refs
Browse files Browse the repository at this point in the history
Allow circular references (on old browsers as well)
  • Loading branch information
twada committed May 6, 2016
2 parents cb26eec + 2951373 commit 41040d3
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 174 deletions.
10 changes: 6 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

var Buffer = require('buffer').Buffer;
var compare = Buffer.compare;
var indexOf = require('indexof');
var filter = require('array-filter');
var pSlice = Array.prototype.slice;
var getPrototypeOf = Object.getPrototypeOf || function(obj) {
Expand Down Expand Up @@ -105,7 +106,7 @@ var objectKeys = (function () {
isEnumerable(obj, 'byteOffset') &&
isEnumerable(obj, 'byteLength')) {
return filter(keys(obj), function (k) {
return OLD_V8_ARRAY_BUFFER_ENUM.indexOf(k) === -1;
return indexOf(OLD_V8_ARRAY_BUFFER_ENUM, k) === -1;
});
} else {
return keys(obj);
Expand Down Expand Up @@ -163,17 +164,18 @@ function _deepEqual(actual, expected, strict, memos) {
// accounts for both named and indexed properties on Arrays.
} else {
memos = memos || {actual: [], expected: []};
var actualIndex = memos.actual.indexOf(actual);

var actualIndex = indexOf(memos.actual, actual);
if (actualIndex !== -1) {
if (actualIndex === memos.expected.indexOf(expected)) {
if (actualIndex === indexOf(memos.expected, expected)) {
return true;
}
}

memos.actual.push(actual);
memos.expected.push(expected);

return objEquiv(actual, expected, strict, memos)
return objEquiv(actual, expected, strict, memos);
}
}

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"bugs": "https://github.com/twada/universal-deep-strict-equal/issues",
"dependencies": {
"array-filter": "^1.0.0",
"indexof": "0.0.1",
"object-keys": "^1.0.9"
},
"devDependencies": {
Expand Down
20 changes: 4 additions & 16 deletions test/test-assert-typedarray-deepequal.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,8 @@
var _deepEqual = require('..');
var assert = require('assert');

function deepEqual(actual, expected, message) {
if (!_deepEqual(actual, expected, false)) {
assert.fail(actual, expected, message, 'deepEqual', deepEqual);
}
};

function makeBlock(f) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
return f.apply(this, args);
};
function deepEqual (actual, expected) {
return _deepEqual(actual, expected, false);
}

function supportsTypedArray() {
Expand Down Expand Up @@ -62,15 +53,12 @@ var notEqualArrayPairs = [
describe('TypedArray deepEqual', function () {
equalArrayPairs.forEach(function (arrayPair, idx) {
it('equalArrayPairs - ' + idx, function () {
deepEqual(arrayPair[0], arrayPair[1]);
assert(deepEqual(arrayPair[0], arrayPair[1]));
});
});
notEqualArrayPairs.forEach(function (arrayPair, idx) {
it('notEqualArrayPairs - ' + idx, function () {
assert.throws(
makeBlock(deepEqual, arrayPair[0], arrayPair[1]),
assert.AssertionError
);
assert(!deepEqual(arrayPair[0], arrayPair[1]));
});
});
});
Expand Down
115 changes: 46 additions & 69 deletions test/test-deep-equal.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,78 +5,60 @@ var _deepEqual = require('..');
var assert = require('assert');
var keys = Object.keys || require('object-keys');

function deepEqual(actual, expected, message) {
if (!_deepEqual(actual, expected, false)) {
assert.fail(actual, expected, message, 'deepEqual', deepEqual);
}
};

function makeBlock(f) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
return f.apply(this, args);
};
function deepEqual (actual, expected) {
return _deepEqual(actual, expected, false);
}

describe('deepEqual', function () {

it('7.2', function () {
assert.doesNotThrow(makeBlock(deepEqual, new Date(2000, 3, 14),
new Date(2000, 3, 14)),
'deepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))');

assert.throws(makeBlock(deepEqual, new Date(), new Date(2000, 3, 14)),
assert.AssertionError,
'deepEqual(new Date(), new Date(2000, 3, 14))');
assert(deepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14)), 'deepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))');
assert(!deepEqual(new Date(), new Date(2000, 3, 14)), 'deepEqual(new Date(), new Date(2000, 3, 14))');
});


it('7.3', function () {
assert.doesNotThrow(makeBlock(deepEqual, /a/, /a/));
assert.doesNotThrow(makeBlock(deepEqual, /a/g, /a/g));
assert.doesNotThrow(makeBlock(deepEqual, /a/i, /a/i));
assert.doesNotThrow(makeBlock(deepEqual, /a/m, /a/m));
assert.doesNotThrow(makeBlock(deepEqual, /a/igm, /a/igm));
assert.throws(makeBlock(deepEqual, /ab/, /a/));
assert.throws(makeBlock(deepEqual, /a/g, /a/));
assert.throws(makeBlock(deepEqual, /a/i, /a/));
assert.throws(makeBlock(deepEqual, /a/m, /a/));
assert.throws(makeBlock(deepEqual, /a/igm, /a/im));
assert(deepEqual(/a/, /a/));
assert(deepEqual(/a/g, /a/g));
assert(deepEqual(/a/i, /a/i));
assert(deepEqual(/a/m, /a/m));
assert(deepEqual(/a/igm, /a/igm));
assert(!deepEqual(/ab/, /a/));
assert(!deepEqual(/a/g, /a/));
assert(!deepEqual(/a/i, /a/));
assert(!deepEqual(/a/m, /a/));
assert(!deepEqual(/a/igm, /a/im));

var re1 = /a/;
re1.lastIndex = 3;
assert.throws(makeBlock(deepEqual, re1, /a/));
assert(!deepEqual(re1, /a/));
});


it('7.4', function () {
assert.doesNotThrow(makeBlock(deepEqual, 4, '4'), 'deepEqual(4, \'4\')');
assert.doesNotThrow(makeBlock(deepEqual, true, 1), 'deepEqual(true, 1)');
assert.throws(makeBlock(deepEqual, 4, '5'),
assert.AssertionError,
'deepEqual( 4, \'5\')');
assert(deepEqual(4, '4'), 'deepEqual(4, \'4\')');
assert(deepEqual(true, 1), 'deepEqual(true, 1)');
assert(!deepEqual(4, '5'), 'deepEqual( 4, \'5\')');
});


it('7.5', function () {
// having the same number of owned properties && the same set of keys
assert.doesNotThrow(makeBlock(deepEqual, {a: 4}, {a: 4}));
assert.doesNotThrow(makeBlock(deepEqual, {a: 4, b: '2'}, {a: 4, b: '2'}));
assert.doesNotThrow(makeBlock(deepEqual, [4], ['4']));
assert.throws(makeBlock(deepEqual, {a: 4}, {a: 4, b: true}),
assert.AssertionError);
assert.doesNotThrow(makeBlock(deepEqual, ['a'], {0: 'a'}));
assert(deepEqual({a: 4}, {a: 4}));
assert(deepEqual({a: 4, b: '2'}, {a: 4, b: '2'}));
assert(deepEqual([4], ['4']));
assert(!deepEqual({a: 4}, {a: 4, b: true}));
assert(deepEqual(['a'], {0: 'a'}));
//(although not necessarily the same order),
assert.doesNotThrow(makeBlock(deepEqual, {a: 4, b: '1'}, {b: '1', a: 4}));
assert(deepEqual({a: 4, b: '1'}, {b: '1', a: 4}));
var a1 = [1, 2, 3];
var a2 = [1, 2, 3];
a1.a = 'test';
a1.b = true;
a2.b = true;
a2.a = 'test';
assert.throws(makeBlock(deepEqual, keys(a1), keys(a2)),
assert.AssertionError);
assert.doesNotThrow(makeBlock(deepEqual, a1, a2));
assert(!deepEqual(keys(a1), keys(a2)));
assert(deepEqual(a1, a2));
});

it('having an identical prototype property', function () {
Expand All @@ -101,24 +83,25 @@ nameBuilder2.prototype = nbRoot;
var nb1 = new nameBuilder('Ryan', 'Dahl');
var nb2 = new nameBuilder2('Ryan', 'Dahl');

assert.doesNotThrow(makeBlock(deepEqual, nb1, nb2));
assert(deepEqual(nb1, nb2));

nameBuilder2.prototype = Object;
nb2 = new nameBuilder2('Ryan', 'Dahl');
assert.doesNotThrow(makeBlock(deepEqual, nb1, nb2));
assert(deepEqual(nb1, nb2));
});

it('primitives and object', function () {
assert.throws(makeBlock(deepEqual, null, {}), assert.AssertionError);
assert.throws(makeBlock(deepEqual, undefined, {}), assert.AssertionError);
assert.throws(makeBlock(deepEqual, 'a', ['a']), assert.AssertionError);
assert.throws(makeBlock(deepEqual, 'a', {0: 'a'}), assert.AssertionError);
assert.throws(makeBlock(deepEqual, 1, {}), assert.AssertionError);
assert.throws(makeBlock(deepEqual, true, {}), assert.AssertionError);
assert(!deepEqual(null, {}));
assert(!deepEqual(undefined, {}));
assert(!deepEqual('a', ['a']));
assert(!deepEqual('a', {0: 'a'}));
assert(!deepEqual(1, {}));
assert(!deepEqual(true, {}));
if (typeof Symbol !== 'undefined') {
assert.throws(makeBlock(deepEqual, Symbol(), {}), assert.AssertionError);
assert(!deepEqual(Symbol(), {}));
}
});

// https://github.com/nodejs/node/issues/6416
it("Make sure circular refs don't throw", function(){
var b = {};
Expand All @@ -127,8 +110,8 @@ b.b = b;
var c = {};
c.b = c;

assert.doesNotThrow(makeBlock(deepEqual, b, c));
assert.doesNotThrow(makeBlock(deepEqual, b, c));
assert(deepEqual(b, c));
assert(deepEqual(b, c));

var d = {};
d.a = 1;
Expand All @@ -138,36 +121,30 @@ var e = {};
e.a = 1;
e.b = e.a;

assert.throws(makeBlock(deepEqual, d, e), /AssertionError/);
assert.throws(makeBlock(deepEqual, d, e), /AssertionError/);
assert(!deepEqual(d, e));
assert(!deepEqual(d, e));
});

describe('primitive wrappers and object', function () {
it('String and array', function () {
if (new String('a')['0'] === 'a') {
assert.doesNotThrow(makeBlock(deepEqual, new String('a'), ['a']),
assert.AssertionError);
assert(deepEqual(new String('a'), ['a']));
} else {
assert.throws(makeBlock(deepEqual, new String('a'), ['a']),
assert.AssertionError);
assert(!deepEqual(new String('a'), ['a']));
}
});
it('String and object', function () {
if (new String('a')['0'] === 'a') {
assert.doesNotThrow(makeBlock(deepEqual, new String('a'), {0: 'a'}),
assert.AssertionError);
assert(deepEqual(new String('a'), {0: 'a'}));
} else {
assert.throws(makeBlock(deepEqual, new String('a'), {0: 'a'}),
assert.AssertionError);
assert(!deepEqual(new String('a'), {0: 'a'}));
}
});
it('Number', function () {
assert.doesNotThrow(makeBlock(deepEqual, new Number(1), {}),
assert.AssertionError);
assert(deepEqual(new Number(1), {}));
});
it('Boolean', function () {
assert.doesNotThrow(makeBlock(deepEqual, new Boolean(true), {}),
assert.AssertionError);
assert(deepEqual(new Boolean(true), {}));
});
});

Expand Down
Loading

0 comments on commit 41040d3

Please sign in to comment.