Fix compseArgs and composeArgsRight and cleanup and correct partial placeholder tests.

This commit is contained in:
John-David Dalton
2014-02-16 14:53:03 -08:00
parent 6913798250
commit 24edd68833
2 changed files with 66 additions and 32 deletions

View File

@@ -1809,21 +1809,21 @@
* @returns {Array} Returns a new array of composed arguments. * @returns {Array} Returns a new array of composed arguments.
*/ */
function composeArgs(partialArgs, partialHolders, args) { function composeArgs(partialArgs, partialHolders, args) {
var index = -1, var holdersLength = partialHolders.length,
length = partialHolders.length, argsIndex = -1,
argsLength = nativeMax(args.length - holdersLength, 0),
leftIndex = -1, leftIndex = -1,
leftLength = partialArgs.length, leftLength = partialArgs.length,
argsLength = nativeMax(args.length - length, 0),
result = Array(argsLength + leftLength); result = Array(argsLength + leftLength);
while (++leftIndex < leftLength) { while (++leftIndex < leftLength) {
result[leftIndex] = partialArgs[leftIndex]; result[leftIndex] = partialArgs[leftIndex];
} }
while (++index < length) { while (++argsIndex < holdersLength) {
result[partialHolders[index]] = args[index]; result[partialHolders[argsIndex]] = args[argsIndex];
} }
while (length < argsLength) { while (argsLength--) {
result[leftIndex++] = args[length++]; result[leftIndex++] = args[argsIndex++];
} }
return result; return result;
} }
@@ -1839,10 +1839,10 @@
* @returns {Array} Returns a new array of composed arguments. * @returns {Array} Returns a new array of composed arguments.
*/ */
function composeArgsRight(partialRightArgs, partialRightHolders, args) { function composeArgsRight(partialRightArgs, partialRightHolders, args) {
var index = -1, var holdersIndex = -1,
length = partialRightHolders.length, holdersLength = partialRightHolders.length,
argsIndex = -1, argsIndex = -1,
argsLength = nativeMax(args.length - length, 0), argsLength = nativeMax(args.length - holdersLength, 0),
rightIndex = -1, rightIndex = -1,
rightLength = partialRightArgs.length, rightLength = partialRightArgs.length,
result = Array(argsLength + rightLength); result = Array(argsLength + rightLength);
@@ -1854,8 +1854,8 @@
while (++rightIndex < rightLength) { while (++rightIndex < rightLength) {
result[pad + rightIndex] = partialRightArgs[rightIndex]; result[pad + rightIndex] = partialRightArgs[rightIndex];
} }
while (++index < length) { while (++holdersIndex < holdersLength) {
result[pad + partialHolders[index]] = args[argsIndex++]; result[pad + partialRightHolders[holdersIndex]] = args[argsIndex++];
} }
return result; return result;
} }

View File

@@ -5950,57 +5950,91 @@
isPartial = methodName == 'partial'; isPartial = methodName == 'partial';
test('`_.' + methodName + '` partially applies arguments', 1, function() { test('`_.' + methodName + '` partially applies arguments', 1, function() {
var fn = function(a) { return a; }; var fn = function(a) { return a; },
equal(func(fn, 'a')(), 'a'); par = func(fn, 'a');
equal(par(), 'a');
}); });
test('`_.' + methodName + '` creates a function that can be invoked with additional arguments', 1, function() { test('`_.' + methodName + '` creates a function that can be invoked with additional arguments', 1, function() {
var fn = function(a, b) { return [a, b]; }, var fn = function(a, b) { return [a, b]; },
expected = ['a', 'b']; expected = ['a', 'b'],
par = func(fn, 'a');
if (!isPartial) { deepEqual(par('b'), isPartial ? expected : expected.reverse());
expected.reverse();
}
deepEqual(func(fn, 'a')('b'), expected);
}); });
test('`_.' + methodName + '` works when there are no partially applied arguments and the created function is invoked without additional arguments', 1, function() { test('`_.' + methodName + '` works when there are no partially applied arguments and the created function is invoked without additional arguments', 1, function() {
var fn = function() { return arguments.length; }; var fn = function() { return arguments.length; },
strictEqual(func(fn)(), 0); par = func(fn);
strictEqual(par(), 0);
}); });
test('`_.' + methodName + '` works when there are no partially applied arguments and the created function is invoked with additional arguments', 1, function() { test('`_.' + methodName + '` works when there are no partially applied arguments and the created function is invoked with additional arguments', 1, function() {
var fn = function(a) { return a; }; var fn = function(a) { return a; },
equal(func(fn)('a'), 'a'); par = func(fn);
equal(par('a'), 'a');
}); });
test('`_.' + methodName + '` should not alter the `this` binding', 3, function() { test('`_.' + methodName + '` should not alter the `this` binding', 3, function() {
var fn = function() { return this.a; }, var fn = function() { return this.a; },
object = { 'a': 1 }; object = { 'a': 1 };
strictEqual(func(_.bind(fn, object))(), object.a); var par = func(_.bind(fn, object));
strictEqual(_.bind(func(fn), object)(), object.a); strictEqual(par(), object.a);
object.partialed = func(fn); par = _.bind(func(fn), object);
strictEqual(object.partialed(), object.a); strictEqual(par(), object.a);
object.par = func(fn);
strictEqual(object.par(), object.a);
}); });
test('`_.' + methodName + '` creates a function with a `length` of `0`', 1, function() { test('`_.' + methodName + '` creates a function with a `length` of `0`', 1, function() {
var fn = function(a, b, c) {}, var fn = function(a, b, c) {},
actual = func(fn, 'a'); par = func(fn, 'a');
strictEqual(actual.length, 0); strictEqual(par.length, 0);
}); });
test('`_.' + methodName + '` ensure `new partialed` is an instance of `func`', 2, function() { test('`_.' + methodName + '` ensure `new partialed` is an instance of `func`', 2, function() {
function Foo(value) { function Foo(value) {
return value && object; return value && object;
} }
var partialed = func(Foo), var par = func(Foo),
object = {}; object = {};
ok(new partialed instanceof Foo); ok(new par instanceof Foo);
strictEqual(new partialed(true), object); strictEqual(new par(true), object);
});
test('`_.' + methodName + '` should support placeholders', 4, function() {
if (_._iteratorTemplate) {
var fn = function() {
return _.reduce(arguments, function(string, chr) {
return string + (chr || '');
}, '');
};
var par = func(fn, _, 'b', _);
equal(par('a', 'c'), 'abc');
equal(par('a'), 'ab');
if (isPartial) {
equal(par('a', 'c', 'd'), 'abcd');
} else {
par = func(fn, _, 'c', _);
equal(par('a', 'b', 'd'), 'abcd');
}
fn = function() { return slice.call(arguments); };
par = func(fn, _, 'b', _);
deepEqual(par(), [undefined, 'b', undefined]);
}
else {
skipTest(4);
}
}); });
test('`_.' + methodName + '` should clone metadata for created functions', 3, function() { test('`_.' + methodName + '` should clone metadata for created functions', 3, function() {