Socket
Socket
Sign inDemoInstall

samsam

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

samsam - npm Package Compare versions

Comparing version 0.1.1 to 1.0.0

.npmignore

256

lib/samsam.js

@@ -1,8 +0,6 @@

((typeof define === "function" && define.amd && function (m) {
define("lodash", m);
}) || (typeof module === "object" &&
typeof require === "function" && function (m) {
module.exports = m(require("lodash"));
}) || function (m) { this.samsam = m(_); }
)(function (_) {
((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
(typeof module === "object" &&
function (m) { module.exports = m(); }) || // Node
function (m) { this.samsam = m(); } // Browser globals
)(function () {
var o = Object.prototype;

@@ -27,2 +25,24 @@ var div = typeof document !== "undefined" && document.createElement("div");

/**
* @name samsam.isArguments
* @param Object object
*
* Returns ``true`` if ``object`` is an ``arguments`` object,
* ``false`` otherwise.
*/
function isArguments(object) {
if (typeof object !== "object" || typeof object.length !== "number" ||
getClass(object) === "Array") {
return false;
}
if (typeof object.callee == "function") { return true; }
try {
object[object.length] = 6;
delete object[object.length];
} catch (e) {
return true;
}
return false;
}
/**
* @name samsam.isElement

@@ -48,2 +68,30 @@ * @param Object object

/**
* @name samsam.keys
* @param Object object
*
* Return an array of own property names.
*/
function keys(object) {
var ks = [], prop;
for (prop in object) {
if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
}
return ks;
}
/**
* @name samsam.isDate
* @param Object value
*
* Returns true if the object is a ``Date``, or *date-like*. Duck typing
* of date objects work by checking that the object has a ``getTime``
* function whose return value equals the return value from the object's
* ``valueOf``.
*/
function isDate(value) {
return typeof value.getTime == "function" &&
value.getTime() == value.valueOf();
}
/**
* @name samsam.isNegZero

@@ -75,2 +123,3 @@ * @param Object value

/**

@@ -88,54 +137,169 @@ * @name samsam.deepEqual

* in ``obj1`` is deepEqual to the corresponding property in ``obj2``
*
* Supports cyclic objects.
*/
function deepEqual(obj1, obj2) {
var type1 = typeof obj1;
var type2 = typeof obj2;
function deepEqualCyclic(obj1, obj2) {
// == null also matches undefined
if (obj1 === obj2 ||
isNaN(obj1) || isNaN(obj2) ||
obj1 == null || obj2 == null ||
type1 !== "object" || type2 !== "object") {
return identical(obj1, obj2);
}
// used for cyclic comparison
// contain already visited objects
var objects1 = [],
objects2 = [],
// contain pathes (position in the object structure)
// of the already visited objects
// indexes same as in objects arrays
paths1 = [],
paths2 = [],
// contains combinations of already compared objects
// in the manner: { "$1['ref']$2['ref']": true }
compared = {};
// Elements are only equal if identical(expected, actual)
if (isElement(obj1) || isElement(obj2)) { return false; }
/**
* used to check, if the value of a property is an object
* (cyclic logic is only needed for objects)
* only needed for cyclic logic
*/
function isObject(value) {
var isDate1 = _.isDate(obj1), isDate2 = _.isDate(obj2);
if (isDate1 || isDate2) {
if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
return false;
if (typeof value === 'object' && value !== null &&
!(value instanceof Boolean) &&
!(value instanceof Date) &&
!(value instanceof Number) &&
!(value instanceof RegExp) &&
!(value instanceof String)) {
return true;
}
}
if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
if (obj1.toString() !== obj2.toString()) { return false; }
return false;
}
var class1 = getClass(obj1);
var class2 = getClass(obj2);
var keys1 = _.keys(obj1);
var keys2 = _.keys(obj2);
/**
* returns the index of the given object in the
* given objects array, -1 if not contained
* only needed for cyclic logic
*/
function getIndex(objects, obj) {
if (_.isArguments(obj1) || _.isArguments(obj2)) {
if (obj1.length !== obj2.length) { return false; }
} else {
if (type1 !== type2 || class1 !== class2 ||
keys1.length !== keys2.length) {
return false;
var i;
for (i = 0; i < objects.length; i++) {
if (objects[i] === obj) {
return i;
}
}
return -1;
}
var key, i, l;
// does the recursion for the deep equal check
return (function deepEqual(obj1, obj2, path1, path2) {
var type1 = typeof obj1;
var type2 = typeof obj2;
for (i = 0, l = keys1.length; i < l; i++) {
key = keys1[i];
if (!o.hasOwnProperty.call(obj2, key) ||
!deepEqual(obj1[key], obj2[key])) {
return false;
// == null also matches undefined
if (obj1 === obj2 ||
isNaN(obj1) || isNaN(obj2) ||
obj1 == null || obj2 == null ||
type1 !== "object" || type2 !== "object") {
return identical(obj1, obj2);
}
}
return true;
// Elements are only equal if identical(expected, actual)
if (isElement(obj1) || isElement(obj2)) { return false; }
var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
if (isDate1 || isDate2) {
if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
return false;
}
}
if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
if (obj1.toString() !== obj2.toString()) { return false; }
}
var class1 = getClass(obj1);
var class2 = getClass(obj2);
var keys1 = keys(obj1);
var keys2 = keys(obj2);
if (isArguments(obj1) || isArguments(obj2)) {
if (obj1.length !== obj2.length) { return false; }
} else {
if (type1 !== type2 || class1 !== class2 ||
keys1.length !== keys2.length) {
return false;
}
}
var key, i, l,
// following vars are used for the cyclic logic
value1, value2,
isObject1, isObject2,
index1, index2,
newPath1, newPath2;
for (i = 0, l = keys1.length; i < l; i++) {
key = keys1[i];
if (!o.hasOwnProperty.call(obj2, key)) {
return false;
}
// Start of the cyclic logic
value1 = obj1[key];
value2 = obj2[key];
isObject1 = isObject(value1);
isObject2 = isObject(value2);
// determine, if the objects were already visited
// (it's faster to check for isObject first, than to
// get -1 from getIndex for non objects)
index1 = isObject1 ? getIndex(objects1, value1) : -1;
index2 = isObject2 ? getIndex(objects2, value2) : -1;
// determine the new pathes of the objects
// - for non cyclic objects the current path will be extended
// by current property name
// - for cyclic objects the stored path is taken
newPath1 = index1 !== -1
? paths1[index1]
: path1 + '[' + JSON.stringify(key) + ']';
newPath2 = index2 !== -1
? paths2[index2]
: path2 + '[' + JSON.stringify(key) + ']';
// stop recursion if current objects are already compared
if (compared[newPath1 + newPath2]) {
return true;
}
// remember the current objects and their pathes
if (index1 === -1 && isObject1) {
objects1.push(value1);
paths1.push(newPath1);
}
if (index2 === -1 && isObject2) {
objects2.push(value2);
paths2.push(newPath2);
}
// remember that the current objects are already compared
if (isObject1 && isObject2) {
compared[newPath1 + newPath2] = true;
}
// End of cyclic logic
// neither value1 nor value2 is a cycle
// continue with next level
if (!deepEqual(value1, value2, newPath1, newPath2)) {
return false;
}
}
return true;
}(obj1, obj2, '$1', '$2'));
}

@@ -208,8 +372,10 @@

return {
isArguments: isArguments,
isElement: isElement,
isDate: isDate,
isNegZero: isNegZero,
identical: identical,
deepEqual: deepEqual,
deepEqual: deepEqualCyclic,
match: match
};
});

13

package.json
{
"name": "samsam",
"version": "0.1.1",
"version": "1.0.0",
"description": "Value identification and comparison functions",
"homepage": "http://busterjs.org/docs/buster-assertions",
"author": { "name": "August Lilleaas and Christian Johansen" },
"author": "Christian Johansen",
"contributors": [{

@@ -15,2 +15,6 @@ "name": "Christian Johansen",

"url": "http://augustl.com"
}, {
"name": "Daniel Wittner",
"email": "d.wittner@gmx.de",
"url": "https://github.com/dwittner"
}],

@@ -25,8 +29,5 @@ "main": "./lib/samsam",

},
"dependencies": {
"lodash": "~0.4"
},
"devDependencies": {
"buster": "0.6.2"
"buster": "0.6.11"
}
}

@@ -159,4 +159,4 @@ if (typeof module === "object" && typeof require === "function") {

fail("'empty' object to date", {}, new Date());
fail("'empty' object to string object", {}, new String());
fail("'empty' object to number object", {}, new Number());
fail("'empty' object to string object", {}, String());
fail("'empty' object to number object", {}, Number());
fail("'empty' object to empty array", {}, []);

@@ -174,2 +174,77 @@

/**
* Tests for cyclic objects.
*/
tests("deepEqual", function (pass, fail) {
(function () {
var cyclic1 = {}, cyclic2 = {};
cyclic1.ref = cyclic1;
cyclic2.ref = cyclic2;
pass("equal cyclic objects (cycle on 2nd level)", cyclic1, cyclic2);
}());
(function () {
var cyclic1 = {}, cyclic2 = {};
cyclic1.ref = cyclic1;
cyclic2.ref = cyclic2;
cyclic2.ref2 = cyclic2;
fail("different cyclic objects (cycle on 2nd level)",
cyclic1, cyclic2);
}());
(function () {
var cyclic1 = {}, cyclic2 = {};
cyclic1.ref = {};
cyclic1.ref.ref = cyclic1;
cyclic2.ref = {};
cyclic2.ref.ref = cyclic2;
pass("equal cyclic objects (cycle on 3rd level)", cyclic1, cyclic2);
}());
(function () {
var cyclic1 = {}, cyclic2 = {};
cyclic1.ref = {};
cyclic1.ref.ref = cyclic1;
cyclic2.ref = {};
cyclic2.ref.ref = cyclic2;
cyclic2.ref.ref2 = cyclic2;
fail("different cyclic objects (cycle on 3rd level)",
cyclic1, cyclic2);
}());
(function () {
var cyclic1 = {}, cyclic2 = {};
cyclic1.ref = cyclic1;
cyclic2.ref = cyclic1;
pass("equal objects even though only one object is cyclic",
cyclic1, cyclic2);
}());
(function () {
var cyclic1 = {}, cyclic2 = {};
cyclic1.ref = {
ref: cyclic1
};
cyclic2.ref = {};
cyclic2.ref.ref = cyclic2.ref;
pass("referencing different but equal cyclic objects",
cyclic1, cyclic2);
}());
(function () {
var cyclic1 = {a: "a"}, cyclic2 = {a: "a"};
cyclic1.ref = {
b: "b",
ref: cyclic1
};
cyclic2.ref = {
b: "b"
};
cyclic2.ref.ref = cyclic2.ref;
fail("referencing different and unequal cyclic objects",
cyclic1, cyclic2);
}());
});
tests("match", function (pass, fail, shouldThrow, add) {

@@ -189,3 +264,3 @@ pass("matching regexp", "Assertions", /[a-z]/);

fail("matching number against string", "Assertions 123", 23);
pass("matching number against similar string", "23", 23);
fail("matching number against similar string", "23", 23);
pass("matching number against itself", 23, 23);

@@ -269,2 +344,3 @@ pass("matcher function returns true",

});
}());

Sorry, the diff of this file is not supported yet

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