diff --git a/build.js b/build.js index cdbf920c6..9b5570f81 100755 --- a/build.js +++ b/build.js @@ -10,9 +10,6 @@ var lodash = require(path.join(__dirname, 'lodash')), minify = require(path.join(__dirname, 'build', 'minify')); - /** Flag used to specify a custom build */ - var isCustom = false; - /** Shortcut used to convert array-like objects to arrays */ var slice = [].slice; @@ -141,6 +138,23 @@ 'zip': ['max', 'pluck'] }; + /** Names of methods to filter for the build */ + var filterMethods = Object.keys(dependencyMap); + + /** Used to specify if `filterMethods` should be used for exclusion or inclusion */ + var filterType = process.argv.reduce(function(result, value) { + if (!result) { + var pair = value.match(/^(exclude|include)=(.*)$/); + if (pair) { + filterMethods = lodash.intersection(filterMethods, pair[2].split(/, */).map(getRealName)); + return pair[1]; + } + } + }, ''); + + /** Flag used to specify a mobile build */ + var isMobile = process.argv.indexOf('mobile') > -1; + /*--------------------------------------------------------------------------*/ /** @@ -344,22 +358,14 @@ /*--------------------------------------------------------------------------*/ // custom build - process.argv.some(function(arg) { - // exit early if not the "exclude" or "include" command option - var pair = arg.match(/^(exclude|include)=(.*)$/); - if (!pair) { - return false; + (function() { + // exit early if "exclude" or "include" options aren't specified + if (!filterType) { + return; } - - var filterType = pair[1], - filterNames = lodash.intersection(Object.keys(dependencyMap), pair[2].split(/, */).map(getRealName)); - - // set custom build flag - isCustom = true; - // remove the specified functions and their dependants if (filterType == 'exclude') { - filterNames.forEach(function(funcName) { + filterMethods.forEach(function(funcName) { getDependants(funcName).concat(funcName).forEach(function(otherName) { source = removeFunction(source, otherName); }); @@ -367,13 +373,13 @@ } // else remove all but the specified functions and their dependencies else { - filterNames = lodash.uniq(filterNames.reduce(function(result, funcName) { + filterMethods = lodash.uniq(filterMethods.reduce(function(result, funcName) { result.push.apply(result, getDependencies(funcName).concat(funcName)); return result; }, [])); lodash.each(dependencyMap, function(dependencies, otherName) { - if (filterNames.indexOf(otherName) < 0) { + if (filterMethods.indexOf(otherName) < 0) { source = removeFunction(source, otherName); } }); @@ -402,10 +408,22 @@ if (isRemoved(source, 'bind', 'functions', 'groupBy', 'invoke', 'isEqual', 'isFunction', 'result', 'sortBy', 'toArray')) { source = removeVar(source, 'funcClass'); } + if (isRemoved(source, 'bind')) { + source = removeVar(source, 'nativeBind'); + } + if (isRemoved(source, 'isArray')) { + source = removeVar(source, 'nativeIsArray'); + } + if (isRemoved(source, 'keys')) { + source = removeVar(source, 'nativeKeys'); + } if (isRemoved(source, 'clone', 'isObject', 'keys')) { source = removeVar(source, 'objectTypes'); source = removeFromCreateIterator(source, 'objectTypes'); } + if (isRemoved(source, 'bind', 'isArray', 'keys')) { + source = removeVar(source, 'reNative'); + } if (isRemoved(source, 'isEmpty', 'isEqual', 'isString', 'size')) { source = removeVar(source, 'stringClass'); } @@ -414,71 +432,70 @@ source = source.replace(/(?:\s*\/\*-+\*\/\s*){2,}/g, function(separators) { return separators.match(/^\s*/)[0] + separators.slice(separators.lastIndexOf('/*')); }); - - return true; - }); - - /*--------------------------------------------------------------------------*/ - - (function() { - // for mobile builds - if (process.argv.indexOf('mobile') > -1) { - // set custom build flag - isCustom = true; - - // inline functions defined with `createIterator` - lodash.functions(lodash).forEach(function(funcName) { - var reFunc = RegExp('( +var ' + funcName + ' *= *)((?:[a-zA-Z]+ *\\|\\| *)?)createIterator\\(((?:{|[a-zA-Z])[\\s\\S]+?)\\);\\n'), - parts = source.match(reFunc); - - // skip if not defined with `createIterator` - if (!parts) { - return; - } - source = source.replace(reFunc, - (funcName == 'keys' - ? '$1$2' + lodash._createIterator(Function('return ' + parts[3])()) - : '$1' + lodash[funcName] - ) + ';\n' - ); - }); - - // remove `iteratorTemplate` - source = removeVar(source, 'iteratorTemplate'); - - // remove JScript [[DontEnum]] fix from `isEqual` - source = source.replace(/(?:\s*\/\/.*\n)*( +)if *\(result *&& *hasDontEnumBug[\s\S]+?\n\1}\n/, '\n'); - } - // for normal builds - else { - // extract `iteratorTemplate` source - var iteratorTemplateCode = /^function[^{]+{([\s\S]+?)}$/.exec(lodash._iteratorTemplate)[1]; - - // remove whitespace and unnecessary code - iteratorTemplateCode = removeWhitespace(iteratorTemplateCode) - .replace(/\|\|\{\}|,__t,__j=Array.prototype.join|function print[^}]+}|\+''/g, '') - .replace(/(\{);|;(\})/g, '$1$2') - .replace(/\(\(__t=\(([^)]+)\)\)==null\?'':__t\)/g, '$1'); - - // ensure escaped characters are interpreted correctly inside the `Function()` string - iteratorTemplateCode = iteratorTemplateCode.replace(/\\/g, '\\\\'); - - // add `iteratorTemplateCode` to `Function()` to avoid strict mode error - // for using a with-statement - iteratorTemplateCode = '$1Function(\'object\',\n$2 "' + iteratorTemplateCode + '"\n$2);\n'; - - // replace `template()` with `Function()` - source = source.replace(/(( +)var iteratorTemplate *= *)([\s\S]+?\n\2.+?);\n/, iteratorTemplateCode); - } - - // remove pseudo private properties - source = source.replace(/(?:\s*\/\/.*)*\s*lodash\._(?:createIterator|iteratorTemplate)\b.+\n/g, '\n'); }()); /*--------------------------------------------------------------------------*/ + if (isMobile) { + // inline functions defined with `createIterator` + lodash.functions(lodash).forEach(function(funcName) { + var reFunc = RegExp('( +var ' + funcName + ' *= *)((?:[a-zA-Z]+ *\\|\\| *)?)createIterator\\(((?:{|[a-zA-Z])[\\s\\S]+?)\\);\\n'), + parts = source.match(reFunc); + + // skip if not defined with `createIterator` + if (!parts) { + return; + } + // extract function's code + var code = funcName == 'keys' + ? '$1$2' + lodash._createIterator(Function('return ' + parts[3])()) + : '$1' + lodash[funcName]; + + // format code + code = code.replace(/\n(?:.*)/g, function(match) { + match = match.slice(1); + return (match == '}' ? '\n ' : '\n ') + match; + }) + ';\n'; + + source = source.replace(reFunc, code); + }); + + // remove `iteratorTemplate` + source = removeVar(source, 'iteratorTemplate'); + + // remove JScript [[DontEnum]] fix from `isEqual` + source = source.replace(/(?:\s*\/\/.*\n)*( +)if *\(result *&& *hasDontEnumBug[\s\S]+?\n\1}\n/, '\n'); + + // remove IE `shift` and `splice` fix + source = source.replace(/(?:\s*\/\/.*\n)*( +)if *\(value.length *=== *0[\s\S]+?\n\1}\n/, '\n'); + } + else { + // inline `iteratorTemplate` template + source = source.replace(/(( +)var iteratorTemplate *= *)([\s\S]+?\n\2.+?);\n/, (function() { + // extract `iteratorTemplate` code + var code = /^function[^{]+{([\s\S]+?)}$/.exec(lodash._iteratorTemplate)[1]; + + code = removeWhitespace(code) + // remove unnecessary code + .replace(/\|\|\{\}|,__t,__j=Array.prototype.join|function print[^}]+}|\+''/g, '') + .replace(/(\{);|;(\})/g, '$1$2') + .replace(/\(\(__t=\(([^)]+)\)\)==null\?'':__t\)/g, '$1') + // ensure escaped characters are interpreted correctly in the string literal + .replace(/\\/g, '\\\\'); + + // add `code` to `Function()` as a string literal to avoid strict mode + // errors caused by the required with-statement + return '$1Function(\'obj\',\n$2 "' + code + '"\n$2);\n'; + }())); + } + + // remove pseudo private properties + source = source.replace(/(?:\s*\/\/.*)*\s*lodash\._(?:createIterator|iteratorTemplate)\b.+\n/g, '\n'); + + /*--------------------------------------------------------------------------*/ + // begin the minification process - if (isCustom) { + if (filterType || isMobile) { fs.writeFileSync(path.join(__dirname, 'lodash.custom.js'), source); minify(source, 'lodash.custom.min', function(result) { fs.writeFileSync(path.join(__dirname, 'lodash.custom.min.js'), result); diff --git a/lodash.min.js b/lodash.min.js index e588a070a..4bdb768c8 100644 --- a/lodash.min.js +++ b/lodash.min.js @@ -11,7 +11,7 @@ g.push(a[f]);return g}function v(a,c){function d(){var g=arguments,h=c;return f| )for(;g--&&(e=N(a[g],c[g],d)););}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return q;for(var h in a)if(s.call(a,h)&&(g++,!(e=s.call(c,h)&&N(a[h],c[h],d))))break;if(e){for(h in c)if(s.call(c,h)&&!(g--))break;e=!g}if(e&&H)for(;7>++f&&(h=ca[f],!s.call(a,h)||!!(e=s.call(c,h)&&N(a[h],c[h],d))););}return d.pop(),e}function da(a){return a}function oa(a){C(P(a),function(c){var d=b[c]=a[c];p.prototype[c]=function(){var a=[this._wrapped];return arguments.length&&L.apply(a,arguments ),a=1==a.length?d.call(b,a[0]):d.apply(b,a),this._chain&&(a=new p(a),a._chain=m),a}})}var m=!0,o=null,q=!1,X="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(u=global),exports),va={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"},H=!{valueOf:0}.propertyIsEnumerable("valueOf"),za=0,J={"boolean":q,"function":m,object:m,number:q,string:q,"undefined":q},Aa=u._,z=RegExp("^"+({}.valueOf+"").replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&" ).replace(/valueOf|for [^\]]+/g,".+?")+"$"),Ba=/__token__(\d+)/g,Ca=/['\n\r\t\u2028\u2029\\]/g,ca="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),T="__token__",w=[],I="[object Array]",la="[object Boolean]",ma="[object Date]",r="[object Function]",O="[object Number]",na="[object RegExp]",K="[object String]",A=Array.prototype,D=Object.prototype,M=A.concat,s=D.hasOwnProperty,L=A.push,l=A.slice,i=D.toString,y=z.test(y=l.bind)&&/\n|Opera/.test -(y+i.call(u.opera))&&y,E=z.test(E=Array.isArray)&&E,Da=u.isFinite,Y=z.test(Y=Object.keys)&&Y,Ea=u.clearTimeout,Q=u.setTimeout;b.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:"obj"};var sa=Function("n","var __p;with(obj){__p='var l,r';if(k){__p+='='+k};__p+=';'+f+';'+q+';';if(c){__p+='var m='+g+'.length;l=-1;';if(o){__p+='if(m===+m){'};__p+=''+c['d']+';while('+c['m']+'){'+c['j']+'}';if(o){__p+='}'}}if(o){if(c){__p+='else{'}if(!i){__p+='var s=typeof '+l+'==\\'function\\';'};__p+=''+o['d']+';for('+o['m']+'){';if(i){if(r){__p+='if('+h+'){'};__p+=''+o['j']+';';if(r){__p+='}'}}else{__p+='if(!(s&&l==\\'prototype\\')';if(r){__p+='&&'+h};__p+='){'+o['j']+'}'};__p+='}';if(i){__p+='var g='+l+'.constructor;';for(var k=0;k<7;k++){__p+='l=\\''+p[k]+'\\';if(';if(p[k]=='constructor'){__p+='!(g&&g.prototype==='+l+')&&'};__p+=''+h+'){'+o['j']+'}'}}if(c){__p+='}'}};__p+=''+e+';return r'}return __p" +(y+i.call(u.opera))&&y,E=z.test(E=Array.isArray)&&E,Da=u.isFinite,Y=z.test(Y=Object.keys)&&Y,Ea=u.clearTimeout,Q=u.setTimeout;b.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:"obj"};var sa=Function("obj","var __p;with(obj){__p='var l,r';if(k){__p+='='+k};__p+=';'+f+';'+q+';';if(c){__p+='var m='+g+'.length;l=-1;';if(o){__p+='if(m===+m){'};__p+=''+c['d']+';while('+c['m']+'){'+c['j']+'}';if(o){__p+='}'}}if(o){if(c){__p+='else{'}if(!i){__p+='var s=typeof '+l+'==\\'function\\';'};__p+=''+o['d']+';for('+o['m']+'){';if(i){if(r){__p+='if('+h+'){'};__p+=''+o['j']+';';if(r){__p+='}'}}else{__p+='if(!(s&&l==\\'prototype\\')';if(r){__p+='&&'+h};__p+='){'+o['j']+'}'};__p+='}';if(i){__p+='var g='+l+'.constructor;';for(var k=0;k<7;k++){__p+='l=\\''+p[k]+'\\';if(';if(p[k]=='constructor'){__p+='!(g&&g.prototype==='+l+')&&'};__p+=''+h+'){'+o['j']+'}'}}if(c){__p+='}'}};__p+=''+e+';return r'}return __p" ),t={a:"f,d,x",k:"f",q:"if(!d){d=k}else if(x){d=c(d,x)}",j:"d(f[l],l,f)"},Z={k:"z",j:"if(!d(f[l],l,f))return!r"},$={a:"n",k:"n",q:"for(var t,u=1,m=arguments.length;ua?c():function(){if(1>--a)return c.apply(this,arguments)}},b.bind=v,b.bindAll=function(a){var c=arguments,d=1;1==c.length&&(d=0,c=P(a));for(var b=c.length;d