@sinonjs/samsam
Advanced tools
Comparing version 2.0.0 to 2.1.0
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
(factory((global.samsam = {}))); | ||
}(this, (function (exports) { 'use strict'; | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('array-from')) : | ||
typeof define === 'function' && define.amd ? define(['exports', 'array-from'], factory) : | ||
(factory((global.samsam = {}),global.arrayFrom)); | ||
}(this, (function (exports,arrayFrom) { 'use strict'; | ||
arrayFrom = arrayFrom && arrayFrom.hasOwnProperty('default') ? arrayFrom['default'] : arrayFrom; | ||
var o = Object.prototype; | ||
var div = typeof document !== "undefined" && document.createElement("div"); | ||
function getClass(value) { | ||
// Returns the internal [[Class]] by calling Object.prototype.toString | ||
// with the provided value as this. Return value is a string, naming the | ||
// internal class, e.g. "Array" | ||
return o.toString.call(value).split(/[ \]]/)[1]; | ||
} | ||
var getClass_1 = getClass; | ||
function isNaN(value) { | ||
@@ -18,13 +28,37 @@ // Unlike global isNaN, this avoids type coercion | ||
function getClass(value) { | ||
// Returns the internal [[Class]] by calling Object.prototype.toString | ||
// with the provided value as this. Return value is a string, naming the | ||
// internal class, e.g. "Array" | ||
return o.toString.call(value).split(/[ \]]/)[1]; | ||
var isNan = isNaN; | ||
/** | ||
* @name samsam.isNegZero | ||
* @param Object value | ||
* | ||
* Returns ``true`` if ``value`` is ``-0``. | ||
*/ | ||
function isNegZero(value) { | ||
return value === 0 && 1 / value === -Infinity; | ||
} | ||
function isDate(value) { | ||
return value instanceof Date; | ||
var isNegZero_1 = isNegZero; | ||
/** | ||
* @name samsam.equal | ||
* @param Object obj1 | ||
* @param Object obj2 | ||
* | ||
* Returns ``true`` if two objects are strictly equal. Compared to | ||
* ``===`` there are two exceptions: | ||
* | ||
* - NaN is considered equal to NaN | ||
* - -0 and +0 are not considered equal | ||
*/ | ||
function identical(obj1, obj2) { | ||
if (obj1 === obj2 || (isNan(obj1) && isNan(obj2))) { | ||
return obj1 !== 0 || isNegZero_1(obj1) === isNegZero_1(obj2); | ||
} | ||
return false; | ||
} | ||
var identical_1 = identical; | ||
/** | ||
@@ -38,8 +72,15 @@ * @name samsam.isArguments | ||
function isArguments(object) { | ||
if (getClass(object) === "Arguments") { return true; } | ||
if (typeof object !== "object" || typeof object.length !== "number" || | ||
getClass(object) === "Array") { | ||
if (getClass_1(object) === "Arguments") { | ||
return true; | ||
} | ||
if ( | ||
typeof object !== "object" || | ||
typeof object.length !== "number" || | ||
getClass_1(object) === "Array" | ||
) { | ||
return false; | ||
} | ||
if (typeof object.callee === "function") { return true; } | ||
if (typeof object.callee === "function") { | ||
return true; | ||
} | ||
try { | ||
@@ -54,2 +95,12 @@ object[object.length] = 6; | ||
var isArguments_1 = isArguments; | ||
function isDate(value) { | ||
return value instanceof Date; | ||
} | ||
var isDate_1 = isDate; | ||
var div = typeof document !== "undefined" && document.createElement("div"); | ||
/** | ||
@@ -65,3 +116,5 @@ * @name samsam.isElement | ||
function isElement(object) { | ||
if (!object || object.nodeType !== 1 || !div) { return false; } | ||
if (!object || object.nodeType !== 1 || !div) { | ||
return false; | ||
} | ||
try { | ||
@@ -76,42 +129,40 @@ object.appendChild(div); | ||
/** | ||
* @name samsam.isNegZero | ||
* @param Object value | ||
* | ||
* Returns ``true`` if ``value`` is ``-0``. | ||
*/ | ||
function isNegZero(value) { | ||
return value === 0 && 1 / value === -Infinity; | ||
var isElement_1 = isElement; | ||
// Returns true when the value is a regular Object and not a specialized Object | ||
// | ||
// This helps speeding up deepEqual cyclic checks | ||
// The premise is that only Objects are stored in the visited array. | ||
// So if this function returns false, we don't have to do the | ||
// expensive operation of searching for the value in the the array of already | ||
// visited objects | ||
function isObject(value) { | ||
return ( | ||
typeof value === "object" && | ||
value !== null && | ||
// none of these are collection objects, so we can return false | ||
!(value instanceof Boolean) && | ||
!(value instanceof Date) && | ||
!(value instanceof Error) && | ||
!(value instanceof Number) && | ||
!(value instanceof RegExp) && | ||
!(value instanceof String) | ||
); | ||
} | ||
/** | ||
* @name samsam.equal | ||
* @param Object obj1 | ||
* @param Object obj2 | ||
* | ||
* Returns ``true`` if two objects are strictly equal. Compared to | ||
* ``===`` there are two exceptions: | ||
* | ||
* - NaN is considered equal to NaN | ||
* - -0 and +0 are not considered equal | ||
*/ | ||
function identical(obj1, obj2) { | ||
if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) { | ||
return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2); | ||
} | ||
var isObject_1 = isObject; | ||
return false; | ||
function isSet(val) { | ||
return (typeof Set !== "undefined" && val instanceof Set) || false; | ||
} | ||
function isSet(val) { | ||
if (typeof Set !== "undefined" && val instanceof Set) { | ||
return true; | ||
} | ||
var isSet_1 = isSet; | ||
return false; | ||
} | ||
function isSubset(s1, s2, compare) { | ||
var values1 = Array.from(s1); | ||
var values2 = Array.from(s2); | ||
// FIXME: IE11 doesn't support Array.from | ||
// Potential solutions: | ||
// - contribute a patch to https://github.com/Volox/eslint-plugin-ie11#readme | ||
// - https://github.com/mathiasbynens/Array.from (doesn't work with matchers) | ||
var values1 = arrayFrom(s1); | ||
var values2 = arrayFrom(s2); | ||
@@ -136,2 +187,16 @@ for (var i = 0; i < values1.length; i++) { | ||
var isSubset_1 = isSubset; | ||
function getClassName(value) { | ||
return Object.getPrototypeOf(value) ? value.constructor.name : null; | ||
} | ||
var getClassName_1 = getClassName; | ||
var every = Array.prototype.every; | ||
var getTime = Date.prototype.getTime; | ||
var hasOwnProperty = Object.prototype.hasOwnProperty; | ||
var indexOf = Array.prototype.indexOf; | ||
var keys = Object.keys; | ||
/** | ||
@@ -153,3 +218,2 @@ * @name samsam.deepEqual | ||
function deepEqualCyclic(first, second) { | ||
// used for cyclic comparison | ||
@@ -168,39 +232,2 @@ // contain already visited objects | ||
/** | ||
* 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) { | ||
if (typeof value === "object" && value !== null && | ||
!(value instanceof Boolean) && | ||
!(value instanceof Date) && | ||
!(value instanceof Number) && | ||
!(value instanceof RegExp) && | ||
!(value instanceof String)) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
/** | ||
* 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) { | ||
var i; | ||
for (i = 0; i < objects.length; i++) { | ||
if (objects[i] === obj) { | ||
return i; | ||
} | ||
} | ||
return -1; | ||
} | ||
// does the recursion for the deep equal check | ||
@@ -212,19 +239,27 @@ return (function deepEqual(obj1, obj2, path1, path2) { | ||
// == null also matches undefined | ||
if (obj1 === obj2 || | ||
isNaN(obj1) || isNaN(obj2) || | ||
obj1 == null || obj2 == null || | ||
type1 !== "object" || type2 !== "object") { | ||
return identical(obj1, obj2); | ||
if ( | ||
obj1 === obj2 || | ||
isNan(obj1) || | ||
isNan(obj2) || | ||
obj1 == null || | ||
obj2 == null || | ||
type1 !== "object" || | ||
type2 !== "object" | ||
) { | ||
return identical_1(obj1, obj2); | ||
} | ||
// Elements are only equal if identical(expected, actual) | ||
if (isElement(obj1) || isElement(obj2)) { | ||
if (isElement_1(obj1) || isElement_1(obj2)) { | ||
return false; | ||
} | ||
var isDate1 = isDate(obj1); | ||
var isDate2 = isDate(obj2); | ||
var isDate1 = isDate_1(obj1); | ||
var isDate2 = isDate_1(obj2); | ||
if (isDate1 || isDate2) { | ||
if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) { | ||
if ( | ||
!isDate1 || | ||
!isDate2 || | ||
getTime.call(obj1) !== getTime.call(obj2) | ||
) { | ||
return false; | ||
@@ -240,12 +275,26 @@ } | ||
var class1 = getClass(obj1); | ||
var class2 = getClass(obj2); | ||
var keys1 = Object.keys(obj1); | ||
var keys2 = Object.keys(obj2); | ||
if (obj1 instanceof Error && obj2 instanceof Error) { | ||
if (obj1.stack !== obj2.stack) { | ||
return false; | ||
} | ||
} | ||
if (isArguments(obj1) || isArguments(obj2)) { | ||
if (obj1.length !== obj2.length) { return false; } | ||
var class1 = getClass_1(obj1); | ||
var class2 = getClass_1(obj2); | ||
var keys1 = keys(obj1); | ||
var keys2 = keys(obj2); | ||
var name1 = getClassName_1(obj1); | ||
var name2 = getClassName_1(obj2); | ||
if (isArguments_1(obj1) || isArguments_1(obj2)) { | ||
if (obj1.length !== obj2.length) { | ||
return false; | ||
} | ||
} else { | ||
if (type1 !== type2 || class1 !== class2 || | ||
keys1.length !== keys2.length) { | ||
if ( | ||
type1 !== type2 || | ||
class1 !== class2 || | ||
keys1.length !== keys2.length || | ||
(name1 && name2 && name1 !== name2) | ||
) { | ||
return false; | ||
@@ -255,54 +304,44 @@ } | ||
if (isSet(obj1) || isSet(obj2)) { | ||
if (!isSet(obj1) || !isSet(obj2) || obj1.size !== obj2.size) { | ||
if (isSet_1(obj1) || isSet_1(obj2)) { | ||
if (!isSet_1(obj1) || !isSet_1(obj2) || obj1.size !== obj2.size) { | ||
return false; | ||
} | ||
return isSubset(obj1, obj2, deepEqual); | ||
return isSubset_1(obj1, obj2, deepEqual); | ||
} | ||
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 every.call(keys1, function(key) { | ||
if (!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 | ||
var value1 = obj1[key]; | ||
var value2 = obj2[key]; | ||
var isObject1 = isObject_1(value1); | ||
var isObject2 = isObject_1(value2); | ||
// determines, 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 | ||
var index1 = isObject1 ? indexOf.call(objects1, value1) : -1; | ||
var index2 = isObject2 ? indexOf.call(objects2, value2) : -1; | ||
// determines the new paths 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) + "]"; | ||
var newPath1 = | ||
index1 !== -1 | ||
? paths1[index1] | ||
: path1 + "[" + JSON.stringify(key) + "]"; | ||
var newPath2 = | ||
index2 !== -1 | ||
? paths2[index2] | ||
: path2 + "[" + JSON.stringify(key) + "]"; | ||
var combinedPath = newPath1 + newPath2; | ||
// stop recursion if current objects are already compared | ||
if (compared[newPath1 + newPath2]) { | ||
if (compared[combinedPath]) { | ||
return true; | ||
} | ||
// remember the current objects and their pathes | ||
// remember the current objects and their paths | ||
if (index1 === -1 && isObject1) { | ||
@@ -319,3 +358,3 @@ objects1.push(value1); | ||
if (isObject1 && isObject2) { | ||
compared[newPath1 + newPath2] = true; | ||
compared[combinedPath] = true; | ||
} | ||
@@ -327,14 +366,13 @@ | ||
// continue with next level | ||
if (!deepEqual(value1, value2, newPath1, newPath2)) { | ||
return false; | ||
} | ||
} | ||
return deepEqual(value1, value2, newPath1, newPath2); | ||
}); | ||
})(first, second, "$1", "$2"); | ||
} | ||
return true; | ||
var deepEqual = deepEqualCyclic; | ||
}(first, second, "$1", "$2")); | ||
} | ||
function arrayContains(array, subset, compare) { | ||
if (subset.length === 0) { return true; } | ||
if (subset.length === 0) { | ||
return true; | ||
} | ||
var i, l, j, k; | ||
@@ -344,3 +382,3 @@ for (i = 0, l = array.length; i < l; ++i) { | ||
for (j = 0, k = subset.length; j < k; ++j) { | ||
if ((i + j) >= l) { | ||
if (i + j >= l) { | ||
return false; | ||
@@ -377,4 +415,8 @@ } | ||
var notNull = typeof object === "string" || !!object; | ||
return notNull && | ||
(String(object)).toLowerCase().indexOf(matcher) >= 0; | ||
return ( | ||
notNull && | ||
String(object) | ||
.toLowerCase() | ||
.indexOf(matcher) >= 0 | ||
); | ||
} | ||
@@ -398,12 +440,12 @@ | ||
if (isSet(object)) { | ||
return isSubset(matcher, object, match); | ||
if (isSet_1(object)) { | ||
return isSubset_1(matcher, object, match); | ||
} | ||
if (getClass(object) === "Array" && getClass(matcher) === "Array") { | ||
if (getClass_1(object) === "Array" && getClass_1(matcher) === "Array") { | ||
return arrayContains(object, matcher, match); | ||
} | ||
if (isDate(matcher)) { | ||
return isDate(object) && object.getTime() === matcher.getTime(); | ||
if (isDate_1(matcher)) { | ||
return isDate_1(object) && object.getTime() === matcher.getTime(); | ||
} | ||
@@ -419,11 +461,19 @@ | ||
var value = object[prop]; | ||
if (typeof value === "undefined" && | ||
typeof object.getAttribute === "function") { | ||
if ( | ||
typeof value === "undefined" && | ||
typeof object.getAttribute === "function" | ||
) { | ||
value = object.getAttribute(prop); | ||
} | ||
if (matcher[prop] === null || typeof matcher[prop] === "undefined") { | ||
if ( | ||
matcher[prop] === null || | ||
typeof matcher[prop] === "undefined" | ||
) { | ||
if (value !== matcher[prop]) { | ||
return false; | ||
} | ||
} else if (typeof value === "undefined" || !match(value, matcher[prop])) { | ||
} else if ( | ||
typeof value === "undefined" || | ||
!match(value, matcher[prop]) | ||
) { | ||
return false; | ||
@@ -435,13 +485,17 @@ } | ||
throw new Error("Matcher was not a string, a number, a " + | ||
"function, a boolean or an object"); | ||
throw new Error( | ||
"Matcher was not a string, a number, a " + | ||
"function, a boolean or an object" | ||
); | ||
} | ||
var match_1 = match; | ||
var samsam = { | ||
isArguments: isArguments, | ||
isElement: isElement, | ||
isNegZero: isNegZero, | ||
identical: identical, | ||
deepEqual: deepEqualCyclic, | ||
match: match | ||
isArguments: isArguments_1, | ||
isElement: isElement_1, | ||
isNegZero: isNegZero_1, | ||
identical: identical_1, | ||
deepEqual: deepEqual, | ||
match: match_1 | ||
}; | ||
@@ -448,0 +502,0 @@ var samsam_1 = samsam.isArguments; |
"use strict"; | ||
var o = Object.prototype; | ||
var div = typeof document !== "undefined" && document.createElement("div"); | ||
var deepEqualCyclic = require("./deep-equal"); | ||
var identical = require("./identical"); | ||
var isArguments = require("./is-arguments"); | ||
var isElement = require("./is-element"); | ||
var isNegZero = require("./is-neg-zero"); | ||
var match = require("./match"); | ||
function isNaN(value) { | ||
// Unlike global isNaN, this avoids type coercion | ||
// typeof check avoids IE host object issues, hat tip to | ||
// lodash | ||
var val = value; // JsLint thinks value !== value is "weird" | ||
return typeof value === "number" && value !== val; | ||
} | ||
function getClass(value) { | ||
// Returns the internal [[Class]] by calling Object.prototype.toString | ||
// with the provided value as this. Return value is a string, naming the | ||
// internal class, e.g. "Array" | ||
return o.toString.call(value).split(/[ \]]/)[1]; | ||
} | ||
function isDate(value) { | ||
return value instanceof Date; | ||
} | ||
/** | ||
* @name samsam.isArguments | ||
* @param Object object | ||
* | ||
* Returns ``true`` if ``object`` is an ``arguments`` object, | ||
* ``false`` otherwise. | ||
*/ | ||
function isArguments(object) { | ||
if (getClass(object) === "Arguments") { return true; } | ||
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 | ||
* @param Object object | ||
* | ||
* Returns ``true`` if ``object`` is a DOM element node. Unlike | ||
* Underscore.js/lodash, this function will return ``false`` if ``object`` | ||
* is an *element-like* object, i.e. a regular object with a ``nodeType`` | ||
* property that holds the value ``1``. | ||
*/ | ||
function isElement(object) { | ||
if (!object || object.nodeType !== 1 || !div) { return false; } | ||
try { | ||
object.appendChild(div); | ||
object.removeChild(div); | ||
} catch (e) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
/** | ||
* @name samsam.isNegZero | ||
* @param Object value | ||
* | ||
* Returns ``true`` if ``value`` is ``-0``. | ||
*/ | ||
function isNegZero(value) { | ||
return value === 0 && 1 / value === -Infinity; | ||
} | ||
/** | ||
* @name samsam.equal | ||
* @param Object obj1 | ||
* @param Object obj2 | ||
* | ||
* Returns ``true`` if two objects are strictly equal. Compared to | ||
* ``===`` there are two exceptions: | ||
* | ||
* - NaN is considered equal to NaN | ||
* - -0 and +0 are not considered equal | ||
*/ | ||
function identical(obj1, obj2) { | ||
if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) { | ||
return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2); | ||
} | ||
return false; | ||
} | ||
function isSet(val) { | ||
if (typeof Set !== "undefined" && val instanceof Set) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
function isSubset(s1, s2, compare) { | ||
var values1 = Array.from(s1); | ||
var values2 = Array.from(s2); | ||
for (var i = 0; i < values1.length; i++) { | ||
var includes = false; | ||
for (var j = 0; j < values2.length; j++) { | ||
if (compare(values2[j], values1[i])) { | ||
includes = true; | ||
break; | ||
} | ||
} | ||
if (!includes) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
/** | ||
* @name samsam.deepEqual | ||
* @param Object first | ||
* @param Object second | ||
* | ||
* Deep equal comparison. Two values are "deep equal" if: | ||
* | ||
* - They are equal, according to samsam.identical | ||
* - They are both date objects representing the same time | ||
* - They are both arrays containing elements that are all deepEqual | ||
* - They are objects with the same set of properties, and each property | ||
* in ``first`` is deepEqual to the corresponding property in ``second`` | ||
* | ||
* Supports cyclic objects. | ||
*/ | ||
function deepEqualCyclic(first, second) { | ||
// used for cyclic comparison | ||
// contain already visited objects | ||
var objects1 = []; | ||
var objects2 = []; | ||
// contain pathes (position in the object structure) | ||
// of the already visited objects | ||
// indexes same as in objects arrays | ||
var paths1 = []; | ||
var paths2 = []; | ||
// contains combinations of already compared objects | ||
// in the manner: { "$1['ref']$2['ref']": true } | ||
var compared = {}; | ||
/** | ||
* 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) { | ||
if (typeof value === "object" && value !== null && | ||
!(value instanceof Boolean) && | ||
!(value instanceof Date) && | ||
!(value instanceof Number) && | ||
!(value instanceof RegExp) && | ||
!(value instanceof String)) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
/** | ||
* 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) { | ||
var i; | ||
for (i = 0; i < objects.length; i++) { | ||
if (objects[i] === obj) { | ||
return i; | ||
} | ||
} | ||
return -1; | ||
} | ||
// does the recursion for the deep equal check | ||
return (function deepEqual(obj1, obj2, path1, path2) { | ||
var type1 = typeof obj1; | ||
var type2 = typeof obj2; | ||
// == null also matches undefined | ||
if (obj1 === obj2 || | ||
isNaN(obj1) || isNaN(obj2) || | ||
obj1 == null || obj2 == null || | ||
type1 !== "object" || type2 !== "object") { | ||
return identical(obj1, obj2); | ||
} | ||
// Elements are only equal if identical(expected, actual) | ||
if (isElement(obj1) || isElement(obj2)) { | ||
return false; | ||
} | ||
var isDate1 = isDate(obj1); | ||
var 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 = Object.keys(obj1); | ||
var keys2 = Object.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; | ||
} | ||
} | ||
if (isSet(obj1) || isSet(obj2)) { | ||
if (!isSet(obj1) || !isSet(obj2) || obj1.size !== obj2.size) { | ||
return false; | ||
} | ||
return isSubset(obj1, obj2, deepEqual); | ||
} | ||
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; | ||
}(first, second, "$1", "$2")); | ||
} | ||
function arrayContains(array, subset, compare) { | ||
if (subset.length === 0) { return true; } | ||
var i, l, j, k; | ||
for (i = 0, l = array.length; i < l; ++i) { | ||
if (compare(array[i], subset[0])) { | ||
for (j = 0, k = subset.length; j < k; ++j) { | ||
if ((i + j) >= l) { | ||
return false; | ||
} | ||
if (!compare(array[i + j], subset[j])) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
/** | ||
* @name samsam.match | ||
* @param Object object | ||
* @param Object matcher | ||
* | ||
* Compare arbitrary value ``object`` with matcher. | ||
*/ | ||
function match(object, matcher) { | ||
if (matcher && typeof matcher.test === "function") { | ||
return matcher.test(object); | ||
} | ||
if (typeof matcher === "function") { | ||
return matcher(object) === true; | ||
} | ||
if (typeof matcher === "string") { | ||
matcher = matcher.toLowerCase(); | ||
var notNull = typeof object === "string" || !!object; | ||
return notNull && | ||
(String(object)).toLowerCase().indexOf(matcher) >= 0; | ||
} | ||
if (typeof matcher === "number") { | ||
return matcher === object; | ||
} | ||
if (typeof matcher === "boolean") { | ||
return matcher === object; | ||
} | ||
if (typeof matcher === "undefined") { | ||
return typeof object === "undefined"; | ||
} | ||
if (matcher === null) { | ||
return object === null; | ||
} | ||
if (isSet(object)) { | ||
return isSubset(matcher, object, match); | ||
} | ||
if (getClass(object) === "Array" && getClass(matcher) === "Array") { | ||
return arrayContains(object, matcher, match); | ||
} | ||
if (isDate(matcher)) { | ||
return isDate(object) && object.getTime() === matcher.getTime(); | ||
} | ||
if (matcher && typeof matcher === "object") { | ||
if (matcher === object) { | ||
return true; | ||
} | ||
var prop; | ||
// eslint-disable-next-line guard-for-in | ||
for (prop in matcher) { | ||
var value = object[prop]; | ||
if (typeof value === "undefined" && | ||
typeof object.getAttribute === "function") { | ||
value = object.getAttribute(prop); | ||
} | ||
if (matcher[prop] === null || typeof matcher[prop] === "undefined") { | ||
if (value !== matcher[prop]) { | ||
return false; | ||
} | ||
} else if (typeof value === "undefined" || !match(value, matcher[prop])) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
throw new Error("Matcher was not a string, a number, a " + | ||
"function, a boolean or an object"); | ||
} | ||
module.exports = { | ||
@@ -419,0 +11,0 @@ isArguments: isArguments, |
{ | ||
"name": "@sinonjs/samsam", | ||
"version": "2.0.0", | ||
"version": "2.1.0", | ||
"description": "Value identification and comparison functions", | ||
@@ -17,2 +17,3 @@ "homepage": "http://sinonjs.github.io/samsam/", | ||
"scripts": { | ||
"benchmark": "node lib/deep-equal-benchmark.js", | ||
"build": "run-s build:dist-folder build:bundle", | ||
@@ -23,3 +24,3 @@ "build:bundle": "rollup -c > dist/samsam.js", | ||
"prepublishOnly": "npm run build && mkdocs gh-deploy -r upstream || mkdocs gh-deploy -r origin", | ||
"test": "mocha ./lib/samsam.test.js", | ||
"test": "mocha ./lib/*.test.js", | ||
"test-coverage": "nyc --reporter text --reporter html --reporter lcovonly npm run test" | ||
@@ -33,9 +34,14 @@ }, | ||
], | ||
"dependencies": {}, | ||
"dependencies": { | ||
"array-from": "^2.1.1" | ||
}, | ||
"devDependencies": { | ||
"@sinonjs/referee": "^2.0.0", | ||
"eslint": "^4.16.0", | ||
"benchmark": "2.1.4", | ||
"eslint": "^4.19.1", | ||
"eslint-config-prettier": "2.9.0", | ||
"eslint-config-sinon": "^1.0.3", | ||
"eslint-plugin-ie11": "^1.0.0", | ||
"eslint-plugin-mocha": "^4.11.0", | ||
"eslint-plugin-prettier": "2.6.2", | ||
"husky": "^0.14.3", | ||
@@ -45,6 +51,8 @@ "jsdom": "^9.12.0", | ||
"lint-staged": "^6.1.0", | ||
"microtime": "2.1.8", | ||
"mkdirp": "^0.5.1", | ||
"mocha": "^5.0.0", | ||
"npm-run-all": "^4.1.2", | ||
"nyc": "^11.6.0", | ||
"nyc": "^11.7.3", | ||
"prettier": "1.13.7", | ||
"rollup": "^0.57.1", | ||
@@ -51,0 +59,0 @@ "rollup-plugin-commonjs": "^9.1.0" |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
57575
22
972
1
20
1
+ Addedarray-from@^2.1.1
+ Addedarray-from@2.1.1(transitive)