From c1c92256ea102300db1596ddc8edbd8b1503b5d6 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 21 Jan 2014 19:59:13 -0800 Subject: [PATCH] Track arity of functions created by `_.bind`, `_.bindKey`, `_.bindAll`, `_.partial`, `_.partialRight`, `_.curry`, and `_.wrap`. --- dist/lodash.compat.js | 239 ++++++++++++++++++++++---------------- dist/lodash.compat.min.js | 123 ++++++++++---------- dist/lodash.js | 239 ++++++++++++++++++++++---------------- dist/lodash.min.js | 114 +++++++++--------- lodash.js | 239 ++++++++++++++++++++++---------------- test/test.js | 62 +++++----- 6 files changed, 577 insertions(+), 439 deletions(-) diff --git a/dist/lodash.compat.js b/dist/lodash.compat.js index c2b9446e2..9eb31c288 100644 --- a/dist/lodash.compat.js +++ b/dist/lodash.compat.js @@ -12,14 +12,7 @@ /** Used as a safe reference for `undefined` in pre ES5 environments */ var undefined; - /** Used to pool arrays and objects used internally */ - var arrayPool = [], - objectPool = []; - - /** Used to generate unique IDs */ - var idCounter = 0; - - /** Used to compose bitmasks for `__bindData__` */ + /** Used to compose bitmasks for wrapper metadata */ var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_FLAG = 4, @@ -27,23 +20,20 @@ PARTIAL_FLAG = 16, PARTIAL_RIGHT_FLAG = 32; - /** Used as the size when optimizations are enabled for large arrays */ + /** Used as the size when optimizations are enabled for arrays */ var LARGE_ARRAY_SIZE = 75; /** Used as the max size of the `arrayPool` and `objectPool` */ var MAX_POOL_SIZE = 40; - /** Used to detect and test whitespace */ - var whitespace = ( - // whitespace - ' \t\x0B\f\xA0\ufeff' + + /** Used as the semantic version number */ + var version = '2.4.1'; - // line terminators - '\n\r\u2028\u2029' + + /** Used as the property name for wrapper metadata */ + var expando = '__lodash@' + version + '__'; - // unicode category "Zs" space separators - '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' - ); + /** Used to generate unique IDs */ + var idCounter = 0; /** Used to match empty string literals in compiled template source */ var reEmptyStringLeading = /\b__p \+= '';/g, @@ -83,6 +73,22 @@ /** Used to match unescaped characters in compiled string literals */ var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; + /** Used to detect and test whitespace */ + var whitespace = ( + // whitespace + ' \t\x0B\f\xA0\ufeff' + + + // line terminators + '\n\r\u2028\u2029' + + + // unicode category "Zs" space separators + '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' + ); + + /** Used to pool arrays and objects used internally */ + var arrayPool = [], + objectPool = []; + /** Used to assign default `context` object properties */ var contextProps = [ 'Array', 'Boolean', 'Date', 'Error', 'Function', 'Math', 'Number', 'Object', @@ -126,7 +132,7 @@ 'trailing': false }; - /** Used as the property descriptor for `__bindData__` */ + /** Used as the property descriptor for wrapper metadata */ var descriptor = { 'configurable': false, 'enumerable': false, @@ -1043,13 +1049,13 @@ * sets its meta data. * * @private - * @param {Array} bindData The bind data array. + * @param {Array} data The metadata array. * @returns {Function} Returns the new bound function. */ - function baseBind(bindData) { - var func = bindData[0], - partialArgs = bindData[2], - thisArg = bindData[4]; + function baseBind(data) { + var func = data[0], + thisArg = data[3], + partialArgs = data[4]; function bound() { // `Function#bind` spec @@ -1071,7 +1077,7 @@ } return func.apply(thisArg, args || arguments); } - setBindData(bound, bindData); + setData(bound, data); return bound; } @@ -1211,26 +1217,26 @@ if (typeof thisArg == 'undefined' || !('prototype' in func)) { return func; } - var bindData = func.__bindData__; - if (typeof bindData == 'undefined') { + var data = func[expando]; + if (typeof data == 'undefined') { if (support.funcNames) { - bindData = !func.name; + data = !func.name; } - bindData = bindData || !support.funcDecomp; - if (!bindData) { + data = data || !support.funcDecomp; + if (!data) { var source = fnToString.call(func); if (!support.funcNames) { - bindData = !reFuncName.test(source); + data = !reFuncName.test(source); } - if (!bindData) { + if (!data) { // checks if `func` references the `this` keyword and stores the result - bindData = reThis.test(source); - setBindData(func, bindData); + data = reThis.test(source); + setData(func, data); } } } // exit early if there are no `this` references or `func` is bound - if (bindData === false || (bindData !== true && bindData[1] & BIND_FLAG)) { + if (data === false || (data !== true && data[1] & BIND_FLAG)) { return func; } switch (argCount) { @@ -1255,16 +1261,16 @@ * sets its meta data. * * @private - * @param {Array} bindData The bind data array. + * @param {Array} data The metadata array. * @returns {Function} Returns the new function. */ - function baseCreateWrapper(bindData) { - var func = bindData[0], - bitmask = bindData[1], - partialArgs = bindData[2], - partialRightArgs = bindData[3], - thisArg = bindData[4], - arity = bindData[5]; + function baseCreateWrapper(data) { + var func = data[0], + bitmask = data[1], + arity = data[2], + thisArg = data[3], + partialArgs = data[4], + partialRightArgs = data[5]; var isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, @@ -1283,10 +1289,15 @@ if (partialRightArgs) { push.apply(args, partialRightArgs); } - if (isCurry && args.length < arity) { + var argsLength = arguments.length; + if (isCurry && argsLength < arity) { bitmask |= PARTIAL_FLAG; - bitmask &= ~PARTIAL_RIGHT_FLAG; - return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~(BIND_FLAG | BIND_KEY_FLAG)), args, null, thisArg, arity]); + bitmask &= ~PARTIAL_RIGHT_FLAG + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newArity = nativeMax(0, arity - argsLength); + return baseCreateWrapper([func, bitmask, newArity, thisArg, args]); } } args || (args = arguments); @@ -1300,7 +1311,7 @@ } return func.apply(thisBinding, args); } - setBindData(bound, bindData); + setData(bound, data); return bound; } @@ -1779,25 +1790,23 @@ * @param {Function|string} func The function or method name to reference. * @param {number} bitmask The bitmask of flags to compose. * The bitmask may be composed of the following flags: - * 1 - `_.bind` - * 2 - `_.bindKey` - * 4 - `_.curry` - * 8 - `_.curry` (bound) + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` + * 8 - `_.curry` (bound) * 16 - `_.partial` * 32 - `_.partialRight` + * @param {number} [arity] The arity of `func`. + * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partialArgs] An array of arguments to prepend to those * provided to the new function. * @param {Array} [partialRightArgs] An array of arguments to append to those * provided to the new function. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {number} [arity] The arity of `func`. * @returns {Function} Returns the new function. */ - function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) { + function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialRightArgs) { var isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, - isCurry = bitmask & CURRY_FLAG, - isCurryBound = bitmask & CURRY_BOUND_FLAG, isPartial = bitmask & PARTIAL_FLAG, isPartialRight = bitmask & PARTIAL_RIGHT_FLAG; @@ -1805,50 +1814,69 @@ throw new TypeError; } if (isPartial && !partialArgs.length) { - bitmask &= ~16; + bitmask &= ~PARTIAL_FLAG; isPartial = partialArgs = false; } if (isPartialRight && !partialRightArgs.length) { - bitmask &= ~32; + bitmask &= ~PARTIAL_RIGHT_FLAG; isPartialRight = partialRightArgs = false; } - var bindData = func && func.__bindData__; - if (bindData && bindData !== true) { - // clone `bindData` - bindData = slice(bindData); - if (bindData[2]) { - bindData[2] = slice(bindData[2]); + var data = !isBindKey && func[expando]; + if (data && data !== true) { + // shallow clone `data` + data = slice(data); + + // clone partial left arguments + if (data[4]) { + data[4] = slice(data[4]); } - if (bindData[3]) { - bindData[3] = slice(bindData[3]); + // clone partial right arguments + if (data[5]) { + data[5] = slice(data[5]); } - // set `thisBinding` is not previously bound - if (isBind && !(bindData[1] & BIND_FLAG)) { - bindData[4] = thisArg; + // set arity if provided + if (typeof arity == 'number') { + data[2] = arity; } - // set if previously bound but not currently (subsequent curried functions) - if (!isBind && bindData[1] & BIND_FLAG) { - bitmask |= 8; + // set `thisArg` if not previously bound + var bound = data[1] & BIND_FLAG; + if (isBind && !bound) { + data[3] = thisArg; } - // set curried arity if not yet set - if (isCurry && !(bindData[1] & CURRY_FLAG)) { - bindData[5] = arity; + // set if currying a bound function + if (!isBind && bound) { + bitmask |= CURRY_BOUND_FLAG; } // append partial left arguments if (isPartial) { - push.apply(bindData[2] || (bindData[2] = []), partialArgs); + if (data[4]) { + push.apply(data[4], partialArgs); + } else { + data[4] = partialArgs; + } } - // append partial right arguments + // prepend partial right arguments if (isPartialRight) { - unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs); + if (data[5]) { + unshift.apply(data[5], partialRightArgs); + } else { + data[5] = partialRightArgs; + } } // merge flags - bindData[1] |= bitmask; - return createWrapper.apply(null, bindData); + data[1] |= bitmask; + return createWrapper.apply(null, data); + } + if (arity == null) { + arity = isBindKey ? 0 : func.length; + } else if (arity < 0) { + arity = 0; } // fast path for `_.bind` - var creater = (bitmask == BIND_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) ? baseBind : baseCreateWrapper; - return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]); + data = [func, bitmask, arity, thisArg, partialArgs, partialRightArgs]; + return (bitmask == BIND_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) + ? baseBind(data) + : baseCreateWrapper(data); } /** @@ -1904,15 +1932,15 @@ } /** - * Sets `this` binding data on a given function. + * Sets wrapper metadata on a given function. * * @private * @param {Function} func The function to set data on. * @param {Array} value The data array to set. */ - var setBindData = !defineProperty ? noop : function(func, value) { + var setData = !defineProperty ? noop : function(func, value) { descriptor.value = value; - defineProperty(func, '__bindData__', descriptor); + defineProperty(func, expando, descriptor); }; /** @@ -4500,9 +4528,14 @@ * // => 'hi fred' */ function bind(func, thisArg) { - return arguments.length > 2 - ? createWrapper(func, BIND_FLAG | PARTIAL_FLAG, slice(arguments, 2), null, thisArg) - : createWrapper(func, BIND_FLAG, null, null, thisArg); + if (arguments.length < 3) { + return createWrapper(func, BIND_FLAG, null, thisArg); + } + var arity = func && (func[expando] ? func[expando][2] : func.length), + partialArgs = slice(arguments, 2); + + arity -= partialArgs.length; + return createWrapper(func, BIND_FLAG | PARTIAL_FLAG, arity, thisArg, partialArgs); } /** @@ -4538,7 +4571,7 @@ while (++index < length) { var key = funcs[index]; - object[key] = createWrapper(object[key], BIND_FLAG, null, null, object); + object[key] = createWrapper(object[key], BIND_FLAG, null, object); } return object; } @@ -4579,9 +4612,9 @@ * // => 'hiya fred!' */ function bindKey(object, key) { - return arguments.length > 2 - ? createWrapper(key, BIND_FLAG | BIND_KEY_FLAG | PARTIAL_FLAG, slice(arguments, 2), null, object) - : createWrapper(key, BIND_FLAG | BIND_KEY_FLAG, null, null, object); + return arguments.length < 3 + ? createWrapper(key, BIND_FLAG | BIND_KEY_FLAG, null, object) + : createWrapper(key, BIND_FLAG | BIND_KEY_FLAG | PARTIAL_FLAG, null, object, slice(arguments, 2)); } /** @@ -4665,8 +4698,10 @@ * // => 6 */ function curry(func, arity) { - arity = typeof arity == 'number' ? arity : (+arity || func.length); - return createWrapper(func, CURRY_FLAG, null, null, null, arity); + if (typeof arity != 'number') { + arity = +arity || null; + } + return createWrapper(func, CURRY_FLAG, arity); } /** @@ -4968,7 +5003,11 @@ * // => 'hi fred' */ function partial(func) { - return createWrapper(func, PARTIAL_FLAG, slice(arguments, 1)); + var arity = func && (func[expando] ? func[expando][2] : func.length), + partialArgs = slice(arguments, 1); + + arity -= partialArgs.length; + return createWrapper(func, PARTIAL_FLAG, arity, null, partialArgs); } /** @@ -5002,7 +5041,11 @@ * // => { '_': _, 'jq': $ } */ function partialRight(func) { - return createWrapper(func, PARTIAL_RIGHT_FLAG, null, slice(arguments, 1)); + var arity = func && (func[expando] ? func[expando][2] : func.length), + partialRightArgs = slice(arguments, 1); + + arity -= partialRightArgs.length; + return createWrapper(func, PARTIAL_RIGHT_FLAG, arity, null, null, partialRightArgs); } /** @@ -5078,7 +5121,7 @@ * // => '

fred, barney, & pebbles

' */ function wrap(value, wrapper) { - return createWrapper(wrapper, PARTIAL_FLAG, [value]); + return createWrapper(wrapper, PARTIAL_FLAG, null, null, [value]); } /*--------------------------------------------------------------------------*/ @@ -7449,7 +7492,7 @@ * @memberOf _ * @type string */ - lodash.VERSION = '2.4.1'; + lodash.VERSION = version; // add "Chaining" functions to the wrapper lodash.prototype.chain = wrapperChain; diff --git a/dist/lodash.compat.min.js b/dist/lodash.compat.min.js index 1f835803c..b03718b84 100644 --- a/dist/lodash.compat.min.js +++ b/dist/lodash.compat.min.js @@ -1,63 +1,68 @@ /** * @license - * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE + * Lo-Dash 2.4.1 (Custom Build) * Build: `lodash -o ./dist/lodash.compat.js` + * Copyright 2012-2014 The Dojo Foundation + * Based on Underscore.js 1.5.2 + * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license */ -;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202=N&&(o=r,e=ae(e));++uo(e,l)&&i.push(l)}return i}function st(n,t){var r=-1,e=n,u=n?n.length:0; -if(typeof u=="number")for(oe.unindexedChars&&or(e)&&(e=e.split(""));++r=N,f=[];if(l)var p=ae(),a=r;else p=u?c():f;for(;++oa(p,h))&&((u||l)&&p.push(h),f.push(g))}return!l&&u&&s(p),f}function wt(n){return function(t,r,e){var o={};if(r=u.createCallback(r,e,3),he(t)){e=-1;for(var a=t.length;++eu;u++)e+="l='"+n.d[u]+"';if((!(k&&n[l])&&g.call(p,l))",n.e||(e+="||(!n[l]&&p[l]!==q[l])"),e+="){"+n.c+"}";e+="}"}return t("e,f,g,i,j,q,o,u,v,w",r+(e+"return r;")+"}")(tt,xr,Dr,Et,er,Cr,ue,at,kr,Sr) -}function Ct(){var n=(n=u.indexOf)===At?t:n;return n}function kt(n){return typeof n=="function"&&Ar.test(Tr.call(n))}function Ot(n){var t,r;return!n||Sr.call(n)!=ut||!Dr.call(n,"constructor")&&(t=n.constructor,rr(t)&&!(t instanceof t))||!oe.argsClass&&Et(n)||!oe.nodeClass&&p(n)?false:oe.ownLast?(le(n,function(n,t,e){return r=Dr.call(e,t),false}),false!==r):(le(n,function(n,t){r=t}),typeof r=="undefined"||Dr.call(n,r))}function Et(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Sr.call(n)==Q||false -}function St(n,t,r){var e=0,o=n?n.length:0;if(typeof t!="number"&&null!=t){var a=-1;for(t=u.createCallback(t,r,3);++ae?Hr(0,u+e):e||0;else if(e)return e=Rt(n,r),u&&n[e]===r?e:-1;return t(n,r,e)}function It(n,t,r){if(typeof t!="number"&&null!=t){var e=0,o=-1,a=n?n.length:0;for(t=u.createCallback(t,r,3);++ot?t=Hr(u+t,0):t>u&&(t=u),typeof r=="undefined"?r=u:0>r?r=Hr(u+r,0):r>u&&(r=u),u=r-t||0,r=sr(u);++e>>1,r(n[e])r?0:r);++t=e)return false;if(typeof n=="string"||!he(n)&&or(n))return Kr?Kr.call(n,t,r):-1r?Hr(0,e+r):r)||0,-1a&&(a=l)}else t=null==t&&or(n)?e:u.createCallback(t,r,3),st(n,function(n,r,e){r=t(n,r,e),r>o&&(o=r,a=n)});return a}function Ut(n,t,r,e){var o=3>arguments.length; -if(t=u.createCallback(t,e,4),he(n)){var a=-1,i=n.length;for(o&&i&&(r=n[++a]);++aarguments.length;return t=u.createCallback(t,e,4),zt(n,function(n,e,u){r=o?(o=false,n):t(r,n,e,u)}),r}function Xt(n){var t=-1,r=n?n.length:0,e=sr(typeof r=="number"?r:0);return st(n,function(n){var r=bt(0,++t);e[t]=e[r],e[r]=n}),e}function Gt(n,t,r){var e;if(t=u.createCallback(t,r,3),he(n)){r=-1;for(var o=n.length;++r=y;m?(u&&(u=Nr(u)),c=a,o=n.apply(i,e)):u||(u=Lr(v,y))}return m&&l?l=Nr(l):l||t===p||(l=Lr(h,t)),r&&(m=true,o=n.apply(i,e)),!m||l||u||(e=i=null),o}}function Qt(n,t,r){var e=arguments,u=0,o=e.length,a=typeof r;if("number"!=a&&"string"!=a||!e[3]||e[3][r]!==t||(o=2),3--n?t.apply(this,arguments):void 0}},u.assign=Qt,u.at=function(n,t){var r=arguments,e=-1,u=gt(r,true,false,1),o=u.length,a=typeof t;for("number"!=a&&"string"!=a||!r[2]||r[2][t]!==n||(o=1),oe.unindexedChars&&or(n)&&(n=n.split("")),r=sr(o);++e=N&&ae(e?n[e]:l)))}var i=n[0],p=-1,g=i?i.length:0,h=[];n:for(;++p(v?r(v,f):a(l,f))){for(e=u,(v||l).push(f);--e;)if(v=o[e],0>(v?r(v,f):a(n[e],f)))continue n;h.push(f)}}return s(o),s(l),h},u.invert=function(n,t){for(var r=-1,e=ye(n),u=e.length,o={};++rr?Hr(0,e+r):Jr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},u.mixin=fr,u.noConflict=function(){return n._=Er,this},u.noop=cr,u.now=_e,u.parseInt=we,u.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Zr(),Jr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):bt(n,t) -},u.reduce=Ut,u.reduceRight=Vt,u.result=function(n,t,r){return null==n?r:(r="undefined"!=typeof n[t]?n[t]:r,rr(r)?n[t]():r)},u.runInContext=_,u.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:ye(n).length},u.some=Gt,u.sortedIndex=Rt,u.template=function(n,t,r){var e=u.templateSettings;n=_r(n||""),r=Yt({},r,e);var o,a=Yt({},r.imports,e.imports),e=ye(a),a=ar(a),i=0,l=r.interpolate||V,c="__p+='",l=br((r.escape||V).source+"|"+l.source+"|"+(l===W?z:V).source+"|"+(r.evaluate||V).source+"|$","g"); -n.replace(l,function(t,r,e,u,a,l){return e||(e=u),c+=n.slice(i,l).replace(G,f),r&&(c+="'+__e("+r+")+'"),a&&(o=true,c+="';"+a+";\n__p+='"),e&&(c+="'+((__t=("+e+"))==null?'':__t)+'"),i=l+t.length,t}),c+="';",l=r=r.variable,l||(r="obj",c="with("+r+"){"+c+"}"),c=(o?c.replace(P,""):c).replace(D,"$1").replace(q,"$1;"),c="function("+r+"){"+(l?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+c+"return __p}";try{var p=vr(e,"return "+c).apply(w,a) -}catch(s){throw s.source=c,s}return t?p(t):(p.source=c,p)},u.trim=me,u.trimLeft=de,u.trimRight=be,u.unescape=function(n){return null==n?"":(n=_r(n),0>n.indexOf(";")?n:n.replace(F,b))},u.uniqueId=function(n){var t=++C;return _r(null==n?"":n)+t},u.all=$t,u.any=Gt,u.detect=Bt,u.findWhere=Bt,u.foldl=Ut,u.foldr=Vt,u.include=Ft,u.inject=Ut,fr(function(){var n={};return vt(u,function(t,r){u.prototype[r]||(n[r]=t)}),n}(),false),u.first=St,u.last=function(n,t,r){var e=0,o=n?n.length:0;if(typeof t!="number"&&null!=t){var a=o; -for(t=u.createCallback(t,r,3);a--&&t(n[a],a,n);)e++}else if(e=t,null==e||r)return n?n[o-1]:w;return e=o-e,Nt(n,0"']/g,L=/<%-([\s\S]+?)%>/g,B=/<%([\s\S]+?)%>/g,W=/<%=([\s\S]+?)%>/g,z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,K=/\w*$/,M=/^\s*function[ \n\r\t]+\w/,U=/^0[xX]/,V=/($^)/,X=/\bthis\b/,G=/['\n\r\t\u2028\u2029\\]/g,H="Array Boolean Date Error Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),J="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),Q="[object Arguments]",Y="[object Array]",Z="[object Boolean]",nt="[object Date]",tt="[object Error]",rt="[object Function]",et="[object Number]",ut="[object Object]",ot="[object RegExp]",at="[object String]",it={}; -it[rt]=false,it[Q]=it[Y]=it[Z]=it[nt]=it[et]=it[ut]=it[ot]=it[at]=true;var lt={leading:false,maxWait:0,trailing:false},ft={configurable:false,enumerable:false,value:null,writable:false},ct={"&":"&","<":"<",">":">",'"':""","'":"'"},pt={"&":"&","<":"<",">":">",""":'"',"'":"'"},st={"function":true,object:true},gt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},ht=st[typeof window]&&window||this,vt=st[typeof exports]&&exports&&!exports.nodeType&&exports,yt=st[typeof global]&&global; -!yt||yt.global!==yt&&yt.window!==yt||(ht=yt);var yt=(st=st[typeof module]&&module&&!module.nodeType&&module)&&st.exports===vt&&vt,mt=_();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(ht._=mt, define(function(){return mt})):vt&&st?yt?(st.exports=mt)._=mt:vt._=mt:ht._=mt}).call(this); \ No newline at end of file +(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202=S&&(o=r,e=le(e));++uo(e,l)&&i.push(l)}return i}function ht(n,t){var r=-1,e=n,u=n?n.length:0; +if(typeof u=="number")for(ie.unindexedChars&&ir(e)&&(e=e.split(""));++r=S,f=[];if(l)var p=le(),a=r;else p=u?c():f;for(;++oa(p,h))&&((u||l)&&p.push(h),f.push(g))}return!l&&u&&s(p),f}function xt(n){return function(t,r,e){var o={};if(r=u.createCallback(r,e,3),ye(t)){e=-1;for(var a=t.length;++er&&(r=0),c=[n,t,r,e,u,o],t==j||t==(j|O)?m(c):st(c))}function kt(n){n.d=Y;var t=mr,r="return function("+n.a+"){",e="var r="+n.b+";if(!j(p)){return r}"; +ie.nonEnumArgs&&(e+="var m=p.length;if(m&&i(p)){l=-1;while(++lu;u++)e+="l='"+n.d[u]+"';if((!(k&&n[l])&&g.call(p,l))",n.e||(e+="||(!n[l]&&p[l]!==q[l])"),e+="){"+n.c+"}"; +e+="}"}return t("e,f,g,i,j,q,o,u,v,w",r+(e+"return r;")+"}")(et,kr,$r,At,or,Or,ae,lt,Er,Ir)}function Ot(){var n=(n=u.indexOf)===Nt?t:n;return n}function Et(n){return typeof n=="function"&&Nr.test(qr.call(n))}function St(n){var t,r;return!n||Ir.call(n)!=at||!$r.call(n,"constructor")&&(t=n.constructor,ur(t)&&!(t instanceof t))||!ie.argsClass&&At(n)||!ie.nodeClass&&p(n)?false:ie.ownLast?(ce(n,function(n,t,e){return r=$r.call(e,t),false}),false!==r):(ce(n,function(n,t){r=t}),typeof r=="undefined"||$r.call(n,r)) +}function At(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Ir.call(n)==Z||false}function It(n,t,r){var e=0,o=n?n.length:0;if(typeof t!="number"&&null!=t){var a=-1;for(t=u.createCallback(t,r,3);++ae?Qr(0,u+e):e||0;else if(e)return e=Pt(n,r),u&&n[e]===r?e:-1;return t(n,r,e)}function Rt(n,t,r){if(typeof t!="number"&&null!=t){var e=0,o=-1,a=n?n.length:0; +for(t=u.createCallback(t,r,3);++ot?t=Qr(u+t,0):t>u&&(t=u),typeof r=="undefined"?r=u:0>r?r=Qr(u+r,0):r>u&&(r=u),u=r-t||0,r=hr(u);++e>>1,r(n[e])r?0:r);++t=e)return false;if(typeof n=="string"||!ye(n)&&ir(n))return Ur?Ur.call(n,t,r):-1r?Qr(0,e+r):r)||0,-1a&&(a=l)}else t=null==t&&ir(n)?e:u.createCallback(t,r,3),ht(n,function(n,r,e){r=t(n,r,e),r>o&&(o=r,a=n)});return a}function Xt(n,t,r,e){var o=3>arguments.length; +if(t=u.createCallback(t,e,4),ye(n)){var a=-1,i=n.length;for(o&&i&&(r=n[++a]);++aarguments.length;return t=u.createCallback(t,e,4),Mt(n,function(n,e,u){r=o?(o=false,n):t(r,n,e,u)}),r}function Ht(n){var t=-1,r=n?n.length:0,e=hr(typeof r=="number"?r:0);return ht(n,function(n){var r=wt(0,++t);e[t]=e[r],e[r]=n}),e}function Jt(n,t,r){var e;if(t=u.createCallback(t,r,3),ye(n)){r=-1;for(var o=n.length;++rarguments.length)return Ct(n,j,null,t);var r=n&&(n[N]?n[N][2]:n.length),e=Tt(arguments,2),r=r-e.length;return Ct(n,j|O,r,t,e)}function Yt(n,t,r){var e,u,o,a,i,l,f,c=0,p=false,s=true;if(!ur(n))throw new xr;if(t=Qr(0,t)||0,true===r)var g=true,s=false;else or(r)&&(g=r.leading,p="maxWait"in r&&(Qr(t,r.maxWait)||0),s="trailing"in r?r.trailing:s);var h=function(){var r=t-(je()-a);0=y;m?(u&&(u=Tr(u)),c=a,o=n.apply(i,e)):u||(u=Wr(v,y))}return m&&l?l=Tr(l):l||t===p||(l=Wr(h,t)),r&&(m=true,o=n.apply(i,e)),!m||l||u||(e=i=null),o}}function Zt(n,t,r){var e=arguments,u=0,o=e.length,a=typeof r;if("number"!=a&&"string"!=a||!e[3]||e[3][r]!==t||(o=2),3--n?t.apply(this,arguments):void 0}},u.assign=Zt,u.at=function(n,t){var r=arguments,e=-1,u=vt(r,true,false,1),o=u.length,a=typeof t;for("number"!=a&&"string"!=a||!r[2]||r[2][t]!==n||(o=1),ie.unindexedChars&&ir(n)&&(n=n.split("")),r=hr(o);++earguments.length?Ct(t,j|x,null,n):Ct(t,j|x|O,null,n,Tt(arguments,2))},u.chain=function(n){return n=new o(n),n.__chain__=true,n},u.compact=function(n){for(var t=-1,r=n?n.length:0,e=0,u=[];++t=S&&le(e?n[e]:l)))}var i=n[0],p=-1,g=i?i.length:0,h=[];n:for(;++p(v?r(v,f):a(l,f))){for(e=u,(v||l).push(f);--e;)if(v=o[e],0>(v?r(v,f):a(n[e],f)))continue n;h.push(f)}}return s(o),s(l),h},u.invert=function(n,t){for(var r=-1,e=de(n),u=e.length,o={};++rr?Qr(0,e+r):Yr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},u.mixin=pr,u.noConflict=function(){return n._=Ar,this},u.noop=sr,u.now=je,u.parseInt=xe,u.random=function(n,t,r){var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=te(),Yr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):wt(n,t) +},u.reduce=Xt,u.reduceRight=Gt,u.result=function(n,t,r){return null==n?r:(r="undefined"!=typeof n[t]?n[t]:r,ur(r)?n[t]():r)},u.runInContext=_,u.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:de(n).length},u.some=Jt,u.sortedIndex=Pt,u.template=function(n,t,r){var e=u.templateSettings;n=jr(n||""),r=nr({},r,e);var o,a=nr({},r.imports,e.imports),e=de(a),a=lr(a),i=0,l=r.interpolate||U,c="__p+='",l=wr((r.escape||U).source+"|"+l.source+"|"+(l===D?W:U).source+"|"+(r.evaluate||U).source+"|$","g"); +n.replace(l,function(t,r,e,u,a,l){return e||(e=u),c+=n.slice(i,l).replace(X,f),r&&(c+="'+__e("+r+")+'"),a&&(o=true,c+="';"+a+";\n__p+='"),e&&(c+="'+((__t=("+e+"))==null?'':__t)+'"),i=l+t.length,t}),c+="';",l=r=r.variable,l||(r="obj",c="with("+r+"){"+c+"}"),c=(o?c.replace(T,""):c).replace(P,"$1").replace(q,"$1;"),c="function("+r+"){"+(l?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+c+"return __p}";try{var p=mr(e,"return "+c).apply(w,a) +}catch(s){throw s.source=c,s}return t?p(t):(p.source=c,p)},u.trim=be,u.trimLeft=_e,u.trimRight=we,u.unescape=function(n){return null==n?"":(n=jr(n),0>n.indexOf(";")?n:n.replace(F,b))},u.uniqueId=function(n){var t=++R;return jr(null==n?"":n)+t},u.all=Dt,u.any=Jt,u.detect=zt,u.findWhere=zt,u.foldl=Xt,u.foldr=Gt,u.include=Bt,u.inject=Xt,pr(function(){var n={};return mt(u,function(t,r){u.prototype[r]||(n[r]=t)}),n}(),false),u.first=It,u.last=function(n,t,r){var e=0,o=n?n.length:0;if(typeof t!="number"&&null!=t){var a=o; +for(t=u.createCallback(t,r,3);a--&&t(n[a],a,n);)e++}else if(e=t,null==e||r)return n?n[o-1]:w;return e=o-e,Tt(n,0"']/g,L=/<%-([\s\S]+?)%>/g,B=/<%([\s\S]+?)%>/g,D=/<%=([\s\S]+?)%>/g,W=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,z=/\w*$/,K=/^\s*function[ \n\r\t]+\w/,M=/^0[xX]/,U=/($^)/,V=/\bthis\b/,X=/['\n\r\t\u2028\u2029\\]/g,G=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",H=[],J=[],Q="Array Boolean Date Error Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),Y="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),Z="[object Arguments]",nt="[object Array]",tt="[object Boolean]",rt="[object Date]",et="[object Error]",ut="[object Function]",ot="[object Number]",at="[object Object]",it="[object RegExp]",lt="[object String]",ft={}; +ft[ut]=false,ft[Z]=ft[nt]=ft[tt]=ft[rt]=ft[ot]=ft[at]=ft[it]=ft[lt]=true;var ct={leading:false,maxWait:0,trailing:false},pt={configurable:false,enumerable:false,value:null,writable:false},st={"&":"&","<":"<",">":">",'"':""","'":"'"},gt={"&":"&","<":"<",">":">",""":'"',"'":"'"},ht={"function":true,object:true},vt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},yt=ht[typeof window]&&window||this,mt=ht[typeof exports]&&exports&&!exports.nodeType&&exports,dt=ht[typeof global]&&global; +!dt||dt.global!==dt&&dt.window!==dt||(yt=dt);var dt=(ht=ht[typeof module]&&module&&!module.nodeType&&module)&&ht.exports===mt&&mt,bt=_();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(yt._=bt, define(function(){return bt})):mt&&ht?dt?(ht.exports=bt)._=bt:mt._=bt:yt._=bt}).call(this); \ No newline at end of file diff --git a/dist/lodash.js b/dist/lodash.js index bacbfa724..af4840e3b 100644 --- a/dist/lodash.js +++ b/dist/lodash.js @@ -12,14 +12,7 @@ /** Used as a safe reference for `undefined` in pre ES5 environments */ var undefined; - /** Used to pool arrays and objects used internally */ - var arrayPool = [], - objectPool = []; - - /** Used to generate unique IDs */ - var idCounter = 0; - - /** Used to compose bitmasks for `__bindData__` */ + /** Used to compose bitmasks for wrapper metadata */ var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_FLAG = 4, @@ -27,23 +20,20 @@ PARTIAL_FLAG = 16, PARTIAL_RIGHT_FLAG = 32; - /** Used as the size when optimizations are enabled for large arrays */ + /** Used as the size when optimizations are enabled for arrays */ var LARGE_ARRAY_SIZE = 75; /** Used as the max size of the `arrayPool` and `objectPool` */ var MAX_POOL_SIZE = 40; - /** Used to detect and test whitespace */ - var whitespace = ( - // whitespace - ' \t\x0B\f\xA0\ufeff' + + /** Used as the semantic version number */ + var version = '2.4.1'; - // line terminators - '\n\r\u2028\u2029' + + /** Used as the property name for wrapper metadata */ + var expando = '__lodash@' + version + '__'; - // unicode category "Zs" space separators - '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' - ); + /** Used to generate unique IDs */ + var idCounter = 0; /** Used to match empty string literals in compiled template source */ var reEmptyStringLeading = /\b__p \+= '';/g, @@ -83,6 +73,22 @@ /** Used to match unescaped characters in compiled string literals */ var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; + /** Used to detect and test whitespace */ + var whitespace = ( + // whitespace + ' \t\x0B\f\xA0\ufeff' + + + // line terminators + '\n\r\u2028\u2029' + + + // unicode category "Zs" space separators + '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' + ); + + /** Used to pool arrays and objects used internally */ + var arrayPool = [], + objectPool = []; + /** Used to assign default `context` object properties */ var contextProps = [ 'Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object', @@ -119,7 +125,7 @@ 'trailing': false }; - /** Used as the property descriptor for `__bindData__` */ + /** Used as the property descriptor for wrapper metadata */ var descriptor = { 'configurable': false, 'enumerable': false, @@ -821,13 +827,13 @@ * sets its meta data. * * @private - * @param {Array} bindData The bind data array. + * @param {Array} data The metadata array. * @returns {Function} Returns the new bound function. */ - function baseBind(bindData) { - var func = bindData[0], - partialArgs = bindData[2], - thisArg = bindData[4]; + function baseBind(data) { + var func = data[0], + thisArg = data[3], + partialArgs = data[4]; function bound() { // `Function#bind` spec @@ -849,7 +855,7 @@ } return func.apply(thisArg, args || arguments); } - setBindData(bound, bindData); + setData(bound, data); return bound; } @@ -989,26 +995,26 @@ if (typeof thisArg == 'undefined' || !('prototype' in func)) { return func; } - var bindData = func.__bindData__; - if (typeof bindData == 'undefined') { + var data = func[expando]; + if (typeof data == 'undefined') { if (support.funcNames) { - bindData = !func.name; + data = !func.name; } - bindData = bindData || !support.funcDecomp; - if (!bindData) { + data = data || !support.funcDecomp; + if (!data) { var source = fnToString.call(func); if (!support.funcNames) { - bindData = !reFuncName.test(source); + data = !reFuncName.test(source); } - if (!bindData) { + if (!data) { // checks if `func` references the `this` keyword and stores the result - bindData = reThis.test(source); - setBindData(func, bindData); + data = reThis.test(source); + setData(func, data); } } } // exit early if there are no `this` references or `func` is bound - if (bindData === false || (bindData !== true && bindData[1] & BIND_FLAG)) { + if (data === false || (data !== true && data[1] & BIND_FLAG)) { return func; } switch (argCount) { @@ -1033,16 +1039,16 @@ * sets its meta data. * * @private - * @param {Array} bindData The bind data array. + * @param {Array} data The metadata array. * @returns {Function} Returns the new function. */ - function baseCreateWrapper(bindData) { - var func = bindData[0], - bitmask = bindData[1], - partialArgs = bindData[2], - partialRightArgs = bindData[3], - thisArg = bindData[4], - arity = bindData[5]; + function baseCreateWrapper(data) { + var func = data[0], + bitmask = data[1], + arity = data[2], + thisArg = data[3], + partialArgs = data[4], + partialRightArgs = data[5]; var isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, @@ -1061,10 +1067,15 @@ if (partialRightArgs) { push.apply(args, partialRightArgs); } - if (isCurry && args.length < arity) { + var argsLength = arguments.length; + if (isCurry && argsLength < arity) { bitmask |= PARTIAL_FLAG; - bitmask &= ~PARTIAL_RIGHT_FLAG; - return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~(BIND_FLAG | BIND_KEY_FLAG)), args, null, thisArg, arity]); + bitmask &= ~PARTIAL_RIGHT_FLAG + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newArity = nativeMax(0, arity - argsLength); + return baseCreateWrapper([func, bitmask, newArity, thisArg, args]); } } args || (args = arguments); @@ -1078,7 +1089,7 @@ } return func.apply(thisBinding, args); } - setBindData(bound, bindData); + setData(bound, data); return bound; } @@ -1554,25 +1565,23 @@ * @param {Function|string} func The function or method name to reference. * @param {number} bitmask The bitmask of flags to compose. * The bitmask may be composed of the following flags: - * 1 - `_.bind` - * 2 - `_.bindKey` - * 4 - `_.curry` - * 8 - `_.curry` (bound) + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` + * 8 - `_.curry` (bound) * 16 - `_.partial` * 32 - `_.partialRight` + * @param {number} [arity] The arity of `func`. + * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partialArgs] An array of arguments to prepend to those * provided to the new function. * @param {Array} [partialRightArgs] An array of arguments to append to those * provided to the new function. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {number} [arity] The arity of `func`. * @returns {Function} Returns the new function. */ - function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) { + function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialRightArgs) { var isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, - isCurry = bitmask & CURRY_FLAG, - isCurryBound = bitmask & CURRY_BOUND_FLAG, isPartial = bitmask & PARTIAL_FLAG, isPartialRight = bitmask & PARTIAL_RIGHT_FLAG; @@ -1580,50 +1589,69 @@ throw new TypeError; } if (isPartial && !partialArgs.length) { - bitmask &= ~16; + bitmask &= ~PARTIAL_FLAG; isPartial = partialArgs = false; } if (isPartialRight && !partialRightArgs.length) { - bitmask &= ~32; + bitmask &= ~PARTIAL_RIGHT_FLAG; isPartialRight = partialRightArgs = false; } - var bindData = func && func.__bindData__; - if (bindData && bindData !== true) { - // clone `bindData` - bindData = slice(bindData); - if (bindData[2]) { - bindData[2] = slice(bindData[2]); + var data = !isBindKey && func[expando]; + if (data && data !== true) { + // shallow clone `data` + data = slice(data); + + // clone partial left arguments + if (data[4]) { + data[4] = slice(data[4]); } - if (bindData[3]) { - bindData[3] = slice(bindData[3]); + // clone partial right arguments + if (data[5]) { + data[5] = slice(data[5]); } - // set `thisBinding` is not previously bound - if (isBind && !(bindData[1] & BIND_FLAG)) { - bindData[4] = thisArg; + // set arity if provided + if (typeof arity == 'number') { + data[2] = arity; } - // set if previously bound but not currently (subsequent curried functions) - if (!isBind && bindData[1] & BIND_FLAG) { - bitmask |= 8; + // set `thisArg` if not previously bound + var bound = data[1] & BIND_FLAG; + if (isBind && !bound) { + data[3] = thisArg; } - // set curried arity if not yet set - if (isCurry && !(bindData[1] & CURRY_FLAG)) { - bindData[5] = arity; + // set if currying a bound function + if (!isBind && bound) { + bitmask |= CURRY_BOUND_FLAG; } // append partial left arguments if (isPartial) { - push.apply(bindData[2] || (bindData[2] = []), partialArgs); + if (data[4]) { + push.apply(data[4], partialArgs); + } else { + data[4] = partialArgs; + } } - // append partial right arguments + // prepend partial right arguments if (isPartialRight) { - unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs); + if (data[5]) { + unshift.apply(data[5], partialRightArgs); + } else { + data[5] = partialRightArgs; + } } // merge flags - bindData[1] |= bitmask; - return createWrapper.apply(null, bindData); + data[1] |= bitmask; + return createWrapper.apply(null, data); + } + if (arity == null) { + arity = isBindKey ? 0 : func.length; + } else if (arity < 0) { + arity = 0; } // fast path for `_.bind` - var creater = (bitmask == BIND_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) ? baseBind : baseCreateWrapper; - return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]); + data = [func, bitmask, arity, thisArg, partialArgs, partialRightArgs]; + return (bitmask == BIND_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) + ? baseBind(data) + : baseCreateWrapper(data); } /** @@ -1651,15 +1679,15 @@ } /** - * Sets `this` binding data on a given function. + * Sets wrapper metadata on a given function. * * @private * @param {Function} func The function to set data on. * @param {Array} value The data array to set. */ - var setBindData = !defineProperty ? noop : function(func, value) { + var setData = !defineProperty ? noop : function(func, value) { descriptor.value = value; - defineProperty(func, '__bindData__', descriptor); + defineProperty(func, expando, descriptor); }; /** @@ -4229,9 +4257,14 @@ * // => 'hi fred' */ function bind(func, thisArg) { - return arguments.length > 2 - ? createWrapper(func, BIND_FLAG | PARTIAL_FLAG, slice(arguments, 2), null, thisArg) - : createWrapper(func, BIND_FLAG, null, null, thisArg); + if (arguments.length < 3) { + return createWrapper(func, BIND_FLAG, null, thisArg); + } + var arity = func && (func[expando] ? func[expando][2] : func.length), + partialArgs = slice(arguments, 2); + + arity -= partialArgs.length; + return createWrapper(func, BIND_FLAG | PARTIAL_FLAG, arity, thisArg, partialArgs); } /** @@ -4267,7 +4300,7 @@ while (++index < length) { var key = funcs[index]; - object[key] = createWrapper(object[key], BIND_FLAG, null, null, object); + object[key] = createWrapper(object[key], BIND_FLAG, null, object); } return object; } @@ -4308,9 +4341,9 @@ * // => 'hiya fred!' */ function bindKey(object, key) { - return arguments.length > 2 - ? createWrapper(key, BIND_FLAG | BIND_KEY_FLAG | PARTIAL_FLAG, slice(arguments, 2), null, object) - : createWrapper(key, BIND_FLAG | BIND_KEY_FLAG, null, null, object); + return arguments.length < 3 + ? createWrapper(key, BIND_FLAG | BIND_KEY_FLAG, null, object) + : createWrapper(key, BIND_FLAG | BIND_KEY_FLAG | PARTIAL_FLAG, null, object, slice(arguments, 2)); } /** @@ -4394,8 +4427,10 @@ * // => 6 */ function curry(func, arity) { - arity = typeof arity == 'number' ? arity : (+arity || func.length); - return createWrapper(func, CURRY_FLAG, null, null, null, arity); + if (typeof arity != 'number') { + arity = +arity || null; + } + return createWrapper(func, CURRY_FLAG, arity); } /** @@ -4697,7 +4732,11 @@ * // => 'hi fred' */ function partial(func) { - return createWrapper(func, PARTIAL_FLAG, slice(arguments, 1)); + var arity = func && (func[expando] ? func[expando][2] : func.length), + partialArgs = slice(arguments, 1); + + arity -= partialArgs.length; + return createWrapper(func, PARTIAL_FLAG, arity, null, partialArgs); } /** @@ -4731,7 +4770,11 @@ * // => { '_': _, 'jq': $ } */ function partialRight(func) { - return createWrapper(func, PARTIAL_RIGHT_FLAG, null, slice(arguments, 1)); + var arity = func && (func[expando] ? func[expando][2] : func.length), + partialRightArgs = slice(arguments, 1); + + arity -= partialRightArgs.length; + return createWrapper(func, PARTIAL_RIGHT_FLAG, arity, null, null, partialRightArgs); } /** @@ -4807,7 +4850,7 @@ * // => '

fred, barney, & pebbles

' */ function wrap(value, wrapper) { - return createWrapper(wrapper, PARTIAL_FLAG, [value]); + return createWrapper(wrapper, PARTIAL_FLAG, null, null, [value]); } /*--------------------------------------------------------------------------*/ @@ -7165,7 +7208,7 @@ * @memberOf _ * @type string */ - lodash.VERSION = '2.4.1'; + lodash.VERSION = version; // add "Chaining" functions to the wrapper lodash.prototype.chain = wrapperChain; diff --git a/dist/lodash.min.js b/dist/lodash.min.js index 857960e65..972e59f21 100644 --- a/dist/lodash.min.js +++ b/dist/lodash.min.js @@ -1,59 +1,63 @@ /** * @license - * Lo-Dash 2.4.1 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE + * Lo-Dash 2.4.1 (Custom Build) * Build: `lodash modern -o ./dist/lodash.js` + * Copyright 2012-2014 The Dojo Foundation + * Based on Underscore.js 1.5.2 + * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license */ -;(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202=N&&(o=r,e=re(e));++uo(e,f)&&a.push(f)}return a}function st(n,t){var r=-1,e=n?n.length:0;if(typeof e=="number")for(;++r=N,l=[];if(f)var s=re(),i=r;else s=u?c():l;for(;++oi(s,h))&&((u||f)&&s.push(h),l.push(g))}return!f&&u&&p(s),l}function _t(n){return function(t,r,e){var u={};r=y.createCallback(r,e,3),e=-1;var o=t?t.length:0;if(typeof o=="number")for(;++ee?Ur(0,u+e):e||0;else if(e)return e=Nt(n,r),u&&n[e]===r?e:-1;return t(n,r,e)}function St(n,t,r){if(typeof t!="number"&&null!=t){var e=0,u=-1,o=n?n.length:0;for(t=y.createCallback(t,r,3);++ut?t=Ur(u+t,0):t>u&&(t=u),typeof r=="undefined"?r=u:0>r?r=Ur(u+r,0):r>u&&(r=u),u=r-t||0,r=cr(u);++e>>1,r(n[e])r?0:r);++t=e)return false;if(typeof n=="string"||!fe(n)&&er(n))return Wr?Wr.call(n,t,r):-1r?Ur(0,e+r):r)||0,-1o&&(o=a)}else t=null==t&&er(n)?e:y.createCallback(t,r,3),st(n,function(n,r,e){r=t(n,r,e),r>u&&(u=r,o=n)});return o}function Kt(n,t,r,e){var u=3>arguments.length;t=y.createCallback(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(r=n[++o]);++oarguments.length;return t=y.createCallback(t,e,4),zt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function Ut(n){var t=-1,r=n?n.length:0,e=cr(typeof r=="number"?r:0); -return st(n,function(n){var r=dt(0,++t);e[t]=e[r],e[r]=n}),e}function Vt(n,t,r){var e;t=y.createCallback(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number")for(;++r=y;m?(i&&(i=Sr(i)),s=f,a=n.apply(l,o)):i||(i=Fr(e,y))}return m&&c?c=Sr(c):c||t===g||(c=Fr(u,t)),r&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function Ht(n,t,r){var e=arguments,u=0,o=e.length,i=typeof r; -if("number"!=i&&"string"!=i||!e[3]||e[3][r]!==t||(o=2),3--n?t.apply(this,arguments):void 0}},y.assign=Ht,y.at=function(n,t){var r=arguments,e=-1,u=gt(r,true,false,1),o=u.length,i=typeof t;for("number"!=i&&"string"!=i||!r[2]||r[2][t]!==n||(o=1),r=cr(o);++e=N&&re(e?n[e]:f)))}var a=n[0],s=-1,g=a?a.length:0,h=[];n:for(;++s(v?r(v,l):i(f,l))){for(e=u,(v||f).push(l);--e;)if(v=o[e],0>(v?r(v,l):i(n[e],l)))continue n;h.push(l)}}return p(o),p(f),h},y.invert=function(n,t){for(var r=-1,e=ce(n),u=e.length,o={};++rr?Ur(0,e+r):Vr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},y.mixin=ar,y.noConflict=function(){return n._=xr,this},y.noop=fr,y.now=he,y.parseInt=ve,y.random=function(n,t,r){var e=null==n,u=null==t; -return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Hr(),Vr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):dt(n,t)},y.reduce=Kt,y.reduceRight=Mt,y.result=function(n,t,r){return null==n?r:(r="undefined"!=typeof n[t]?n[t]:r,nr(r)?n[t]():r)},y.runInContext=b,y.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:ce(n).length},y.some=Vt,y.sortedIndex=Nt,y.template=function(n,t,r){var e=y.templateSettings; -n=dr(n||""),r=Jt({},r,e);var u,o=Jt({},r.imports,e.imports),e=ce(o),o=ur(o),i=0,a=r.interpolate||U,f="__p+='",a=mr((r.escape||U).source+"|"+a.source+"|"+(a===z?L:U).source+"|"+(r.evaluate||U).source+"|$","g");n.replace(a,function(t,r,e,o,a,c){return e||(e=o),f+=n.slice(i,c).replace(X,l),r&&(f+="'+__e("+r+")+'"),a&&(u=true,f+="';"+a+";\n__p+='"),e&&(f+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t}),f+="';",a=r=r.variable,a||(r="obj",f="with("+r+"){"+f+"}"),f=(u?f.replace(T,""):f).replace(D,"$1").replace(F,"$1;"),f="function("+r+"){"+(a?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+f+"return __p}"; -try{var c=gr(e,"return "+f).apply(_,o)}catch(p){throw p.source=f,p}return t?c(t):(c.source=f,c)},y.trim=pe,y.trimLeft=se,y.trimRight=ge,y.unescape=function(n){return null==n?"":(n=dr(n),0>n.indexOf(";")?n:n.replace($,d))},y.uniqueId=function(n){var t=++k;return dr(null==n?"":n)+t},y.all=$t,y.any=Vt,y.detect=qt,y.findWhere=qt,y.foldl=Kt,y.foldr=Mt,y.include=Ft,y.inject=Kt,ar(function(){var n={};return vt(y,function(t,r){y.prototype[r]||(n[r]=t)}),n}(),false),y.first=Ot,y.last=function(n,t,r){var e=0,u=n?n.length:0; -if(typeof t!="number"&&null!=t){var o=u;for(t=y.createCallback(t,r,3);o--&&t(n[o],o,n);)e++}else if(e=t,null==e||r)return n?n[u-1]:_;return e=u-e,Et(n,0"']/g,q=/<%-([\s\S]+?)%>/g,W=/<%([\s\S]+?)%>/g,z=/<%=([\s\S]+?)%>/g,L=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,P=/\w*$/,K=/^\s*function[ \n\r\t]+\w/,M=/^0[xX]/,U=/($^)/,V=/\bthis\b/,X=/['\n\r\t\u2028\u2029\\]/g,G="Array Boolean Date Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),H="[object Arguments]",J="[object Array]",Q="[object Boolean]",Y="[object Date]",Z="[object Function]",nt="[object Number]",tt="[object Object]",rt="[object RegExp]",et="[object String]",ut={}; -ut[Z]=false,ut[H]=ut[J]=ut[Q]=ut[Y]=ut[nt]=ut[tt]=ut[rt]=ut[et]=true;var ot={leading:false,maxWait:0,trailing:false},it={configurable:false,enumerable:false,value:null,writable:false},at={"&":"&","<":"<",">":">",'"':""","'":"'"},ft={"&":"&","<":"<",">":">",""":'"',"'":"'"},lt={"function":true,object:true},ct={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},pt=lt[typeof window]&&window||this,st=lt[typeof exports]&&exports&&!exports.nodeType&&exports,gt=lt[typeof global]&&global; -!gt||gt.global!==gt&>.window!==gt||(pt=gt);var gt=(lt=lt[typeof module]&&module&&!module.nodeType&&module)&<.exports===st&&st,ht=b();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(pt._=ht, define(function(){return ht})):st&<?gt?(lt.exports=ht)._=ht:st._=ht:pt._=ht}).call(this); \ No newline at end of file +(function(){function n(n,t){if(n!==t){if(n>t||typeof n=="undefined")return 1;if(ne||13e||8202r||13r||8202=A&&(o=r,e=ue(e));++uo(e,f)&&a.push(f)}return a}function ht(n,t){var r=-1,e=n?n.length:0;if(typeof e=="number")for(;++r=A,l=[];if(f)var s=ue(),i=r;else s=u?c():l;for(;++oi(s,h))&&((u||f)&&s.push(h),l.push(g))}return!f&&u&&p(s),l}function jt(n){return function(t,r,e){var u={};r=y.createCallback(r,e,3),e=-1;var o=t?t.length:0;if(typeof o=="number")for(;++er&&(r=0),c=[n,t,r,e,u,o],t==w||t==(w|C)?S(c):pt(c))}function xt(){var n=(n=y.indexOf)===Et?t:n; +return n}function Ct(n){return typeof n=="function"&&Sr.test(Ir.call(n))}function Ot(n){var t,r;return n&&Ar.call(n)==et&&(Fr.call(n,"constructor")||(t=n.constructor,!rr(t)||t instanceof t))?(o(n,function(n,t){r=t}),typeof r=="undefined"||Fr.call(n,r)):false}function At(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Ar.call(n)==Q||false}function St(n,t,r){var e=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=-1;for(t=y.createCallback(t,r,3);++oe?Xr(0,u+e):e||0;else if(e)return e=It(n,r),u&&n[e]===r?e:-1;return t(n,r,e)}function Nt(n,t,r){if(typeof t!="number"&&null!=t){var e=0,u=-1,o=n?n.length:0;for(t=y.createCallback(t,r,3);++ut?t=Xr(u+t,0):t>u&&(t=u),typeof r=="undefined"?r=u:0>r?r=Xr(u+r,0):r>u&&(r=u),u=r-t||0,r=sr(u);++e>>1,r(n[e])r?0:r);++t=e)return false;if(typeof n=="string"||!ce(n)&&or(n))return Lr?Lr.call(n,t,r):-1r?Xr(0,e+r):r)||0,-1o&&(o=a)}else t=null==t&&or(n)?e:y.createCallback(t,r,3),ht(n,function(n,r,e){r=t(n,r,e),r>u&&(u=r,o=n)});return o}function Ut(n,t,r,e){var u=3>arguments.length;t=y.createCallback(t,e,4);var o=-1,i=n?n.length:0;if(typeof i=="number")for(u&&i&&(r=n[++o]);++oarguments.length;return t=y.createCallback(t,e,4),Pt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function Xt(n){var t=-1,r=n?n.length:0,e=sr(typeof r=="number"?r:0); +return ht(n,function(n){var r=_t(0,++t);e[t]=e[r],e[r]=n}),e}function Gt(n,t,r){var e;t=y.createCallback(t,r,3),r=-1;var u=n?n.length:0;if(typeof u=="number")for(;++rarguments.length)return kt(n,w,null,t);var r=n&&(n[N]?n[N][2]:n.length),e=Rt(arguments,2),r=r-e.length;return kt(n,w|C,r,t,e)}function Jt(n,t,r){function e(){c&&Nr(c),i=c=p=_,(h||g!==t)&&(s=ye(),a=n.apply(l,o),c||i||(o=l=null))}function u(){var r=t-(ye()-f); +0=y;m?(i&&(i=Nr(i)),s=f,a=n.apply(l,o)):i||(i=Dr(e,y))}return m&&c?c=Nr(c):c||t===g||(c=Dr(u,t)),r&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a +}}function Qt(n,t,r){var e=arguments,u=0,o=e.length,i=typeof r;if("number"!=i&&"string"!=i||!e[3]||e[3][r]!==t||(o=2),3--n?t.apply(this,arguments):void 0}},y.assign=Qt,y.at=function(n,t){var r=arguments,e=-1,u=vt(r,true,false,1),o=u.length,i=typeof t;for("number"!=i&&"string"!=i||!r[2]||r[2][t]!==n||(o=1),r=sr(o);++earguments.length?kt(t,w|j,null,n):kt(t,w|j|C,null,n,Rt(arguments,2))},y.chain=function(n){return n=new m(n),n.__chain__=true,n},y.compact=function(n){for(var t=-1,r=n?n.length:0,e=0,u=[];++t=A&&ue(e?n[e]:f)))}var a=n[0],s=-1,g=a?a.length:0,h=[];n:for(;++s(v?r(v,l):i(f,l))){for(e=u,(v||f).push(l);--e;)if(v=o[e],0>(v?r(v,l):i(n[e],l)))continue n;h.push(l)}}return p(o),p(f),h},y.invert=function(n,t){for(var r=-1,e=se(n),u=e.length,o={};++rr?Xr(0,e+r):Gr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},y.mixin=lr,y.noConflict=function(){return n._=Or,this},y.noop=cr,y.now=ye,y.parseInt=me,y.random=function(n,t,r){var e=null==n,u=null==t; +return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=Qr(),Gr(n+r*(t-n+parseFloat("1e-"+((r+"").length-1))),t)):_t(n,t)},y.reduce=Ut,y.reduceRight=Vt,y.result=function(n,t,r){return null==n?r:(r="undefined"!=typeof n[t]?n[t]:r,rr(r)?n[t]():r)},y.runInContext=b,y.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:se(n).length},y.some=Gt,y.sortedIndex=It,y.template=function(n,t,r){var e=y.templateSettings; +n=_r(n||""),r=Yt({},r,e);var u,o=Yt({},r.imports,e.imports),e=se(o),o=ir(o),i=0,a=r.interpolate||M,f="__p+='",a=br((r.escape||M).source+"|"+a.source+"|"+(a===W?z:M).source+"|"+(r.evaluate||M).source+"|$","g");n.replace(a,function(t,r,e,o,a,c){return e||(e=o),f+=n.slice(i,c).replace(V,l),r&&(f+="'+__e("+r+")+'"),a&&(u=true,f+="';"+a+";\n__p+='"),e&&(f+="'+((__t=("+e+"))==null?'':__t)+'"),i=c+t.length,t}),f+="';",a=r=r.variable,a||(r="obj",f="with("+r+"){"+f+"}"),f=(u?f.replace(I,""):f).replace(T,"$1").replace(F,"$1;"),f="function("+r+"){"+(a?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+f+"return __p}"; +try{var c=vr(e,"return "+f).apply(_,o)}catch(p){throw p.source=f,p}return t?c(t):(c.source=f,c)},y.trim=ge,y.trimLeft=he,y.trimRight=ve,y.unescape=function(n){return null==n?"":(n=_r(n),0>n.indexOf(";")?n:n.replace($,d))},y.uniqueId=function(n){var t=++R;return _r(null==n?"":n)+t},y.all=qt,y.any=Gt,y.detect=zt,y.findWhere=zt,y.foldl=Ut,y.foldr=Vt,y.include=Dt,y.inject=Ut,lr(function(){var n={};return mt(y,function(t,r){y.prototype[r]||(n[r]=t)}),n}(),false),y.first=St,y.last=function(n,t,r){var e=0,u=n?n.length:0; +if(typeof t!="number"&&null!=t){var o=u;for(t=y.createCallback(t,r,3);o--&&t(n[o],o,n);)e++}else if(e=t,null==e||r)return n?n[u-1]:_;return e=u-e,Rt(n,0"']/g,D=/<%-([\s\S]+?)%>/g,q=/<%([\s\S]+?)%>/g,W=/<%=([\s\S]+?)%>/g,z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,L=/\w*$/,P=/^\s*function[ \n\r\t]+\w/,K=/^0[xX]/,M=/($^)/,U=/\bthis\b/,V=/['\n\r\t\u2028\u2029\\]/g,X=" \t\x0B\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",G=[],H=[],J="Array Boolean Date Function Math Number Object RegExp Set String _ clearTimeout document isFinite isNaN parseInt setTimeout TypeError window WinRTError".split(" "),Q="[object Arguments]",Y="[object Array]",Z="[object Boolean]",nt="[object Date]",tt="[object Function]",rt="[object Number]",et="[object Object]",ut="[object RegExp]",ot="[object String]",it={}; +it[tt]=false,it[Q]=it[Y]=it[Z]=it[nt]=it[rt]=it[et]=it[ut]=it[ot]=true;var at={leading:false,maxWait:0,trailing:false},ft={configurable:false,enumerable:false,value:null,writable:false},lt={"&":"&","<":"<",">":">",'"':""","'":"'"},ct={"&":"&","<":"<",">":">",""":'"',"'":"'"},pt={"function":true,object:true},st={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},gt=pt[typeof window]&&window||this,ht=pt[typeof exports]&&exports&&!exports.nodeType&&exports,vt=pt[typeof global]&&global; +!vt||vt.global!==vt&&vt.window!==vt||(gt=vt);var vt=(pt=pt[typeof module]&&module&&!module.nodeType&&module)&&pt.exports===ht&&ht,yt=b();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(gt._=yt, define(function(){return yt})):ht&&pt?vt?(pt.exports=yt)._=yt:ht._=yt:gt._=yt}).call(this); \ No newline at end of file diff --git a/lodash.js b/lodash.js index bbeeb7a34..dbc388320 100644 --- a/lodash.js +++ b/lodash.js @@ -11,14 +11,7 @@ /** Used as a safe reference for `undefined` in pre ES5 environments */ var undefined; - /** Used to pool arrays and objects used internally */ - var arrayPool = [], - objectPool = []; - - /** Used to generate unique IDs */ - var idCounter = 0; - - /** Used to compose bitmasks for `__bindData__` */ + /** Used to compose bitmasks for wrapper metadata */ var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_FLAG = 4, @@ -26,23 +19,20 @@ PARTIAL_FLAG = 16, PARTIAL_RIGHT_FLAG = 32; - /** Used as the size when optimizations are enabled for large arrays */ + /** Used as the size when optimizations are enabled for arrays */ var LARGE_ARRAY_SIZE = 75; /** Used as the max size of the `arrayPool` and `objectPool` */ var MAX_POOL_SIZE = 40; - /** Used to detect and test whitespace */ - var whitespace = ( - // whitespace - ' \t\x0B\f\xA0\ufeff' + + /** Used as the semantic version number */ + var version = '2.4.1'; - // line terminators - '\n\r\u2028\u2029' + + /** Used as the property name for wrapper metadata */ + var expando = '__lodash@' + version + '__'; - // unicode category "Zs" space separators - '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' - ); + /** Used to generate unique IDs */ + var idCounter = 0; /** Used to match empty string literals in compiled template source */ var reEmptyStringLeading = /\b__p \+= '';/g, @@ -82,6 +72,22 @@ /** Used to match unescaped characters in compiled string literals */ var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; + /** Used to detect and test whitespace */ + var whitespace = ( + // whitespace + ' \t\x0B\f\xA0\ufeff' + + + // line terminators + '\n\r\u2028\u2029' + + + // unicode category "Zs" space separators + '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' + ); + + /** Used to pool arrays and objects used internally */ + var arrayPool = [], + objectPool = []; + /** Used to assign default `context` object properties */ var contextProps = [ 'Array', 'Boolean', 'Date', 'Error', 'Function', 'Math', 'Number', 'Object', @@ -125,7 +131,7 @@ 'trailing': false }; - /** Used as the property descriptor for `__bindData__` */ + /** Used as the property descriptor for wrapper metadata */ var descriptor = { 'configurable': false, 'enumerable': false, @@ -1057,13 +1063,13 @@ * sets its meta data. * * @private - * @param {Array} bindData The bind data array. + * @param {Array} data The metadata array. * @returns {Function} Returns the new bound function. */ - function baseBind(bindData) { - var func = bindData[0], - partialArgs = bindData[2], - thisArg = bindData[4]; + function baseBind(data) { + var func = data[0], + thisArg = data[3], + partialArgs = data[4]; function bound() { // `Function#bind` spec @@ -1085,7 +1091,7 @@ } return func.apply(thisArg, args || arguments); } - setBindData(bound, bindData); + setData(bound, data); return bound; } @@ -1225,26 +1231,26 @@ if (typeof thisArg == 'undefined' || !('prototype' in func)) { return func; } - var bindData = func.__bindData__; - if (typeof bindData == 'undefined') { + var data = func[expando]; + if (typeof data == 'undefined') { if (support.funcNames) { - bindData = !func.name; + data = !func.name; } - bindData = bindData || !support.funcDecomp; - if (!bindData) { + data = data || !support.funcDecomp; + if (!data) { var source = fnToString.call(func); if (!support.funcNames) { - bindData = !reFuncName.test(source); + data = !reFuncName.test(source); } - if (!bindData) { + if (!data) { // checks if `func` references the `this` keyword and stores the result - bindData = reThis.test(source); - setBindData(func, bindData); + data = reThis.test(source); + setData(func, data); } } } // exit early if there are no `this` references or `func` is bound - if (bindData === false || (bindData !== true && bindData[1] & BIND_FLAG)) { + if (data === false || (data !== true && data[1] & BIND_FLAG)) { return func; } switch (argCount) { @@ -1269,16 +1275,16 @@ * sets its meta data. * * @private - * @param {Array} bindData The bind data array. + * @param {Array} data The metadata array. * @returns {Function} Returns the new function. */ - function baseCreateWrapper(bindData) { - var func = bindData[0], - bitmask = bindData[1], - partialArgs = bindData[2], - partialRightArgs = bindData[3], - thisArg = bindData[4], - arity = bindData[5]; + function baseCreateWrapper(data) { + var func = data[0], + bitmask = data[1], + arity = data[2], + thisArg = data[3], + partialArgs = data[4], + partialRightArgs = data[5]; var isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, @@ -1297,10 +1303,15 @@ if (partialRightArgs) { push.apply(args, partialRightArgs); } - if (isCurry && args.length < arity) { + var argsLength = arguments.length; + if (isCurry && argsLength < arity) { bitmask |= PARTIAL_FLAG; - bitmask &= ~PARTIAL_RIGHT_FLAG; - return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~(BIND_FLAG | BIND_KEY_FLAG)), args, null, thisArg, arity]); + bitmask &= ~PARTIAL_RIGHT_FLAG + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newArity = nativeMax(0, arity - argsLength); + return baseCreateWrapper([func, bitmask, newArity, thisArg, args]); } } args || (args = arguments); @@ -1314,7 +1325,7 @@ } return func.apply(thisBinding, args); } - setBindData(bound, bindData); + setData(bound, data); return bound; } @@ -1793,25 +1804,23 @@ * @param {Function|string} func The function or method name to reference. * @param {number} bitmask The bitmask of flags to compose. * The bitmask may be composed of the following flags: - * 1 - `_.bind` - * 2 - `_.bindKey` - * 4 - `_.curry` - * 8 - `_.curry` (bound) + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` + * 8 - `_.curry` (bound) * 16 - `_.partial` * 32 - `_.partialRight` + * @param {number} [arity] The arity of `func`. + * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partialArgs] An array of arguments to prepend to those * provided to the new function. * @param {Array} [partialRightArgs] An array of arguments to append to those * provided to the new function. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {number} [arity] The arity of `func`. * @returns {Function} Returns the new function. */ - function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) { + function createWrapper(func, bitmask, arity, thisArg, partialArgs, partialRightArgs) { var isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, - isCurry = bitmask & CURRY_FLAG, - isCurryBound = bitmask & CURRY_BOUND_FLAG, isPartial = bitmask & PARTIAL_FLAG, isPartialRight = bitmask & PARTIAL_RIGHT_FLAG; @@ -1819,50 +1828,69 @@ throw new TypeError; } if (isPartial && !partialArgs.length) { - bitmask &= ~16; + bitmask &= ~PARTIAL_FLAG; isPartial = partialArgs = false; } if (isPartialRight && !partialRightArgs.length) { - bitmask &= ~32; + bitmask &= ~PARTIAL_RIGHT_FLAG; isPartialRight = partialRightArgs = false; } - var bindData = func && func.__bindData__; - if (bindData && bindData !== true) { - // clone `bindData` - bindData = slice(bindData); - if (bindData[2]) { - bindData[2] = slice(bindData[2]); + var data = !isBindKey && func[expando]; + if (data && data !== true) { + // shallow clone `data` + data = slice(data); + + // clone partial left arguments + if (data[4]) { + data[4] = slice(data[4]); } - if (bindData[3]) { - bindData[3] = slice(bindData[3]); + // clone partial right arguments + if (data[5]) { + data[5] = slice(data[5]); } - // set `thisBinding` is not previously bound - if (isBind && !(bindData[1] & BIND_FLAG)) { - bindData[4] = thisArg; + // set arity if provided + if (typeof arity == 'number') { + data[2] = arity; } - // set if previously bound but not currently (subsequent curried functions) - if (!isBind && bindData[1] & BIND_FLAG) { - bitmask |= 8; + // set `thisArg` if not previously bound + var bound = data[1] & BIND_FLAG; + if (isBind && !bound) { + data[3] = thisArg; } - // set curried arity if not yet set - if (isCurry && !(bindData[1] & CURRY_FLAG)) { - bindData[5] = arity; + // set if currying a bound function + if (!isBind && bound) { + bitmask |= CURRY_BOUND_FLAG; } // append partial left arguments if (isPartial) { - push.apply(bindData[2] || (bindData[2] = []), partialArgs); + if (data[4]) { + push.apply(data[4], partialArgs); + } else { + data[4] = partialArgs; + } } - // append partial right arguments + // prepend partial right arguments if (isPartialRight) { - unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs); + if (data[5]) { + unshift.apply(data[5], partialRightArgs); + } else { + data[5] = partialRightArgs; + } } // merge flags - bindData[1] |= bitmask; - return createWrapper.apply(null, bindData); + data[1] |= bitmask; + return createWrapper.apply(null, data); + } + if (arity == null) { + arity = isBindKey ? 0 : func.length; + } else if (arity < 0) { + arity = 0; } // fast path for `_.bind` - var creater = (bitmask == BIND_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) ? baseBind : baseCreateWrapper; - return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]); + data = [func, bitmask, arity, thisArg, partialArgs, partialRightArgs]; + return (bitmask == BIND_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) + ? baseBind(data) + : baseCreateWrapper(data); } /** @@ -1919,15 +1947,15 @@ } /** - * Sets `this` binding data on a given function. + * Sets wrapper metadata on a given function. * * @private * @param {Function} func The function to set data on. * @param {Array} value The data array to set. */ - var setBindData = !defineProperty ? noop : function(func, value) { + var setData = !defineProperty ? noop : function(func, value) { descriptor.value = value; - defineProperty(func, '__bindData__', descriptor); + defineProperty(func, expando, descriptor); }; /** @@ -4516,9 +4544,14 @@ * // => 'hi fred' */ function bind(func, thisArg) { - return arguments.length > 2 - ? createWrapper(func, BIND_FLAG | PARTIAL_FLAG, slice(arguments, 2), null, thisArg) - : createWrapper(func, BIND_FLAG, null, null, thisArg); + if (arguments.length < 3) { + return createWrapper(func, BIND_FLAG, null, thisArg); + } + var arity = func && (func[expando] ? func[expando][2] : func.length), + partialArgs = slice(arguments, 2); + + arity -= partialArgs.length; + return createWrapper(func, BIND_FLAG | PARTIAL_FLAG, arity, thisArg, partialArgs); } /** @@ -4554,7 +4587,7 @@ while (++index < length) { var key = funcs[index]; - object[key] = createWrapper(object[key], BIND_FLAG, null, null, object); + object[key] = createWrapper(object[key], BIND_FLAG, null, object); } return object; } @@ -4595,9 +4628,9 @@ * // => 'hiya fred!' */ function bindKey(object, key) { - return arguments.length > 2 - ? createWrapper(key, BIND_FLAG | BIND_KEY_FLAG | PARTIAL_FLAG, slice(arguments, 2), null, object) - : createWrapper(key, BIND_FLAG | BIND_KEY_FLAG, null, null, object); + return arguments.length < 3 + ? createWrapper(key, BIND_FLAG | BIND_KEY_FLAG, null, object) + : createWrapper(key, BIND_FLAG | BIND_KEY_FLAG | PARTIAL_FLAG, null, object, slice(arguments, 2)); } /** @@ -4681,8 +4714,10 @@ * // => 6 */ function curry(func, arity) { - arity = typeof arity == 'number' ? arity : (+arity || func.length); - return createWrapper(func, CURRY_FLAG, null, null, null, arity); + if (typeof arity != 'number') { + arity = +arity || null; + } + return createWrapper(func, CURRY_FLAG, arity); } /** @@ -4984,7 +5019,11 @@ * // => 'hi fred' */ function partial(func) { - return createWrapper(func, PARTIAL_FLAG, slice(arguments, 1)); + var arity = func && (func[expando] ? func[expando][2] : func.length), + partialArgs = slice(arguments, 1); + + arity -= partialArgs.length; + return createWrapper(func, PARTIAL_FLAG, arity, null, partialArgs); } /** @@ -5018,7 +5057,11 @@ * // => { '_': _, 'jq': $ } */ function partialRight(func) { - return createWrapper(func, PARTIAL_RIGHT_FLAG, null, slice(arguments, 1)); + var arity = func && (func[expando] ? func[expando][2] : func.length), + partialRightArgs = slice(arguments, 1); + + arity -= partialRightArgs.length; + return createWrapper(func, PARTIAL_RIGHT_FLAG, arity, null, null, partialRightArgs); } /** @@ -5094,7 +5137,7 @@ * // => '

fred, barney, & pebbles

' */ function wrap(value, wrapper) { - return createWrapper(wrapper, PARTIAL_FLAG, [value]); + return createWrapper(wrapper, PARTIAL_FLAG, null, null, [value]); } /*--------------------------------------------------------------------------*/ @@ -7466,7 +7509,7 @@ * @memberOf _ * @type string */ - lodash.VERSION = '2.4.1'; + lodash.VERSION = version; // add "Chaining" functions to the wrapper lodash.prototype.chain = wrapperChain; diff --git a/test/test.js b/test/test.js index 17fd3d385..a90f947be 100644 --- a/test/test.js +++ b/test/test.js @@ -1,6 +1,9 @@ ;(function(root, undefined) { 'use strict'; + /** Used as the size when optimizations are enabled for arrays */ + var LARGE_ARRAY_SIZE = 75; + /** Used to store Lo-Dash to test for bad extensions/shims */ var lodashBizarro = root.lodashBizarro; @@ -144,15 +147,15 @@ (_.runInContext ? _.runInContext(root) : _) )); + /** Used as the property name for wrapper metadata */ + var expando = '__lodash@' + _.VERSION + '__'; + /** Used to pass falsey values to methods */ var falsey = [, '', 0, false, NaN, null, undefined]; /** Used to pass empty values to methods */ var empties = [[], {}].concat(falsey.slice(1)); - /** Used as the size when optimizations are enabled for large arrays */ - var LARGE_ARRAY_SIZE = 75; - /** Used to set property descriptors */ var defineProperty = (function() { try { @@ -468,7 +471,7 @@ } catch(e) { actual = null; } - equal('__bindData__' in actual, false, message('Object.defineProperty')); + equal(expando in actual, false, message('Object.defineProperty')); try { actual = [lodashBizarro.isPlainObject({}), lodashBizarro.isPlainObject([])]; @@ -1503,7 +1506,7 @@ } }); - test('should only write `__bindData__` to named functions', 3, function() { + test('should only write metadata to named functions', 3, function() { function a() {}; function c() {}; @@ -1512,16 +1515,16 @@ if (defineProperty && _.support.funcDecomp) { _.createCallback(a, object); - ok('__bindData__' in a); + ok(expando in a); _.createCallback(b, object); - equal('__bindData__' in b, false); + equal(expando in b, false); if (_.support.funcNames) { _.support.funcNames = false; _.createCallback(c, object); - ok('__bindData__' in c); + ok(expando in c); _.support.funcNames = true; } else { @@ -1533,12 +1536,12 @@ } }); - test('should not write `__bindData__` when `_.support.funcDecomp` is `false`', 1, function() { + test('should not write metadata when `_.support.funcDecomp` is `false`', 1, function() { function a() {}; if (defineProperty && lodashBizarro) { lodashBizarro.createCallback(a, {}); - equal('__bindData__' in a, false); + equal(expando in a, false); } else { skipTest(); @@ -1557,13 +1560,12 @@ test('should curry based on the number of arguments provided', 3, function() { var curried = _.curry(func); - equal(curried(1)(2)(3), 6); equal(curried(1, 2)(3), 6); equal(curried(1, 2, 3), 6); }); - test('should work with partial methods', 2, function() { + test('should work with partialed methods', 2, function() { var curried = _.curry(func), a = _.partial(curried, 1), b = _.partialRight(a, 3), @@ -1576,7 +1578,6 @@ test('should return a function with a `length` of `0`', 6, function() { _.times(2, function(index) { var curried = index ? _.curry(func, 4) : _.curry(func); - strictEqual(curried.length, 0); strictEqual(curried(1).length, 0); strictEqual(curried(1, 2).length, 0); @@ -1599,9 +1600,7 @@ var value = this || {}; return value[a] + value[b] + value[c]; } - var object = { 'a': 1, 'b': 2, 'c': 3 }; - equal(_.curry(_.bind(func, object), 3)('a')('b')('c'), 6); equal(_.curry(_.bind(func, object), 3)('a', 'b')('c'), 6); equal(_.curry(_.bind(func, object), 3)('a', 'b', 'c'), 6); @@ -1611,7 +1610,6 @@ equal(_.bind(_.curry(func), object)('a', 'b', 'c'), 6); object.func = _.curry(func); - ok(_.isEqual(object.func('a')('b')('c'), NaN)); ok(_.isEqual(object.func('a', 'b')('c'), NaN)); equal(object.func('a', 'b', 'c'), 6); @@ -5862,22 +5860,18 @@ isPartial = methodName == 'partial'; test('`_.' + methodName + '` partially applies without additional arguments', 1, function() { - var arg = 'a', - fn = function(x) { return x; }; - - equal(func(fn, arg)(), arg); + var fn = function(a) { return a; }; + equal(func(fn, 'a')(), 'a'); }); test('`_.' + methodName + '` partially applies with additional arguments', 1, function() { - var arg1 = 'a', - arg2 = 'b', - expected = [arg1, arg2], - fn = function(x, y) { return [x, y]; }; + var expected = ['a', 'b'], + fn = function(a, b) { return [a, b]; }; if (!isPartial) { expected.reverse(); } - deepEqual(func(fn, arg1)(arg2), expected); + deepEqual(func(fn, 'a')('b'), expected); }); test('`_.' + methodName + '` works without partially applying arguments, without additional arguments', 1, function() { @@ -5886,10 +5880,8 @@ }); test('`_.' + methodName + '` works without partially applying arguments, with additional arguments', 1, function() { - var arg = 'a', - fn = function(x) { return x; }; - - equal(func(fn)(arg), arg); + var fn = function(a) { return a; }; + equal(func(fn)('a'), 'a'); }); test('`_.' + methodName + '` should not alter the `this` binding', 3, function() { @@ -5910,7 +5902,7 @@ strictEqual(actual.length, 0); }); - test('ensure `new bound` is an instance of `func`', 2, function() { + test('`_.' + methodName + '` ensure `new bound` is an instance of `func`', 2, function() { function Foo(value) { return value && object; } @@ -5921,7 +5913,7 @@ strictEqual(new bound(true), object); }); - test('`_.' + methodName + '` should clone `__bindData__` for created functions', 3, function() { + test('`_.' + methodName + '` should clone metadata for created functions', 3, function() { function greet(greeting, name) { return greeting + ' ' + name; } @@ -5933,6 +5925,14 @@ equal(par2(), isPartial ? 'hi barney' : 'barney hi'); equal(par3(), isPartial ? 'hi pebbles' : 'pebbles hi'); }); + + test('`_.' + methodName + '` should work with curried methods', 2, function() { + var fn = function(a, b, c) { return a + b + c; }, + curried = _.curry(func(fn, 1)); + + equal(curried(2, 3), 6); + equal(curried(2)(3), 6); + }); }); /*--------------------------------------------------------------------------*/