mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-01-31 15:27:50 +00:00
Ensure _.at works with an out of range index when chaining.
This commit is contained in:
70
lodash.js
70
lodash.js
@@ -43,7 +43,8 @@
|
||||
|
||||
/** Used to indicate the type of lazy iteratees. */
|
||||
var LAZY_FILTER_FLAG = 1,
|
||||
LAZY_MAP_FLAG = 2;
|
||||
LAZY_MAP_FLAG = 2,
|
||||
LAZY_WHILE_FLAG = 3;
|
||||
|
||||
/** Used as the `TypeError` message for "Functions" methods. */
|
||||
var FUNC_ERROR_TEXT = 'Expected a function';
|
||||
@@ -6837,6 +6838,45 @@
|
||||
return interceptor(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wrapped array of values corresponding to `paths` of the wrapped object.
|
||||
*
|
||||
* @name at
|
||||
* @memberOf _
|
||||
* @category Chain
|
||||
* @param {...(string|string[])} [paths] The property paths of elements to pick,
|
||||
* specified individually or in arrays.
|
||||
* @returns {Object} Returns the new `lodash` wrapper instance.
|
||||
* @example
|
||||
*
|
||||
* var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
|
||||
*
|
||||
* _(object).at(['a[0].b.c', 'a[1]']);
|
||||
* // => [3, 4]
|
||||
*
|
||||
* _(['a', 'b', 'c']).at(0, 2);
|
||||
* // => ['a', 'c']
|
||||
*/
|
||||
var wrapperAt = rest(function(paths) {
|
||||
paths = baseFlatten(paths);
|
||||
var length = paths.length,
|
||||
start = length ? paths[0] : 0,
|
||||
value = this.__wrapped__,
|
||||
interceptor = function(object) { return baseAt(object, paths); };
|
||||
|
||||
if (length > 1 || this.__actions__.length || !(value instanceof LazyWrapper) || !isIndex(start)) {
|
||||
return this.thru(interceptor);
|
||||
}
|
||||
value = value.slice(start, +start + (length ? 1 : 0));
|
||||
value.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
|
||||
return new LodashWrapper(value, this.__chain__).thru(function(object) {
|
||||
if (length && !object.length) {
|
||||
object.push(undefined);
|
||||
}
|
||||
return object;
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Enables explicit method chaining on the wrapper object.
|
||||
*
|
||||
@@ -7000,7 +7040,7 @@
|
||||
* @name reverse
|
||||
* @memberOf _
|
||||
* @category Chain
|
||||
* @returns {Object} Returns the new reversed `lodash` wrapper instance.
|
||||
* @returns {Object} Returns the new `lodash` wrapper instance.
|
||||
* @example
|
||||
*
|
||||
* var array = [1, 2, 3];
|
||||
@@ -13865,7 +13905,7 @@
|
||||
// Add `LazyWrapper` methods that accept an `iteratee` value.
|
||||
arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
|
||||
var type = index + 1,
|
||||
isFilter = type != LAZY_MAP_FLAG;
|
||||
isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
|
||||
|
||||
LazyWrapper.prototype[methodName] = function(iteratee) {
|
||||
var result = this.clone();
|
||||
@@ -13893,16 +13933,6 @@
|
||||
};
|
||||
});
|
||||
|
||||
LazyWrapper.prototype.at = rest(function(paths) {
|
||||
paths = baseFlatten(paths);
|
||||
var length = paths.length,
|
||||
start = length ? paths[0] : 0;
|
||||
|
||||
return (length < 2 && isIndex(start))
|
||||
? this.slice(start, length ? (+start + 1) : start)
|
||||
: new LazyWrapper(this);
|
||||
});
|
||||
|
||||
LazyWrapper.prototype.compact = function() {
|
||||
return this.filter(identity);
|
||||
};
|
||||
@@ -13953,15 +13983,15 @@
|
||||
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
||||
var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
|
||||
isTaker = /^(?:head|last)$/.test(methodName),
|
||||
retUnwrapped = isTaker || /^find/.test(methodName),
|
||||
lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName];
|
||||
lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
|
||||
retUnwrapped = isTaker || /^find/.test(methodName);
|
||||
|
||||
if (!lodashFunc) {
|
||||
return;
|
||||
}
|
||||
lodash.prototype[methodName] = function() {
|
||||
var args = isTaker ? [1] : arguments,
|
||||
value = this.__wrapped__,
|
||||
var value = this.__wrapped__,
|
||||
args = isTaker ? [1] : arguments,
|
||||
isLazy = value instanceof LazyWrapper,
|
||||
iteratee = args[0],
|
||||
useLazy = isLazy || isArray(value);
|
||||
@@ -13975,8 +14005,7 @@
|
||||
// Avoid lazy use if the iteratee has a "length" value other than `1`.
|
||||
isLazy = useLazy = false;
|
||||
}
|
||||
var action = { 'func': thru, 'args': [interceptor], 'thisArg': undefined },
|
||||
chainAll = this.__chain__,
|
||||
var chainAll = this.__chain__,
|
||||
isHybrid = !!this.__actions__.length,
|
||||
isUnwrapped = retUnwrapped && !chainAll,
|
||||
onlyLazy = isLazy && !isHybrid;
|
||||
@@ -13984,7 +14013,7 @@
|
||||
if (!retUnwrapped && useLazy) {
|
||||
value = onlyLazy ? value : new LazyWrapper(this);
|
||||
var result = func.apply(value, args);
|
||||
result.__actions__.push(action);
|
||||
result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
|
||||
return new LodashWrapper(result, chainAll);
|
||||
}
|
||||
if (isUnwrapped && onlyLazy) {
|
||||
@@ -14031,6 +14060,7 @@
|
||||
LazyWrapper.prototype.value = lazyValue;
|
||||
|
||||
// Add chaining functions to the `lodash` wrapper.
|
||||
lodash.prototype.at = wrapperAt;
|
||||
lodash.prototype.chain = wrapperChain;
|
||||
lodash.prototype.commit = wrapperCommit;
|
||||
lodash.prototype.next = wrapperNext;
|
||||
|
||||
15
test/test.js
15
test/test.js
@@ -1269,7 +1269,7 @@
|
||||
});
|
||||
|
||||
QUnit.test('should support shortcut fusion', function(assert) {
|
||||
assert.expect(6);
|
||||
assert.expect(8);
|
||||
|
||||
if (!isNpm) {
|
||||
var array = lodashStable.range(LARGE_ARRAY_SIZE),
|
||||
@@ -1277,16 +1277,19 @@
|
||||
iteratee = function(value) { count++; return square(value); },
|
||||
lastIndex = LARGE_ARRAY_SIZE - 1;
|
||||
|
||||
_.each([lastIndex, lastIndex + '', []], function(n, index) {
|
||||
_.each([lastIndex, lastIndex + '', LARGE_ARRAY_SIZE, []], function(n, index) {
|
||||
count = 0;
|
||||
var actual = _(array).map(iteratee).at(n).value();
|
||||
var actual = _(array).map(iteratee).at(n).value(),
|
||||
expected = index < 2 ? 1 : 0;
|
||||
|
||||
assert.strictEqual(count, index == 2 ? 0 : 1);
|
||||
assert.deepEqual(actual, index == 2 ? [] : [square(lastIndex)]);
|
||||
assert.strictEqual(count, expected);
|
||||
|
||||
expected = index == 3 ? [] : [index == 2 ? undefined : square(lastIndex)];
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
}
|
||||
else {
|
||||
skipTest(assert, 6);
|
||||
skipTest(assert, 8);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user