From ba3ede584eda7779e18d39cd38700e6060b11996 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Thu, 13 Aug 2015 08:57:48 -0700 Subject: [PATCH] Add stack params to several `customizer` callback calls. --- lodash.js | 28 +++++++++++++++--------- test/test.js | 61 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 53 insertions(+), 36 deletions(-) diff --git a/lodash.js b/lodash.js index b0aea215f..54aa059c2 100644 --- a/lodash.js +++ b/lodash.js @@ -1602,7 +1602,7 @@ function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { var result; if (customizer) { - result = object ? customizer(value, key, object) : customizer(value); + result = object ? customizer(value, key, object, stackA, stackB) : customizer(value); } if (result !== undefined) { return result; @@ -3489,9 +3489,13 @@ // Ignore non-index properties. while (++index < arrLength) { var arrValue = array[index], - othValue = other[index], - result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + othValue = other[index]; + if (customizer) { + var result = isLoose + ? customizer(othValue, arrValue, index, other, array, stackA, stackB) + : customizer(arrValue, othValue, index, array, other, stackA, stackB); + } if (result !== undefined) { if (result) { continue; @@ -3585,9 +3589,13 @@ while (++index < objLength) { key = objProps[index]; var objValue = object[key], - othValue = other[key], - result = customizer ? customizer(isLoose ? othValue : objValue, isLoose? objValue : othValue, key) : undefined; + othValue = other[key]; + if (customizer) { + var result = isLoose + ? customizer(othValue, objValue, key, other, object, stackA, stackB) + : customizer(objValue, othValue, key, object, other, stackA, stackB); + } // Recursively compare objects (susceptible to call stack limits). if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { return false; @@ -7640,7 +7648,7 @@ * This method is like `_.clone` except that it accepts `customizer` which * is invoked to produce the cloned value. If `customizer` returns `undefined` * cloning is handled by the method instead. The `customizer` is invoked with - * up to three arguments; (value [, index|key, object]). + * up to five arguments; (value [, index|key, object, stackA, stackB]). * * @static * @memberOf _ @@ -7964,10 +7972,10 @@ } /** - * This method is like `_.isEqual` except that it accepts `customizer` which - * is invoked to compare values. If `customizer` returns `undefined` comparisons - * are handled by the method instead. The `customizer` is invoked with up to - * three arguments: (value, other [, index|key]). + * This method is like `_.isEqual` except that it accepts `customizer` which is + * invoked to compare values. If `customizer` returns `undefined` comparisons are + * handled by the method instead. The `customizer` is invoked with up to seven arguments: + * (objectValue, otherValue [, index|key, object, other, stackA, stackB]). * * @static * @memberOf _ diff --git a/test/test.js b/test/test.js index 7c688293a..6819dbdf4 100644 --- a/test/test.js +++ b/test/test.js @@ -2020,7 +2020,7 @@ argsList.push(slice.call(arguments)); }); - deepEqual(argsList, isDeepWith ? [[foo], [1, 'a', foo]] : [[foo]]); + deepEqual(argsList, isDeepWith ? [[foo], [1, 'a', foo, [foo], [{ 'a': 1 }]]] : [[foo]]); }); test('`_.' + methodName + '` should handle cloning if `customizer` returns `undefined`', 1, function() { @@ -5150,13 +5150,17 @@ test('`_.' + methodName + '` should provide the correct `customizer` arguments', 3, function() { var args, object = { 'a': 1 }, - source = { 'a': 2 }; + source = { 'a': 2 }, + expected = [1, 2, 'a', object, source]; func(object, source, function() { args || (args = slice.call(arguments)); }); - deepEqual(args, [1, 2, 'a', object, source], 'primitive property values'); + if (isMergeWith) { + expected.push(undefined, undefined); + } + deepEqual(args, expected, 'primitive property values'); args = null; object = { 'a': 1 }; @@ -5166,7 +5170,11 @@ args || (args = slice.call(arguments)); }); - deepEqual(args, [undefined, 2, 'b', object, source], 'missing destination property'); + expected = [undefined, 2, 'b', object, source]; + if (isMergeWith) { + expected.push(undefined, undefined); + } + deepEqual(args, expected, 'missing destination property'); var argsList = [], objectValue = [1, 2], @@ -5179,9 +5187,10 @@ argsList.push(slice.call(arguments)); }); - var expected = [[objectValue, sourceValue, 'a', object, source]]; + expected = [[objectValue, sourceValue, 'a', object, source]]; if (isMergeWith) { - expected.push([undefined, 2, 'b', sourceValue, sourceValue]); + expected[0].push([sourceValue], [sourceValue]); + expected.push([undefined, 2, 'b', sourceValue, sourceValue, [sourceValue], [sourceValue]]); } deepEqual(argsList, expected, 'object property values'); }); @@ -7055,14 +7064,14 @@ var expected = [ [object1, object2], - [object1.a, object2.a, 'a'], - [object1.a[0], object2.a[0], 0], - [object1.a[1], object2.a[1], 1], - [object1.b, object2.b, 'b'], - [object1.b.a, object2.b.a, 'a'], - [object1.b.a[0], object2.b.a[0], 0], - [object1.b.a[1], object2.b.a[1], 1], - [object1.b.b, object2.b.b, 'b'] + [object1.a, object2.a, 'a', object1, object2, [], []], + [object1.a[0], object2.a[0], 0, object1.a, object2.a, [], []], + [object1.a[1], object2.a[1], 1, object1.a, object2.a, [], []], + [object1.b, object2.b, 'b', object1.b, object2.b, [], []], + [object1.b.a, object2.b.a, 'a', object1.b, object2.b, [], []], + [object1.b.a[0], object2.b.a[0], 0, object1.b.a, object2.b.a, [], []], + [object1.b.a[1], object2.b.a[1], 1, object1.b.a, object2.b.a, [], []], + [object1.b.b, object2.b.b, 'b', object1.b.b, object2.b.b, [], []] ]; _.isEqualWith(object1, object2, function() { @@ -7519,18 +7528,18 @@ object2.b = object1; var expected = [ - [object1.a, object2.a, 'a'], - [object1.a[0], object2.a[0], 0], - [object1.a[1], object2.a[1], 1], - [object1.b, object2.b, 'b'], - [object1.b.a, object2.b.a, 'a'], - [object1.b.a[0], object2.b.a[0], 0], - [object1.b.a[1], object2.b.a[1], 1], - [object1.b.b, object2.b.b, 'b'], - [object1.b.b.a, object2.b.b.a, 'a'], - [object1.b.b.a[0], object2.b.b.a[0], 0], - [object1.b.b.a[1], object2.b.b.a[1], 1], - [object1.b.b.b, object2.b.b.b, 'b'] + [object1.a, object2.a, 'a', object1, object2, [], []], + [object1.a[0], object2.a[0], 0, object1.a, object2.a, [], []], + [object1.a[1], object2.a[1], 1, object1.a, object2.a, [], []], + [object1.b, object2.b, 'b', object1, object2, [], []], + [object1.b.a, object2.b.a, 'a', object1.b, object2.b, [], []], + [object1.b.a[0], object2.b.a[0], 0, object1.b.a, object2.b.a, [], []], + [object1.b.a[1], object2.b.a[1], 1, object1.b.a, object2.b.a, [], []], + [object1.b.b, object2.b.b, 'b', object1.b, object2.b, [], []], + [object1.b.b.a, object2.b.b.a, 'a', object1.b.b, object2.b.b, [], []], + [object1.b.b.a[0], object2.b.b.a[0], 0, object1.b.b.a, object2.b.b.a, [], []], + [object1.b.b.a[1], object2.b.b.a[1], 1, object1.b.b.a, object2.b.b.a, [], []], + [object1.b.b.b, object2.b.b.b, 'b', object1.b.b, object2.b.b, [], []] ]; _.isMatchWith(object1, object2, function() {