diff --git a/lodash.js b/lodash.js index f0e8af6b6..47251e8b5 100644 --- a/lodash.js +++ b/lodash.js @@ -6220,6 +6220,26 @@ }; } + /** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ + function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; + } + /** * Merges the function metadata of `source` into `data`. * @@ -6486,7 +6506,7 @@ * @param {string} string The string to convert. * @returns {Array} Returns the property path array. */ - var stringToPath = memoize(function(string) { + var stringToPath = memoizeCapped(function(string) { string = toString(string); var result = []; @@ -10341,9 +10361,6 @@ return cache.get(key); } var result = func.apply(this, args); - if (cache.size === MAX_MEMOIZE_SIZE) { - cache = cache.clear() || cache; - } memoized.cache = cache.set(key, result) || cache; return result; }; diff --git a/test/test.js b/test/test.js index be731c7db..a17ffa996 100644 --- a/test/test.js +++ b/test/test.js @@ -733,7 +733,8 @@ lodashStable.each([ 'baseEach', 'isIndex', - 'isIterateeCall' + 'isIterateeCall', + 'memoizeCapped' ], function(funcName) { _['_' + funcName] = interopRequire(path.join(basePath, '_' + funcName)); }); @@ -14657,54 +14658,32 @@ _.memoize.Cache = oldCache; }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('memoizeCapped'); + + (function() { + var func = _._memoizeCapped; QUnit.test('should enforce a max cache size of `MAX_MEMOIZE_SIZE`', function(assert) { assert.expect(2); - var memoized = _.memoize(identity), - cache = memoized.cache; + if (func) { + var memoized = func(identity), + cache = memoized.cache; - lodashStable.times(MAX_MEMOIZE_SIZE, memoized); - assert.strictEqual(cache.size, MAX_MEMOIZE_SIZE); + lodashStable.times(MAX_MEMOIZE_SIZE, memoized); + assert.strictEqual(cache.size, MAX_MEMOIZE_SIZE); - memoized(MAX_MEMOIZE_SIZE); - assert.strictEqual(cache.size, 1); - }); - - QUnit.test('should not error when the max cache size is exceeded with a weak map', function(assert) { - assert.expect(1); - - if (WeakMap) { - var memoized = _.memoize(identity), - pass = true; - - try { - memoized.cache = new WeakMap; - lodashStable.times(MAX_MEMOIZE_SIZE + 1, function() { memoized({}); }); - } catch (e) { - pass = false; - } - assert.ok(pass); + memoized(MAX_MEMOIZE_SIZE); + assert.strictEqual(cache.size, 1); } else { - skipAssert(assert); + skipAssert(assert, 2); } }); - - QUnit.test('should not error when the max cache size is exceeded with an immutable map', function(assert) { - assert.expect(1); - - var memoized = _.memoize(identity), - pass = true; - - try { - memoized.cache = new ImmutableCache; - lodashStable.times(MAX_MEMOIZE_SIZE + 1, memoized); - } catch (e) { - pass = false; - } - assert.ok(pass); - }); }()); /*--------------------------------------------------------------------------*/