Skip to content

Commit

Permalink
Merge pull request #43 from canjs/42-set-map
Browse files Browse the repository at this point in the history
adds Map, Set and Weak support
  • Loading branch information
justinbmeyer authored Sep 21, 2017
2 parents 88da6fc + 0851c44 commit 1d9c253
Show file tree
Hide file tree
Showing 11 changed files with 357 additions and 54 deletions.
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
2 changes: 2 additions & 0 deletions can-reflect-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ require("./reflections/shape/shape-test");
require("./reflections/get-set/get-set-test");
require("./reflections/call/call-test");
require("./reflections/observe/observe-test");
require("./types/map-test");
require("./types/set-test");
3 changes: 3 additions & 0 deletions can-reflect.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@ var reflect = {};
}
});

require("./types/map");
require("./types/set");

module.exports = namespace.Reflect = reflect;
25 changes: 0 additions & 25 deletions index.html

This file was deleted.

19 changes: 15 additions & 4 deletions reflections/get-set/get-set.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var reflections = {
*
* @signature `setKeyValue(obj, key, value)`
*
* Set the property on Map-like `obj`, identified by the String or Symbol value `key`, to the value `value`.
* Set the property on Map-like `obj`, identified by the String, Symbol or Object value `key`, to the value `value`.
* The default behavior can be overridden on `obj` by implementing [can-symbol/symbols/setKeyValue @@@@can.setKeyValue],
* otherwise native named property access is used for string keys, and `Object.defineProperty` is used to set symbols.
*
Expand Down Expand Up @@ -179,12 +179,23 @@ var reflections = {
}
},

splice: function(obj, index, howMany, values){
splice: function(obj, index, removing, adding){
var howMany;
if(typeof removing !== "number") {
var updateValues = obj[canSymbol.for("can.updateValues")];
if(updateValues) {
return updateValues.call(obj, index, removing, adding);
}
howMany = removing.length;
} else {
howMany = removing;
}

var splice = obj[canSymbol.for("can.splice")];
if(splice) {
return splice.call(obj, index, howMany, values);
return splice.call(obj, index, howMany, adding);
}
return [].splice.apply(obj, [index, howMany].concat(values) );
return [].splice.apply(obj, [index, howMany].concat(adding) );
}
};
/**
Expand Down
100 changes: 75 additions & 25 deletions reflections/shape/shape.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ var getSetReflections = require("../get-set/get-set");
var typeReflections = require("../type/type");
var helpers = require("../helpers");

var shapeReflections;

var shiftFirstArgumentToThis = function(func){
return function(){
Expand All @@ -17,6 +18,8 @@ var shiftedGetKeyValue = shiftFirstArgumentToThis(getSetReflections.getKeyValue)
var setKeyValueSymbol = canSymbol.for("can.setKeyValue");
var shiftedSetKeyValue = shiftFirstArgumentToThis(getSetReflections.setKeyValue);

var sizeSymbol = canSymbol.for("can.size");

var serializeMap = null;

var hasUpdateSymbol = helpers.makeGetFirstSymbolValue(["can.updateDeep","can.assignDeep","can.setKeyValue"]);
Expand Down Expand Up @@ -122,16 +125,53 @@ function makeSerializer(methodName, symbolsToCheck){
};
}

// returns a Map type of the keys mapped to true
var makeMap;
if(typeof Map !== "undefined") {
makeMap = function(keys) {
var map = new Map();
shapeReflections.eachIndex(keys, function(key){
map.set(key, true);
})
return map;
};
} else {
makeMap = function(keys) {
var map = {};
keys.forEach(function(key){
map[key] = true;
});


function makeMap(keys) {
var map = {};
keys.forEach(function(key){
map[key] = true;
});
return map;
return {
get: function(key){
return map[key];
},
set: function(key, value) {
map[key] = value;
},
keys: function(){
return keys
}
};
};
}

// creates an optimized hasOwnKey lookup.
// If the object has hasOwnKey, then we just use that.
// Otherwise, try to put all keys in a map.
var fastHasOwnKey = function(obj){
var hasOwnKey = obj[canSymbol.for("can.hasOwnKey")];
if(hasOwnKey) {
return hasOwnKey.bind(obj);
} else {
var map = makeMap( shapeReflections.getOwnEnumerableKeys(obj) );
return function(key) {
return map.get(key)
};
}
};


// combines patches if it makes sense
function addPatch(patches, patch) {
var lastPatch = patches[patches.length -1];
Expand Down Expand Up @@ -177,7 +217,7 @@ function updateDeepList(target, source, isAssign) {
return target;
}

var shapeReflections = {
shapeReflections = {
/**
* @function {Object, function(*), [Object]} can-reflect/shape.each each
* @parent can-reflect/shape
Expand All @@ -189,7 +229,7 @@ var shapeReflections = {
* iterating over numeric indexes from 0 to `obj.length - 1` and calling `callback` with each property and
* index, optionally with `context` as `this` (defaulting to `obj`). If not, `each` functions as
* [can-reflect/shape.eachKey eachKey],
* iterating over every Number and String key on `obj` and calling `callback` on each one.
* iterating over every key on `obj` and calling `callback` on each one.
*
* ```
* var foo = new DefineMap({ bar: "baz" });
Expand Down Expand Up @@ -267,6 +307,14 @@ var shapeReflections = {
eachListLike: function(list, callback, context){
var index = -1;
var length = list.length;
if( length === undefined ) {
var size = list[sizeSymbol];
if(size) {
length = size.call(list);
} else {
throw new Error("can-reflect: unable to iterate.");
}
}

while (++index < length) {
var item = list[index];
Expand Down Expand Up @@ -528,20 +576,20 @@ var shapeReflections = {

assignMap: function(target, source) {
// read each key and set it on target
var targetKeyMap = makeMap(this.getOwnEnumerableKeys(target));
var hasOwnKey = fastHasOwnKey(target);
var getKeyValue = target[getKeyValueSymbol] || shiftedGetKeyValue;
var setKeyValue = target[setKeyValueSymbol] || shiftedSetKeyValue;
this.eachKey(source,function(value, key){
// if the target doesn't have this key or the keys are not the same
if(!targetKeyMap[key] || getKeyValue.call(target, key) !== value) {
if(!hasOwnKey(key) || getKeyValue.call(target, key) !== value) {
setKeyValue.call(target, key, value);
}
});
return target;
},
assignList: function(target, source) {
var inserting = this.toArray(source);
getSetReflections.splice(target, 0, inserting.length, inserting );
getSetReflections.splice(target, 0, inserting, inserting );
return target;
},
assign: function(target, source) {
Expand All @@ -555,12 +603,12 @@ var shapeReflections = {
},
assignDeepMap: function(target, source) {

var targetKeyMap = makeMap(this.getOwnEnumerableKeys(target));
var hasOwnKey = fastHasOwnKey(target);
var getKeyValue = target[getKeyValueSymbol] || shiftedGetKeyValue;
var setKeyValue = target[setKeyValueSymbol] || shiftedSetKeyValue;

this.eachKey(source, function(newVal, key){
if(!targetKeyMap[key]) {
if(!hasOwnKey(key)) {
// set no matter what
getSetReflections.setKeyValue(target, key, newVal);
} else {
Expand Down Expand Up @@ -601,11 +649,11 @@ var shapeReflections = {
var targetSetKeyValue = target[setKeyValueSymbol] || shiftedSetKeyValue;

this.eachKey(target, function(curVal, key){
if(!sourceKeyMap[key]) {
if(!sourceKeyMap.get(key)) {
getSetReflections.deleteKeyValue(target, key);
return;
}
sourceKeyMap[key] = false;
sourceKeyMap.set(key, false);
var newVal = sourceGetKeyValue.call(source, key);

// if either was primitive, no recursive update possible
Expand All @@ -614,16 +662,18 @@ var shapeReflections = {
}
}, this);

for(var key in sourceKeyMap) {
if(sourceKeyMap[key]) {
this.eachIndex(sourceKeyMap.keys(), function(key){
if(sourceKeyMap.get(key)) {
targetSetKeyValue.call(target, key, sourceGetKeyValue.call(source, key) );
}
}
})

return target;
},
updateList: function(target, source) {
var inserting = this.toArray(source);
getSetReflections.splice(target, 0, target.length, inserting );

getSetReflections.splice(target, 0, target, inserting );
return target;
},
update: function(target, source) {
Expand All @@ -643,11 +693,11 @@ var shapeReflections = {

this.eachKey(target, function(curVal, key){

if(!sourceKeyMap[key]) {
if(!sourceKeyMap.get(key)) {
getSetReflections.deleteKeyValue(target, key);
return;
}
sourceKeyMap[key] = false;
sourceKeyMap.set(key, false);
var newVal = sourceGetKeyValue.call(source, key);

// if either was primitive, no recursive update possible
Expand All @@ -659,11 +709,11 @@ var shapeReflections = {

}, this);

for(var key in sourceKeyMap) {
if(sourceKeyMap[key]) {
this.eachIndex(sourceKeyMap.keys(), function(key){
if(sourceKeyMap.get(key)) {
targetSetKeyValue.call(target, key, sourceGetKeyValue.call(source, key) );
}
}
})
return target;
},
updateDeepList: function(target, source) {
Expand Down
Loading

0 comments on commit 1d9c253

Please sign in to comment.