Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #17: Support objects with cycles #91

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions benchmark/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const suite = new Benchmark.Suite;
const equalPackages = {
'fast-deep-equal': require('..'),
'fast-deep-equal/es6': require('../es6'),
'fast-deep-equal/es6cycles': require('../es6cycles'),
'fast-equals': require('fast-equals').deepEqual,
'nano-equal': true,
'shallow-equal-fuzzy': true,
Expand Down
11 changes: 7 additions & 4 deletions build.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ var doT = require('dot');
doT.templateSettings.strip = false;

var jst = doT.compile(fs.readFileSync('./src/index.jst', 'utf8'));
fs.writeFileSync('./index.js', jst({es6: false}));
fs.writeFileSync('./react.js', jst({es6: false, react: true}));
fs.writeFileSync('./index.js', jst({es6: false }));
fs.writeFileSync('./react.js', jst({es6: false, react: true }));
try { fs.mkdirSync('./es6'); } catch(e) {}
fs.writeFileSync('./es6/index.js', jst({es6: true}));
fs.writeFileSync('./es6/react.js', jst({es6: true, react: true}));
fs.writeFileSync('./es6/index.js', jst({es6: true }));
fs.writeFileSync('./es6/react.js', jst({es6: true, react: true }));
try { fs.mkdirSync('./es6cycles'); } catch(e) {}
fs.writeFileSync('./es6cycles/index.js', jst({es6: true, cycles: true}));
fs.writeFileSync('./es6cycles/react.js', jst({es6: true, react: true, cycles: true }));
105 changes: 105 additions & 0 deletions spec/cycle_tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
'use strict';

var obj1 = {a: 1, b: 2};
var obj2 = {a: 1, b: 2};
var obj3 = {a: 1, b: 2};
obj1.c = obj2;
obj2.c = obj3;
obj3.c = obj3;

var obj4 = {e: 3, f: 4};
var obj5 = {a: 1, b: 2};
var obj6 = {a: 1, b: 2};
obj4.c = obj4;
obj5.c = obj4;
obj6.c = obj6;

var obj7 = {a: 1, b: 2};
var obj8 = {a: 1, b: 2};
var obj9 = {a: 1, b: 2};
obj7.c = obj7;
obj8.c = obj9;
obj9.c = obj8;

var arr1 = [1, 2];
var arr2 = [1, 2];
var arr3 = [1, 2];
arr1.push(arr2);
arr2.push(arr3);
arr3.push(arr3);

var arr4 = [3, 4];
var arr5 = [1, 2];
var arr6 = [1, 2];
arr4.push(arr4);
arr5.push(arr4);
arr6.push(arr6);


module.exports = [
{
description: 'cyclic objects',
tests: [
{
description: 'equal cyclic objects #1',
value1: obj1,
value2: obj2,
equal: true
},
{
description: 'equal cyclic objects #2',
value1: obj1,
value2: obj3,
equal: true
},
{
description: 'equal cyclic objects #3',
value1: obj2,
value2: obj3,
equal: true
},
{
description: 'equal cyclic objects #4',
value1: obj7,
value2: obj8,
equal: true
},
{
description: 'not equal cyclic objects',
value1: obj5,
value2: obj6,
equal: false
}
]
},

{
description: 'cyclic arrays',
tests: [
{
description: 'equal cyclic arrays #1',
value1: arr1,
value2: arr2,
equal: true
},
{
description: 'equal cyclic arrays #2',
value1: arr1,
value2: arr3,
equal: true
},
{
description: 'equal cyclic arrays #3',
value1: arr2,
value2: arr3,
equal: true
},
{
description: 'not equal cyclic arrays',
value1: arr5,
value2: arr6,
equal: false
}
]
},
];
4 changes: 4 additions & 0 deletions spec/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ var equal = require('..');
var equalReact = require('../react');
var es6equal = require('../es6');
var es6equalReact = require('../es6/react');
var es6cyclesEqual = require('../es6cycles');
var assert = require('assert');

testCases(equal, 'equal - standard tests', require('./tests'));
testCases(es6equal, 'es6 equal - standard tests', require('./tests'));
testCases(es6equal, 'es6 equal - es6 tests', require('./es6tests'));
testCases(es6cyclesEqual, 'es6 cycles equal - standard tests', require('./tests'));
testCases(es6cyclesEqual, 'es6 cycles equal - es6 tests', require('./es6tests'));
testCases(es6cyclesEqual, 'es6 cycles equal - cycle tests', require('./cycle_tests'));

testCases(equalReact, 'equal react - standard tests', require('./tests'));
testCases(es6equalReact, 'es6 equal react - standard tests', require('./tests'));
Expand Down
15 changes: 11 additions & 4 deletions src/index.jst
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,25 @@
var envHasBigInt64Array = typeof BigInt64Array !== 'undefined';
{{?}}

module.exports = function equal(a, b) {
module.exports = function equal(a, b, compared) {
if (a === b) return true;

if (a && b && typeof a == 'object' && typeof b == 'object') {
if (a.constructor !== b.constructor) return false;

{{? it.es6 && it.cycles }}
if (!compared) compared = { a: new Set(), b: new Set() };
if (compared.a.has(a) && compared.b.has(b)) return true;
if (!compared.a.has(a)) compared.a.add(a);
if (!compared.b.has(b)) compared.b.add(b);
{{?}}

var length, i, keys;
if (Array.isArray(a)) {
length = a.length;
if (length != b.length) return false;
for (i = length; i-- !== 0;)
if (!equal(a[i], b[i])) return false;
if (!equal(a[i], b[i], compared)) return false;
return true;
}

Expand All @@ -27,7 +34,7 @@ module.exports = function equal(a, b) {
for (i of a.entries())
if (!b.has(i[0])) return false;
for (i of a.entries())
if (!equal(i[1], b.get(i[0]))) return false;
if (!equal(i[1], b.get(i[0]), compared)) return false;
return true;
}

Expand Down Expand Up @@ -68,7 +75,7 @@ module.exports = function equal(a, b) {
continue;
}
{{?}}
if (!equal(a[key], b[key])) return false;
if (!equal(a[key], b[key], compared)) return false;
}

return true;
Expand Down