Avoid binding functions in _.createCallback if they don't reference this.

Former-commit-id: d491414e7e1536d3241a607ba07120f629ff2410
This commit is contained in:
John-David Dalton
2013-05-20 09:20:51 -07:00
parent 242e8a3bd6
commit 01621f75b6
3 changed files with 116 additions and 35 deletions

View File

@@ -1385,6 +1385,9 @@
function removeRunInContext(source) {
source = removeVar(source, 'contextProps');
// replace reference in `reThis` assignment
source = source.replace(/\btest\(runInContext\)/, 'test(function() { return this; })');
// remove function scaffolding, leaving most of its content
source = source.replace(matchFunction(source, 'runInContext'), function(match) {
return match

View File

@@ -55,6 +55,9 @@
/** Used to match "interpolate" template delimiters */
var reInterpolate = /<%=([\s\S]+?)%>/g;
/** Used to detect functions containing a `this` reference */
var reThis = (reThis = /\bthis\b/) && reThis.test(runInContext) && reThis;
/** Used to detect and test whitespace */
var whitespace = (
// whitespace
@@ -188,6 +191,7 @@
clearTimeout = context.clearTimeout,
concat = arrayProto.concat,
floor = Math.floor,
fnToString = Function.prototype.toString,
getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
hasOwnProperty = objectProto.hasOwnProperty,
push = arrayProto.push,
@@ -4578,27 +4582,27 @@
return result;
};
}
if (typeof thisArg != 'undefined') {
if (argCount === 1) {
return function(value) {
return func.call(thisArg, value);
};
}
if (argCount === 2) {
return function(a, b) {
return func.call(thisArg, a, b);
};
}
if (argCount === 4) {
return function(accumulator, value, index, collection) {
return func.call(thisArg, accumulator, value, index, collection);
};
}
return function(value, index, collection) {
return func.call(thisArg, value, index, collection);
if (typeof thisArg == 'undefined' || (reThis && !reThis.test(fnToString.call(func)))) {
return func;
}
if (argCount === 1) {
return function(value) {
return func.call(thisArg, value);
};
}
return func;
if (argCount === 2) {
return function(a, b) {
return func.call(thisArg, a, b);
};
}
if (argCount === 4) {
return function(accumulator, value, index, collection) {
return func.call(thisArg, accumulator, value, index, collection);
};
}
return function(value, index, collection) {
return func.call(thisArg, value, index, collection);
};
}
/**

View File

@@ -1129,6 +1129,80 @@
/*--------------------------------------------------------------------------*/
QUnit.module('exclude command');
(function() {
var commands = [
'exclude',
'minus'
];
commands.forEach(function(command) {
asyncTest('`lodash ' + command + '=runInContext`', function() {
var start = _.after(2, _.once(QUnit.start));
build(['-s', command + '=runInContext'], function(data) {
var basename = path.basename(data.outputPath, '.js'),
context = createContext(),
source = data.source;
vm.runInContext(data.source, context);
var lodash = context._,
array = [0];
var actual = lodash.map(array, function() {
return String(this[0]);
}, array);
deepEqual(actual, ['0'], basename);
equal('runInContext' in lodash, false, basename);
start();
});
});
asyncTest('`lodash ' + command + '=mixin`', function() {
var start = _.after(2, _.once(QUnit.start));
build(['-s', command + '=mixin'], function(data) {
var basename = path.basename(data.outputPath, '.js'),
context = createContext(),
source = data.source;
vm.runInContext(data.source, context);
var lodash = context._;
var actual = lodash([1, 2, 3])
.map(function(num) { return num * num; })
.value();
deepEqual(actual, [1, 4, 9], basename);
equal('mixin' in lodash, false, basename);
start();
});
});
asyncTest('`lodash ' + command + '=value`', function() {
var start = _.after(2, _.once(QUnit.start));
build(['-s', command + '=value'], function(data) {
var basename = path.basename(data.outputPath, '.js'),
context = createContext(),
source = data.source;
vm.runInContext(data.source, context);
var lodash = context._;
strictEqual(lodash([1]), undefined, basename);
deepEqual(_.keys(lodash.prototype), [], basename);
start();
});
});
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('exports command');
(function() {
@@ -1440,19 +1514,19 @@
var command = origCommand;
if (index == 1) {
if (/legacy|mobile/.test(command)) {
if (/\b(?:legacy|mobile)\b/.test(command)) {
return;
}
command = 'mobile ' + command;
}
else if (index == 2) {
if (/legacy|modern/.test(command)) {
if (/\b(?:legacy|modern)\b/.test(command)) {
return;
}
command = 'modern ' + command;
}
else if (index == 3) {
if (/category|legacy|underscore/.test(command)) {
if (/\b(?:category|legacy|underscore)\b/.test(command)) {
return;
}
command = 'underscore ' + command;
@@ -1464,8 +1538,8 @@
var methodNames,
basename = path.basename(data.outputPath, '.js'),
context = createContext(),
isBackbone = /backbone/.test(command),
isUnderscore = isBackbone || /underscore/.test(command),
isBackbone = /\bbackbone\b/.test(command),
isUnderscore = isBackbone || /\bunderscore\b/.test(command),
exposeAssign = !isUnderscore,
exposeZipObject = !isUnderscore;
@@ -1475,11 +1549,11 @@
console.log(e);
}
// add method names explicitly
if (/include/.test(command)) {
methodNames = command.match(/include=(\S*)/)[1].split(/, */);
if (/\binclude=/.test(command)) {
methodNames = command.match(/\binclude=(\S*)/)[1].split(/, */);
}
// add method names required by Backbone and Underscore builds
if (/backbone/.test(command) && !methodNames) {
if (/\bbackbone\b/.test(command) && !methodNames) {
methodNames = backboneDependencies.slice();
}
if (isUnderscore) {
@@ -1490,20 +1564,20 @@
methodNames = underscoreMethods.slice();
}
}
if (/category/.test(command)) {
methodNames = (methodNames || []).concat(command.match(/category=(\S*)/)[1].split(/, */).map(capitalize));
if (/\bcategory=/.test(command)) {
methodNames = (methodNames || []).concat(command.match(/\bcategory=(\S*)/)[1].split(/, */).map(capitalize));
}
if (!methodNames) {
methodNames = lodashMethods.slice();
}
if (/plus/.test(command)) {
methodNames = methodNames.concat(command.match(/plus=(\S*)/)[1].split(/, */));
if (/\bplus=/.test(command)) {
methodNames = methodNames.concat(command.match(/\bplus=(\S*)/)[1].split(/, */));
}
if (/minus/.test(command)) {
methodNames = _.without.apply(_, [methodNames].concat(expandMethodNames(command.match(/minus=(\S*)/)[1].split(/, */))));
if (/\bminus=/.test(command)) {
methodNames = _.without.apply(_, [methodNames].concat(expandMethodNames(command.match(/\bminus=(\S*)/)[1].split(/, */))));
}
if (/exclude/.test(command)) {
methodNames = _.without.apply(_, [methodNames].concat(expandMethodNames(command.match(/exclude=(\S*)/)[1].split(/, */))));
if (/\bexclude=/.test(command)) {
methodNames = _.without.apply(_, [methodNames].concat(expandMethodNames(command.match(/\bexclude=(\S*)/)[1].split(/, */))));
}
// expand categories to real method names