From 93a01506e428edcbcd442f3a0ba101ef8cab94aa Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Wed, 29 May 2013 08:30:13 -0500 Subject: [PATCH] Add/fix build tests for mixed method builds. Former-commit-id: 2b97810ca6960670ea646c6eda962bd4585fda04 --- build.js | 69 +++++++++++++++++------------ test/test-build.js | 106 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 146 insertions(+), 29 deletions(-) diff --git a/build.js b/build.js index 0c489374f..9a48bb166 100755 --- a/build.js +++ b/build.js @@ -2052,8 +2052,6 @@ source = setUseStrictOption(source, isStrict); if (isLegacy) { - source = removeKeysOptimization(source); - source = removeSetImmediate(source); source = removeSupportProp(source, 'fastBind'); source = replaceSupportProp(source, 'argsClass', 'false'); @@ -2121,21 +2119,18 @@ source = source.replace(matchFunction(source, 'isPlainObject'), function(match) { return match.replace(/!getPrototypeOf[^:]+:\s*/, ''); }); - - // replace `_.isRegExp` - source = replaceFunction(source, 'isRegExp', [ - 'function isRegExp(value) {', - " return value ? (typeof value == 'object' && toString.call(value) == regexpClass) : false;", - '}' - ].join('\n')); } } - if (isLegacy || isMobile || isUnderscore) { + if ((isLegacy || isMobile || isUnderscore) && !useLodashMethod('createCallback')) { source = removeBindingOptimization(source); } - if (isMobile || isUnderscore) { - source = removeKeysOptimization(source); - source = removeSetImmediate(source); + if (isLegacy || isMobile || isUnderscore) { + if (!useLodashMethod('assign') && !useLodashMethod('defaults') && !useLodashMethod('forIn') && !useLodashMethod('forOwn')) { + source = removeKeysOptimization(source); + } + if (!useLodashMethod('defer')) { + source = removeSetImmediate(source); + } } if (isModern || isUnderscore) { source = removeSupportArgsClass(source); @@ -2170,6 +2165,15 @@ '}', ].join('\n')); + // replace `_.isRegExp` + if (!isUnderscore || (isUnderscore && useLodashMethod('isRegExp'))) { + source = replaceFunction(source, 'isRegExp', [ + 'function isRegExp(value) {', + " return value ? (typeof value == 'object' && toString.call(value) == regexpClass) : false;", + '}' + ].join('\n')); + } + // replace `_.map` source = replaceFunction(source, 'map', [ 'function map(collection, callback, thisArg) {', @@ -2216,7 +2220,7 @@ } else if (/^(?:max|min)$/.test(methodName)) { match = match.replace(/\bbasicEach\(/, 'forEach('); - if (!isUnderscore) { + if (!isUnderscore || useLodashMethod(methodName)) { return match; } } @@ -2641,8 +2645,9 @@ source = replaceFunction(source, 'template', [ 'function template(text, data, options) {', + ' var settings = lodash.templateSettings;', " text || (text = '');", - ' options = defaults({}, options, lodash.templateSettings);', + ' options = iteratorTemplate ? defaults({}, options, settings) : settings;', '', ' var index = 0,', ' source = "__p += \'",', @@ -2834,8 +2839,13 @@ source = source.replace(/lodash\.support *= */, ''); // replace `slice` with `nativeSlice.call` - source = removeFunction(source, 'slice'); - source = source.replace(/([^.])\bslice\(/g, '$1nativeSlice.call('); + _.each(['clone', 'first', 'initial', 'last', 'rest', 'toArray'], function(methodName) { + if (!useLodashMethod(methodName)) { + source = source.replace(matchFunction(source, methodName), function(match) { + return match.replace(/([^.])\bslice\(/g, '$1nativeSlice.call('); + }); + } + }); // remove conditional `charCodeCallback` use from `_.max` and `_.min` _.each(['max', 'min'], function(methodName) { @@ -2846,16 +2856,6 @@ } }); - // modify `_.isEqual` and `shimIsPlainObject` to use the private `indicatorObject` - if (!useLodashMethod('forIn')) { - source = source.replace(matchFunction(source, 'isEqual'), function(match) { - return match.replace(/\(result *= *(.+?)\);/g, '!(result = $1) && indicatorObject;'); - }); - - source = source.replace(matchFunction(source, 'shimIsPlainObject'), function(match) { - return match.replace(/return false/, 'return indicatorObject'); - }); - } // remove unneeded variables if (!useLodashMethod('clone') && !useLodashMethod('cloneDeep')) { source = removeVar(source, 'cloneableClasses'); @@ -2884,7 +2884,7 @@ ].join(indent); }) .replace(/thisBinding *=[^}]+}/, 'thisBinding = thisArg;\n') - .replace(/\(args *=.+/, 'partialArgs.concat(slice(args))'); + .replace(/\(args *=.+/, 'partialArgs.concat(nativeSlice.call(args))'); }); } } @@ -2988,6 +2988,16 @@ }); }); } + // modify `_.isEqual` and `shimIsPlainObject` to use the private `indicatorObject` + if (!useLodashMethod('forIn')) { + source = source.replace(matchFunction(source, 'isEqual'), function(match) { + return match.replace(/\(result *= *(.+?)\);/g, '!(result = $1) && indicatorObject;'); + }); + + source = source.replace(matchFunction(source, 'shimIsPlainObject'), function(match) { + return match.replace(/return false/, 'return indicatorObject'); + }); + } // remove `thisArg` from unexposed `forIn` and `forOwn` _.each(['forIn', 'forOwn'], function(methodName) { @@ -3240,6 +3250,9 @@ 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)) { source = removeVar(source, 'Error'); source = removeVar(source, 'errorProto'); diff --git a/test/test-build.js b/test/test-build.js index 3fcd3f452..aa296ad84 100644 --- a/test/test-build.js +++ b/test/test-build.js @@ -6,7 +6,7 @@ var vm = require('vm'); /** Load other modules */ - var _ = require('../lodash.js'), + var _ = require('../dist/lodash.js'), build = require('../build.js'), minify = require('../build/minify.js'), util = require('../build/util.js'); @@ -1445,6 +1445,110 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('mixed underscore and lodash methods'); + + (function() { + var methodNames = [ + 'assign', + 'bindKey', + 'clone', + 'contains', + 'debouce', + 'defaults', + 'defer', + 'difference', + 'every', + 'filter', + 'find', + 'findWhere', + 'first', + 'flatten', + 'forEach', + 'forOwn', + 'intersection', + 'initial', + 'isEmpty', + 'isEqual', + 'isPlainObject', + 'isRegExp', + 'last', + 'map', + 'max', + 'memoize', + 'min', + 'omit', + 'partial', + 'partialRight', + 'pick', + 'pluck', + 'reduce', + 'result', + 'rest', + 'some', + 'tap', + 'template', + 'throttle', + 'times', + 'toArray', + 'transform', + 'uniq', + 'uniqueId', + 'value', + 'where', + 'zip' + ]; + + function strip(value) { + return String(value) + .replace(/^ *\/\/.*/gm, '') + .replace(/\b(?:basicEach|context|forEach|forOwn|window)\b/g, '') + .replace(/\blodash\.(createCallback\()\b/g, '$1') + .replace(/[\s;]/g, ''); + } + + methodNames.forEach(function(methodName) { + var command = 'underscore plus=' + methodName; + + if (methodName == 'createCallback') { + command += ',where'; + } + if (methodName == 'zip') { + command += ',unzip'; + } + if (methodName != 'chain' && _.contains(chainingMethods.concat('mixin'), methodName)) { + command += ',chain'; + } + if (_.contains(['isEqual', 'isPlainObject'], methodName)) { + command += ',forIn'; + } + if (_.contains(['contains', 'every', 'find', 'some', 'transform'], methodName)) { + command += ',forOwn'; + } + asyncTest('`lodash ' + command +'`', function() { + var start = _.after(2, _.once(QUnit.start)); + + build(['-s'].concat(command.split(' ')), function(data) { + var array = [{ 'value': 1 }], + basename = path.basename(data.outputPath, '.js'), + context = createContext(); + + vm.runInContext(data.source, context, true); + var lodash = context._; + + if (methodName == 'chain' || methodName == 'defer') { + notEqual(strip(lodash[methodName]), strip(_[methodName]), basename); + } else if (!/\.min$/.test(basename)) { + equal(strip(lodash[methodName]), strip(_[methodName]), basename); + } + testMethod(lodash, methodName, basename); + start(); + }); + }); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash build'); (function() {