Array equality treats undefined elements as equal however they got in there
- Fixes #786
This commit is contained in:
@@ -2879,36 +2879,43 @@ getJasmineRequireObj().matchersUtil = function(j$) {
|
|||||||
var size = 0;
|
var size = 0;
|
||||||
// Recursively compare objects and arrays.
|
// Recursively compare objects and arrays.
|
||||||
// Compare array lengths to determine if a deep comparison is necessary.
|
// Compare array lengths to determine if a deep comparison is necessary.
|
||||||
if (className == '[object Array]' && a.length !== b.length) {
|
if (className == '[object Array]') {
|
||||||
result = false;
|
size = a.length;
|
||||||
}
|
if (size !== b.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (result) {
|
while (size--) {
|
||||||
// Objects with different constructors are not equivalent, but `Object`s
|
result = eq(a[size], b[size], aStack, bStack, customTesters);
|
||||||
// or `Array`s from different frames are.
|
if (!result) {
|
||||||
if (className !== '[object Array]') {
|
|
||||||
var aCtor = a.constructor, bCtor = b.constructor;
|
|
||||||
if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor &&
|
|
||||||
isFunction(bCtor) && bCtor instanceof bCtor)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
// Deep compare objects.
|
// Objects with different constructors are not equivalent, but `Object`s
|
||||||
var aKeys = keys(a), key;
|
// or `Array`s from different frames are.
|
||||||
size = aKeys.length;
|
var aCtor = a.constructor, bCtor = b.constructor;
|
||||||
|
if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor &&
|
||||||
|
isFunction(bCtor) && bCtor instanceof bCtor)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that both objects contain the same number of properties before comparing deep equality.
|
// Deep compare objects.
|
||||||
if (keys(b).length !== size) { return false; }
|
var aKeys = keys(a, className == '[object Array]'), key;
|
||||||
|
size = aKeys.length;
|
||||||
|
|
||||||
while (size--) {
|
// Ensure that both objects contain the same number of properties before comparing deep equality.
|
||||||
key = aKeys[size];
|
if (keys(b, className == '[object Array]').length !== size) { return false; }
|
||||||
// Deep compare each member
|
|
||||||
result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters);
|
|
||||||
|
|
||||||
if (!result) {
|
while (size--) {
|
||||||
return false;
|
key = aKeys[size];
|
||||||
}
|
// Deep compare each member
|
||||||
|
result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove the first object from the stack of traversed objects.
|
// Remove the first object from the stack of traversed objects.
|
||||||
@@ -2917,8 +2924,8 @@ getJasmineRequireObj().matchersUtil = function(j$) {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
function keys(obj) {
|
function keys(obj, isArray) {
|
||||||
return Object.keys ? Object.keys(obj) :
|
var allKeys = Object.keys ? Object.keys(obj) :
|
||||||
(function(o) {
|
(function(o) {
|
||||||
var keys = [];
|
var keys = [];
|
||||||
for (var key in o) {
|
for (var key in o) {
|
||||||
@@ -2928,6 +2935,19 @@ getJasmineRequireObj().matchersUtil = function(j$) {
|
|||||||
}
|
}
|
||||||
return keys;
|
return keys;
|
||||||
})(obj);
|
})(obj);
|
||||||
|
|
||||||
|
if (!isArray) {
|
||||||
|
return allKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
var extraKeys = [];
|
||||||
|
for (var i in allKeys) {
|
||||||
|
if (!allKeys[i].match(/^[0-9]+$/)) {
|
||||||
|
extraKeys.push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return extraKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
function has(obj, key) {
|
function has(obj, key) {
|
||||||
|
|||||||
@@ -54,6 +54,13 @@ describe("matchersUtil", function() {
|
|||||||
expect(jasmineUnderTest.matchersUtil.equals([1, 2], [1, 2])).toBe(true);
|
expect(jasmineUnderTest.matchersUtil.equals([1, 2], [1, 2])).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("passes for Arrays that are equivalent, with elements added by changing length", function() {
|
||||||
|
var foo = [];
|
||||||
|
foo.length = 1;
|
||||||
|
|
||||||
|
expect(jasmineUnderTest.matchersUtil.equals(foo, [undefined])).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it("fails for Arrays that are not equivalent", function() {
|
it("fails for Arrays that are not equivalent", function() {
|
||||||
expect(jasmineUnderTest.matchersUtil.equals([1, 2], [1, 2, 3])).toBe(false);
|
expect(jasmineUnderTest.matchersUtil.equals([1, 2], [1, 2, 3])).toBe(false);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -161,36 +161,43 @@ getJasmineRequireObj().matchersUtil = function(j$) {
|
|||||||
var size = 0;
|
var size = 0;
|
||||||
// Recursively compare objects and arrays.
|
// Recursively compare objects and arrays.
|
||||||
// Compare array lengths to determine if a deep comparison is necessary.
|
// Compare array lengths to determine if a deep comparison is necessary.
|
||||||
if (className == '[object Array]' && a.length !== b.length) {
|
if (className == '[object Array]') {
|
||||||
result = false;
|
size = a.length;
|
||||||
}
|
if (size !== b.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (result) {
|
while (size--) {
|
||||||
// Objects with different constructors are not equivalent, but `Object`s
|
result = eq(a[size], b[size], aStack, bStack, customTesters);
|
||||||
// or `Array`s from different frames are.
|
if (!result) {
|
||||||
if (className !== '[object Array]') {
|
|
||||||
var aCtor = a.constructor, bCtor = b.constructor;
|
|
||||||
if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor &&
|
|
||||||
isFunction(bCtor) && bCtor instanceof bCtor)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
// Deep compare objects.
|
// Objects with different constructors are not equivalent, but `Object`s
|
||||||
var aKeys = keys(a), key;
|
// or `Array`s from different frames are.
|
||||||
size = aKeys.length;
|
var aCtor = a.constructor, bCtor = b.constructor;
|
||||||
|
if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor &&
|
||||||
|
isFunction(bCtor) && bCtor instanceof bCtor)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that both objects contain the same number of properties before comparing deep equality.
|
// Deep compare objects.
|
||||||
if (keys(b).length !== size) { return false; }
|
var aKeys = keys(a, className == '[object Array]'), key;
|
||||||
|
size = aKeys.length;
|
||||||
|
|
||||||
while (size--) {
|
// Ensure that both objects contain the same number of properties before comparing deep equality.
|
||||||
key = aKeys[size];
|
if (keys(b, className == '[object Array]').length !== size) { return false; }
|
||||||
// Deep compare each member
|
|
||||||
result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters);
|
|
||||||
|
|
||||||
if (!result) {
|
while (size--) {
|
||||||
return false;
|
key = aKeys[size];
|
||||||
}
|
// Deep compare each member
|
||||||
|
result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove the first object from the stack of traversed objects.
|
// Remove the first object from the stack of traversed objects.
|
||||||
@@ -199,8 +206,8 @@ getJasmineRequireObj().matchersUtil = function(j$) {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
function keys(obj) {
|
function keys(obj, isArray) {
|
||||||
return Object.keys ? Object.keys(obj) :
|
var allKeys = Object.keys ? Object.keys(obj) :
|
||||||
(function(o) {
|
(function(o) {
|
||||||
var keys = [];
|
var keys = [];
|
||||||
for (var key in o) {
|
for (var key in o) {
|
||||||
@@ -210,6 +217,19 @@ getJasmineRequireObj().matchersUtil = function(j$) {
|
|||||||
}
|
}
|
||||||
return keys;
|
return keys;
|
||||||
})(obj);
|
})(obj);
|
||||||
|
|
||||||
|
if (!isArray) {
|
||||||
|
return allKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
var extraKeys = [];
|
||||||
|
for (var i in allKeys) {
|
||||||
|
if (!allKeys[i].match(/^[0-9]+$/)) {
|
||||||
|
extraKeys.push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return extraKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
function has(obj, key) {
|
function has(obj, key) {
|
||||||
|
|||||||
Reference in New Issue
Block a user