Fix placeholder support without metadata.

This commit is contained in:
John-David Dalton
2014-07-24 21:29:22 -07:00
parent 3004c58798
commit e402347d73
2 changed files with 57 additions and 79 deletions

100
lodash.js
View File

@@ -39,6 +39,9 @@
*/
var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
/** Used as the internal argument placeholder */
var PLACEHOLDER = '__lodash_placeholder__';
/** Used to generate unique IDs */
var idCounter = 0;
@@ -1068,26 +1071,6 @@
/*--------------------------------------------------------------------------*/
/**
* Appends placeholder indexes to `array` adding `offset` to each appended index.
*
* @private
* @param {Array} array The array of placeholder indexes to append to.
* @param {Array} indexes The array of placeholder indexes to append.
* @param {number} offset The placeholder offset.
* @returns {Array} Returns `array`.
*/
function appendHolders(array, indexes, offset) {
var length = array.length,
index = indexes.length;
array.length += index;
while (index--) {
array[length + index] = indexes[index] + offset;
}
return array;
}
/**
* A specialized version of `_.forEach` for arrays without support for
* callback shorthands or `this` binding.
@@ -1599,7 +1582,7 @@
}
if (isCurry || isCurryRight) {
var placeholder = wrapper.placeholder,
newPartialHolders = getHolders(args, placeholder);
newPartialHolders = replaceHolders(args, placeholder);
length -= newPartialHolders.length;
@@ -2831,29 +2814,21 @@
}
// append partial left arguments
if (isPartial) {
var partialHolders = data[5],
funcPartialArgs = funcData[4];
var funcPartialArgs = funcData[4];
if (funcPartialArgs) {
appendHolders(funcData[5], partialHolders, funcPartialArgs.length);
push.apply(funcPartialArgs, partialArgs);
} else {
funcData[4] = partialArgs;
funcData[5] = partialHolders;
funcPartialArgs = composeArgs(funcPartialArgs, funcData[5], partialArgs);
}
funcData[4] = funcPartialArgs || partialArgs;
funcData[5] = funcPartialArgs ? replaceHolders(funcPartialArgs, PLACEHOLDER) : data[5];
}
// prepend partial right arguments
if (isPartialRight) {
var partialRightHolders = data[7],
funcPartialRightArgs = funcData[6];
var funcPartialRightArgs = funcData[6];
if (funcPartialRightArgs) {
appendHolders(funcData[7], partialRightHolders, funcPartialRightArgs.length);
unshift.apply(funcPartialRightArgs, partialRightArgs);
} else {
funcData[6] = partialRightArgs;
funcData[7] = partialRightHolders;
funcPartialRightArgs = composeArgsRight(funcPartialRightArgs, funcData[7], partialRightArgs);
}
funcData[6] = funcPartialRightArgs || partialRightArgs;
funcData[7] = funcPartialRightArgs ? replaceHolders(funcPartialRightArgs, PLACEHOLDER) : data[7];
}
// merge flags
funcData[1] |= bitmask;
@@ -2881,26 +2856,6 @@
return arguments.length ? result(func, thisArg, argCount) : result;
}
/**
* Finds the indexes of all placeholder elements in `array`.
*
* @private
* @param {Array} array The array to inspect.
* @returns {Array} Returns the new array of placeholder indexes.
*/
function getHolders(array, placeholder) {
var index = -1,
length = array.length,
result = [];
while (++index < length) {
if (array[index] === placeholder) {
result.push(index);
}
}
return result;
}
/**
* Gets the appropriate "indexOf" function. If the `_.indexOf` method is
* customized this function returns the custom method, otherwise it returns
@@ -2984,6 +2939,29 @@
};
}
/**
* Replaces all `placeholder` elements in `array` with an internal placeholder
* and returns an array of their indexes.
*
* @private
* @param {Array} array The array to modify.
* @param {*} placeholder The placeholder to replace.
* @returns {Array} Returns the new array of placeholder indexes.
*/
function replaceHolders(array, placeholder) {
var index = -1,
length = array.length,
result = [];
while (++index < length) {
if (array[index] === placeholder) {
array[index] = PLACEHOLDER;
result.push(index);
}
}
return result;
}
/**
* Sets wrapper metadata on a given function.
*
@@ -5701,7 +5679,7 @@
return createWrapper([func, BIND_FLAG, null, thisArg]);
}
var args = slice(arguments, 2),
partialHolders = getHolders(args, bind.placeholder);
partialHolders = replaceHolders(args, bind.placeholder);
return basePartial(func, BIND_FLAG | PARTIAL_FLAG, args, partialHolders, thisArg);
}
@@ -5779,7 +5757,7 @@
var data = [key, BIND_FLAG | BIND_KEY_FLAG, null, object];
if (arguments.length > 2) {
var args = slice(arguments, 2);
data.push(args, getHolders(args, bindKey.placeholder));
data.push(args, replaceHolders(args, bindKey.placeholder));
}
return createWrapper(data);
}
@@ -6254,7 +6232,7 @@
*/
function partial(func) {
var args = slice(arguments, 1),
partialHolders = getHolders(args, partial.placeholder);
partialHolders = replaceHolders(args, partial.placeholder);
return basePartial(func, PARTIAL_FLAG, args, partialHolders);
}
@@ -6292,7 +6270,7 @@
*/
function partialRight(func) {
var args = slice(arguments, 1),
partialHolders = getHolders(args, partialRight.placeholder);
partialHolders = replaceHolders(args, partialRight.placeholder);
return basePartial(func, PARTIAL_RIGHT_FLAG, args, partialHolders);
}

