Ensure _.flattenDeep works on arrays with circular references. [closes #1664]

This commit is contained in:
John-David Dalton
2015-11-25 09:19:24 -08:00
parent e6de183651
commit dd64f5eac4
2 changed files with 39 additions and 3 deletions

View File

@@ -2489,9 +2489,10 @@
* @param {boolean} [isDeep] Specify a deep flatten.
* @param {boolean} [isStrict] Restrict flattening to arrays-like objects.
* @param {Array} [result=[]] The initial result value.
* @param {Object} [stack] Tracks traversed arrays.
* @returns {Array} Returns the new flattened array.
*/
function baseFlatten(array, isDeep, isStrict, result) {
function baseFlatten(array, isDeep, isStrict, result, stack) {
result || (result = []);
var index = -1,
@@ -2502,9 +2503,18 @@
if (isArrayLikeObject(value) &&
(isStrict || isArray(value) || isArguments(value))) {
if (isDeep) {
stack || (stack = new Stack);
if (stack.get(array)) {
return result;
}
stack.set(array, true);
// Recursively flatten arrays (susceptible to call stack limits).
baseFlatten(value, isDeep, isStrict, result);
} else {
baseFlatten(value, isDeep, isStrict, result, stack);
stack['delete'](array);
}
else {
arrayPush(result, value);
}
} else if (!isStrict) {

View File

@@ -5081,6 +5081,32 @@
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.flattenDeep');
(function() {
QUnit.test('should flatten arrays with circular references', function(assert) {
assert.expect(2);
var array = [1, 2];
array.push(array);
var expected = [1, 2, 1, 2];
try {
var actual = _.flattenDeep(array);
} catch (e) {}
assert.deepEqual(actual, expected);
array = [1, 2];
array = [array, [array]];
assert.deepEqual(_.flattenDeep(array), expected);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('flatten methods');
(function() {