From 0b8592a35c4cb0ab3a7b825d1d9b37dfa1eade43 Mon Sep 17 00:00:00 2001 From: Marc Hassan Date: Thu, 21 Mar 2019 23:54:53 -0400 Subject: [PATCH] mergeWith: stack passed to customizer should always be defined (#4244) Summary: If the first values encountered in the `object` in mergeWith are not objects, `stack` is undefined when passed to the `customizer`. Once the first object-ish value is encountered, `stack` gets initialized, and all further calls to `customizer` include a defined `stack`. This PR makes `stack` always defined, even before the first object-ish value is encountered. --- lodash.js | 2 +- test/test.js | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/lodash.js b/lodash.js index b894cf753..783feb9b9 100644 --- a/lodash.js +++ b/lodash.js @@ -3588,8 +3588,8 @@ return; } baseFor(source, function(srcValue, key) { + stack || (stack = new Stack); if (isObject(srcValue)) { - stack || (stack = new Stack); baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); } else { diff --git a/test/test.js b/test/test.js index 284fa5ebf..2a2b97c52 100644 --- a/test/test.js +++ b/test/test.js @@ -15280,18 +15280,21 @@ }); QUnit.test('should provide `stack` to `customizer`', function(assert) { - assert.expect(1); + assert.expect(4); - var actual; + var actual = []; - _.mergeWith({}, { 'a': { 'b': 2 } }, function() { - actual = _.last(arguments); + _.mergeWith({}, { 'z': 1, 'a': { 'b': 2 } }, function() { + actual.push(_.last(arguments)); }); - assert.ok(isNpm - ? actual.constructor.name == 'Stack' - : actual instanceof mapCaches.Stack - ); + assert.strictEqual(actual.length, 3); + _.each(actual, function(a) { + assert.ok(isNpm + ? a.constructor.name == 'Stack' + : a instanceof mapCaches.Stack + ); + }); }); QUnit.test('should overwrite primitives with source object clones', function(assert) {