View File

@@ -8111,21 +8111,21 @@
var a = _.bindKey(object, 'fn', ph2, 2),
b = _.partialRight(a, ph4, 6),
c = _.partial(b, ph3, 4);
c = _.partial(b, 1, ph3, 4);
deepEqual(c(1, 3, 5), expected);
deepEqual(c(3, 5), expected);
a = _.bind(fn, object, ph1, 2);
b = _.partialRight(a, ph4, 6);
c = _.partial(b, ph3, 4);
c = _.partial(b, 1, ph3, 4);
deepEqual(c(1, 3, 5), expected);
deepEqual(c(3, 5), expected);
a = _.partial(fn, ph3, 2)
b = _.bind(a, object, ph1, 4);
a = _.partial(fn, ph3, 2)
b = _.bind(a, object, 1, ph1, 4);
c = _.partialRight(b, ph4, 6);
deepEqual(c(1, 3, 5), expected);
deepEqual(c(3, 5), expected);
});
test('combinations of functions with overlaping placeholders should work', 3, function() {
@@ -8133,26 +8133,26 @@
return slice.call(arguments);
}
var expected = [1, 2, 3, 4, 5],
var expected = [1, 2, 3, 4],
object = { 'fn': fn };
var a = _.bindKey(object, 'fn', ph2, 2),
b = _.partialRight(a, ph4, 5),
c = _.partial(b, ph3, 4);
b = _.partialRight(a, ph4, 4),
c = _.partial(b, ph3, 3);
deepEqual(c(1, 3), expected);
deepEqual(c(1), expected);
a = _.bind(fn, object, ph1, 2);
b = _.partialRight(a, ph4, 5);
c = _.partial(b, ph3, 4);
b = _.partialRight(a, ph4, 4);
c = _.partial(b, ph3, 3);
deepEqual(c(1, 3), expected);
deepEqual(c(1), expected);
a = _.partial(fn, ph3, 2)
b = _.bind(a, object, ph1, 4);
c = _.partialRight(b, ph4, 5);
a = _.partial(fn, ph3, 2)
b = _.bind(a, object, ph1, 3);
c = _.partialRight(b, ph4, 4);
deepEqual(c(1, 3), expected);
deepEqual(c(1), expected);
});
test('recursively bound functions should work', 1, function() {