Make matchFunction and matchProp ignore leading comments by default, make removeProp remove variable assignments too, and ensure inline require calls have the correct dependency paths.

Former-commit-id: 47e265e550ca863af5902c07df63809f47c1f96d
This commit is contained in:
John-David Dalton
2013-07-16 09:07:42 -07:00
parent e385b3499b
commit 854ea26ab7
2 changed files with 94 additions and 96 deletions

188
build.js
View File

@@ -623,7 +623,7 @@
*/ */
function addUnderscoreChaining(source) { function addUnderscoreChaining(source) {
// add `_.chain` // add `_.chain`
source = source.replace(matchFunction(source, 'tap'), function(match) { source = source.replace(matchFunction(source, 'tap', true), function(match) {
var indent = getIndent(match); var indent = getIndent(match);
return match && (indent + [ return match && (indent + [
'', '',
@@ -660,7 +660,7 @@
}); });
// add `wrapperChain` // add `wrapperChain`
source = source.replace(matchFunction(source, 'wrapperToString'), function(match) { source = source.replace(matchFunction(source, 'wrapperToString', true), function(match) {
var indent = getIndent(match); var indent = getIndent(match);
return match && (indent + [ return match && (indent + [
'', '',
@@ -831,16 +831,21 @@
'support': true 'support': true
}; };
var getDepPaths = function(dependencies, fromPath) { var getDepPath = function(dep, fromPath) {
fromPath || (fromPath = ''); fromPath || (fromPath = '');
return dependencies.map(function(dep) {
var toPath = getPath(dep),
relative = path.relative(fromPath, toPath).replace(RegExp(path.sepEscaped, 'g'), sep);
if (relative.charAt(0) != '.') { var toPath = getPath(dep),
relative = '.' + (relative ? sep + relative : ''); relative = path.relative(fromPath, toPath).replace(RegExp(path.sepEscaped, 'g'), sep);
}
return relative + sep + dep; if (relative.charAt(0) != '.') {
relative = '.' + (relative ? sep + relative : '');
}
return relative + sep + dep;
};
var getDepPaths = function(dependencies, fromPath) {
return dependencies.map(function(dep) {
return getDepPath(dep, fromPath);
}); });
}; };
@@ -881,11 +886,11 @@
'iife=' + iife.join('\n'), 'iife=' + iife.join('\n'),
'-o', path.join(outputPath, modulePath + identifier + '.js') '-o', path.join(outputPath, modulePath + identifier + '.js')
), function(data) { ), function(data) {
// replace deps inline // replace circular dependencies inline
_.each(circDeps, function(dep) { _.each(circDeps, function(dep) {
// avoid identifiers in strings // avoid identifiers in strings
data.source = data.source.replace(RegExp('(["\'])(?:(?!\\1)[^\\n\\\\]|\\\\.)*\\1|\\b' + dep + '\\b', 'g'), function(match) { data.source = data.source.replace(RegExp('(["\'])(?:(?!\\1)[^\\n\\\\]|\\\\.)*\\1|\\b' + dep + '\\b', 'g'), function(match) {
return /^["']/.test(match) ? match : "require('" + match + "')"; return /^["']/.test(match) ? match : "require('" + getDepPath(match, modulePath) + "')";
}); });
}); });
defaultBuildCallback(data); defaultBuildCallback(data);
@@ -1465,30 +1470,31 @@
* @private * @private
* @param {String} source The source to inspect. * @param {String} source The source to inspect.
* @param {String} funcName The name of the function to match. * @param {String} funcName The name of the function to match.
* @param {Boolean} [leadingComments] A flag to indicate including leading comments.
* @returns {String} Returns the matched function snippet. * @returns {String} Returns the matched function snippet.
*/ */
function matchFunction(source, funcName) { function matchFunction(source, funcName, leadingComments) {
var result = _.reduce([ var result = _.reduce([
// match variable declarations with `createIterator` and `template` // match variable declarations with `createIterator` and `template`
'( *)var ' + funcName + ' *=.*?(?:createIterator|template)\\((?:.+|[\\s\\S]+?\\n\\1}?)\\);\\n', '( *)var ' + funcName + ' *=.*?(?:createIterator|template)\\((?:.+|[\\s\\S]+?\\n\\3}?)\\);\\n',
// match a function declaration // match a function declaration
'( *)function ' + funcName + '\\b[\\s\\S]+?\\n\\1}\\n', '( *)function ' + funcName + '\\b[\\s\\S]+?\\n\\3}\\n',
// match a variable declaration with function expression // match a variable declaration with function expression
'( *)var ' + funcName + ' *=.*?function\\(.+?\{\\n[\\s\\S]+?\\n\\1}(?:\\(\\)\\))?;\\n', '( *)var ' + funcName + ' *=.*?function\\(.+?\{\\n[\\s\\S]+?\\n\\3}(?:\\(\\)\\))?;\\n',
// match a simple variable declaration // match a simple variable declaration
'( *)var ' + funcName + ' *=.+?;\\n' ' *var ' + funcName + ' *=.+?;\\n'
], function(result, reSource) { ], function(result, reSource) {
return result || (result = source.match(RegExp( return result || (result = source.match(RegExp(
multilineComment + '(' + multilineComment + ')' +
reSource '(' + reSource + ')'
))) && result[0]; ))) && result.slice(1, 3);
}, null); }, null);
if (/@type +Function\b/.test(result) || return result && (
/(?:function(?:\s+\w+)?\b|createIterator|template)\(/.test(result)) { /@type +Function\b/.test(result[0]) ||
return result; /(?:function(?:\s+\w+)?\b|createIterator|template)\(/.test(result[1]))
} ? (leadingComments ? result[0] : '') + result[1]
return ''; : '';
} }
/** /**
@@ -1498,11 +1504,12 @@
* @private * @private
* @param {String} source The source to inspect. * @param {String} source The source to inspect.
* @param {String} propName The name of the property to match. * @param {String} propName The name of the property to match.
* @param {Boolean} [leadingComments] A flag to indicate including leading comments.
* @returns {String} Returns the matched property snippet. * @returns {String} Returns the matched property snippet.
*/ */
function matchProp(source, propName) { function matchProp(source, propName, leadingComments) {
var result = source.match(RegExp( var result = source.match(RegExp(
multilineComment + (leadingComments ? multilineComment : '\\n') +
'(?: *|.*?=\\s*)lodash\\._?' + propName + '\\s*=[\\s\\S]+?' + '(?: *|.*?=\\s*)lodash\\._?' + propName + '\\s*=[\\s\\S]+?' +
'(?:\\(function[\\s\\S]+?\\([^)]*\\)\\);\\n(?=\\n)|' + '(?:\\(function[\\s\\S]+?\\([^)]*\\)\\);\\n(?=\\n)|' +
'[;}]\\n(?=\\n(?!\\s*\\(func)))' '[;}]\\n(?=\\n(?!\\s*\\(func)))'
@@ -1695,7 +1702,7 @@
return removeRunInContext(source, funcName); return removeRunInContext(source, funcName);
} }
// remove function // remove function
if ((snippet = matchFunction(source, funcName))) { if ((snippet = matchFunction(source, funcName, true))) {
source = source.replace(snippet, ''); source = source.replace(snippet, '');
} }
@@ -1857,14 +1864,7 @@
* @returns {String} Returns the modified source. * @returns {String} Returns the modified source.
*/ */
function removeProp(source, propName) { function removeProp(source, propName) {
return source.replace(matchProp(source, propName), function(match) { return source.replace(matchProp(source, propName, true), '');
var snippet = RegExp(
multilineComment +
'.*?=\\s*(?=lodash\\._?' + propName + '\\s*=)'
).exec(match);
return snippet ? snippet[0] + 'undefined;\n' : '';
});
} }
/** /**
@@ -1896,7 +1896,7 @@
source = source.replace(/^(?: *\/\/.*\s*)* *lodash\.runInContext *=[\s\S]+?;\n/m, ''); source = source.replace(/^(?: *\/\/.*\s*)* *lodash\.runInContext *=[\s\S]+?;\n/m, '');
// remove function scaffolding, leaving most of its content // remove function scaffolding, leaving most of its content
source = source.replace(matchFunction(source, 'runInContext'), function(match) { source = source.replace(matchFunction(source, 'runInContext', true), function(match) {
return match return match
.replace(/^[\s\S]+?function runInContext[\s\S]+?context *= *context.+| *return lodash[\s\S]+$/g, '') .replace(/^[\s\S]+?function runInContext[\s\S]+?context *= *context.+| *return lodash[\s\S]+$/g, '')
.replace(/^ {4}/gm, ' '); .replace(/^ {4}/gm, ' ');
@@ -2258,9 +2258,6 @@
if (!snippet) { if (!snippet) {
return source; return source;
} }
// clip snippet after the JSDoc comment block
snippet = snippet.replace(/^\s*(?:\/\/.*|\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)\n/, '');
source = source.replace(snippet, function() { source = source.replace(snippet, function() {
return funcValue return funcValue
.replace(RegExp('^' + getIndent(funcValue), 'gm'), getIndent(snippet)) .replace(RegExp('^' + getIndent(funcValue), 'gm'), getIndent(snippet))
@@ -2962,14 +2959,14 @@
// replace `_.isPlainObject` with `shimIsPlainObject` // replace `_.isPlainObject` with `shimIsPlainObject`
source = source.replace( source = source.replace(
matchFunction(source, 'isPlainObject').replace(/[\s\S]+?var isPlainObject *= */, ''), matchFunction(source, 'isPlainObject').replace(/^ *var isPlainObject *= */m, ''),
matchFunction(source, 'shimIsPlainObject').replace(/[\s\S]+?function shimIsPlainObject/, 'function').replace(/\s*$/, ';\n') matchFunction(source, 'shimIsPlainObject').replace(/^ *function shimIsPlainObject/m, 'function').replace(/\s*$/, ';\n')
); );
// replace `_.keys` with `shimKeys` // replace `_.keys` with `shimKeys`
source = source.replace( source = source.replace(
matchFunction(source, 'keys').replace(/[\s\S]+?var keys.*= */, ''), matchFunction(source, 'keys').replace(/^ *var keys.*= */m, ''),
matchFunction(source, 'shimKeys').replace(/[\s\S]+?var shimKeys *= */, '') matchFunction(source, 'shimKeys').replace(/^ *var shimKeys *= */m, '')
); );
} }
if (isModern) { if (isModern) {
@@ -3664,10 +3661,6 @@
'}' '}'
].join('\n')); ].join('\n'));
} }
// unexpose `lodash.support`
if (!isLodash('support')) {
source = source.replace(/\blodash\.support *= */, '');
}
// replace `htmlEscapes` entries with hex entities // replace `htmlEscapes` entries with hex entities
if (!isLodash('escape')) { if (!isLodash('escape')) {
source = source.replace(matchVar(source, 'htmlEscapes'), function(match) { source = source.replace(matchVar(source, 'htmlEscapes'), function(match) {
@@ -3978,23 +3971,7 @@
.replace(/(?:\s*\/\/.*)*\n( *)(?:basicEach|forEach)\(\['[\s\S]+?\n\1}.+/g, '') .replace(/(?:\s*\/\/.*)*\n( *)(?:basicEach|forEach)\(\['[\s\S]+?\n\1}.+/g, '')
.replace(/(?:\s*\/\/.*)*\n *lodash\.prototype\.[\s\S]+?;/g, ''); .replace(/(?:\s*\/\/.*)*\n *lodash\.prototype\.[\s\S]+?;/g, '');
} }
if (isNoDep) { if (!isNoDep) {
source = removeAssignments(source);
source = removeFromCreateIterator(source, 'lodash');
source = removeGetIndexOf(source);
source = removeLodashWrapper(source);
if (isExcluded('lodash')) {
source = removeFunction(source, 'lodash');
}
// remove function aliases
_.each(buildFuncs, function(funcName) {
_.each(getAliases(funcName), function(alias) {
source = removeFunction(source, alias);
});
});
}
else {
if (isExcluded('bind')) { if (isExcluded('bind')) {
source = removeSupportProp(source, 'fastBind'); source = removeSupportProp(source, 'fastBind');
} }
@@ -4045,6 +4022,36 @@
} }
} }
// remove code used to resolve unneeded `support` properties
source = source.replace(matchVar(source, 'support'), function(match) {
return match.replace(/^ *\(function[\s\S]+?\n(( *)var ctor *=[\s\S]+?(?:\n *for.+)+\n)([\s\S]+?)}\(1\)\);\n/m, function(match, setup, indent, body) {
var modified = setup;
if (!/\.spliceObjects *=(?! *(?:false|true))/.test(body)) {
modified = modified.replace(/^ *object *=.+\n/m, '');
}
if (!/\.enumPrototypes *=(?! *(?:false|true))/.test(body) &&
!/\.nonEnumShadows *=(?! *(?:false|true))/.test(body) &&
!/\.ownLast *=(?! *(?:false|true))/.test(body)) {
modified = modified
.replace(/\bctor *=.+\s+/, '')
.replace(/^ *ctor\.prototype.+\s+.+\n/m, '')
.replace(/(?:,\n)? *props *=[^;=]+/, '')
.replace(/^ *for *\((?=prop)/, '$&var ')
}
if (!/\.nonEnumArgs *=(?! *(?:false|true))/.test(body)) {
modified = modified.replace(/^ *for *\(.+? arguments.+\n/m, '');
}
// cleanup the empty var statement
modified = modified.replace(/^ *var;\n/m, '');
// if no setup then remove IIFE
return /^\s*$/.test(modified)
? body.replace(RegExp('^' + indent, 'gm'), indent.slice(0, -2))
: match.replace(setup, modified);
});
});
// remove functions from the build // remove functions from the build
allFuncs.forEach(function(otherName) { allFuncs.forEach(function(otherName) {
if (!_.contains(buildFuncs, otherName) && if (!_.contains(buildFuncs, otherName) &&
@@ -4098,37 +4105,15 @@
} }
}()); }());
// remove code used to resolve unneeded `support` properties
source = source.replace(matchVar(source, 'support'), function(match) {
return match.replace(/^ *\(function[\s\S]+?\n(( *)var ctor *=[\s\S]+?(?:\n *for.+)+\n)([\s\S]+?)}\(1\)\);\n/m, function(match, setup, indent, body) {
var modified = setup;
if (!/\.spliceObjects *=(?! *(?:false|true))/.test(body)) {
modified = modified.replace(/^ *object *=.+\n/m, '');
}
if (!/\.enumPrototypes *=(?! *(?:false|true))/.test(body) &&
!/\.nonEnumShadows *=(?! *(?:false|true))/.test(body) &&
!/\.ownLast *=(?! *(?:false|true))/.test(body)) {
modified = modified
.replace(/\bctor *=.+\s+/, '')
.replace(/^ *ctor\.prototype.+\s+.+\n/m, '')
.replace(/(?:,\n)? *props *=[^;=]+/, '')
.replace(/^ *for *\((?=prop)/, '$&var ')
}
if (!/\.nonEnumArgs *=(?! *(?:false|true))/.test(body)) {
modified = modified.replace(/^ *for *\(.+? arguments.+\n/m, '');
}
// cleanup the empty var statement
modified = modified.replace(/^ *var;\n/m, '');
// if no setup then remove IIFE
return /^\s*$/.test(modified)
? body.replace(RegExp('^' + indent, 'gm'), indent.slice(0, -2))
: match.replace(setup, modified);
});
});
if (isNoDep) { if (isNoDep) {
source = removeAssignments(source);
source = removeFromCreateIterator(source, 'lodash');
source = removeGetIndexOf(source);
source = removeLodashWrapper(source);
if (isExcluded('lodash')) {
source = removeFunction(source, 'lodash');
}
// replace the `lodash.templateSettings` property assignment with a variable assignment // replace the `lodash.templateSettings` property assignment with a variable assignment
source = source.replace(/\b(lodash\.)(?=templateSettings *=)/, 'var '); source = source.replace(/\b(lodash\.)(?=templateSettings *=)/, 'var ');
@@ -4154,6 +4139,19 @@
source = removeVar(source, varName); source = removeVar(source, varName);
} }
}); });
// remove function aliases
_.each(buildFuncs, function(funcName) {
_.each(getAliases(funcName), function(alias) {
source = removeFunction(source, alias);
});
});
}
else if (isUnderscore) {
// unexpose `lodash.support`
if (!isLodash('support')) {
source = source.replace(/\blodash\.support *= */, '');
}
} }
} }
if (_.size(source.match(/\bfreeModule\b/g)) < 2) { if (_.size(source.match(/\bfreeModule\b/g)) < 2) {

View File

@@ -1128,7 +1128,7 @@
data.array = data.bottom = data.loop = data.top = ''; data.array = data.bottom = data.loop = data.top = '';
data.init = 'iterable'; data.init = 'iterable';
data.useHas = true; data.useHas = true;
data.useKeys = !!keys; data.useKeys = true;
// merge options into a template data object // merge options into a template data object
for (var object, index = 0; object = arguments[index]; index++) { for (var object, index = 0; object = arguments[index]; index++) {