Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

should-equal

Package Overview
Dependencies
Maintainers
1
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

should-equal - npm Package Compare versions

Comparing version 0.3.1 to 0.4.0

.eslintrc

259

index.js
var getType = require('should-type');
var format = require('./format');
var hasOwnProperty = Object.prototype.hasOwnProperty;

@@ -17,10 +18,8 @@

function format(msg) {
var args = arguments;
for(var i = 1, l = args.length; i < l; i++) {
msg = msg.replace(/%s/, args[i]);
}
return msg;
function typeToString(t) {
return t.type + (t.cls ? '(' + t.cls + (t.sub ? ' ' + t.sub : '') + ')' : '');
}
var REASON = {

@@ -35,20 +34,18 @@ PLUS_0_AND_MINUS_0: '+0 is not equal to -0',

MISSING_KEY: '%s has no key %s',
CIRCULAR_VALUES: 'A has circular reference that was visited not in the same time as B'
CIRCULAR_VALUES: 'A has circular reference that was visited not in the same time as B',
SET_MAP_MISSING_ENTRY: 'Set/Map missing entry'
};
function eqInternal(a, b, opts, stackA, stackB, path, fails) {
function eqInternal(a, b, opts, stackA, stackB, path) {
var r = EQUALS;
function result(comparison, reason) {
var res = makeResult(comparison, path, reason, a, b);
if(!comparison && opts.collectAllFails) {
fails.push(res);
}
return res;
return makeResult(comparison, path, reason, a, b);
}
function checkPropertyEquality(property) {
return eqInternal(a[property], b[property], opts, stackA, stackB, path.concat([property]), fails);
return eqInternal(a[property], b[property], opts, stackA, stackB, path.concat([property]));
}
// equal a and b exit early

@@ -66,6 +63,12 @@ if(a === b) {

// if objects has different types they are not equals
if(typeA !== typeB) return result(false, format(REASON.DIFFERENT_TYPES, typeA, typeB));
var typeDifferents = typeA.type !== typeB.type || typeA.cls !== typeB.cls;
switch(typeA) {
if(typeDifferents || ((opts.checkSubType && typeA.sub !== typeB.sub) || !opts.checkSubType)) {
return result(false, format(REASON.DIFFERENT_TYPES, typeToString(typeA), typeToString(typeB)));
}
//early checks for types
switch(typeA.type) {
case 'number':
// NaN !== NaN
return (a !== a) ? result(b !== b, REASON.NAN_NUMBER)

@@ -75,10 +78,2 @@ // but treat `+0` vs. `-0` as not equal

case 'regexp':
p = ['source', 'global', 'multiline', 'lastIndex', 'ignoreCase'];
while(p.length) {
r = checkPropertyEquality(p.shift());
if(!opts.collectAllFails && !r.result) return r;
}
break;
case 'boolean':

@@ -88,38 +83,127 @@ case 'string':

case 'date':
if(+a !== +b && !opts.collectAllFails) {
return result(false, REASON.EQUALITY);
}
break;
case 'object-number':
case 'object-boolean':
case 'object-string':
r = eqInternal(a.valueOf(), b.valueOf(), opts, stackA, stackB, path, fails);
if(!r.result && !opts.collectAllFails) {
r.reason = REASON.WRAPPED_VALUE;
case 'function':
var fA = a.toString(), fB = b.toString();
r = eqInternal(fA, fB, opts, stackA, stackB, path);
if(!r.result) {
r.reason = REASON.FUNCTION_SOURCES;
return r;
}
break;
case 'buffer':
r = checkPropertyEquality('length');
if(!opts.collectAllFails && !r.result) return r;
break;//check user properties
l = a.length;
while(l--) {
r = checkPropertyEquality(l);
if(!opts.collectAllFails && !r.result) return r;
}
case 'object':
// additional checks for object instances
switch(typeA.cls) {
// check regexp flags
// TODO add es6 flags
case 'regexp':
p = ['source', 'global', 'multiline', 'lastIndex', 'ignoreCase'];
while(p.length) {
r = checkPropertyEquality(p.shift());
if(!r.result) return r;
}
break;//check user properties
return EQUALS;
//check by timestamp only
case 'date':
if(+a !== +b) {
return result(false, REASON.EQUALITY);
}
break;//check user properties
case 'error':
p = ['name', 'message'];
while(p.length) {
r = checkPropertyEquality(p.shift());
if(!opts.collectAllFails && !r.result) return r;
//primitive type wrappers
case 'number':
case 'boolean':
case 'string':
r = eqInternal(a.valueOf(), b.valueOf(), opts, stackA, stackB, path);
if(!r.result) {
r.reason = REASON.WRAPPED_VALUE;
return r;
}
break;//check user properties
//node buffer
case 'buffer':
//if length different it is obviously different
r = checkPropertyEquality('length');
if(!r.result) return r;
l = a.length;
while(l--) {
r = checkPropertyEquality(l);
if(!r.result) return r;
}
//we do not check for user properties because
//node Buffer have some strange hidden properties
return EQUALS;
case 'error':
//check defined properties
p = ['name', 'message'];
while(p.length) {
r = checkPropertyEquality(p.shift());
if(!r.result) return r;
}
break;//check user properties
case 'array':
case 'arguments':
case 'typed-array':
r = checkPropertyEquality('length');
if(!r.result) return r;
break;//check user properties
case 'array-buffer':
r = checkPropertyEquality('byteLength');
if(!r.result) return r;
break;//check user properties
case 'map':
case 'set':
r = checkPropertyEquality('size');
if(!r.result) return r;
stackA.push(a);
stackB.push(b);
var iteratorMethod = typeA.cls == 'map' ? 'entries' : 'keys';
var itA = a[iteratorMethod]();
var nextA = itA.next();
while(!nextA.done) {
var itB = b[iteratorMethod]();
var nextB = itB.next();
while(!nextB.done) {
r = eqInternal(nextA.value, nextB.value, opts, stackA, stackB, path);
if(r.result) {
break;
}
nextB = itB.next();
}
if(!r.result) {
break;
}
nextA = itA.next();
}
stackA.pop();
stackB.pop();
if(!r.result) {
r.reason = REASON.SET_MAP_MISSING_ENTRY;
return r;
}
break; //check user properties
}
break;
}

@@ -129,4 +213,3 @@

// stacks contain references only
stackA || (stackA = []);
stackB || (stackB = []);
//

@@ -144,28 +227,9 @@ l = stackA.length;

var hasProperty,
keysComparison,
key;
var key;
if(typeA === 'array' || typeA === 'arguments' || typeA === 'typed-array') {
r = checkPropertyEquality('length');
if(!opts.collectAllFails && !r.result) return r;
}
if(typeA === 'array-buffer' || typeA === 'typed-array') {
r = checkPropertyEquality('byteLength');
if(!opts.collectAllFails && !r.result) return r;
}
if(typeB === 'function') {
var fA = a.toString(), fB = b.toString();
r = eqInternal(fA, fB, opts, stackA, stackB, path, fails);
r.reason = REASON.FUNCTION_SOURCES;
if(!opts.collectAllFails && !r.result) return r;
}
for(key in b) {
if(hasOwnProperty.call(b, key)) {
r = result(hasOwnProperty.call(a, key), format(REASON.MISSING_KEY, 'A', key));
if(!r.result && !opts.collectAllFails) {
return r;
if(!r.result) {
break;
}

@@ -175,4 +239,4 @@

r = checkPropertyEquality(key);
if(!r.result && !opts.collectAllFails) {
return r;
if(!r.result) {
break;
}

@@ -183,8 +247,10 @@ }

// ensure both objects have the same number of properties
for(key in a) {
if(hasOwnProperty.call(a, key)) {
r = result(hasOwnProperty.call(b, key), format(REASON.MISSING_KEY, 'B', key));
if(!r.result && !opts.collectAllFails) {
return r;
if(r.result) {
// ensure both objects have the same number of properties
for(key in a) {
if(hasOwnProperty.call(a, key)) {
r = result(hasOwnProperty.call(b, key), format(REASON.MISSING_KEY, 'B', key));
if(!r.result) {
return r;
}
}

@@ -197,6 +263,8 @@ }

if(!r.result) return r;
var prototypesEquals = false, canComparePrototypes = false;
if(opts.checkProtoEql) {
if(Object.getPrototypeOf) {
if(Object.getPrototypeOf) {//TODO should i check prototypes for === or use eq?
prototypesEquals = Object.getPrototypeOf(a) === Object.getPrototypeOf(b);

@@ -209,6 +277,6 @@ canComparePrototypes = true;

if(canComparePrototypes && !prototypesEquals && !opts.collectAllFails) {
if(canComparePrototypes && !prototypesEquals) {
r = result(prototypesEquals, REASON.EQUALITY_PROTOTYPE);
r.showReason = true;
if(!r.result && !opts.collectAllFails) {
if(!r.result) {
return r;

@@ -219,17 +287,14 @@ }

if(typeB === 'function') {
r = checkPropertyEquality('prototype');
if(!r.result && !opts.collectAllFails) return r;
}
return EQUALS;
}
var defaultOptions = {checkProtoEql: true, collectAllFails: false};
var defaultOptions = {
checkProtoEql: true,
checkSubType: true
};
function eq(a, b, opts) {
opts = opts || defaultOptions;
var fails = [];
var r = eqInternal(a, b, opts || defaultOptions, [], [], [], fails);
return opts.collectAllFails ? fails : r;
var r = eqInternal(a, b, opts, [], [], []);
return r;
}

@@ -236,0 +301,0 @@

{
"name": "should-equal",
"version": "0.3.1",
"version": "0.4.0",
"description": "Deep comparison of 2 instances for should.js",

@@ -25,8 +25,8 @@ "main": "index.js",

"devDependencies": {
"mocha": "^2.0.0",
"mocha": "latest",
"mocha-better-spec-reporter": "latest"
},
"dependencies": {
"should-type": "0.0.4"
"should-type": "0.1.0"
}
}

@@ -7,3 +7,6 @@ var assert = require('assert');

var msg = !r.result && (r.reason + ' at ' + r.path + ' ' + r.a + ' =/= ' + r.b);
assert.ok(r.result, msg);
if(!r.result) {
assert.equal(a, b, msg);
}
}

@@ -382,2 +385,38 @@

}
});
});
it('es6 sets', function() {
if(typeof Set !== 'undefined') {
var s1 = new Set([1, 2, 3]);
var s2 = new Set([1, 2, 3]);
var s3 = new Set(['a', 'b', 'c']);
var s4 = new Set([]);
var s5 = new Set([{ a: 1}, { a: 1}, { a: 1}]);
var s6 = new Set([{ a: 1}, { a: 1}, { a: 1}]);
eq(s1, s2);
ne(s1, s3);
ne(s1, s4);
ne(s1, s5);
eq(s5, s6);
}
});
it('es6 maps', function() {
if(typeof Map !== 'undefined') {
var m1 = new Map([[1, 1], [2, 2], [3, 3]]);
var m2 = new Map([[1, 1], [2, 2], [3, 3]]);
var m3 = new Map([[1, 2], [2, 3], [3, 4]]);
var m4 = new Map([[{ a: 10}, 2], [{ a: 11}, 2], [{ a: 12}, 2]]);
var m5 = new Map([[{ a: 11}, 2], [{ a: 12}, 2], [{ a: 13}, 2]]);
var m6 = new Map([[{ a: 11}, 2], [{ a: 12}, 2], [{ a: 13}, 2]]);
eq(m1, m1);
eq(m1, m2);
ne(m3, m2);
ne(m4, m5);
eq(m5, m6);
}
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc