mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-09 23:34:42 +00:00
fix(angular): do not copy $$hashKey in copy/extend functions.
Copying the $$hashKey as part of copy/extend operations makes little sense since hashkey is used primarily as an object id, especially in the context of the ngRepeat directive. This change maintains the existing $$hashKey of an object that is being copied into (likewise for extend). It is not uncommon to take an item in a collection, copy it, and then append it to the collection. By copying the $$hashKey, this leads to duplicate object errors with the current ngRepeat. Closes #1875
This commit is contained in:
parent
1240641f76
commit
016e1e675e
2 changed files with 77 additions and 0 deletions
|
|
@ -195,6 +195,21 @@ function nextUid() {
|
||||||
return uid.join('');
|
return uid.join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set or clear the hashkey for an object.
|
||||||
|
* @param obj object
|
||||||
|
* @param h the hashkey (!truthy to delete the hashkey)
|
||||||
|
*/
|
||||||
|
function setHashKey(obj, h) {
|
||||||
|
if (h) {
|
||||||
|
obj.$$hashKey = h;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delete obj.$$hashKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc function
|
* @ngdoc function
|
||||||
* @name angular.extend
|
* @name angular.extend
|
||||||
|
|
@ -208,6 +223,7 @@ function nextUid() {
|
||||||
* @param {...Object} src Source object(s).
|
* @param {...Object} src Source object(s).
|
||||||
*/
|
*/
|
||||||
function extend(dst) {
|
function extend(dst) {
|
||||||
|
var h = dst.$$hashKey;
|
||||||
forEach(arguments, function(obj){
|
forEach(arguments, function(obj){
|
||||||
if (obj !== dst) {
|
if (obj !== dst) {
|
||||||
forEach(obj, function(value, key){
|
forEach(obj, function(value, key){
|
||||||
|
|
@ -215,6 +231,8 @@ function extend(dst) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setHashKey(dst,h);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -569,12 +587,14 @@ function copy(source, destination){
|
||||||
destination.push(copy(source[i]));
|
destination.push(copy(source[i]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
var h = destination.$$hashKey;
|
||||||
forEach(destination, function(value, key){
|
forEach(destination, function(value, key){
|
||||||
delete destination[key];
|
delete destination[key];
|
||||||
});
|
});
|
||||||
for ( var key in source) {
|
for ( var key in source) {
|
||||||
destination[key] = copy(source[key]);
|
destination[key] = copy(source[key]);
|
||||||
}
|
}
|
||||||
|
setHashKey(destination,h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return destination;
|
return destination;
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,63 @@ describe('angular', function() {
|
||||||
src = dst = [2, 4];
|
src = dst = [2, 4];
|
||||||
expect(function() { copy(src, dst); }).toThrow("Can't copy equivalent objects or arrays");
|
expect(function() { copy(src, dst); }).toThrow("Can't copy equivalent objects or arrays");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not copy the private $$hashKey', function() {
|
||||||
|
var src,dst;
|
||||||
|
src = {};
|
||||||
|
hashKey(src);
|
||||||
|
dst = copy(src);
|
||||||
|
expect(hashKey(dst)).not.toEqual(hashKey(src));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should retain the previous $$hashKey', function() {
|
||||||
|
var src,dst,h;
|
||||||
|
src = {};
|
||||||
|
dst = {};
|
||||||
|
// force creation of a hashkey
|
||||||
|
h = hashKey(dst);
|
||||||
|
hashKey(src);
|
||||||
|
dst = copy(src,dst);
|
||||||
|
|
||||||
|
// make sure we don't copy the key
|
||||||
|
expect(hashKey(dst)).not.toEqual(hashKey(src));
|
||||||
|
// make sure we retain the old key
|
||||||
|
expect(hashKey(dst)).toEqual(h);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("extend", function() {
|
||||||
|
|
||||||
|
it('should not copy the private $$hashKey', function() {
|
||||||
|
var src,dst;
|
||||||
|
src = {};
|
||||||
|
dst = {};
|
||||||
|
hashKey(src);
|
||||||
|
dst = extend(dst,src);
|
||||||
|
expect(hashKey(dst)).not.toEqual(hashKey(src));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should retain the previous $$hashKey', function() {
|
||||||
|
var src,dst,h;
|
||||||
|
src = {};
|
||||||
|
dst = {};
|
||||||
|
h = hashKey(dst);
|
||||||
|
hashKey(src);
|
||||||
|
dst = extend(dst,src);
|
||||||
|
// make sure we don't copy the key
|
||||||
|
expect(hashKey(dst)).not.toEqual(hashKey(src));
|
||||||
|
// make sure we retain the old key
|
||||||
|
expect(hashKey(dst)).toEqual(h);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work when extending with itself', function() {
|
||||||
|
var src,dst,h;
|
||||||
|
dst = src = {};
|
||||||
|
h = hashKey(dst);
|
||||||
|
dst = extend(dst,src);
|
||||||
|
// make sure we retain the old key
|
||||||
|
expect(hashKey(dst)).toEqual(h);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('shallow copy', function() {
|
describe('shallow copy', function() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue