PageRenderTime 76ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/node_modules/grunt/node_modules/lodash/build.js

https://bitbucket.org/biojazzard/gantry-eboracast
JavaScript | 1736 lines | 1152 code | 181 blank | 403 comment | 168 complexity | ce21d2130e9d6256e839791140e32d04 MD5 | raw file
Possible License(s): MIT, JSON, BSD-2-Clause, Unlicense, GPL-2.0, WTFPL, LGPL-3.0, Apache-2.0, 0BSD, BSD-3-Clause, CC-BY-SA-3.0

Large files files are truncated, but you can click here to view the full file

  1. #!/usr/bin/env node
  2. ;(function() {
  3. 'use strict';
  4. /** Load modules */
  5. var fs = require('fs'),
  6. path = require('path'),
  7. vm = require('vm'),
  8. minify = require(path.join(__dirname, 'build', 'minify.js')),
  9. _ = require(path.join(__dirname, 'lodash.js'));
  10. /** The current working directory */
  11. var cwd = process.cwd();
  12. /** Used for array method references */
  13. var arrayRef = [];
  14. /** Shortcut used to push arrays of values to an array */
  15. var push = arrayRef.push;
  16. /** Shortcut used to convert array-like objects to arrays */
  17. var slice = arrayRef.slice;
  18. /** Shortcut to the `stdout` object */
  19. var stdout = process.stdout;
  20. /** Used to associate aliases with their real names */
  21. var aliasToRealMap = {
  22. 'all': 'every',
  23. 'any': 'some',
  24. 'collect': 'map',
  25. 'detect': 'find',
  26. 'drop': 'rest',
  27. 'each': 'forEach',
  28. 'foldl': 'reduce',
  29. 'foldr': 'reduceRight',
  30. 'head': 'first',
  31. 'include': 'contains',
  32. 'inject': 'reduce',
  33. 'methods': 'functions',
  34. 'select': 'filter',
  35. 'tail': 'rest',
  36. 'take': 'first',
  37. 'unique': 'uniq'
  38. };
  39. /** Used to associate real names with their aliases */
  40. var realToAliasMap = {
  41. 'contains': ['include'],
  42. 'every': ['all'],
  43. 'filter': ['select'],
  44. 'find': ['detect'],
  45. 'first': ['head', 'take'],
  46. 'forEach': ['each'],
  47. 'functions': ['methods'],
  48. 'map': ['collect'],
  49. 'reduce': ['foldl', 'inject'],
  50. 'reduceRight': ['foldr'],
  51. 'rest': ['drop', 'tail'],
  52. 'some': ['any'],
  53. 'uniq': ['unique']
  54. };
  55. /** Used to track function dependencies */
  56. var dependencyMap = {
  57. 'after': [],
  58. 'bind': ['isFunction', 'isObject'],
  59. 'bindAll': ['bind', 'functions'],
  60. 'chain': ['mixin'],
  61. 'clone': ['extend', 'forEach', 'forOwn', 'isArguments', 'isObject', 'isPlainObject'],
  62. 'compact': [],
  63. 'compose': [],
  64. 'contains': ['indexOf', 'isString', 'some'],
  65. 'countBy': ['forEach'],
  66. 'debounce': [],
  67. 'defaults': ['isArguments'],
  68. 'defer': [],
  69. 'delay': [],
  70. 'difference': ['indexOf'],
  71. 'escape': [],
  72. 'every': ['forEach', 'isArray'],
  73. 'extend': ['isArguments'],
  74. 'filter': ['forEach'],
  75. 'find': ['forEach'],
  76. 'first': [],
  77. 'flatten': ['isArray'],
  78. 'forEach': ['identity', 'isString'],
  79. 'forIn': ['identity', 'isArguments'],
  80. 'forOwn': ['identity', 'isArguments'],
  81. 'functions': ['forIn', 'isFunction'],
  82. 'groupBy': ['forEach'],
  83. 'has': [],
  84. 'identity': [],
  85. 'indexOf': ['sortedIndex'],
  86. 'initial': [],
  87. 'intersection': ['filter', 'indexOf'],
  88. 'invert': ['forOwn'],
  89. 'invoke': ['forEach'],
  90. 'isArguments': [],
  91. 'isArray': [],
  92. 'isBoolean': [],
  93. 'isDate': [],
  94. 'isElement': [],
  95. 'isEmpty': ['forOwn', 'isArguments', 'isFunction'],
  96. 'isEqual': ['isArguments', 'isFunction'],
  97. 'isFinite': [],
  98. 'isFunction': [],
  99. 'isNaN': [],
  100. 'isNull': [],
  101. 'isNumber': [],
  102. 'isObject': [],
  103. 'isPlainObject': ['forIn', 'isArguments', 'isFunction'],
  104. 'isRegExp': [],
  105. 'isString': [],
  106. 'isUndefined': [],
  107. 'keys': ['forOwn', 'isArguments', 'isObject'],
  108. 'last': [],
  109. 'lastIndexOf': [],
  110. 'lateBind': ['isFunction', 'isObject'],
  111. 'map': ['forEach', 'isArray'],
  112. 'max': ['forEach', 'isArray', 'isString'],
  113. 'memoize': [],
  114. 'merge': ['forOwn', 'isArray', 'isPlainObject'],
  115. 'min': ['forEach', 'isArray', 'isString'],
  116. 'mixin': ['forEach', 'functions'],
  117. 'noConflict': [],
  118. 'object': [],
  119. 'omit': ['forIn', 'indexOf'],
  120. 'once': [],
  121. 'pairs': ['forOwn'],
  122. 'partial': ['isFunction', 'isObject'],
  123. 'pick': ['forIn'],
  124. 'pluck': ['forEach'],
  125. 'random': [],
  126. 'range': [],
  127. 'reduce': ['forEach'],
  128. 'reduceRight': ['forEach', 'isString', 'keys'],
  129. 'reject': ['filter'],
  130. 'rest': [],
  131. 'result': ['isFunction'],
  132. 'shuffle': ['forEach'],
  133. 'size': ['keys'],
  134. 'some': ['forEach', 'isArray'],
  135. 'sortBy': ['forEach'],
  136. 'sortedIndex': ['identity'],
  137. 'tap': ['mixin'],
  138. 'template': ['escape'],
  139. 'throttle': [],
  140. 'times': [],
  141. 'toArray': ['values'],
  142. 'unescape': [],
  143. 'union': ['uniq'],
  144. 'uniq': ['identity', 'indexOf'],
  145. 'uniqueId': [],
  146. 'value': ['mixin'],
  147. 'values': ['forOwn'],
  148. 'where': ['filter', 'forIn'],
  149. 'without': ['indexOf'],
  150. 'wrap': [],
  151. 'zip': ['max', 'pluck']
  152. };
  153. /** Used to inline `iteratorTemplate` */
  154. var iteratorOptions = [
  155. 'args',
  156. 'arrayLoop',
  157. 'bottom',
  158. 'firstArg',
  159. 'hasDontEnumBug',
  160. 'isKeysFast',
  161. 'objectLoop',
  162. 'noArgsEnum',
  163. 'noCharByIndex',
  164. 'shadowed',
  165. 'top',
  166. 'useHas',
  167. 'useStrict'
  168. ];
  169. /** List of all Lo-Dash methods */
  170. var allMethods = _.keys(dependencyMap);
  171. /** List Backbone's Lo-Dash dependencies */
  172. var backboneDependencies = [
  173. 'bind',
  174. 'bindAll',
  175. 'clone',
  176. 'contains',
  177. 'escape',
  178. 'every',
  179. 'extend',
  180. 'filter',
  181. 'find',
  182. 'first',
  183. 'forEach',
  184. 'groupBy',
  185. 'has',
  186. 'indexOf',
  187. 'initial',
  188. 'invoke',
  189. 'isArray',
  190. 'isEmpty',
  191. 'isEqual',
  192. 'isFunction',
  193. 'isObject',
  194. 'isRegExp',
  195. 'keys',
  196. 'last',
  197. 'lastIndexOf',
  198. 'lateBind',
  199. 'map',
  200. 'max',
  201. 'min',
  202. 'mixin',
  203. 'reduce',
  204. 'reduceRight',
  205. 'reject',
  206. 'rest',
  207. 'result',
  208. 'shuffle',
  209. 'size',
  210. 'some',
  211. 'sortBy',
  212. 'sortedIndex',
  213. 'toArray',
  214. 'uniqueId',
  215. 'without'
  216. ];
  217. /** List of methods used by Underscore */
  218. var underscoreMethods = _.without.apply(_, [allMethods].concat([
  219. 'forIn',
  220. 'forOwn',
  221. 'isPlainObject',
  222. 'lateBind',
  223. 'merge',
  224. 'partial'
  225. ]));
  226. /** List of ways to export the `lodash` function */
  227. var exportsAll = [
  228. 'amd',
  229. 'commonjs',
  230. 'global',
  231. 'node'
  232. ];
  233. /*--------------------------------------------------------------------------*/
  234. /**
  235. * Compiles template files matched by the given file path `pattern` into a
  236. * single source, extending `_.templates` with precompiled templates named after
  237. * each template file's basename.
  238. *
  239. * @private
  240. * @param {String} [pattern='<cwd>/*.jst'] The file path pattern.
  241. * @param {Object} options The options object.
  242. * @returns {String} Returns the compiled source.
  243. */
  244. function buildTemplate(pattern, options) {
  245. pattern || (pattern = path.join(cwd, '*.jst'));
  246. var directory = path.dirname(pattern);
  247. var source = [
  248. ';(function(window) {',
  249. " var freeExports = typeof exports == 'object' && exports &&",
  250. " (typeof global == 'object' && global && global == global.global && (window = global), exports);",
  251. '',
  252. ' var templates = {},',
  253. ' _ = window._;',
  254. ''
  255. ];
  256. // convert to a regexp
  257. pattern = RegExp(
  258. path.basename(pattern)
  259. .replace(/[.+?^=!:${}()|[\]\/\\]/g, '\\$&')
  260. .replace(/\*/g, '.*?') + '$'
  261. );
  262. fs.readdirSync(directory).forEach(function(filename) {
  263. var filePath = path.join(directory, filename);
  264. if (pattern.test(filename)) {
  265. var text = fs.readFileSync(filePath, 'utf8'),
  266. precompiled = getFunctionSource(_.template(text, null, options)),
  267. prop = filename.replace(/\..*$/, '');
  268. source.push(" templates['" + prop.replace(/'/g, "\\'") + "'] = " + precompiled + ';', '');
  269. }
  270. });
  271. source.push(
  272. " if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {",
  273. " define(['" + options.moduleId + "'], function(lodash) {",
  274. ' lodash.templates = lodash.extend(lodash.templates || {}, templates);',
  275. ' });',
  276. " } else if (freeExports) {",
  277. " if (typeof module == 'object' && module && module.exports == freeExports) {",
  278. ' (module.exports = templates).templates = templates;',
  279. ' } else {',
  280. ' freeExports.templates = templates;',
  281. ' }',
  282. ' } else if (_) {',
  283. ' _.templates = _.extend(_.templates || {}, templates);',
  284. ' }',
  285. '}(this));'
  286. );
  287. return source.join('\n');
  288. }
  289. /**
  290. * Removes unnecessary comments, whitespace, and pseudo private properties.
  291. *
  292. * @private
  293. * @param {String} source The source to process.
  294. * @returns {String} Returns the modified source.
  295. */
  296. function cleanupSource(source) {
  297. return source
  298. // remove pseudo private properties
  299. .replace(/(?:(?:\s*\/\/.*)*\s*lodash\._[^=]+=.+\n)+/g, '\n')
  300. // remove lines with just whitespace and semicolons
  301. .replace(/^ *;\n/gm, '')
  302. // consolidate consecutive horizontal rule comment separators
  303. .replace(/(?:\s*\/\*-+\*\/\s*){2,}/g, function(separators) {
  304. return separators.match(/^\s*/)[0] + separators.slice(separators.lastIndexOf('/*'));
  305. });
  306. }
  307. /**
  308. * Writes the help message to standard output.
  309. *
  310. * @private
  311. */
  312. function displayHelp() {
  313. console.log([
  314. '',
  315. ' Commands:',
  316. '',
  317. ' lodash backbone Build with only methods required by Backbone',
  318. ' lodash csp Build supporting default Content Security Policy restrictions',
  319. ' lodash legacy Build tailored for older browsers without ES5 support',
  320. ' lodash mobile Build with IE < 9 bug fixes & method compilation removed',
  321. ' lodash strict Build with `_.bindAll`, `_.defaults`, & `_.extend` in strict mode',
  322. ' lodash underscore Build tailored for projects already using Underscore',
  323. ' lodash include=... Comma separated method/category names to include in the build',
  324. ' lodash minus=... Comma separated method/category names to remove from those included in the build',
  325. ' lodash plus=... Comma separated method/category names to add to those included in the build',
  326. ' lodash category=... Comma separated categories of methods to include in the build (case-insensitive)',
  327. ' (i.e. “arrays”, “chaining”, “collections”, “functions”, “objects”, and “utilities”)',
  328. ' lodash exports=... Comma separated names of ways to export the `lodash` function',
  329. ' (i.e. “amd”, “commonjs”, “global”, “node”, and “none”)',
  330. ' lodash iife=... Code to replace the immediately-invoked function expression that wraps Lo-Dash',
  331. ' (e.g. `lodash iife="!function(window,undefined){%output%}(this)"`)',
  332. '',
  333. ' lodash template=... File path pattern used to match template files to precompile',
  334. ' (e.g. `lodash template=./*.jst`)',
  335. ' lodash settings=... Template settings used when precompiling templates',
  336. ' (e.g. `lodash settings="{interpolate:/\\\\{\\\\{([\\\\s\\\\S]+?)\\\\}\\\\}/g}"`)',
  337. ' lodash moduleId=... The AMD module ID of Lo-Dash, which defaults to “lodash”, used by precompiled templates',
  338. '',
  339. ' All arguments, except `legacy` with `csp` or `mobile`, may be combined.',
  340. ' Unless specified by `-o` or `--output`, all files created are saved to the current working directory.',
  341. '',
  342. ' Options:',
  343. '',
  344. ' -c, --stdout Write output to standard output',
  345. ' -d, --debug Write only the debug output',
  346. ' -h, --help Display help information',
  347. ' -m, --minify Write only the minified output',
  348. ' -o, --output Write output to a given path/filename',
  349. ' -s, --silent Skip status updates normally logged to the console',
  350. ' -V, --version Output current version of Lo-Dash',
  351. ''
  352. ].join('\n'));
  353. }
  354. /**
  355. * Gets the aliases associated with a given function name.
  356. *
  357. * @private
  358. * @param {String} methodName The name of the method to get aliases for.
  359. * @returns {Array} Returns an array of aliases.
  360. */
  361. function getAliases(methodName) {
  362. return realToAliasMap[methodName] || [];
  363. }
  364. /**
  365. * Gets the Lo-Dash method assignments snippet from `source`.
  366. *
  367. * @private
  368. * @param {String} source The source to inspect.
  369. * @returns {String} Returns the method assignments snippet.
  370. */
  371. function getMethodAssignments(source) {
  372. return (source.match(/lodash\.VERSION *= *[\s\S]+?\/\*-+\*\/\n/) || [''])[0];
  373. }
  374. /**
  375. * Gets an array of depenants for a method by a given name.
  376. *
  377. * @private
  378. * @param {String} methodName The name of the method to query.
  379. * @returns {Array} Returns an array of method dependants.
  380. */
  381. function getDependants(methodName) {
  382. // iterate over the `dependencyMap`, adding the names of methods that
  383. // have `methodName` as a dependency
  384. return _.reduce(dependencyMap, function(result, dependencies, otherName) {
  385. if (_.contains(dependencies, methodName)) {
  386. result.push(otherName);
  387. }
  388. return result;
  389. }, []);
  390. }
  391. /**
  392. * Gets an array of dependencies for a given method name. If passed an array
  393. * of dependencies it will return an array containing the given dependencies
  394. * plus any additional detected sub-dependencies.
  395. *
  396. * @private
  397. * @param {Array|String} methodName A single method name or array of
  398. * dependencies to query.
  399. * @returns {Array} Returns an array of method dependencies.
  400. */
  401. function getDependencies(methodName) {
  402. var dependencies = Array.isArray(methodName) ? methodName : dependencyMap[methodName];
  403. if (!dependencies) {
  404. return [];
  405. }
  406. // recursively accumulate the dependencies of the `methodName` function, and
  407. // the dependencies of its dependencies, and so on.
  408. return _.uniq(dependencies.reduce(function(result, otherName) {
  409. result.push.apply(result, getDependencies(otherName).concat(otherName));
  410. return result;
  411. }, []));
  412. }
  413. /**
  414. * Gets the formatted source of the given function.
  415. *
  416. * @private
  417. * @param {Function} func The function to process.
  418. * @returns {String} Returns the formatted source.
  419. */
  420. function getFunctionSource(func) {
  421. var source = func.source || (func + '');
  422. // format leading whitespace
  423. return source.replace(/\n(?:.*)/g, function(match, index) {
  424. match = match.slice(1);
  425. return (
  426. match == '}' && source.indexOf('}', index + 2) == -1 ? '\n ' : '\n '
  427. ) + match;
  428. });
  429. }
  430. /**
  431. * Gets the `_.isArguments` fallback from `source`.
  432. *
  433. * @private
  434. * @param {String} source The source to inspect.
  435. * @returns {String} Returns the `isArguments` fallback.
  436. */
  437. function getIsArgumentsFallback(source) {
  438. return (source.match(/(?:\s*\/\/.*)*\n( *)if *\(noArgsClass\)[\s\S]+?};\n\1}/) || [''])[0];
  439. }
  440. /**
  441. * Gets the `_.isFunction` fallback from `source`.
  442. *
  443. * @private
  444. * @param {String} source The source to inspect.
  445. * @returns {String} Returns the `isFunction` fallback.
  446. */
  447. function getIsFunctionFallback(source) {
  448. return (source.match(/(?:\s*\/\/.*)*\n( *)if *\(isFunction\(\/x\/[\s\S]+?};\n\1}/) || [''])[0];
  449. }
  450. /**
  451. * Gets the names of methods in `source` belonging to the given `category`.
  452. *
  453. * @private
  454. * @param {String} source The source to inspect.
  455. * @param {String} category The category to filter by.
  456. * @returns {Array} Returns a new array of method names belonging to the given category.
  457. */
  458. function getMethodsByCategory(source, category) {
  459. return allMethods.filter(function(methodName) {
  460. return category && RegExp('@category ' + category + '\\b').test(matchFunction(source, methodName));
  461. });
  462. }
  463. /**
  464. * Gets the real name, not alias, of a given method name.
  465. *
  466. * @private
  467. * @param {String} methodName The name of the method to resolve.
  468. * @returns {String} Returns the real method name.
  469. */
  470. function getRealName(methodName) {
  471. return aliasToRealMap[methodName] || methodName;
  472. }
  473. /**
  474. * Determines if all functions of the given names have been removed from `source`.
  475. *
  476. * @private
  477. * @param {String} source The source to inspect.
  478. * @param {String} [funcName1, funcName2, ...] The names of functions to check.
  479. * @returns {Boolean} Returns `true` if all functions have been removed, else `false`.
  480. */
  481. function isRemoved(source) {
  482. return slice.call(arguments, 1).every(function(funcName) {
  483. return !matchFunction(source, funcName);
  484. });
  485. }
  486. /**
  487. * Searches `source` for a `funcName` function declaration, expression, or
  488. * assignment and returns the matched snippet.
  489. *
  490. * @private
  491. * @param {String} source The source to inspect.
  492. * @param {String} funcName The name of the function to match.
  493. * @returns {String} Returns the matched function snippet.
  494. */
  495. function matchFunction(source, funcName) {
  496. var result = source.match(RegExp(
  497. // match multi-line comment block (could be on a single line)
  498. '(?:\\n +/\\*[^*]*\\*+(?:[^/][^*]*\\*+)*/\\n)?' +
  499. // begin non-capturing group
  500. '(?:' +
  501. // match a function declaration
  502. '( *)function ' + funcName + '\\b[\\s\\S]+?\\n\\1}|' +
  503. // match a variable declaration with `createIterator`
  504. ' +var ' + funcName + ' *=.*?createIterator\\((?:{|[a-zA-Z])[\\s\\S]+?\\);|' +
  505. // match a variable declaration with function expression
  506. '( *)var ' + funcName + ' *=.*?function[\\s\\S]+?\\n\\2};' +
  507. // end non-capturing group
  508. ')\\n'
  509. ));
  510. return result ? result[0] : '';
  511. }
  512. /**
  513. * Converts a comma separated options string into an array.
  514. *
  515. * @private
  516. * @param {String} value The option to convert.
  517. * @returns {Array} Returns the new converted array.
  518. */
  519. function optionToArray(value) {
  520. return value.match(/\w+=(.*)$/)[1].split(/, */);
  521. }
  522. /**
  523. * Converts a comma separated options string into an array containing
  524. * only real method names.
  525. *
  526. * @private
  527. * @param {String} source The source to inspect.
  528. * @param {String} value The option to convert.
  529. * @returns {Array} Returns the new converted array.
  530. */
  531. function optionToMethodsArray(source, value) {
  532. var methodNames = optionToArray(value);
  533. // convert categories to method names
  534. methodNames.forEach(function(category) {
  535. push.apply(methodNames, getMethodsByCategory(source, category));
  536. });
  537. // convert aliases to real method names
  538. methodNames = methodNames.map(getRealName);
  539. // remove nonexistent and duplicate method names
  540. return _.uniq(_.intersection(allMethods, methodNames));
  541. }
  542. /**
  543. * Removes the all references to `refName` from `createIterator` in `source`.
  544. *
  545. * @private
  546. * @param {String} source The source to process.
  547. * @param {String} refName The name of the reference to remove.
  548. * @returns {String} Returns the modified source.
  549. */
  550. function removeFromCreateIterator(source, refName) {
  551. var snippet = matchFunction(source, 'createIterator');
  552. if (snippet) {
  553. // clip the snippet at the `factory` assignment
  554. snippet = snippet.match(/Function\([\s\S]+$/)[0];
  555. var modified = snippet.replace(RegExp('\\b' + refName + '\\b,? *', 'g'), '');
  556. source = source.replace(snippet, modified);
  557. }
  558. return source;
  559. }
  560. /**
  561. * Removes the `funcName` function declaration, expression, or assignment and
  562. * associated code from `source`.
  563. *
  564. * @private
  565. * @param {String} source The source to process.
  566. * @param {String} funcName The name of the function to remove.
  567. * @returns {String} Returns the source with the function removed.
  568. */
  569. function removeFunction(source, funcName) {
  570. var modified,
  571. snippet = matchFunction(source, funcName);
  572. // exit early if function is not found
  573. if (!snippet) {
  574. return source;
  575. }
  576. // remove function
  577. source = source.replace(snippet, '');
  578. // grab the method assignments snippet
  579. snippet = getMethodAssignments(source);
  580. // remove assignment and aliases
  581. modified = getAliases(funcName).concat(funcName).reduce(function(result, otherName) {
  582. return result.replace(RegExp('(?:\\n *//.*\\s*)* *lodash\\.' + otherName + ' *= *.+\\n'), '');
  583. }, snippet);
  584. // replace with the modified snippet
  585. source = source.replace(snippet, modified);
  586. return removeFromCreateIterator(source, funcName);
  587. }
  588. /**
  589. * Removes the `_.isArguments` fallback from `source`.
  590. *
  591. * @private
  592. * @param {String} source The source to process.
  593. * @returns {String} Returns the source with the `isArguments` fallback removed.
  594. */
  595. function removeIsArgumentsFallback(source) {
  596. return source.replace(getIsArgumentsFallback(source), '');
  597. }
  598. /**
  599. * Removes the `_.isFunction` fallback from `source`.
  600. *
  601. * @private
  602. * @param {String} source The source to process.
  603. * @returns {String} Returns the source with the `isFunction` fallback removed.
  604. */
  605. function removeIsFunctionFallback(source) {
  606. return source.replace(getIsFunctionFallback(source), '');
  607. }
  608. /**
  609. * Removes the `Object.keys` object iteration optimization from `source`.
  610. *
  611. * @private
  612. * @param {String} source The source to process.
  613. * @returns {String} Returns the modified source.
  614. */
  615. function removeKeysOptimization(source) {
  616. return removeVar(source, 'isKeysFast')
  617. // remove optimized branch in `iteratorTemplate`
  618. .replace(/(?: *\/\/.*\n)* *'( *)<% *if *\(isKeysFast[\s\S]+?'\1<% *} *else *\{ *%>.+\n([\s\S]+?) *'\1<% *} *%>.+/, "'\\n' +\n$2")
  619. // remove data object property assignment in `createIterator`
  620. .replace(/ *'isKeysFast':.+\n/, '');
  621. }
  622. /**
  623. * Removes all `noArgsClass` references from `source`.
  624. *
  625. * @private
  626. * @param {String} source The source to process.
  627. * @returns {String} Returns the modified source.
  628. */
  629. function removeNoArgsClass(source) {
  630. return removeVar(source, 'noArgsClass')
  631. // remove `noArgsClass` from `_.clone` and `_.isEqual`
  632. .replace(/ *\|\| *\(noArgsClass *&&[^)]+?\)\)/g, '')
  633. // remove `noArgsClass` from `_.isEqual`
  634. .replace(/if *\(noArgsClass[^}]+?}\n/, '\n');
  635. }
  636. /**
  637. * Removes all `noNodeClass` references from `source`.
  638. *
  639. * @private
  640. * @param {String} source The source to process.
  641. * @returns {String} Returns the modified source.
  642. */
  643. function removeNoNodeClass(source) {
  644. return source
  645. // remove `noNodeClass` assignment
  646. .replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *try *\{(?:\s*\/\/.*)*\n *var noNodeClass[\s\S]+?catch[^}]+}\n/, '')
  647. // remove `noNodeClass` from `isPlainObject`
  648. .replace(/\(!noNodeClass *\|\|[\s\S]+?\)\) *&&/, '')
  649. // remove `noNodeClass` from `_.isEqual`
  650. .replace(/ *\|\| *\(noNodeClass *&&[\s\S]+?\)\)\)/, '');
  651. }
  652. /**
  653. * Removes a given variable from `source`.
  654. *
  655. * @private
  656. * @param {String} source The source to process.
  657. * @param {String} varName The name of the variable to remove.
  658. * @returns {String} Returns the source with the variable removed.
  659. */
  660. function removeVar(source, varName) {
  661. // simplify `cloneableClasses`
  662. if (varName == 'cloneableClasses') {
  663. source = source.replace(/(var cloneableClasses *=)[\s\S]+?(true;\n)/, '$1$2');
  664. }
  665. // simplify `hasObjectSpliceBug`
  666. if (varName == 'hasObjectSpliceBug') {
  667. source = source.replace(/(var hasObjectSpliceBug *=)[^;]+/, '$1false');
  668. }
  669. source = source.replace(RegExp(
  670. // match multi-line comment block
  671. '(?:\\n +/\\*[^*]*\\*+(?:[^/][^*]*\\*+)*/)?\\n' +
  672. // match a variable declaration that's not part of a declaration list
  673. '( *)var ' + varName + ' *= *(?:.+?(?:;|&&\\n[^;]+;)|(?:\\w+\\(|{)[\\s\\S]+?\\n\\1.+?;)\\n|' +
  674. // match a variable in a declaration list
  675. '\\n +' + varName + ' *=.+?,'
  676. ), '');
  677. // remove a varaible at the start of a variable declaration list
  678. source = source.replace(RegExp('(var +)' + varName + ' *=.+?,\\s+'), '$1');
  679. // remove a variable at the end of a variable declaration list
  680. source = source.replace(RegExp(',\\s*' + varName + ' *=.+?;'), ';');
  681. // remove variable reference from `cloneableClasses` assignments
  682. source = source.replace(RegExp('cloneableClasses\\[' + varName + '\\] *= *(?:false|true)?', 'g'), '');
  683. return removeFromCreateIterator(source, varName);
  684. }
  685. /**
  686. * Searches `source` for a `varName` variable declaration and replaces its
  687. * assigned value with `varValue`.
  688. *
  689. * @private
  690. * @param {String} source The source to inspect.
  691. * @param {String} varName The name of the variable to replace.
  692. * @returns {String} Returns the source with the variable replaced.
  693. */
  694. function replaceVar(source, varName, varValue) {
  695. // replace a variable that's not part of a declaration list
  696. var result = source.replace(RegExp(
  697. '(( *)var ' + varName + ' *= *)' +
  698. '(?:.+?;|(?:Function\\(.+?|.*?[^,])\\n[\\s\\S]+?\\n\\2.+?;)\\n'
  699. ), '$1' + varValue + ';\n');
  700. if (source == result) {
  701. // replace a varaible at the start or middle of a declaration list
  702. result = source.replace(RegExp('((?:var|\\n) +' + varName + ' *=).+?,'), '$1 ' + varValue + ',');
  703. }
  704. if (source == result) {
  705. // replace a variable at the end of a variable declaration list
  706. result = source.replace(RegExp('(,\\s*' + varName + ' *=).+?;'), '$1 ' + varValue + ';');
  707. }
  708. return result;
  709. }
  710. /**
  711. * Hard-codes the `useStrict` template option value for `iteratorTemplate`.
  712. *
  713. * @private
  714. * @param {String} source The source to process.
  715. * @param {Boolean} value The value to set.
  716. * @returns {String} Returns the modified source.
  717. */
  718. function setUseStrictOption(source, value) {
  719. // inject "use strict"
  720. if (value) {
  721. source = source.replace(/^[\s\S]*?function[^{]+{/, "$&\n 'use strict';");
  722. }
  723. // replace `useStrict` branch in `value` with hard-coded option
  724. return source.replace(/(?: *\/\/.*\n)*(\s*)' *<%.+?useStrict.+/, value ? "$1'\\'use strict\\';\\n' +" : '');
  725. }
  726. /*--------------------------------------------------------------------------*/
  727. /**
  728. * Creates a debug and/or minified build, executing the `callback` for each.
  729. * The `callback` is invoked with two arguments; (filePath, outputSource).
  730. *
  731. * Note: For a list of commands see `displayHelp()` or run `lodash --help`.
  732. *
  733. * @param {Array} [options=[]] An array of commands.
  734. * @param {Function} callback The function called per build.
  735. */
  736. function build(options, callback) {
  737. options || (options = []);
  738. // the debug version of `source`
  739. var debugSource;
  740. // used to report invalid command-line arguments
  741. var invalidArgs = _.reject(options.slice(options[0] == 'node' ? 2 : 0), function(value, index, options) {
  742. if (/^(?:-o|--output)$/.test(options[index - 1]) ||
  743. /^(?:category|exclude|exports|iife|include|moduleId|minus|plus|settings|template)=.*$/i.test(value)) {
  744. return true;
  745. }
  746. return [
  747. 'backbone',
  748. 'csp',
  749. 'legacy',
  750. 'mobile',
  751. 'strict',
  752. 'underscore',
  753. '-c', '--stdout',
  754. '-d', '--debug',
  755. '-h', '--help',
  756. '-m', '--minify',
  757. '-o', '--output',
  758. '-s', '--silent',
  759. '-V', '--version'
  760. ].indexOf(value) > -1;
  761. });
  762. // report invalid arguments
  763. if (invalidArgs.length) {
  764. console.log(
  765. '\n' +
  766. 'Invalid argument' + (invalidArgs.length > 1 ? 's' : '') +
  767. ' passed: ' + invalidArgs.join(', ')
  768. );
  769. displayHelp();
  770. return;
  771. }
  772. // display help message
  773. if (_.find(options, function(arg) {
  774. return /^(?:-h|--help)$/.test(arg);
  775. })) {
  776. displayHelp();
  777. return;
  778. }
  779. // display `lodash.VERSION`
  780. if (_.find(options, function(arg) {
  781. return /^(?:-V|--version)$/.test(arg);
  782. })) {
  783. console.log(_.VERSION);
  784. return;
  785. }
  786. /*------------------------------------------------------------------------*/
  787. // backup `dependencyMap` to restore later
  788. var dependencyBackup = _.clone(dependencyMap, true);
  789. // used to specify a custom IIFE to wrap Lo-Dash
  790. var iife = options.reduce(function(result, value) {
  791. var match = value.match(/iife=(.*)/);
  792. return match ? match[1] : result;
  793. }, null);
  794. // flag used to specify a Backbone build
  795. var isBackbone = options.indexOf('backbone') > -1;
  796. // flag used to specify a Content Security Policy build
  797. var isCSP = options.indexOf('csp') > -1 || options.indexOf('CSP') > -1;
  798. // flag used to specify only creating the debug build
  799. var isDebug = options.indexOf('-d') > -1 || options.indexOf('--debug') > -1;
  800. // flag used to specify a legacy build
  801. var isLegacy = options.indexOf('legacy') > -1;
  802. // flag used to specify an Underscore build
  803. var isUnderscore = options.indexOf('underscore') > -1;
  804. // flag used to specify only creating the minified build
  805. var isMinify = !isDebug && options.indexOf('-m') > -1 || options.indexOf('--minify')> -1;
  806. // flag used to specify a mobile build
  807. var isMobile = !isLegacy && (isCSP || isUnderscore || options.indexOf('mobile') > -1);
  808. // flag used to specify writing output to standard output
  809. var isStdOut = options.indexOf('-c') > -1 || options.indexOf('--stdout') > -1;
  810. // flag used to specify skipping status updates normally logged to the console
  811. var isSilent = isStdOut || options.indexOf('-s') > -1 || options.indexOf('--silent') > -1;
  812. // flag used to specify `_.bindAll`, `_.extend`, and `_.defaults` are
  813. // constructed using the "use strict" directive
  814. var isStrict = options.indexOf('strict') > -1;
  815. // used to specify the ways to export the `lodash` function
  816. var exportsOptions = options.reduce(function(result, value) {
  817. return /exports/.test(value) ? optionToArray(value).sort() : result;
  818. }, isUnderscore
  819. ? ['commonjs', 'global', 'node']
  820. : exportsAll.slice()
  821. );
  822. // used to specify the AMD module ID of Lo-Dash used by precompiled templates
  823. var moduleId = options.reduce(function(result, value) {
  824. var match = value.match(/moduleId=(.*)/);
  825. return match ? match[1] : result;
  826. }, 'lodash');
  827. // used to specify the output path for builds
  828. var outputPath = options.reduce(function(result, value, index) {
  829. if (/-o|--output/.test(value)) {
  830. result = options[index + 1];
  831. result = path.join(fs.realpathSync(path.dirname(result)), path.basename(result));
  832. }
  833. return result;
  834. }, '');
  835. // used to match external template files to precompile
  836. var templatePattern = options.reduce(function(result, value) {
  837. var match = value.match(/template=(.+)$/);
  838. return match
  839. ? path.join(fs.realpathSync(path.dirname(match[1])), path.basename(match[1]))
  840. : result;
  841. }, '');
  842. // used when precompiling template files
  843. var templateSettings = options.reduce(function(result, value) {
  844. var match = value.match(/settings=(.+)$/);
  845. return match
  846. ? Function('return {' + match[1].replace(/^{|}$/g, '') + '}')()
  847. : result;
  848. }, _.extend(_.clone(_.templateSettings), {
  849. 'moduleId': moduleId
  850. }));
  851. // flag used to specify a template build
  852. var isTemplate = !!templatePattern;
  853. // the lodash.js source
  854. var source = fs.readFileSync(path.join(__dirname, 'lodash.js'), 'utf8');
  855. // flag used to specify replacing Lo-Dash's `_.clone` with Underscore's
  856. var useUnderscoreClone = isUnderscore;
  857. // flags used to specify exposing Lo-Dash methods in an Underscore build
  858. var exposeForIn = !isUnderscore,
  859. exposeForOwn = !isUnderscore,
  860. exposeIsPlainObject = !isUnderscore;
  861. /*------------------------------------------------------------------------*/
  862. // names of methods to include in the build
  863. var buildMethods = !isTemplate && (function() {
  864. var result;
  865. var minusMethods = options.reduce(function(accumulator, value) {
  866. return /exclude|minus/.test(value)
  867. ? _.union(accumulator, optionToMethodsArray(source, value))
  868. : accumulator;
  869. }, []);
  870. var plusMethods = options.reduce(function(accumulator, value) {
  871. return /plus/.test(value)
  872. ? _.union(accumulator, optionToMethodsArray(source, value))
  873. : accumulator;
  874. }, []);
  875. // update dependencies
  876. if (isMobile) {
  877. dependencyMap.reduceRight = ['forEach', 'keys'];
  878. }
  879. if (isUnderscore) {
  880. dependencyMap.contains = ['indexOf', 'some'],
  881. dependencyMap.isEqual = ['isArray', 'isFunction'];
  882. dependencyMap.isEmpty = ['isArray', 'isString'];
  883. dependencyMap.max = ['forEach', 'isArray'];
  884. dependencyMap.min = ['forEach', 'isArray'];
  885. dependencyMap.pick = [];
  886. dependencyMap.template = ['defaults', 'escape'];
  887. if (useUnderscoreClone) {
  888. dependencyMap.clone = ['extend', 'isArray'];
  889. }
  890. }
  891. // add method names explicitly
  892. options.some(function(value) {
  893. return /include/.test(value) &&
  894. (result = getDependencies(optionToMethodsArray(source, value)));
  895. });
  896. // include Lo-Dash's methods if explicitly requested
  897. if (result) {
  898. exposeForIn = result.indexOf('forIn') > -1;
  899. exposeForOwn = result.indexOf('forOwn') > -1;
  900. exposeIsPlainObject = result.indexOf('isPlainObject') > -1;
  901. useUnderscoreClone = result.indexOf('clone') < 0;
  902. }
  903. // add method names required by Backbone and Underscore builds
  904. if (isBackbone && !result) {
  905. result = getDependencies(backboneDependencies);
  906. }
  907. if (isUnderscore && !result) {
  908. result = getDependencies(underscoreMethods);
  909. }
  910. // add method names by category
  911. options.some(function(value) {
  912. if (!/category/.test(value)) {
  913. return false;
  914. }
  915. // resolve method names belonging to each category (case-insensitive)
  916. var methodNames = optionToArray(value).reduce(function(accumulator, category) {
  917. var capitalized = category[0].toUpperCase() + category.toLowerCase().slice(1);
  918. return accumulator.concat(getMethodsByCategory(source, capitalized));
  919. }, []);
  920. return (result = _.union(result || [], getDependencies(methodNames)));
  921. });
  922. if (!result) {
  923. result = allMethods.slice();
  924. }
  925. if (plusMethods.length) {
  926. result = _.union(result, getDependencies(plusMethods));
  927. }
  928. if (minusMethods.length) {
  929. result = _.without.apply(_, [result].concat(minusMethods, getDependants(result)));
  930. }
  931. return result;
  932. }());
  933. /*------------------------------------------------------------------------*/
  934. // load customized Lo-Dash module
  935. var lodash = !isTemplate && (function() {
  936. var context = vm.createContext({
  937. 'clearTimeout': clearTimeout,
  938. 'console': console,
  939. 'setTimeout': setTimeout
  940. });
  941. source = setUseStrictOption(source, isStrict);
  942. if (isLegacy) {
  943. _.each(['getPrototypeOf', 'isBindFast', 'isKeysFast', 'nativeBind', 'nativeIsArray', 'nativeKeys'], function(varName) {
  944. source = replaceVar(source, varName, 'false');
  945. });
  946. source = replaceVar(source, 'noArgsClass', 'true');
  947. source = removeKeysOptimization(source);
  948. }
  949. else if (isUnderscore) {
  950. // remove unneeded variables
  951. source = removeVar(source, 'cloneableClasses');
  952. // remove large array optimizations
  953. source = removeFunction(source, 'cachedContains');
  954. source = removeVar(source, 'largeArraySize');
  955. // replace `_.clone`
  956. if (useUnderscoreClone) {
  957. source = source.replace(/^( *)function clone[\s\S]+?\n\1}/m, [
  958. ' function clone(value) {',
  959. ' return value && objectTypes[typeof value]',
  960. ' ? (isArray(value) ? slice.call(value) : extend({}, value))',
  961. ' : value',
  962. ' }'
  963. ].join('\n'));
  964. }
  965. // replace `_.contains`
  966. source = source.replace(/^( *)function contains[\s\S]+?\n\1}/m, [
  967. ' function contains(collection, target) {',
  968. ' var length = collection ? collection.length : 0;',
  969. " return typeof length == 'number'",
  970. ' ? indexOf(collection, target) > -1',
  971. ' : some(collection, function(value) { return value === target; });',
  972. ' }'
  973. ].join('\n'));
  974. // replace `_.difference`
  975. source = source.replace(/^( *)function difference[\s\S]+?\n\1}/m, [
  976. ' function difference(array) {',
  977. ' var index = -1,',
  978. ' length = array.length,',
  979. ' flattened = concat.apply(arrayRef, arguments),',
  980. ' result = [];',
  981. '',
  982. ' while (++index < length) {',
  983. ' var value = array[index]',
  984. ' if (indexOf(flattened, value, length) < 0) {',
  985. ' result.push(value);',
  986. ' }',
  987. ' }',
  988. ' return result',
  989. ' }'
  990. ].join('\n'));
  991. // replace `_.intersection`
  992. source = source.replace(/^( *)function intersection[\s\S]+?\n\1}/m, [
  993. ' function intersection(array) {',
  994. ' var args = arguments,',
  995. ' argsLength = args.length,',
  996. ' result = [];',
  997. '',
  998. ' forEach(array, function(value) {',
  999. ' if (indexOf(result, value) < 0) {',
  1000. ' var length = argsLength;',
  1001. ' while (--length) {',
  1002. ' if (indexOf(args[length], value) < 0) {',
  1003. ' return;',
  1004. ' }',
  1005. ' }',
  1006. ' result.push(value);',
  1007. ' }',
  1008. ' });',
  1009. ' return result;',
  1010. ' }'
  1011. ].join('\n'));
  1012. // replace `_.isEmpty`
  1013. source = source.replace(/^( *)function isEmpty[\s\S]+?\n\1}/m, [
  1014. ' function isEmpty(value) {',
  1015. ' if (!value) {',
  1016. ' return true;',
  1017. ' }',
  1018. ' if (isArray(value) || isString(value)) {',
  1019. ' return !value.length;',
  1020. ' }',
  1021. ' for (var key in value) {',
  1022. ' if (hasOwnProperty.call(value, key)) {',
  1023. ' return false;',
  1024. ' }',
  1025. ' }',
  1026. ' return true;',
  1027. ' }'
  1028. ].join('\n'));
  1029. // replace `_.isFinite`
  1030. source = source.replace(/^( *)function isFinite[\s\S]+?\n\1}/m, [
  1031. ' function isFinite(value) {',
  1032. ' return nativeIsFinite(value) && toString.call(value) == numberClass;',
  1033. ' }'
  1034. ].join('\n'));
  1035. // replace `_.omit`
  1036. source = source.replace(/^( *)function omit[\s\S]+?\n\1}/m, [
  1037. ' function omit(object) {',
  1038. ' var props = concat.apply(arrayRef, arguments),',
  1039. ' result = {};',
  1040. '',
  1041. ' forIn(object, function(value, key) {',
  1042. ' if (indexOf(props, key, 1) < 0) {',
  1043. ' result[key] = value;',
  1044. ' }',
  1045. ' });',
  1046. ' return result;',
  1047. ' }'
  1048. ].join('\n'));
  1049. // replace `_.pick`
  1050. source = source.replace(/^( *)function pick[\s\S]+?\n\1}/m, [
  1051. ' function pick(object) {',
  1052. ' var index = 0,',
  1053. ' props = concat.apply(arrayRef, arguments),',
  1054. ' length = props.length,',
  1055. ' result = {};',
  1056. '',
  1057. ' while (++index < length) {',
  1058. ' var prop = props[index];',
  1059. ' if (prop in object) {',
  1060. ' result[prop] = object[prop];',
  1061. ' }',
  1062. ' }',
  1063. ' return result;',
  1064. ' }'
  1065. ].join('\n'));
  1066. // replace `_.uniq`
  1067. source = source.replace(/^( *)function uniq[\s\S]+?\n\1}/m, [
  1068. ' function uniq(array, isSorted, callback, thisArg) {',
  1069. ' var index = -1,',
  1070. ' length = array ? array.length : 0,',
  1071. ' result = [],',
  1072. ' seen = result;',
  1073. '',
  1074. ' if (callback) {',
  1075. ' seen = [];',
  1076. ' callback = createCallback(callback, thisArg);',
  1077. ' }',
  1078. ' while (++index < length) {',
  1079. ' var value = array[index],',
  1080. ' computed = callback ? callback(value, index, array) : value;',
  1081. '',
  1082. ' if (isSorted',
  1083. ' ? !index || seen[seen.length - 1] !== computed',
  1084. ' : indexOf(seen, computed) < 0',
  1085. ' ) {',
  1086. ' if (callback) {',
  1087. ' seen.push(computed);',
  1088. ' }',
  1089. ' result.push(value);',
  1090. ' }',
  1091. ' }',
  1092. ' return result;',
  1093. ' }'
  1094. ].join('\n'));
  1095. // replace `_.without`
  1096. source = source.replace(/^( *)function without[\s\S]+?\n\1}/m, [
  1097. ' function without(array) {',
  1098. ' var index = -1,',
  1099. ' length = array.length,',
  1100. ' result = [];',
  1101. '',
  1102. ' while (++index < length) {',
  1103. ' var value = array[index]',
  1104. ' if (indexOf(arguments, value, 1) < 0) {',
  1105. ' result.push(value);',
  1106. ' }',
  1107. ' }',
  1108. ' return result',
  1109. ' }'
  1110. ].join('\n'));
  1111. // remove `arguments` object check from `_.isEqual`
  1112. source = source.replace(/ *\|\| *className *== *argsClass/, '');
  1113. // simplify DOM node check from `_.isEqual`
  1114. source = source.replace(/(if *\(className *!= *objectClass).+?noNodeClass[\s\S]+?{/, '$1) {');
  1115. // remove conditional `charCodeCallback` use from `_.max` and `_.min`
  1116. source = source.replace(/!callback *&& *isString\(collection\)[\s\S]+?: */g, '');
  1117. // remove unused features from `createBound`
  1118. if (buildMethods.indexOf('partial') == -1) {
  1119. source = source.replace(matchFunction(source, 'createBound'), function(match) {
  1120. return match
  1121. .replace(/(function createBound\([^{]+{)[\s\S]+?(\n *function bound)/, '$1$2')
  1122. .replace(/thisBinding *=[^}]+}/, 'thisBinding = thisArg;\n');
  1123. });
  1124. }
  1125. }
  1126. if (isMobile) {
  1127. source = replaceVar(source, 'isKeysFast', 'false');
  1128. source = removeKeysOptimization(source);
  1129. // remove `prototype` [[Enumerable]] fix from `_.keys`
  1130. source = source.replace(/(?:\s*\/\/.*)*(\s*return *).+?propertyIsEnumerable[\s\S]+?: */, '$1');
  1131. // remove `prototype` [[Enumerable]] fix from `iteratorTemplate`
  1132. source = source
  1133. .replace(/(?: *\/\/.*\n)* *' *(?:<% *)?if *\(!hasDontEnumBug *(?:&&|\))[\s\S]+?<% *} *(?:%>|').+/g, '')
  1134. .replace(/!hasDontEnumBug *\|\|/g, '');
  1135. }
  1136. vm.runInContext(source, context);
  1137. return context._;
  1138. }());
  1139. /*------------------------------------------------------------------------*/
  1140. if (isTemplate) {
  1141. source = buildTemplate(templatePattern, templateSettings);
  1142. }
  1143. else {
  1144. // simplify template snippets by removing unnecessary brackets
  1145. source = source.replace(
  1146. RegExp("{(\\\\n' *\\+\\s*.*?\\+\\n\\s*' *)}(?:\\\\n)?' *([,\\n])", 'g'), "$1'$2"
  1147. );
  1148. source = source.replace(
  1149. RegExp("{(\\\\n' *\\+\\s*.*?\\+\\n\\s*' *)}(?:\\\\n)?' *\\+", 'g'), "$1;\\n'+"
  1150. );
  1151. // remove methods from the build
  1152. allMethods.forEach(function(otherName) {
  1153. if (!_.contains(buildMethods, otherName)) {
  1154. source = removeFunction(source, otherName);
  1155. }
  1156. });
  1157. // remove `isArguments` fallback before `isArguments` is transformed by
  1158. // other parts of the build process
  1159. if (isRemoved(source, 'isArguments')) {
  1160. source = removeIsArgumentsFallback(source);
  1161. }
  1162. /*----------------------------------------------------------------------*/
  1163. if (isLegacy) {
  1164. _.each(['isBindFast', 'nativeBind', 'nativeIsArray', 'nativeKeys'], function(varName) {
  1165. source = removeVar(source, varName);
  1166. });
  1167. _.each(['bind', 'isArray'], function(methodName) {
  1168. var snippet = matchFunction(source, methodName),
  1169. modified = snippet;
  1170. // remove native `Function#bind` branch in `_.bind`
  1171. if (methodName == 'bind') {
  1172. modified = modified.replace(/(?:\s*\/\/.*)*\s*return isBindFast[^:]+:\s*/, 'return ');
  1173. }
  1174. // remove native `Array.isArray` branch in `_.isArray`
  1175. else {
  1176. modified = modified.replace(/nativeIsArray * \|\|/, '');
  1177. }
  1178. source = source.replace(snippet, modified);
  1179. });
  1180. // replace `_.keys` with `shimKeys`
  1181. if (!isRemoved(source, 'keys')) {
  1182. source = source.replace(
  1183. matchFunction(source, 'keys').replace(/[\s\S]+?var keys *= */, ''),
  1184. matchFunction(source, 'shimKeys').replace(/[\s\S]+?function shimKeys/, 'function').replace(/}\n$/, '};\n')
  1185. );
  1186. source = removeFunction(source, 'shimKeys');
  1187. }
  1188. // replace `_.isArguments` with fallback
  1189. if (!isRemoved(source, 'isArguments')) {
  1190. source = source.replace(
  1191. matchFunction(source, 'isArguments').replace(/[\s\S]+?function isArguments/, ''),
  1192. getIsArgumentsFallback(source).match(/isArguments *= *function([\s\S]+?) *};/)[1] + ' }\n'
  1193. );
  1194. source = removeIsArgumentsFallback(source);
  1195. }
  1196. source = removeVar(source, 'reNative');
  1197. source = removeFromCreateIterator(source, 'nativeKeys');
  1198. }
  1199. /*----------------------------------------------------------------------*/
  1200. if (isMobile) {
  1201. // inline all functions defined with `createIterator`
  1202. _.functions(lodash).forEach(function(methodName) {
  1203. var reFunc = RegExp('(\\bvar ' + methodName + ' *= *)createIterator\\(((?:{|[a-zA-Z])[\\s\\S]+?)\\);\\n');
  1204. // skip if not defined with `createIterator`
  1205. if (!reFunc.test(source)) {
  1206. return;
  1207. }
  1208. // extract, format, and inject the compiled function's source code
  1209. source = source.replace(reFunc, '$1' + getFunctionSource(lodash[methodName]) + ';\n');
  1210. });
  1211. if (isUnderscore) {
  1212. // remove `_.forIn`, `_.forOwn`, and `_.isPlainObject` assignments
  1213. (function() {
  1214. var snippet = getMethodAssignments(source),
  1215. modified = snippet;
  1216. if (!exposeForIn) {
  1217. modified = modified.replace(/(?:\n *\/\/.*\s*)* *lodash\.forIn *= *.+\n/, '');
  1218. }
  1219. if (!exposeForOwn) {
  1220. modified = modified.replace(/(?:\n *\/\/.*\s*)* *lodash\.forOwn *= *.+\n/, '');
  1221. }
  1222. if (!exposeIsPlainObject) {
  1223. modified = modified.replace(/(?:\n *\/\/.*\s*)* *lodash\.isPlainObject *= *.+\n/, '');
  1224. }
  1225. source = source.replace(snippet, modified);
  1226. }());
  1227. // replace `isArguments` and its fallback
  1228. (function() {
  1229. var snippet = matchFunction(source, 'isArguments')
  1230. .replace(/function isArguments/, 'lodash.isArguments = function');
  1231. source = removeFunction(source, 'isArguments');
  1232. source = source.replace(getIsArgumentsFallback(source), function(match) {
  1233. return snippet + '\n' + match
  1234. .replace(/\bisArguments\b/g, 'lodash.$&')
  1235. .replace(/\bnoArgsClass\b/g, '!lodash.isArguments(arguments)');
  1236. });
  1237. }());
  1238. // remove chainability from `_.forEach`
  1239. source = source.replace(matchFunction(source, 'forEach'), function(match) {
  1240. return match.replace(/return result([};\s]+)$/, '$1');
  1241. });
  1242. // unexpose "exit early" feature from `_.forEach`, `_.forIn`, and `_.forOwn`
  1243. _.each(['forEach', 'forIn', 'forOwn'], function(methodName) {
  1244. source = source.replace(matchFunction(source, methodName), function(match) {
  1245. return match.replace(/=== *false\)/g, '=== indicatorObject)');
  1246. });
  1247. });
  1248. // modify `_.every` and `_.some` to use the private `indicatorObject`
  1249. source = source.replace(matchFunction(source, 'every'), function(match) {
  1250. return match.replace(/\(result *= *(.+?)\);/, '!(result = $1) && indicatorObject;');
  1251. });
  1252. source = source.replace(matchFunction(source, 'some'), function(match) {
  1253. return match.replace(/!\(result *= *(.+?)\);/, '(result = $1) && indicatorObject;');
  1254. });
  1255. // replace `_.template`
  1256. source = source.replace(/^( *)function template[\s\S]+?\n\1}/m, function() {
  1257. return [
  1258. ' function template(text, data, options) {',
  1259. " text || (text = '');",
  1260. ' options = defaults({}, options, lodash.templateSettings);',
  1261. '',
  1262. ' var index = 0,',
  1263. ' source = "__p += \'",',
  1264. ' variable = options.variable;',
  1265. '',
  1266. ' var reDelimiters = RegExp(',
  1267. " (options.escape || reNoMatch).source + '|' +",
  1268. " (options.interpolate || reNoMatch).source + '|' +",
  1269. " (options.evaluate || reNoMatch).source + '|$'",
  1270. " , 'g');",
  1271. '',
  1272. ' text.replace(reDelimiters, function(match, escapeValue, interpolateValue, evaluateValue, offset) {',
  1273. ' source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);',
  1274. ' source +=',
  1275. ' escapeValue ? "\' +\\n_.escape(" + escapeValue + ") +\\n\'" :',
  1276. ' evaluateVal…

Large files files are truncated, but you can click here to view the full file