can-reflect
Advanced tools
Comparing version 1.3.0 to 1.4.0
{ | ||
"name": "can-reflect", | ||
"version": "1.3.0", | ||
"version": "1.4.0", | ||
"description": "reflection on unknown data types", | ||
@@ -5,0 +5,0 @@ "homepage": "http://canjs.com", |
@@ -199,2 +199,28 @@ var canSymbol = require("can-symbol"); | ||
return [].splice.apply(obj, [index, howMany].concat(adding) ); | ||
}, | ||
addValues: function(obj, adding, index) { | ||
var add = obj[canSymbol.for("can.addValues")]; | ||
if(add) { | ||
return add.call(obj, adding, index); | ||
} | ||
if(Array.isArray(obj) && index === undefined) { | ||
return obj.push.apply(obj, adding); | ||
} | ||
return reflections.splice(obj, index, [], adding); | ||
}, | ||
removeValues: function(obj, removing, index) { | ||
var removeValues = obj[canSymbol.for("can.removeValues")]; | ||
if(removeValues) { | ||
return removeValues.call(obj, removing, index); | ||
} | ||
if(Array.isArray(obj) && index === undefined) { | ||
removing.forEach(function(item){ | ||
var index = obj.indexOf(item); | ||
if(index >=0) { | ||
obj.splice(index, 1); | ||
} | ||
}); | ||
return; | ||
} | ||
return reflections.splice(obj, index, removing, []); | ||
} | ||
@@ -201,0 +227,0 @@ }; |
@@ -19,3 +19,15 @@ var canSymbol = require("can-symbol"); | ||
}; | ||
}, | ||
// The `in` check is from jQuery’s fix for an iOS 8 64-bit JIT object length bug: | ||
// https://github.com/jquery/jquery/pull/2185 | ||
hasLength: function(list){ | ||
var type = typeof list; | ||
var length = list && type !== 'boolean' && | ||
typeof list !== 'number' && | ||
"length" in list && list.length; | ||
// var length = "length" in obj && obj.length; | ||
return typeof list !== "function" && | ||
( length === 0 || typeof length === "number" && length > 0 && ( length - 1 ) in list ); | ||
} | ||
}; |
@@ -595,2 +595,35 @@ var canSymbol = require("can-symbol"); | ||
}, | ||
/** | ||
* @function can-reflect/shape.assign assign | ||
* @parent can-reflect/shape | ||
* @description Assign one objects values to another | ||
* | ||
* @signature `.assign(target, source)` | ||
* | ||
* Copies the values (and properties if map-like) from `source` onto `target`. | ||
* | ||
* For map-like objects, every enumerable property on `target` is copied: | ||
* | ||
* ```js | ||
* var target = {}; | ||
* var source = {key : "value"}; | ||
* var restult = canReflect.assign(target, source); | ||
* result === target //-> true | ||
* target //-> {key : "value"} | ||
* ``` | ||
* | ||
* For Arrays, enumerated values are copied over, but the length of the array will not be | ||
* trunkated. Use [can-reflect.update] for trunkating. | ||
* | ||
* ```js | ||
* var target = ["a","b","c"]; | ||
* var source = ["A","B"]; | ||
* canReflect.assign(target, source); | ||
* target //-> ["A","B","c"] | ||
* ``` | ||
* | ||
* @param {Object} target The value that will be updated with `source`'s values. | ||
* @param {Object} source A source of values to copy to `target`. | ||
* @return {Object} The target. | ||
*/ | ||
assign: function(target, source) { | ||
@@ -633,2 +666,27 @@ if(typeReflections.isIteratorLike(source) || typeReflections.isMoreListLikeThanMapLike(source) ) { | ||
}, | ||
/** | ||
* @function can-reflect/shape.assignDeep assignDeep | ||
* @parent can-reflect/shape | ||
* @description Assign one objects values to another, and performs the same action for all child values. | ||
* | ||
* @signature `.assignDeep(target, source)` | ||
* | ||
* Copies the values (and properties if map-like) from `source` onto `target` and repeates for all child | ||
* values. | ||
* | ||
* For map-like objects, every enumerable property on `target` is copied: | ||
* | ||
* ```js | ||
* var target = {name: {first: "Justin"}}; | ||
* var source = {name: {last: "Meyer"}}; | ||
* var restult = canReflect.assignDeep(target, source); | ||
* target //-> {name: {first: "Justin", last: "Meyer"}} | ||
* ``` | ||
* | ||
* An object can control the behavior of `assignDeep` using the [can-symbol/symbols/assignDeep] symbol. | ||
* | ||
* @param {Object} target The value that will be updated with `source`'s values. | ||
* @param {Object} source A source of values to copy to `target`. | ||
* @return {Object} The target. | ||
*/ | ||
assignDeep: function(target, source){ | ||
@@ -681,2 +739,34 @@ var assignDeep = target[canSymbol.for("can.assignDeep")]; | ||
}, | ||
/** | ||
* @function can-reflect/shape.update update | ||
* @parent can-reflect/shape | ||
* @description Updates the values of an object match the values of an other object. | ||
* | ||
* @signature `.update(target, source)` | ||
* | ||
* Updates the values (and properties if map-like) of `target` to match the values of `source`. This does | ||
* not recursively update. For that, use [can-reflect/shape.updateDeep]. | ||
* | ||
* For map-like objects, every enumerable property on `target` is copied: | ||
* | ||
* ```js | ||
* var target = {name: {first: "Justin"}, age: 34}; | ||
* var source = {name: {last: "Meyer"}}; | ||
* var restult = canReflect.assignDeep(target, source); | ||
* target //-> {name: {last: "Meyer"}} | ||
* ``` | ||
* | ||
* With Arrays all items of the source will be replaced with the new items. | ||
* | ||
* ```js | ||
* var target = ["a","b","c"]; | ||
* var source = ["A","B"]; | ||
* canReflect.assign(target, source); | ||
* target //-> ["A","B"] | ||
* ``` | ||
* | ||
* @param {Object} target The value that will be updated with `source`'s values. | ||
* @param {Object} source A source of values to copy to `target`. | ||
* @return {Object} The target. | ||
*/ | ||
update: function(target, source) { | ||
@@ -725,2 +815,28 @@ if(typeReflections.isIteratorLike(source) || typeReflections.isMoreListLikeThanMapLike(source) ) { | ||
}, | ||
/** | ||
* @function can-reflect/shape.updateDeep updateDeep | ||
* @parent can-reflect/shape | ||
* @description Makes the values of an object match the values of an other object including all children values. | ||
* | ||
* @signature `.updateDeep(target, source)` | ||
* | ||
* Updates the values (and properties if map-like) of `target` to match the values of `source`. | ||
* | ||
* For map-like objects, every enumerable property on `target` is copied: | ||
* | ||
* ```js | ||
* var target = {name: {first: "Justin"}, age: 34}; | ||
* var source = {name: {last: "Meyer"}}; | ||
* var restult = canReflect.assignDeep(target, source); | ||
* target //-> {name: {last: "Meyer"}} | ||
* ``` | ||
* | ||
* An object can control the behavior of `assignDeep` using the [can-symbol/symbols/updateDeep] symbol. | ||
* | ||
* For list-like objects, a diff and patch strategy is used. This attempts to limit the number of changes. | ||
* | ||
* @param {Object} target The value that will be updated with `source`'s values. | ||
* @param {Object} source A source of values to copy to `target`. | ||
* @return {Object} The target. | ||
*/ | ||
updateDeep: function(target, source){ | ||
@@ -743,2 +859,24 @@ var updateDeep = target[canSymbol.for("can.updateDeep")]; | ||
getAllKeys: function(){}, | ||
/** | ||
* @function can-reflect/shape.assignSymbols assignSymbols | ||
* @parent can-reflect/shape | ||
* @description Assign well known symbols and values to an object. | ||
* | ||
* @signature `.assignSymbols(target, source)` | ||
* | ||
* Converts each property name on the `source` object to a [can-symbol.for well known symbol] | ||
* and uses that symbol to set the corresponding value on target. | ||
* | ||
* This is used to easily set symbols correctly even when symbol isn't natively supported. | ||
* | ||
* ```js | ||
* canReflect.assignSymbols(Map.prototype, { | ||
* "can.getKeyValue": Map.prototype.get | ||
* }) | ||
* ``` | ||
* | ||
* @param {Object} target The value that will be updated with `source`'s symbols and values. | ||
* @param {Object<name,value>} source A source of symbol names and values to copy to `target`. | ||
* @return {Object} The target. | ||
*/ | ||
assignSymbols: function(target, source){ | ||
@@ -750,5 +888,64 @@ this.eachKey(source, function(value, key){ | ||
}, | ||
isSerializable: isSerializable | ||
isSerializable: isSerializable, | ||
/** | ||
* @function can-reflect/shape.size size | ||
* @parent can-reflect/shape | ||
* @description Return the number of items in the collection. | ||
* | ||
* @signature `.size(target)` | ||
* | ||
* Returns the number of items contained in `target`. Target can | ||
* provide the size using the [can-symbol/symbols/size] symbol. | ||
* | ||
* If the `target` has a numeric `length` property that is greater than or equal to 0, that | ||
* `length` will be returned. | ||
* | ||
* ```js | ||
* canReflect.size([1,2,3]) //-> 3 | ||
* ``` | ||
* | ||
* If the `target` is [can-reflect.isListLike], the values of the list will be counted. | ||
* | ||
* If the `target` is a plain JS object, the number of enumerable properties will be returned. | ||
* | ||
* ```js | ||
* canReflect.size({foo:"bar"}) //-> 1 | ||
* ``` | ||
* | ||
* If the `target` is anything else, `undefined` is returned. | ||
* | ||
* @param {Object} target The container object. | ||
* @return {Number} The number of values in the target. | ||
*/ | ||
size: function(obj){ | ||
var size = obj[sizeSymbol]; | ||
var count = 0; | ||
if(size) { | ||
return size.call(obj); | ||
} | ||
else if(helpers.hasLength(obj)){ | ||
return obj.length | ||
} | ||
else if(typeReflections.isListLike(obj)){ | ||
this.each(obj, function(){ | ||
count++; | ||
}); | ||
return count; | ||
} | ||
else if( obj ) { | ||
for(var prop in obj) { | ||
if(obj.hasOwnProperty(prop)) { | ||
count++; | ||
} | ||
} | ||
return count; | ||
} | ||
else { | ||
return undefined; | ||
} | ||
} | ||
}; | ||
shapeReflections.keys = shapeReflections.getOwnEnumerableKeys; | ||
module.exports = shapeReflections; |
@@ -144,3 +144,3 @@ var canSymbol = require("can-symbol"); | ||
* canReflect.isBuiltIn(null); // -> true | ||
* canReflect.isBuiltIn({}); // -> true | ||
* canReflect.isBuiltIn({}); // -> true | ||
* canReflect.isBuiltIn(1); // -> true | ||
@@ -155,3 +155,3 @@ * canReflect.isBuiltIn([]); // -> true | ||
* ``` | ||
* | ||
* | ||
* Not supported in browsers that have implementations of Map/Set where | ||
@@ -171,3 +171,3 @@ * `toString` is not properly implemented to return `[object Map]`/`[object Set]`. | ||
isPlainObject(obj) || | ||
(Object.prototype.toString.call(obj) !== '[object Object]' && | ||
(Object.prototype.toString.call(obj) !== '[object Object]' && | ||
Object.prototype.toString.call(obj).indexOf('[object ') !== -1)) { | ||
@@ -352,12 +352,3 @@ return true; | ||
} | ||
// The `in` check is from jQuery’s fix for an iOS 8 64-bit JIT object length bug: | ||
// https://github.com/jquery/jquery/pull/2185 | ||
var length = list && type !== 'boolean' && | ||
typeof list !== 'number' && | ||
"length" in list && list.length; | ||
// var length = "length" in obj && obj.length; | ||
return typeof list !== "function" && | ||
( length === 0 || typeof length === "number" && length > 0 && ( length - 1 ) in list ); | ||
return helpers.hasLength(list); | ||
} | ||
@@ -364,0 +355,0 @@ |
123537
3233