Cleanup setData.

This commit is contained in:
John-David Dalton
2014-08-18 00:35:04 -07:00
parent 1416655d53
commit 8f9eed154e

View File

@@ -23,6 +23,10 @@
PARTIAL_FLAG = 32, PARTIAL_FLAG = 32,
PARTIAL_RIGHT_FLAG = 64; PARTIAL_RIGHT_FLAG = 64;
/** Used to detect when a function becomes hot */
var HOT_COUNT = 150,
HOT_SPAN = 16;
/** Used as the property name for wrapper metadata */ /** Used as the property name for wrapper metadata */
var EXPANDO = '__lodash_' + VERSION.replace(/[-.]/g, '_') + '__'; var EXPANDO = '__lodash_' + VERSION.replace(/[-.]/g, '_') + '__';
@@ -1379,7 +1383,7 @@
if (!data) { if (!data) {
// checks if `func` references the `this` keyword and stores the result // checks if `func` references the `this` keyword and stores the result
data = reThis.test(source) || isNative(func); data = reThis.test(source) || isNative(func);
setData(func, data); baseSetData(func, data);
} }
} }
} }
@@ -2205,6 +2209,28 @@
return accumulator; return accumulator;
} }
/**
* The base implementation of `setData` without support for hot loop detection.
*
* @private
* @param {Function} func The function to associate metadata with.
* @param {*} data The metadata.
* @returns {Function} Returns `func`.
*/
function baseSetData(func, data) {
metaMap.set(func, data);
return func;
}
// fallback for environments without `WeakMap`
if (!WeakMap) {
baseSetData = !defineProperty ? identity : function(func, value) {
descriptor.value = value;
defineProperty(func, EXPANDO, descriptor);
descriptor.value = null;
return func;
};
}
/** /**
* The base implementation of `_.some` without support for callback shorthands * The base implementation of `_.some` without support for callback shorthands
* or `this` binding. * or `this` binding.
@@ -2723,8 +2749,8 @@
isPartialRight = false; isPartialRight = false;
partialRightArgs = partialRightHolders = null; partialRightArgs = partialRightHolders = null;
} }
var data = !isBindKey && getData(func); var data = (data = !isBindKey && getData(func)) && data !== true && data;
if (data && data !== true) { if (data) {
var funcBitmask = data[1], var funcBitmask = data[1],
funcIsBind = funcBitmask & BIND_FLAG, funcIsBind = funcBitmask & BIND_FLAG,
isBind = bitmask & BIND_FLAG; isBind = bitmask & BIND_FLAG;
@@ -2770,7 +2796,8 @@
} else { } else {
result = createHybridWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders); result = createHybridWrapper(func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders);
} }
return setData(result, [func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders]); var setter = data ? baseSetData : setData;
return setter(result, [func, bitmask, arity, thisArg, partialArgs, partialHolders, partialRightArgs, partialRightHolders]);
} }
/** /**
@@ -3010,49 +3037,34 @@
/** /**
* Sets metadata for `func`. * Sets metadata for `func`.
* *
* **Note**: If this function becomes hot, i.e. is called a lot in a short
* period of time, it will trip its breaker and transition to an identity
* function to avoid garbage collection pauses.
*
* @private * @private
* @param {Function} func The function to associate metadata with. * @param {Function} func The function to associate metadata with.
* @param {*} data The metadata. * @param {*} data The metadata.
* @returns {Function} Returns `func`. * @returns {Function} Returns `func`.
*/ */
function baseSetData(func, data) { var setData = (function() {
metaMap.set(func, data);
return func;
}
// fallback for environments without `WeakMap`
if (!WeakMap) {
baseSetData = !defineProperty ? identity : function(func, value) {
descriptor.value = value;
defineProperty(func, EXPANDO, descriptor);
descriptor.value = null;
return func;
};
}
function trip(func, times, wait) {
var count = 0, var count = 0,
lastCalled = 0; lastCalled = 0;
return function(key, value) { return function(key, value) {
var stamp = now ? now() : 0, var stamp = now ? now() : 0,
remaining = wait - (stamp - lastCalled); remaining = HOT_SPAN - (stamp - lastCalled);
lastCalled = stamp; lastCalled = stamp;
if (remaining > 0) { if (remaining > 0) {
if (++count > times) { if (++count > HOT_COUNT) {
var dataFunc = typeof value == 'object' && isFunction(dataFunc = value[0]) && dataFunc; return key;
if (typeof getData(key) == 'undefined' && !(dataFunc && getData(dataFunc) != 'undefined')) {
return key;
}
} }
} else { } else {
count = 0; count = 0;
} }
return func(key, value); return baseSetData(key, value);
} };
} }());
var setData = trip(baseSetData, 50, 16);
/** /**
* A fallback implementation of `_.isPlainObject` which checks if `value` * A fallback implementation of `_.isPlainObject` which checks if `value`