mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-06 09:47:48 +00:00
Add support for cloning symbol properties to _.clone and _.cloneDeep.
This commit is contained in:
66
lodash.js
66
lodash.js
@@ -1428,6 +1428,7 @@
|
|||||||
clearTimeout = context.clearTimeout,
|
clearTimeout = context.clearTimeout,
|
||||||
enumerate = Reflect ? Reflect.enumerate : undefined,
|
enumerate = Reflect ? Reflect.enumerate : undefined,
|
||||||
getPrototypeOf = Object.getPrototypeOf,
|
getPrototypeOf = Object.getPrototypeOf,
|
||||||
|
getOwnPropertySymbols = Object.getOwnPropertySymbols,
|
||||||
iteratorSymbol = typeof (iteratorSymbol = Symbol && Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined,
|
iteratorSymbol = typeof (iteratorSymbol = Symbol && Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined,
|
||||||
parseFloat = context.parseFloat,
|
parseFloat = context.parseFloat,
|
||||||
pow = Math.pow,
|
pow = Math.pow,
|
||||||
@@ -1460,8 +1461,8 @@
|
|||||||
var mapCtorString = Map ? funcToString.call(Map) : '',
|
var mapCtorString = Map ? funcToString.call(Map) : '',
|
||||||
setCtorString = Set ? funcToString.call(Set) : '';
|
setCtorString = Set ? funcToString.call(Set) : '';
|
||||||
|
|
||||||
/** Used to convert symbols to strings. */
|
/** Used to convert symbol objects to primitives. */
|
||||||
var symbolToString = Symbol ? Symbol.prototype.toString : undefined;
|
var symbolValueOf = Symbol ? Symbol.prototype.valueOf : undefined;
|
||||||
|
|
||||||
/** Used to lookup unminified function names. */
|
/** Used to lookup unminified function names. */
|
||||||
var realNames = {};
|
var realNames = {};
|
||||||
@@ -2112,6 +2113,26 @@
|
|||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns own symbol properties of `source` to `object`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object} object The destination object.
|
||||||
|
* @param {Object} source The source object.
|
||||||
|
* @returns {Object} Returns `object`.
|
||||||
|
*/
|
||||||
|
function assignSymbols(object, source) {
|
||||||
|
var index = -1,
|
||||||
|
symbols = getSymbols(source),
|
||||||
|
length = symbols.length;
|
||||||
|
|
||||||
|
while (++index < length) {
|
||||||
|
var symbol = symbols[index];
|
||||||
|
object[symbol] = source[symbol];
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes `key` and its value from the associative array.
|
* Removes `key` and its value from the associative array.
|
||||||
*
|
*
|
||||||
@@ -2276,7 +2297,7 @@
|
|||||||
if (isArr) {
|
if (isArr) {
|
||||||
result = initCloneArray(value);
|
result = initCloneArray(value);
|
||||||
if (!isDeep) {
|
if (!isDeep) {
|
||||||
return copyArray(value, result);
|
result = copyArray(value, result);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var tag = getTag(value),
|
var tag = getTag(value),
|
||||||
@@ -2288,13 +2309,19 @@
|
|||||||
}
|
}
|
||||||
result = initCloneObject(isFunc ? {} : value);
|
result = initCloneObject(isFunc ? {} : value);
|
||||||
if (!isDeep) {
|
if (!isDeep) {
|
||||||
return baseAssign(result, value);
|
result = baseAssign(result, value);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return cloneableTags[tag]
|
|
||||||
? initCloneByTag(value, tag, isDeep)
|
|
||||||
: (object ? value : {});
|
|
||||||
}
|
}
|
||||||
|
else if (!cloneableTags[tag]) {
|
||||||
|
return object ? value : {};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = initCloneByTag(value, tag, isDeep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = assignSymbols(result, value);
|
||||||
|
if (!isDeep) {
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
// Check for circular references and return its corresponding clone.
|
// Check for circular references and return its corresponding clone.
|
||||||
stack || (stack = new Stack);
|
stack || (stack = new Stack);
|
||||||
@@ -2777,10 +2804,7 @@
|
|||||||
if (value === other) {
|
if (value === other) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (value == null || other == null || (
|
if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
|
||||||
!(typeof value == 'symbol' || isObject(value)) &&
|
|
||||||
!(typeof other == 'symbol' || isObjectLike(other))
|
|
||||||
)) {
|
|
||||||
return value !== value && other !== other;
|
return value !== value && other !== other;
|
||||||
}
|
}
|
||||||
return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack);
|
return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack);
|
||||||
@@ -3766,10 +3790,7 @@
|
|||||||
* @returns {Object} Returns the cloned symbol.
|
* @returns {Object} Returns the cloned symbol.
|
||||||
*/
|
*/
|
||||||
function cloneSymbol(symbol) {
|
function cloneSymbol(symbol) {
|
||||||
var Ctor = symbol.constructor,
|
return typeof symbol == 'object' ? Object(symbolValueOf.call(symbol)) : symbol;
|
||||||
result = Ctor(symbolToString.call(symbol).slice(7, -1));
|
|
||||||
|
|
||||||
return typeof symbol == 'object' ? Object(result) : result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4550,7 +4571,7 @@
|
|||||||
equalFunc(convert(object), convert(other), customizer, bitmask | UNORDERED_COMPARE_FLAG);
|
equalFunc(convert(object), convert(other), customizer, bitmask | UNORDERED_COMPARE_FLAG);
|
||||||
|
|
||||||
case symbolTag:
|
case symbolTag:
|
||||||
return symbolToString.call(object) == symbolToString.call(other);
|
return symbolValueOf.call(object) == symbolValueOf.call(other);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -4714,6 +4735,17 @@
|
|||||||
return isNative(value) ? value : undefined;
|
return isNative(value) ? value : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an array of the own symbol properties of `object`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object} object The object to query.
|
||||||
|
* @returns {Array} Returns the array of symbols.
|
||||||
|
*/
|
||||||
|
var getSymbols = getOwnPropertySymbols || function() {
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `toStringTag` of `value`.
|
* Gets the `toStringTag` of `value`.
|
||||||
*
|
*
|
||||||
|
|||||||
43
test/test.js
43
test/test.js
@@ -2220,7 +2220,6 @@
|
|||||||
'sets': set,
|
'sets': set,
|
||||||
'strings': 'a',
|
'strings': 'a',
|
||||||
'string objects': Object('a'),
|
'string objects': Object('a'),
|
||||||
'symbols': symbol,
|
|
||||||
'undefined values': undefined
|
'undefined values': undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2313,14 +2312,12 @@
|
|||||||
QUnit.test('`_.' + methodName + '` should clone ' + key, function(assert) {
|
QUnit.test('`_.' + methodName + '` should clone ' + key, function(assert) {
|
||||||
assert.expect(2);
|
assert.expect(2);
|
||||||
|
|
||||||
var useUnstable = /^(?:maps|sets|symbols)$/.test(key),
|
var isEqual = (key == 'maps' || key == 'sets') ? _.isEqual : lodashStable.isEqual,
|
||||||
isEqual = useUnstable ? _.isEqual : lodashStable.isEqual,
|
|
||||||
isObject = useUnstable ? _.isObject : lodashStable.isObject,
|
|
||||||
actual = func(object);
|
actual = func(object);
|
||||||
|
|
||||||
assert.ok(isEqual(actual, object));
|
assert.ok(isEqual(actual, object));
|
||||||
|
|
||||||
if (isObject(object)) {
|
if (lodashStable.isObject(object)) {
|
||||||
assert.notStrictEqual(actual, object);
|
assert.notStrictEqual(actual, object);
|
||||||
} else {
|
} else {
|
||||||
assert.strictEqual(actual, object);
|
assert.strictEqual(actual, object);
|
||||||
@@ -2364,10 +2361,12 @@
|
|||||||
assert.strictEqual(actual.lastIndex, 3);
|
assert.strictEqual(actual.lastIndex, 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('`_.' + methodName + '` should clone symbol objects', function(assert) {
|
QUnit.test('`_.' + methodName + '` should clone symbols', function(assert) {
|
||||||
assert.expect(3);
|
assert.expect(4);
|
||||||
|
|
||||||
if (Symbol) {
|
if (Symbol) {
|
||||||
|
assert.strictEqual(func(symbol), symbol);
|
||||||
|
|
||||||
var object = Object(symbol),
|
var object = Object(symbol),
|
||||||
actual = func(object);
|
actual = func(object);
|
||||||
|
|
||||||
@@ -2376,7 +2375,7 @@
|
|||||||
assert.notStrictEqual(actual, object);
|
assert.notStrictEqual(actual, object);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
skipTest(assert, 3);
|
skipTest(assert, 4);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -7640,6 +7639,9 @@
|
|||||||
QUnit.module('lodash.isEqual');
|
QUnit.module('lodash.isEqual');
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
var symbol1 = Symbol ? Symbol('a') : true,
|
||||||
|
symbol2 = Symbol ? Symbol('b') : false;
|
||||||
|
|
||||||
QUnit.test('should compare primitives', function(assert) {
|
QUnit.test('should compare primitives', function(assert) {
|
||||||
assert.expect(1);
|
assert.expect(1);
|
||||||
|
|
||||||
@@ -7650,6 +7652,7 @@
|
|||||||
['a', 'a', true], ['a', Object('a'), true], [Object('a'), Object('a'), true], ['a', 'b', false], ['a', ['a'], false],
|
['a', 'a', true], ['a', Object('a'), true], [Object('a'), Object('a'), true], ['a', 'b', false], ['a', ['a'], false],
|
||||||
[true, true, true], [true, Object(true), true], [Object(true), Object(true), true], [true, 1, false], [true, 'a', false],
|
[true, true, true], [true, Object(true), true], [Object(true), Object(true), true], [true, 1, false], [true, 'a', false],
|
||||||
[false, false, true], [false, Object(false), true], [Object(false), Object(false), true], [false, 0, false], [false, '', false],
|
[false, false, true], [false, Object(false), true], [Object(false), Object(false), true], [false, 0, false], [false, '', false],
|
||||||
|
[symbol1, symbol1, true], [symbol1, Object(symbol1), true], [Object(symbol1), Object(symbol1), true], [symbol1, symbol2, false],
|
||||||
[null, null, true], [null, undefined, false], [null, {}, false], [null, '', false],
|
[null, null, true], [null, undefined, false], [null, {}, false], [null, '', false],
|
||||||
[undefined, undefined, true], [undefined, null, false], [undefined, '', false]
|
[undefined, undefined, true], [undefined, null, false], [undefined, '', false]
|
||||||
];
|
];
|
||||||
@@ -8154,30 +8157,6 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('should compare symbols', function(assert) {
|
|
||||||
assert.expect(4);
|
|
||||||
|
|
||||||
if (Symbol) {
|
|
||||||
var symbol1 = Symbol('a'),
|
|
||||||
symbol2 = Symbol('b');
|
|
||||||
|
|
||||||
assert.strictEqual(_.isEqual(symbol1, symbol2), false);
|
|
||||||
|
|
||||||
symbol2 = Symbol('a');
|
|
||||||
assert.strictEqual(_.isEqual(symbol1, symbol2), true);
|
|
||||||
|
|
||||||
symbol1 = Symbol();
|
|
||||||
symbol2 = Symbol('');
|
|
||||||
assert.strictEqual(_.isEqual(symbol1, symbol2), true);
|
|
||||||
|
|
||||||
symbol1 = Symbol(null);
|
|
||||||
assert.strictEqual(_.isEqual(symbol1, symbol2), false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
skipTest(assert, 4);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.test('should compare typed arrays', function(assert) {
|
QUnit.test('should compare typed arrays', function(assert) {
|
||||||
assert.expect(1);
|
assert.expect(1);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user