bug fix - when setting a custom attr that points to self, the setAttrs method no longer gets stuck in a recursive loop throwing a stack overflow error. Also, objects that were instantiated from a class (non-literal objects) are no longer serializable

This commit is contained in:
Eric Rowell 2012-05-26 18:31:13 -07:00
parent fd6bdb570c
commit 44ba6f7e5b
6 changed files with 87 additions and 30 deletions

26
dist/kinetic-core.js vendored
View File

@ -148,7 +148,7 @@ Kinetic.GlobalObject = {
} }
}, },
/* /*
* utilities * cherry-picked and modified utilities from underscore.js
*/ */
_isElement: function(obj) { _isElement: function(obj) {
return !!(obj && obj.nodeType == 1); return !!(obj && obj.nodeType == 1);
@ -166,6 +166,14 @@ Kinetic.GlobalObject = {
_isNumber: function(obj) { _isNumber: function(obj) {
return toString.call(obj) == '[object Number]'; return toString.call(obj) == '[object Number]';
}, },
_hasMethods: function(obj) {
var names = [];
for(var key in obj) {
if(this._isFunction(obj[key]))
names.push(key);
}
return names.length > 0;
},
/* /*
* The argument can be: * The argument can be:
* - an integer (will be applied to both x and y) * - an integer (will be applied to both x and y)
@ -513,10 +521,10 @@ Kinetic.Node.prototype = {
} }
/* /*
* if property is an object, then add an empty object * if property is a pure object (no methods), then add an empty object
* to the node and then traverse * to the node and then traverse
*/ */
if(go._isObject(val) && !go._isArray(val) && !go._isElement(val)) { if(go._isObject(val) && !go._isArray(val) && !go._isElement(val) && !go._hasMethods(val)) {
if(obj[key] === undefined) { if(obj[key] === undefined) {
obj[key] = {}; obj[key] = {};
} }
@ -1628,12 +1636,12 @@ Kinetic.Stage.prototype = {
var cleanAttrs = node.attrs; var cleanAttrs = node.attrs;
// remove function, image, and DOM attrs // remove function, image, DOM, and objects with methods
for (var key in cleanAttrs) { for(var key in cleanAttrs) {
var val = cleanAttrs[key]; var val = cleanAttrs[key];
if (go._isFunction(val) || go._isElement(val)) { if(go._isFunction(val) || go._isElement(val) || go._hasMethods(val)) {
cleanAttrs[key] = undefined; cleanAttrs[key] = undefined;
} }
} }
obj.attrs = cleanAttrs; obj.attrs = cleanAttrs;

File diff suppressed because one or more lines are too long

View File

@ -120,7 +120,7 @@ Kinetic.GlobalObject = {
} }
}, },
/* /*
* utilities * cherry-picked and modified utilities from underscore.js
*/ */
_isElement: function(obj) { _isElement: function(obj) {
return !!(obj && obj.nodeType == 1); return !!(obj && obj.nodeType == 1);
@ -138,6 +138,14 @@ Kinetic.GlobalObject = {
_isNumber: function(obj) { _isNumber: function(obj) {
return toString.call(obj) == '[object Number]'; return toString.call(obj) == '[object Number]';
}, },
_hasMethods: function(obj) {
var names = [];
for(var key in obj) {
if(this._isFunction(obj[key]))
names.push(key);
}
return names.length > 0;
},
/* /*
* The argument can be: * The argument can be:
* - an integer (will be applied to both x and y) * - an integer (will be applied to both x and y)

View File

@ -157,10 +157,10 @@ Kinetic.Node.prototype = {
} }
/* /*
* if property is an object, then add an empty object * if property is a pure object (no methods), then add an empty object
* to the node and then traverse * to the node and then traverse
*/ */
if(go._isObject(val) && !go._isArray(val) && !go._isElement(val)) { if(go._isObject(val) && !go._isArray(val) && !go._isElement(val) && !go._hasMethods(val)) {
if(obj[key] === undefined) { if(obj[key] === undefined) {
obj[key] = {}; obj[key] = {};
} }

View File

@ -185,12 +185,12 @@ Kinetic.Stage.prototype = {
var cleanAttrs = node.attrs; var cleanAttrs = node.attrs;
// remove function, image, and DOM attrs // remove function, image, DOM, and objects with methods
for (var key in cleanAttrs) { for(var key in cleanAttrs) {
var val = cleanAttrs[key]; var val = cleanAttrs[key];
if (go._isFunction(val) || go._isElement(val)) { if(go._isFunction(val) || go._isElement(val) || go._hasMethods(val)) {
cleanAttrs[key] = undefined; cleanAttrs[key] = undefined;
} }
} }
obj.attrs = cleanAttrs; obj.attrs = cleanAttrs;

View File

@ -1167,6 +1167,47 @@ Test.prototype.tests = {
}); });
//stage.start(); //stage.start();
}, },
'SHAPE - add shape with custom attr pointing to self': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
circle = new Kinetic.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: 'green',
stroke: 'black',
strokeWidth: 4,
centerOffset: {
x: 0,
y: 0
},
scale: {
x: 2,
y: 2
}
});
layer.add(circle);
stage.add(layer);
/*
* add custom attr that points to self. The setAttrs method should
* not inifinitely recurse causing a stack overflow
*/
circle.setAttrs({
self: circle
});
/*
* serialize the stage. The json should succeed because objects that have
* methods, such as self, are not serialized, and will therefore avoid
* circular json errors.
*/
var json = stage.toJSON();
},
'SHAPE - set fill after instantiation': function(containerId) { 'SHAPE - set fill after instantiation': function(containerId) {
var stage = new Kinetic.Stage({ var stage = new Kinetic.Stage({
container: containerId, container: containerId,