diff --git a/bower.json b/bower.json
index 2186e53884f..0e50ae2de9c 100644
--- a/bower.json
+++ b/bower.json
@@ -11,6 +11,7 @@
"license": "MIT",
"devDependencies": {
"qunit": "~1.12.0",
- "zepto": "~1.0.0"
+ "zepto": "~1.0.0",
+ "benchmark": "~1.0.0"
}
}
diff --git a/lib/stealconfig.js b/lib/stealconfig.js
index e721889a195..891aad726a6 100644
--- a/lib/stealconfig.js
+++ b/lib/stealconfig.js
@@ -28,7 +28,8 @@
map: {
"*": {
"jquery/jquery.js": "jquery",
- "can/util/util.js": "can/util/jquery/jquery.js"
+ "can/util/util.js": "can/util/jquery/jquery.js",
+ "benchmark/benchmark.js":"benchmark"
}
},
paths: {
@@ -38,7 +39,8 @@
"yui/yui.js": "lib/yui-3.7.3.js",
"zepto/zepto.js": "lib/zepto.1.0.js",
"can/": "",
- "jquerypp/": "http://jquerypp.com/release/1.0.1/steal/"
+ "jquerypp/": "http://jquerypp.com/release/1.0.1/steal/",
+ "benchmark": "bower_components/benchmark/benchmark.js"
},
shim: {
jquery: {
diff --git a/list/list.js b/list/list.js
index 009393bf7ef..2c407e4236b 100644
--- a/list/list.js
+++ b/list/list.js
@@ -79,11 +79,18 @@ steal("can/util","can/map", function(can, Map){
this.length = 0;
can.cid(this, ".map")
this._init = 1;
+ instances = instances || [];
+
+
if( can.isDeferred(instances) ) {
this.replace(instances)
} else {
+ var teardownMapping = instances.length && can.Map.helpers.addToMap(instances, this);
this.push.apply(this, can.makeArray(instances || []));
}
+
+ teardownMapping && teardownMapping();
+
// this change needs to be ignored
this.bind('change',can.proxy(this._changes,this));
can.simpleExtend(this, options);
diff --git a/map/benchmark.html b/map/benchmark.html
new file mode 100644
index 00000000000..90b21300be9
--- /dev/null
+++ b/map/benchmark.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/map/map.js b/map/map.js
index 5c9a663b968..0dbb95396ff 100644
--- a/map/map.js
+++ b/map/map.js
@@ -50,27 +50,6 @@ steal('can/util','can/util/bind','can/construct', 'can/util/batch',function(can,
// A map that temporarily houses a reference
// to maps that have already been made for a plain ole JS object
madeMap = null,
- addToMap = function(obj, instance){
- var teardown = false;
- if(!madeMap){
- teardown = true;
- madeMap = {}
- }
- // record if it has a Cid before we add one
- var hasCid = obj._cid;
- var cid = can.cid(obj);
-
- // only update if there already isn't one
- if( !madeMap[cid] ){
-
- madeMap[cid] = {
- obj: obj,
- instance: instance,
- added: !hasCid
- }
- }
- return teardown;
- },
teardownMap = function(){
for(var cid in madeMap){
if(madeMap[cid].added) {
@@ -82,6 +61,7 @@ steal('can/util','can/util/bind','can/construct', 'can/util/batch',function(can,
getMapFromObject = function(obj){
return madeMap && madeMap[obj._cid] && madeMap[obj._cid].instance
};
+
/**
* @add can.Map
*/
@@ -99,9 +79,13 @@ steal('can/util','can/util/bind','can/construct', 'can/util/batch',function(can,
if(!this.defaults){
this.defaults = {};
}
+ // a list of the compute properties
+ this._computes = [];
for(var prop in this.prototype){
if(typeof this.prototype[prop] !== "function"){
this.defaults[prop] = this.prototype[prop];
+ } else if(this.prototype[prop].isComputed) {
+ this._computes.push(prop)
}
}
}
@@ -111,6 +95,7 @@ steal('can/util','can/util/bind','can/construct', 'can/util/batch',function(can,
}
},
+ _computes: [],
// keep so it can be overwritten
bind: can.bindAndSetup,
on: can.bindAndSetup,
@@ -118,6 +103,28 @@ steal('can/util','can/util/bind','can/construct', 'can/util/batch',function(can,
off: can.unbindAndTeardown,
id: "id",
helpers: {
+ addToMap: function(obj, instance){
+ var teardown;
+ if(!madeMap){
+ teardown = teardownMap;
+ madeMap = {}
+ }
+ // record if it has a Cid before we add one
+ var hasCid = obj._cid;
+ var cid = can.cid(obj);
+
+ // only update if there already isn't one
+ if( !madeMap[cid] ){
+
+ madeMap[cid] = {
+ obj: obj,
+ instance: instance,
+ added: !hasCid
+ }
+ }
+ return teardown;
+ },
+
canMakeObserve : function( obj ) {
return obj && !can.isDeferred(obj) && (can.isArray(obj) || can.isPlainObject( obj ) || ( obj instanceof can.Map ));
},
@@ -228,7 +235,7 @@ steal('can/util','can/util/bind','can/construct', 'can/util/batch',function(can,
// Sets all `attrs`.
this._init = 1;
this._setupComputes();
- var teardownMapping = obj && addToMap(obj, this);
+ var teardownMapping = obj && can.Map.helpers.addToMap(obj, this);
/**
* @property {*} can.Map.prototype.DEFAULT-ATTR
*
@@ -263,9 +270,9 @@ steal('can/util','can/util/bind','can/construct', 'can/util/batch',function(can,
*/
var data = can.extend( can.extend(true,{},this.constructor.defaults || {}), obj )
this.attr(data);
- if(teardownMapping){
- teardownMap()
- }
+
+ teardownMapping && teardownMapping()
+
this.bind('change',can.proxy(this._changes,this));
delete this._init;
@@ -358,17 +365,15 @@ steal('can/util','can/util/bind','can/construct', 'can/util/batch',function(can,
* Getter/Setter computes.
*/
_setupComputes: function(){
- var prototype = this.constructor.prototype;
- this._computedBindings = {}
- for(var prop in prototype){
- if(prototype[prop] && prototype[prop].isComputed){
- this[prop] = prototype[prop].clone(this);
- this._computedBindings[prop] = {
- count: 0
- }
+ var computes = this.constructor._computes;
+ this._computedBindings = {};
+ for(var i = 0, len = computes.length, prop; i< len; i++) {
+ prop = computes[i];
+ this[prop] = this[prop].clone(this);
+ this._computedBindings[prop] = {
+ count: 0
}
}
-
},
_bindsetup: makeBindSetup(),
_bindteardown: function(){
diff --git a/map/map_benchmark.js b/map/map_benchmark.js
new file mode 100644
index 00000000000..2a9d302175b
--- /dev/null
+++ b/map/map_benchmark.js
@@ -0,0 +1,18 @@
+steal('can/map', 'can/list','can/test/benchmarks.js',function(Map, List, benchmarks){
+
+ benchmarks.add(
+ "Adding a big array to an object",
+ function(){
+ var map = new can.Map(),
+ objects = [];
+
+ for (var i = 0; i < 10; i++){
+ objects.push({prop: 'prop', nest: {prop: 'prop', nest: {prop: 'prop'}}})
+ }
+ },
+ function(){
+ map.attr('obj', objects)
+ });
+
+
+})
diff --git a/test/benchmarks.js b/test/benchmarks.js
new file mode 100644
index 00000000000..4de96a2690d
--- /dev/null
+++ b/test/benchmarks.js
@@ -0,0 +1,33 @@
+steal("steal","benchmark", function(steal){
+
+ var suite = new Benchmark.Suite;
+
+ suite.on('cycle', function(event) {
+ console.log(String(event.target));
+ })
+
+ var benchmarks = {
+ add: function(name, setup, benchmark){
+ if(!benchmark){
+ benchmark = setup;
+ setup = undefined
+ }
+ suite.add(name, benchmark, {
+ setup: setup
+ });
+ return this;
+ },
+ run: function(){
+ suite.run({ 'async': true, 'queued': true });
+ },
+ suite: suite,
+ on: function(){
+ return suite.on.apply(this, arguments)
+ }
+ }
+ steal.bind("done", function(){
+ benchmarks.run();
+ })
+
+ return benchmarks;
+})
diff --git a/util/jquery/jquery.js b/util/jquery/jquery.js
index 3fc3de0eeaa..acadf8386cb 100644
--- a/util/jquery/jquery.js
+++ b/util/jquery/jquery.js
@@ -84,6 +84,11 @@ steal('jquery', 'can/util/can.js', 'can/util/array/each.js', "can/util/inserted"
}
return this;
+ },
+ proxy: function(fn, context){
+ return function(){
+ return fn.apply(context, arguments)
+ }
}
});