diff --git a/lodash.js b/lodash.js index 99997c9ab..a89ca30e7 100644 --- a/lodash.js +++ b/lodash.js @@ -2739,7 +2739,7 @@ * @returns {*} Returns the resolved value. */ function baseGet(object, path) { - path = isKey(path, object) ? [path + ''] : baseCastPath(path); + path = isKey(path, object) ? [path] : baseCastPath(path); var index = 0, length = path.length; @@ -3306,12 +3306,22 @@ * @returns {Object} Returns the new object. */ function basePickBy(object, predicate) { - var result = {}; - baseForIn(object, function(value, key) { + var props = keysIn(object); + if (!isArray(object)) { + arrayPush(props, getSymbolsIn(object)); + } + var index = -1, + length = props.length, + result = {}; + + while (++index < length) { + var key = props[index], + value = object[key]; + if (predicate(value, key)) { result[key] = value; } - }); + } return result; } @@ -3459,7 +3469,7 @@ * @returns {Object} Returns `object`. */ function baseSet(object, path, value, customizer) { - path = isKey(path, object) ? [path + ''] : baseCastPath(path); + path = isKey(path, object) ? [path] : baseCastPath(path); var index = -1, length = path.length, @@ -3736,7 +3746,7 @@ * @returns {boolean} Returns `true` if the property is deleted, else `false`. */ function baseUnset(object, path) { - path = isKey(path, object) ? [path + ''] : baseCastPath(path); + path = isKey(path, object) ? [path] : baseCastPath(path); object = parent(object, path); var key = last(path); return (object != null && has(object, key)) ? delete object[key] : true; @@ -5036,7 +5046,7 @@ } /** - * Creates an array of the own symbol properties of `object`. + * Creates an array of the own enumerable symbol properties of `object`. * * @private * @param {Object} object The object to query. @@ -5046,6 +5056,23 @@ return []; }; + /** + * Creates an array of the own and inherited enumerable symbol properties + * of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbolsIn = !getOwnPropertySymbols ? getSymbols : function(object) { + var result = []; + while (object) { + arrayPush(result, getSymbols(object)); + object = getPrototypeOf(object); + } + return result; + }; + /** * Gets the `toStringTag` of `value`. * diff --git a/test/test.js b/test/test.js index 7c4f493ca..5b1a2e6c0 100644 --- a/test/test.js +++ b/test/test.js @@ -7066,7 +7066,7 @@ assert.strictEqual(func(args, 1), true); }); - QUnit.test('`_.' + methodName + '` should work with non-string `path` arguments', function(assert) { + QUnit.test('`_.' + methodName + '` should work with a non-string `path`', function(assert) { assert.expect(2); var array = [1, 2, 3]; @@ -7076,6 +7076,25 @@ }); }); + QUnit.test('`_.' + methodName + '` should work with a symbol `path`', function(assert) { + assert.expect(1); + + function Foo() { + this[symbol] = 1; + } + + if (Symbol) { + var symbol2 = Symbol('b'); + Foo.prototype[symbol2] = 2; + var path = isHas ? symbol : symbol2; + + assert.strictEqual(func(new Foo, path), true); + } + else { + skipAssert(assert); + } + }); + QUnit.test('`_.' + methodName + '` should work for objects with a `[[Prototype]]` of `null`', function(assert) { assert.expect(1); @@ -16531,13 +16550,15 @@ var expected = { 'a': 1, 'c': 3 }, func = _[methodName], object = { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }, - prop = function(object, props) { return props; }; + prop = lodashStable.nthArg(1); if (methodName == 'pickBy') { prop = function(object, props) { - props = typeof props == 'string' ? [props] : props; + props = lodashStable.isArray(props) ? props : [props]; return function(value) { - return _.some(props, function(key) { return object[key] === value; }); + return lodashStable.some(props, function(key) { + return object[key] === value; + }); }; }; } @@ -16548,7 +16569,7 @@ assert.deepEqual(func(object, prop(object, ['a', 'c'])), expected); }); - QUnit.test('`_.' + methodName + '` should iterate over inherited string keyed properties', function(assert) { + QUnit.test('`_.' + methodName + '` should pick inherited properties', function(assert) { assert.expect(1); function Foo() {} @@ -16558,6 +16579,28 @@ assert.deepEqual(func(foo, prop(foo, ['a', 'c'])), expected); }); + QUnit.test('`_.' + methodName + '` should pick symbol properties', function(assert) { + assert.expect(2); + + function Foo() { + this[symbol] = 1; + } + + if (Symbol) { + var symbol2 = Symbol('b'); + Foo.prototype[symbol2] = 2; + + var foo = new Foo, + actual = func(foo, prop(foo, [symbol, symbol2])); + + assert.strictEqual(actual[symbol], 1); + assert.strictEqual(actual[symbol2], 2); + } + else { + skipAssert(assert, 2); + } + }); + QUnit.test('`_.' + methodName + '` should work with an array `object` argument', function(assert) { assert.expect(1); @@ -17903,7 +17946,7 @@ lodashStable.each(['get', 'result'], function(methodName) { var func = _[methodName]; - QUnit.test('`_.' + methodName + '` should get property values', function(assert) { + QUnit.test('`_.' + methodName + '` should get string keyed property values', function(assert) { assert.expect(2); var object = { 'a': 1 }; @@ -17913,6 +17956,20 @@ }); }); + QUnit.test('`_.' + methodName + '` should get symbol keyed property values', function(assert) { + assert.expect(1); + + if (Symbol) { + var object = {}; + object[symbol] = 1; + + assert.strictEqual(func(object, symbol), 1); + } + else { + skipAssert(assert); + } + }); + QUnit.test('`_.' + methodName + '` should get deep property values', function(assert) { assert.expect(2);