mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-12 03:47:50 +00:00
Drop funcDecomp optimization in baseCallback and ensure shortcut fusion for _.flow and _.flowRight works in minified builds.
This commit is contained in:
116
lodash.src.js
116
lodash.src.js
@@ -120,9 +120,6 @@
|
|||||||
var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g,
|
var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g,
|
||||||
reHasRegExpChars = RegExp(reRegExpChars.source);
|
reHasRegExpChars = RegExp(reRegExpChars.source);
|
||||||
|
|
||||||
/** Used to detect functions containing a `this` reference. */
|
|
||||||
var reThis = /\bthis\b/;
|
|
||||||
|
|
||||||
/** Used to match unescaped characters in compiled string literals. */
|
/** Used to match unescaped characters in compiled string literals. */
|
||||||
var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
|
var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
|
||||||
|
|
||||||
@@ -153,7 +150,7 @@
|
|||||||
'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document',
|
'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document',
|
||||||
'isFinite', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array',
|
'isFinite', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array',
|
||||||
'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
|
'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
|
||||||
'window', 'WinRTError'
|
'window'
|
||||||
];
|
];
|
||||||
|
|
||||||
/** Used to fix the JScript `[[DontEnum]]` bug. */
|
/** Used to fix the JScript `[[DontEnum]]` bug. */
|
||||||
@@ -831,6 +828,9 @@
|
|||||||
/** Used to store function metadata. */
|
/** Used to store function metadata. */
|
||||||
var metaMap = WeakMap && new WeakMap;
|
var metaMap = WeakMap && new WeakMap;
|
||||||
|
|
||||||
|
/** Used to lookup unminified function names. */
|
||||||
|
var realNames = {};
|
||||||
|
|
||||||
/** Used to lookup a type array constructors by `toStringTag`. */
|
/** Used to lookup a type array constructors by `toStringTag`. */
|
||||||
var ctorByTag = {};
|
var ctorByTag = {};
|
||||||
ctorByTag[float32Tag] = context.Float32Array;
|
ctorByTag[float32Tag] = context.Float32Array;
|
||||||
@@ -1046,7 +1046,7 @@
|
|||||||
* @memberOf _.support
|
* @memberOf _.support
|
||||||
* @type boolean
|
* @type boolean
|
||||||
*/
|
*/
|
||||||
support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext);
|
support.funcDecomp = /\bthis\b/.test(function() { return this; });
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detect if `Function#name` is supported (all but IE).
|
* Detect if `Function#name` is supported (all but IE).
|
||||||
@@ -1846,9 +1846,9 @@
|
|||||||
function baseCallback(func, thisArg, argCount) {
|
function baseCallback(func, thisArg, argCount) {
|
||||||
var type = typeof func;
|
var type = typeof func;
|
||||||
if (type == 'function') {
|
if (type == 'function') {
|
||||||
return (typeof thisArg != 'undefined' && isBindable(func))
|
return typeof thisArg == 'undefined'
|
||||||
? bindCallback(func, thisArg, argCount)
|
? func
|
||||||
: func;
|
: bindCallback(func, thisArg, argCount);
|
||||||
}
|
}
|
||||||
if (func == null) {
|
if (func == null) {
|
||||||
return identity;
|
return identity;
|
||||||
@@ -3379,29 +3379,37 @@
|
|||||||
if (!length) {
|
if (!length) {
|
||||||
return function() { return arguments[0]; };
|
return function() { return arguments[0]; };
|
||||||
}
|
}
|
||||||
var index = fromRight ? length : -1,
|
var wrapper,
|
||||||
|
index = fromRight ? length : -1,
|
||||||
leftIndex = 0,
|
leftIndex = 0,
|
||||||
funcs = Array(length),
|
funcs = Array(length);
|
||||||
wrapper = new LodashWrapper([]);
|
|
||||||
|
|
||||||
while ((fromRight ? index-- : ++index < length)) {
|
while ((fromRight ? index-- : ++index < length)) {
|
||||||
var func = arguments[index];
|
var func = funcs[leftIndex++] = arguments[index];
|
||||||
if (typeof func != 'function') {
|
if (typeof func != 'function') {
|
||||||
throw new TypeError(FUNC_ERROR_TEXT);
|
throw new TypeError(FUNC_ERROR_TEXT);
|
||||||
}
|
}
|
||||||
var data = func.name === 'wrapper' && getData(func);
|
var funcName = wrapper ? null : getFuncName(func);
|
||||||
if (data && data !== true && isLaziable(data[0])) {
|
if (funcName && (funcName == 'wrapper' || isLaziable(func))) {
|
||||||
wrapper = wrapper[data[0].name].apply(wrapper, data[3]);
|
wrapper = new LodashWrapper([]);
|
||||||
} else if (func.length == 1 && isLaziable(func)) {
|
}
|
||||||
wrapper = wrapper[func.name]();
|
}
|
||||||
} else {
|
index = wrapper ? -1 : length;
|
||||||
wrapper = wrapper.thru(func);
|
while (++index < length) {
|
||||||
|
func = funcs[index];
|
||||||
|
|
||||||
|
var funcName = getFuncName(func),
|
||||||
|
data = funcName == 'wrapper' ? getData(func) : null;
|
||||||
|
|
||||||
|
if (data && isLaziable(data[0])) {
|
||||||
|
wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
|
||||||
|
} else {
|
||||||
|
wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func);
|
||||||
}
|
}
|
||||||
funcs[leftIndex++] = func;
|
|
||||||
}
|
}
|
||||||
return function() {
|
return function() {
|
||||||
var args = arguments;
|
var args = arguments;
|
||||||
if (args.length == 1 && isArray(args[0])) {
|
if (wrapper && args.length == 1 && isArray(args[0])) {
|
||||||
return wrapper.plant(args[0]).value();
|
return wrapper.plant(args[0]).value();
|
||||||
}
|
}
|
||||||
var index = 0,
|
var index = 0,
|
||||||
@@ -3699,10 +3707,10 @@
|
|||||||
|
|
||||||
partials = holders = null;
|
partials = holders = null;
|
||||||
}
|
}
|
||||||
var data = !isBindKey && getData(func),
|
var data = isBindKey ? null : getData(func),
|
||||||
newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];
|
newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];
|
||||||
|
|
||||||
if (data && data !== true) {
|
if (data) {
|
||||||
mergeData(newData, data);
|
mergeData(newData, data);
|
||||||
bitmask = newData[1];
|
bitmask = newData[1];
|
||||||
arity = newData[9];
|
arity = newData[9];
|
||||||
@@ -4055,31 +4063,6 @@
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if `func` is eligible for `this` binding.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Function} func The function to check.
|
|
||||||
* @returns {boolean} Returns `true` if `func` is eligible, else `false`.
|
|
||||||
*/
|
|
||||||
function isBindable(func) {
|
|
||||||
var support = lodash.support,
|
|
||||||
result = !(support.funcNames ? func.name : support.funcDecomp);
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
var source = fnToString.call(func);
|
|
||||||
if (!support.funcNames) {
|
|
||||||
result = !reFuncName.test(source);
|
|
||||||
}
|
|
||||||
if (!result) {
|
|
||||||
// Check if `func` references the `this` keyword and store the result.
|
|
||||||
result = reThis.test(source) || isNative(func);
|
|
||||||
baseSetData(func, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if `value` is a valid array-like index.
|
* Checks if `value` is a valid array-like index.
|
||||||
*
|
*
|
||||||
@@ -4121,9 +4104,28 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var getFuncName = !support.funcNames ? constant('') : function(func) {
|
||||||
|
var result = func.name;
|
||||||
|
if (result) {
|
||||||
|
return realNames[result] || result;
|
||||||
|
}
|
||||||
|
var anons = realNames[result];
|
||||||
|
if (!anons) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
var length = anons.length;
|
||||||
|
while (length--) {
|
||||||
|
var anon = anons[length];
|
||||||
|
if (anon.func == func) {
|
||||||
|
return anon.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
function isLaziable(func) {
|
function isLaziable(func) {
|
||||||
var funcName = support.funcNames ? func.name : '';
|
var funcName = getFuncName(func);
|
||||||
return (funcName && func === lodash[funcName] && funcName in LazyWrapper.prototype) || false;
|
return funcName ? func === lodash[funcName] : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11942,6 +11944,20 @@
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (support.funcNames) {
|
||||||
|
realNames[createHybridWrapper(null, BIND_KEY_FLAG).name] = 'wrapper';
|
||||||
|
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
||||||
|
var lodashFunc = lodash[methodName],
|
||||||
|
key = lodashFunc.name;
|
||||||
|
|
||||||
|
if (key) {
|
||||||
|
realNames[key] = methodName;
|
||||||
|
} else {
|
||||||
|
var anons = realNames[key] || (realNames[key] = []);
|
||||||
|
anons.push({ 'name': methodName, 'func': lodashFunc });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
// Add functions to the lazy wrapper.
|
// Add functions to the lazy wrapper.
|
||||||
LazyWrapper.prototype.clone = lazyClone;
|
LazyWrapper.prototype.clone = lazyClone;
|
||||||
LazyWrapper.prototype.reverse = lazyReverse;
|
LazyWrapper.prototype.reverse = lazyReverse;
|
||||||
|
|||||||
49
test/test.js
49
test/test.js
@@ -2233,7 +2233,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('`_.' + methodName + '` should support shortcut fusion', 3, function() {
|
test('`_.' + methodName + '` should support shortcut fusion', 3, function() {
|
||||||
if (!isNpm) {
|
if (!isNpm && _.support.funcNames) {
|
||||||
var filterCount = 0,
|
var filterCount = 0,
|
||||||
mapCount = 0;
|
mapCount = 0;
|
||||||
|
|
||||||
@@ -2625,53 +2625,6 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return the function provided when there is no `this` reference', 2, function() {
|
|
||||||
function a() {}
|
|
||||||
function b() { return this.b; }
|
|
||||||
|
|
||||||
var object = {};
|
|
||||||
|
|
||||||
if (_.support.funcDecomp) {
|
|
||||||
strictEqual(_.callback(a, object), a);
|
|
||||||
notStrictEqual(_.callback(b, object), b);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
skipTest(2);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should work with bizarro `_.support.funcNames`', 6, function() {
|
|
||||||
function a() {}
|
|
||||||
|
|
||||||
var b = function() {};
|
|
||||||
|
|
||||||
function c() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
var object = {},
|
|
||||||
supportBizarro = lodashBizarro ? lodashBizarro.support : {},
|
|
||||||
funcDecomp = supportBizarro.funcDecomp,
|
|
||||||
funcNames = supportBizarro.funcNames;
|
|
||||||
|
|
||||||
supportBizarro.funcNames = !supportBizarro.funcNames;
|
|
||||||
supportBizarro.funcDecomp = true;
|
|
||||||
|
|
||||||
_.each([a, b, c], function(fn) {
|
|
||||||
if (lodashBizarro && _.support.funcDecomp) {
|
|
||||||
var callback = lodashBizarro.callback(fn, object);
|
|
||||||
strictEqual(callback(), fn === c ? object : undefined);
|
|
||||||
strictEqual(callback === fn, _.support.funcNames && fn === a);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
skipTest(2);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
supportBizarro.funcDecomp = funcDecomp;
|
|
||||||
supportBizarro.funcNames = funcNames;
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should work as an iteratee for methods like `_.map`', 1, function() {
|
test('should work as an iteratee for methods like `_.map`', 1, function() {
|
||||||
var fn = function() { return this instanceof Number; },
|
var fn = function() { return this instanceof Number; },
|
||||||
array = [fn, fn, fn],
|
array = [fn, fn, fn],
|
||||||
|
|||||||
Reference in New Issue
Block a user