From 984a10c1b1e51f112b4cc7e6548b9c1adfe5f80d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 21 Jul 2016 08:41:06 -0700 Subject: [PATCH] Add `isConcatSpreadable` to flatten methods. --- lodash.js | 8 +++++--- test/test.js | 29 ++++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/lodash.js b/lodash.js index a73778a45..a7bf85c13 100644 --- a/lodash.js +++ b/lodash.js @@ -1336,10 +1336,11 @@ Symbol = context.Symbol, Uint8Array = context.Uint8Array, enumerate = Reflect ? Reflect.enumerate : undefined, - iteratorSymbol = typeof (iteratorSymbol = Symbol && Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined, + iteratorSymbol = Symbol ? Symbol.iterator : undefined, objectCreate = context.Object.create, propertyIsEnumerable = objectProto.propertyIsEnumerable, - splice = arrayProto.splice; + splice = arrayProto.splice, + spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined; /** Built-in method references that are mockable. */ var clearTimeout = function(id) { return context.clearTimeout.call(root, id); }, @@ -5869,7 +5870,8 @@ * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. */ function isFlattenable(value) { - return isArray(value) || isArguments(value); + return isArray(value) || isArguments(value) || + !!(spreadableSymbol && value && value[spreadableSymbol]) } /** diff --git a/test/test.js b/test/test.js index 62bc92df9..585d5f047 100644 --- a/test/test.js +++ b/test/test.js @@ -6505,7 +6505,8 @@ (function() { var args = arguments, - array = [1, [2, [3, [4]], 5]]; + array = [1, [2, [3, [4]], 5]], + methodNames = ['flatten', 'flattenDeep', 'flattenDepth']; QUnit.test('should flatten `arguments` objects', function(assert) { assert.expect(3); @@ -6525,12 +6526,34 @@ expected.push(undefined, undefined, undefined); - lodashStable.each([_.flatten(array), _.flattenDeep(array), _.flattenDepth(array)], function(actual) { + lodashStable.each(methodNames, function(methodName) { + var actual = _[methodName](array); assert.deepEqual(actual, expected); assert.ok('4' in actual); }); }); + QUnit.test('should flatten objects with a truthy `Symbol.isConcatSpreadable` value', function(assert) { + assert.expect(1); + + if (Symbol && Symbol.isConcatSpreadable) { + var object = { '0': 'a', 'length': 1 }, + array = [object], + expected = lodashStable.map(methodNames, lodashStable.constant(['a'])); + + object[Symbol.isConcatSpreadable] = true; + + var actual = lodashStable.map(methodNames, function(methodName) { + return _[methodName](array); + }); + + assert.deepEqual(actual, expected); + } + else { + skipAssert(assert); + } + }); + QUnit.test('should work with extremely large arrays', function(assert) { assert.expect(3); @@ -22907,7 +22930,7 @@ QUnit.test('should convert iterables to arrays', function(assert) { assert.expect(1); - if (!isNpm && Symbol && Symbol.iterator) { + if (Symbol && Symbol.iterator) { var object = { '0': 'a', 'length': 1 }; object[Symbol.iterator] = arrayProto[Symbol.iterator];