Add removeComments, removePseudoPrivate, and track more private properties and other dependencies in build.js.

Former-commit-id: 66a9d849080d20549bbdfda7965db1b31ac5388c
This commit is contained in:
John-David Dalton
2013-06-17 23:21:34 -07:00
parent 600148f501
commit 512e5b0240

147
build.js
View File

@@ -105,7 +105,7 @@
'findKey': ['createCallback', 'forOwn'], 'findKey': ['createCallback', 'forOwn'],
'first': ['slice'], 'first': ['slice'],
'flatten': ['isArray', 'overloadWrapper'], 'flatten': ['isArray', 'overloadWrapper'],
'forEach': ['basicEach', 'createCallback', 'isArguments', 'isArray', 'isString', 'keys'], 'forEach': ['basicEach', 'createCallback', 'isArray'],
'forIn': ['createCallback', 'createIterator', 'isArguments'], 'forIn': ['createCallback', 'createIterator', 'isArguments'],
'forOwn': ['createCallback', 'createIterator', 'isArguments', 'keys'], 'forOwn': ['createCallback', 'createIterator', 'isArguments', 'keys'],
'functions': ['forIn', 'isFunction'], 'functions': ['forIn', 'isFunction'],
@@ -219,17 +219,29 @@
/** Used to track property dependencies */ /** Used to track property dependencies */
var propDependencyMap = { var propDependencyMap = {
'assign': ['objectTypes'],
'at': ['support'], 'at': ['support'],
'basicEach': ['objectTypes'],
'bind': ['support'], 'bind': ['support'],
'bindKey': ['indicatorObject'],
'clone': ['support'], 'clone': ['support'],
'createCallback': ['indicatorObject'],
'defaults': ['objectTypes'],
'forIn': ['objectTypes'],
'forOwn': ['objectTypes'],
'isArguments': ['support'], 'isArguments': ['support'],
'isEmpty': ['support'], 'isEmpty': ['indicatorObject', 'support'],
'isEqual': ['support'], 'isEqual': ['support'],
'isObject': ['objectTypes'],
'isPlainObject': ['support'], 'isPlainObject': ['support'],
'isRegExp': ['objectTypes'],
'iteratorTemplate': ['support'], 'iteratorTemplate': ['support'],
'keys': ['support'], 'keys': ['support'],
'merge': ['indicatorObject'],
'partialRight': ['indicatorObject'],
'reduceRight': ['support'], 'reduceRight': ['support'],
'shimIsPlainObject': ['support'], 'shimIsPlainObject': ['support'],
'shimKeys': ['objectTypes'],
'template': ['templateSettings'], 'template': ['templateSettings'],
'toArray': ['support'] 'toArray': ['support']
}; };
@@ -695,21 +707,25 @@
* @returns {String} Returns the modified source. * @returns {String} Returns the modified source.
*/ */
function cleanupSource(source) { function cleanupSource(source) {
source = removePseudoPrivate(source);
return source return source
// remove pseudo private properties // consolidate consecutive horizontal rule comment separators
.replace(/(?:(?:\s*\/\/.*)*\s*lodash\._[^=]+=.+\n)+/g, '\n') .replace(/(?:\s*\/\*-+\*\/\s*){2,}/g, function(separators) {
return separators.match(/^\s*/)[0] + separators.slice(separators.lastIndexOf('/*'));
})
// remove unneeded single line comments
.replace(/(\{\s*)?(\n *\/\/.*)(\s*\})/g, function(match, prelude, comment, postlude) {
return (!prelude && postlude) ? postlude : match;
})
// remove unneeded horizontal rule comment separators
.replace(/(\{\n)\s*\/\*-+\*\/\n|^ *\/\*-+\*\/\n(\s*\})/gm, '$1$2')
// remove extraneous whitespace // remove extraneous whitespace
.replace(/^ *\n/gm, '\n') .replace(/^ *\n/gm, '\n')
// remove lines with just whitespace and semicolons // remove lines with just whitespace and semicolons
.replace(/^ *;\n/gm, '') .replace(/^ *;\n/gm, '')
// consolidate multiple newlines // consolidate multiple newlines
.replace(/\n{3,}/g, '\n\n') .replace(/\n{3,}/g, '\n\n');
// consolidate consecutive horizontal rule comment separators
.replace(/(?:\s*\/\*-+\*\/\s*){2,}/g, function(separators) {
return separators.match(/^\s*/)[0] + separators.slice(separators.lastIndexOf('/*'));
})
// remove unneeded horizontal rule comment separators
.replace(/(\{\n)\s*\/\*-+\*\/\n|\n *\/\*-+\*\/\n(\s*\})/gm, '$1$2');
} }
/** /**
@@ -843,17 +859,21 @@
* *
* @private * @private
* @param {Array|String} methodName A method name or array of dependencies to query. * @param {Array|String} methodName A method name or array of dependencies to query.
* @param {Boolean} [isShallow=false] A flag to indicate getting only the immediate dependencies.
* @param- {Object} [stackA=[]] Internally used track queried methods. * @param- {Object} [stackA=[]] Internally used track queried methods.
* @returns {Array} Returns an array of method dependencies. * @returns {Array} Returns an array of method dependencies.
*/ */
function getDependencies(methodName, stack) { function getDependencies(methodName, isShallow, stack) {
var dependencies = _.isArray(methodName) var dependencies = _.isArray(methodName)
? methodName ? methodName
: (hasOwnProperty.call(dependencyMap, methodName) && dependencyMap[methodName]); : (hasOwnProperty.call(dependencyMap, methodName) && dependencyMap[methodName]);
if (!dependencies) { if (!dependencies || !dependencies.length) {
return []; return [];
} }
if (isShallow) {
return dependencies.slice();
}
stack || (stack = []); stack || (stack = []);
// recursively accumulate the dependencies of the `methodName` function, and // recursively accumulate the dependencies of the `methodName` function, and
@@ -861,7 +881,7 @@
return _.uniq(dependencies.reduce(function(result, otherName) { return _.uniq(dependencies.reduce(function(result, otherName) {
if (!_.contains(stack, otherName)) { if (!_.contains(stack, otherName)) {
stack.push(otherName); stack.push(otherName);
result.push.apply(result, getDependencies(otherName, stack).concat(otherName)); result.push.apply(result, getDependencies(otherName, isShallow, stack).concat(otherName));
} }
return result; return result;
}, [])); }, []));
@@ -1034,9 +1054,9 @@
function getVars(source) { function getVars(source) {
var indentA = isRemoved(source, 'runInContext') ? ' {2}' : ' {2,4}', var indentA = isRemoved(source, 'runInContext') ? ' {2}' : ' {2,4}',
indentB = isRemoved(source, 'runInContext') ? ' {6}' : ' {6,8}', indentB = isRemoved(source, 'runInContext') ? ' {6}' : ' {6,8}',
snippet = source.replace(/^ *(?:\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/|\/\/.+)\n/gm, ''),
result = []; result = [];
var snippet = removeComments(source);
snippet.replace(RegExp( snippet.replace(RegExp(
'^(' + indentA + ')var (\\w+) *(?:|= *(?:.+?(?:|&&\\n[^;]+)|(?:\\w+\\(|[{[(]\\n)[\\s\\S]+?\\n\\1[^\\n ]+?));\\n|' + '^(' + indentA + ')var (\\w+) *(?:|= *(?:.+?(?:|&&\\n[^;]+)|(?:\\w+\\(|[{[(]\\n)[\\s\\S]+?\\n\\1[^\\n ]+?));\\n|' +
'^' + indentA + 'var (\\w+) *=.+?,\\n(?= *\\w+ *=)|' + '^' + indentA + 'var (\\w+) *=.+?,\\n(?= *\\w+ *=)|' +
@@ -1081,11 +1101,8 @@
var indentA = isShallow ? ' {2}' : ' {2,4}', var indentA = isShallow ? ' {2}' : ' {2,4}',
indentB = isShallow ? ' {6}' : ' {6,8}'; indentB = isShallow ? ' {6}' : ' {6,8}';
var snippet = source var snippet = removePseudoPrivate(source);
// remove comments snippet = removeComments(source);
.replace(/^ *(?:\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/|\/\/.+)\n/gm, '')
// remove pseudo private properties
.replace(/^ *lodash\._[^=]+=.+\n/gm, '');
var match = RegExp( var match = RegExp(
'^(' + indentA + ')var ' + varName + ' *(?:|= *(?:.+?(?:|&&\\n[^;]+)|(?:\\w+\\(|[{[(]\\n)[\\s\\S]+?\\n\\1[^\\n ]+?));\\n|' + '^(' + indentA + ')var ' + varName + ' *(?:|= *(?:.+?(?:|&&\\n[^;]+)|(?:\\w+\\(|[{[(]\\n)[\\s\\S]+?\\n\\1[^\\n ]+?));\\n|' +
@@ -1097,6 +1114,7 @@
if (!match) { if (!match) {
return false; return false;
} }
// remove the variable assignment from the source
snippet = snippet.slice(0, match.index) + snippet.slice(match.index + match[0].length); snippet = snippet.slice(0, match.index) + snippet.slice(match.index + match[0].length);
return RegExp('[^.\\w"\']' + varName + '\\b').test(snippet); return RegExp('[^.\\w"\']' + varName + '\\b').test(snippet);
} }
@@ -1171,6 +1189,17 @@
return _.uniq(_.intersection(allMethods, methodNames)); return _.uniq(_.intersection(allMethods, methodNames));
} }
/**
* Removes all comments from `source`.
*
* @private
* @param {String} source The source to process.
* @returns {String} Returns the modified source.
*/
function removeComments(source) {
return source.replace(/^ *(?:\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/|\/\/.+)\n/gm, '');
}
/** /**
* Removes all references to `identifier` from `createIterator` in `source`. * Removes all references to `identifier` from `createIterator` in `source`.
* *
@@ -1260,15 +1289,13 @@
source = source.replace(snippet, ''); source = source.replace(snippet, '');
} }
snippet = getMethodAssignments(source);
source = removePseudoPrivate(source, funcName);
// remove method assignment from `lodash.prototype` // remove method assignment from `lodash.prototype`
source = source.replace(RegExp('^ *lodash\\.prototype\\.' + funcName + ' *=[\\s\\S]+?;\\n', 'm'), ''); source = source.replace(RegExp('^ *lodash\\.prototype\\.' + funcName + ' *=[\\s\\S]+?;\\n', 'm'), '');
// remove pseudo private methods
source = source.replace(RegExp('^(?: *//.*\\s*)* *lodash\\._' + funcName + ' *=[\\s\\S]+?;\\n', 'm'), '');
// grab the method assignments snippet
snippet = getMethodAssignments(source);
// remove assignment and aliases // remove assignment and aliases
var modified = getAliases(funcName).concat(funcName).reduce(function(result, otherName) { var modified = getAliases(funcName).concat(funcName).reduce(function(result, otherName) {
return result.replace(RegExp('^(?: *//.*\\s*)* *lodash\\.' + otherName + ' *=[\\s\\S]+?;\\n', 'm'), ''); return result.replace(RegExp('^(?: *//.*\\s*)* *lodash\\.' + otherName + ' *=[\\s\\S]+?;\\n', 'm'), '');
@@ -1379,6 +1406,20 @@
return source; return source;
} }
/**
* Removes the specified pseudo private property from `source`. If a `propName`
* is not specified, all pseudo private properties are removed.
*
* @private
* @param {String} source The source to process.
* @param {String} [funcName] The name of the property to remove.
* @returns {String} Returns the modified source.
*/
function removePseudoPrivate(source, propName) {
propName || (propName = '\\w+');
return source.replace(RegExp('^(?: *//.*\\s*)* *lodash\\._' + propName + ' *=[\\s\\S]+?;\\n', 'gm'), '');
}
/** /**
* Removes all `runInContext` references from `source`. * Removes all `runInContext` references from `source`.
* *
@@ -2131,6 +2172,22 @@
dependencyMap.createCallback = _.without(dependencyMap.createCallback, 'isEqual'); dependencyMap.createCallback = _.without(dependencyMap.createCallback, 'isEqual');
dependencyMap.where.push('find', 'isEmpty'); dependencyMap.where.push('find', 'isEmpty');
} }
if (!useLodashMethod('forOwn')) {
_.each(['contains', 'every', 'find', 'transform', 'forOwn', 'some'], function(methodName) {
(propDependencyMap[methodName] || (propDependencyMap[methodName] = [])).push('indicatorObject');
});
}
if (!useLodashMethod('forIn')) {
_.each(['isEqual', 'shimIsPlainObject'], function(methodName) {
(propDependencyMap[methodName] || (propDependencyMap[methodName] = [])).push('indicatorObject');
});
}
_.each(['basicEach', 'forEach', 'forIn', 'forOwn'], function(methodName) {
if (methodName == 'basicEach' || !useLodashMethod(methodName)) {
(propDependencyMap[methodName] || (propDependencyMap[methodName] = [])).push('indicatorObject');
}
});
_.each(['clone', 'difference', 'intersection', 'isEqual', 'sortBy', 'uniq'], function(methodName) { _.each(['clone', 'difference', 'intersection', 'isEqual', 'sortBy', 'uniq'], function(methodName) {
if (methodName == 'clone' if (methodName == 'clone'
@@ -2141,6 +2198,15 @@
} }
}); });
_.each(['clone', 'first', 'initial', 'last', 'rest', 'toArray'], function(methodName) {
if (methodName == 'clone'
? (!useLodashMethod('clone') && !useLodashMethod('cloneDeep'))
: !useLodashMethod(methodName)
) {
dependencyMap[methodName] = _.without(dependencyMap[methodName], 'slice');
}
});
_.each(['debounce', 'throttle'], function(methodName) { _.each(['debounce', 'throttle'], function(methodName) {
if (!useLodashMethod(methodName)) { if (!useLodashMethod(methodName)) {
dependencyMap[methodName] = []; dependencyMap[methodName] = [];
@@ -2193,6 +2259,16 @@
}); });
if (!isMobile) { if (!isMobile) {
_.each(['clone', 'transform', 'value'], function(methodName) {
dependencyMap[methodName] = _.without(dependencyMap[methodName], 'basicEach');
dependencyMap[methodName].push('forEach');
});
_.each(['contains', 'every', 'filter', 'find', 'forEach', 'map', 'max', 'min', 'reduce', 'some'], function(methodName) {
dependencyMap[methodName] = _.without(dependencyMap[methodName], 'basicEach');
dependencyMap[methodName].push('forOwn');
});
_.each(['every', 'find', 'filter', 'forEach', 'forIn', 'forOwn', 'map', 'reduce'], function(methodName) { _.each(['every', 'find', 'filter', 'forEach', 'forIn', 'forOwn', 'map', 'reduce'], function(methodName) {
if (!(isUnderscore && useLodashMethod(methodName))) { if (!(isUnderscore && useLodashMethod(methodName))) {
dependencyMap[methodName] = _.without(dependencyMap[methodName], 'isArguments', 'isArray'); dependencyMap[methodName] = _.without(dependencyMap[methodName], 'isArguments', 'isArray');
@@ -3136,12 +3212,9 @@
source = addChainMethods(source); source = addChainMethods(source);
} }
// replace `basicEach` references with `forEach` and `forOwn` // replace `basicEach` references with `forEach` and `forOwn`
if ((isUnderscore || (isModern && !isMobile)) && if (isUnderscore || (isModern && !isMobile)) {
_.contains(buildMethods, 'forEach') && _.contains(buildMethods, 'forOwn')) {
source = removeFunction(source, 'basicEach'); source = removeFunction(source, 'basicEach');
source = removePseudoPrivate(source, 'basicEach');
// remove `lodash._basicEach` pseudo property
source = source.replace(/^ *lodash\._basicEach *=[\s\S]+?;\n/m, '');
// replace `basicEach` with `_.forOwn` in "Collections" methods // replace `basicEach` with `_.forOwn` in "Collections" methods
source = source.replace(/\bbasicEach(?=\(collection)/g, 'forOwn'); source = source.replace(/\bbasicEach(?=\(collection)/g, 'forOwn');
@@ -3219,7 +3292,7 @@
}); });
// modify `_.contains`, `_.every`, `_.find`, `_.some`, and `_.transform` to use the private `indicatorObject` // modify `_.contains`, `_.every`, `_.find`, `_.some`, and `_.transform` to use the private `indicatorObject`
if (isUnderscore && (/\bbasicEach\(/.test(source) || !useLodashMethod('forOwn'))) { if (isUnderscore && !useLodashMethod('forOwn')) {
source = source.replace(matchFunction(source, 'every'), function(match) { source = source.replace(matchFunction(source, 'every'), function(match) {
return match.replace(/\(result *= *(.+?)\);/g, '!(result = $1) && indicatorObject;'); return match.replace(/\(result *= *(.+?)\);/g, '!(result = $1) && indicatorObject;');
}); });
@@ -3494,12 +3567,6 @@
} }
}); });
if (!/\bbasicEach\(/.test(source)) {
source = removeFunction(source, 'basicEach');
}
if (_.size(source.match(/[^.]slice\(/g)) < 2) {
source = removeFunction(source, 'slice');
}
if (!/^ *support\.(?:enumErrorProps|nonEnumShadows) *=/m.test(source)) { if (!/^ *support\.(?:enumErrorProps|nonEnumShadows) *=/m.test(source)) {
source = removeFromCreateIterator(source, 'errorClass'); source = removeFromCreateIterator(source, 'errorClass');
source = removeFromCreateIterator(source, 'errorProto'); source = removeFromCreateIterator(source, 'errorProto');
@@ -3581,8 +3648,8 @@
var outputUsed = false; var outputUsed = false;
// flag to specify creating a custom build // flag to specify creating a custom build
var isCustom = ( var isCustom = !isNoDep && (
isLegacy || isMapped || isModern || isNoDep || isStrict || isUnderscore || outputPath || isLegacy || isMapped || isModern || isStrict || isUnderscore || outputPath ||
/(?:category|exclude|exports|iife|include|minus|plus)=.*$/.test(options) || /(?:category|exclude|exports|iife|include|minus|plus)=.*$/.test(options) ||
!_.isEqual(exportsOptions, exportsAll) !_.isEqual(exportsOptions, exportsAll)
); );