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