diff --git a/index.js b/index.js index 8e5e333..d3a27bc 100644 --- a/index.js +++ b/index.js @@ -235,8 +235,10 @@ function extensiveDeepEqualByType(leftHandOperand, rightHandOperand, leftHandTyp case 'Uint32Array': case 'Float32Array': case 'Float64Array': - case 'Array': return iterableEqual(leftHandOperand, rightHandOperand, options); + case 'Array': + return iterableEqual(leftHandOperand, rightHandOperand, options) && + arrayExtraKeysEqual(leftHandOperand, rightHandOperand, options); case 'RegExp': return regexpEqual(leftHandOperand, rightHandOperand); case 'Generator': @@ -338,6 +340,37 @@ function iterableEqual(leftHandOperand, rightHandOperand, options) { return true; } +/*! + * `iterableEqual` only compares indices 0..length-1, so an array-index own-enumerable + * property (own or inherited, matching `getEnumerableKeys`) is otherwise never noticed -- + * this checks the rest, per the documented "all own and inherited enumerable properties + * are considered" rule. + * + * @param {Array} leftHandOperand + * @param {Array} rightHandOperand + * @param {Object} [options] (Optional) + * @return {Boolean} result + */ +function arrayExtraKeysEqual(leftHandOperand, rightHandOperand, options) { + var length = leftHandOperand.length; + function isNotArrayIndex(key) { + return !(/^(0|[1-9]\d*)$/.test(key) && Number(key) < length); + } + + var leftHandKeys = getEnumerableKeys(leftHandOperand).filter(isNotArrayIndex) + .concat(getEnumerableSymbols(leftHandOperand)); + var rightHandKeys = getEnumerableKeys(rightHandOperand).filter(isNotArrayIndex) + .concat(getEnumerableSymbols(rightHandOperand)); + + if (leftHandKeys.length !== rightHandKeys.length) { + return false; + } + if (iterableEqual(mapSymbols(leftHandKeys).sort(), mapSymbols(rightHandKeys).sort()) === false) { + return false; + } + return keysEqual(leftHandOperand, rightHandOperand, leftHandKeys, options); +} + /*! * Simple equality for generator objects such as those returned by generator functions. * diff --git a/test/index.js b/test/index.js index c6d4c33..2a11888 100644 --- a/test/index.js +++ b/test/index.js @@ -277,6 +277,21 @@ describe('Generic', function () { assert(eql(new Array(1), new Array(100)) === false, 'eql(new Array(1), new Array(100)) === false'); }); + it('considers extra own-enumerable properties, not just indices', function () { + var withExtraX1 = [ 1, 2, 3 ]; + withExtraX1.extra = 'x'; + var withExtraY = [ 1, 2, 3 ]; + withExtraY.extra = 'y'; + var withExtraX2 = [ 1, 2, 3 ]; + withExtraX2.extra = 'x'; + + assert(eql(withExtraX1, withExtraY) === false, + 'arrays with the same indices but different extra properties are not equal'); + assert(eql(withExtraX1, withExtraX2), + 'arrays with the same indices and the same extra properties are equal'); + assert(eql([ 1, 2, 3 ], [ 1, 2, 3 ]), 'arrays with no extra properties are unaffected'); + }); + }); describe('objects', function () {