Skip to content
Browse files

many edge case bugs fixes

  • Loading branch information...
1 parent 32316d1 commit c874f0da2d7226573f0f22709fd80d902a1e5110 @ericz ericz committed Aug 16, 2011
Showing with 113 additions and 43 deletions.
  1. +103 −33 lib/client/now.js
  2. +10 −10 lib/scopeTable.js
View
136 lib/client/now.js
@@ -19,14 +19,18 @@
try {
Object.defineProperty({}, '', {});
return false;
- } catch (err) {
- return true;
+ } catch (err) {
+ if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) {
+ return false;
+ } else {
+ return true;
+ }
}
- return true;
}());
-
+
var fqnMap = {
data: {},
+ arrays: {},
get: function (fqn) {
return fqnMap.data[fqn];
},
@@ -51,7 +55,7 @@
deleteChildren: function (fqn) {
var keys = this.data[fqn];
var children = [];
- if (Array.isArray(this.data[fqn])) {
+ if (util.isArray(this.data[fqn])) {
// Deleting a child will remove it via splice.
for (var i = 0; keys.length;) {
// Recursive delete all children.
@@ -75,7 +79,14 @@
var children = this.deleteChildren(fqn);
children.push(fqn);
delete this.data[fqn];
+ this.unflagAsArray(fqn);
return children;
+ },
+ flagAsArray: function (val) {
+ return (this.arrays[val] = true);
+ },
+ unflagAsArray: function (val) {
+ delete this.arrays[val];
}
};
util = {
@@ -130,6 +141,9 @@
var currVar = util.forceGetParentVarAtFqn(scope, fqn);
var key = path.pop();
fqnMap.set(fqn, (value && typeof value === 'object') ? [] : value);
+ if (util.isArray(value)) {
+ fqnMap.flagAsArray(fqn);
+ }
currVar[key] = value;
if (!(isIE || util.isArray(currVar))) {
util.watch(currVar, key, fqn);
@@ -196,17 +210,14 @@
if (val && typeof val === 'object') {
fqnMap.deleteVar(fqn);
socket.emit('del', [fqn]);
- delete obj[label];
- obj[label] = newVal;
- lib.processScope(obj, fqn.substring(0, fqn.lastIndexOf('.')));
+ val = newVal;
+ lib.processScope(obj, fqn.substring(0, fqn.lastIndexOf('.')));
return newVal;
}
- val = newVal;
if (newVal && typeof newVal === 'object') {
fqnMap.deleteVar(fqn);
socket.emit('del', [fqn]);
- delete obj[label];
- obj[label] = newVal;
+ val = newVal;
lib.processScope(obj, fqn.substring(0, fqn.lastIndexOf('.')));
return newVal;
}
@@ -224,13 +235,28 @@
if (Object.defineProperty) {
Object.defineProperty(obj, label, {get: getter, set: setter});
} else {
- if (obj.__defineGetter__) {
- obj.__defineGetter__(label, getter);
- }
if (obj.__defineSetter__) {
obj.__defineSetter__(label, setter);
}
+ if (obj.__defineGetter__) {
+ obj.__defineGetter__(label, getter);
+ }
}
+ },
+
+ unwatch: function(obj, label) {
+ //try {
+ if (Object.defineProperty) {
+ Object.defineProperty(obj, label, {get: undefined, set: undefined});
+ } else {
+ if (obj.__defineSetter__) {
+ obj.__defineSetter__(label, undefined);
+ }
+ if (obj.__defineGetter__) {
+ obj.__defineGetter__(label, undefined);
+ }
+ }
+ //} catch (e) {}
}
};
@@ -323,7 +349,9 @@
constructRemoteFunction: function (fqn) {
var remoteFn = function () {
+
lib.processNowScope();
+
var args = [];
for (var i = 0, ii = arguments.length; i < ii; i++) {
args[i] = arguments[i];
@@ -406,41 +434,77 @@
}
},
traverseScope: function (obj, path, data) {
+
if (obj && typeof obj === 'object') {
var objIsArray = util.isArray(obj);
var keys = fqnMap.get(path);
- var hasProperties = false;
for (var key in obj) {
- hasProperties = true;
var fqn = path + '.' + key;
- var val = obj[key];
-
+
if (fqn === 'now.core' || fqn === 'now.ready') {
continue;
}
- var type = typeof val;
+
if (util.hasProperty(obj, key)) {
- if (isIE || objIsArray) {
- if (!(val && type === 'object') && fqnMap.get(fqn) !== val) {
- fqnMap.set(fqn, val);
- data[fqn] = util.getValOrFqn(val, fqn);
- }
- } else {
- if (fqnMap.get(fqn) === undefined) {
- util.watch(obj, key, fqn);
- if (type !== 'object' || !val) {
+
+ var val = obj[key];
+ var mapVal = fqnMap.get(fqn);
+ var wasArray = fqnMap.arrays[fqn];
+ var valIsArray = util.isArray(val);
+ var valIsObj = val && typeof val === 'object';
+ var wasObject = util.isArray(mapVal) && !wasArray;
+
+ if (objIsArray || isIE) {
+ if (valIsObj) {
+ if (valIsArray) {
+ // Value is an array
+ if (!wasArray) {
+ fqnMap.set(fqn, []);
+ fqnMap.flagAsArray(fqn);
+ data[fqn] = [];
+ }
+ } else {
+ // Value is object
+ if (!wasObject) {
+ fqnMap.set(fqn, []);
+ fqnMap.unflagAsArray(fqn);
+ data[fqn] = {};
+ }
+ }
+ } else {
+ // Value is primitive / func
+ if (val !== mapVal) {
fqnMap.set(fqn, val);
+ fqnMap.unflagAsArray(fqn);
data[fqn] = util.getValOrFqn(val, fqn);
}
}
+ } else if (mapVal === undefined) {
+ util.watch(obj, key, fqn);
+
+ if (valIsObj) {
+ if (valIsArray) {
+ // Value is array
+ fqnMap.set(fqn, []);
+ fqnMap.flagAsArray(fqn);
+ data[fqn] = [];
+ } else {
+ // Value is object
+ fqnMap.set(fqn, []);
+ data[fqn] = {};
+ }
+ } else {
+ // Value is primitive / func
+ fqnMap.set(fqn, val);
+ data[fqn] = util.getValOrFqn(val, fqn);
+ }
+ }
+ if (valIsObj) {
+ lib.traverseScope(val, fqn, data);
}
}
- lib.traverseScope(val, fqn, data);
- }
- if (!(hasProperties || fqnMap.get(path))) {
- fqnMap.set(path, []);
- data[path] = obj;
}
+
if (keys && typeof keys === 'object') {
var toDelete = [];
// Scan for deleted keys.
@@ -457,7 +521,13 @@
}
}
}
+
+ },
+
+ traverseScopeIE: function (obj, path, data) {
}
+
+
};
var dependencies = [
View
20 lib/scopeTable.js
@@ -17,14 +17,15 @@ ScopeTable.prototype.set = function (fqn, val) {
var parent = fqn.substring(0, lastIndex);
this.addParent(parent, fqn.substring(lastIndex + 1));
}
+ delete this.arrays[fqn];
return (this.data[fqn] = val);
};
ScopeTable.prototype.addParent = function (parent, key) {
- if (parent && !Array.isArray(this.data[parent])) {
- this.set(parent, []); // Handle changing a non-object to an object.
- }
if (parent) {
+ if (!Array.isArray(this.data[parent])) {
+ this.set(parent, []); // Handle changing a non-object to an object.
+ }
this.data[parent].push(key);
}
};
@@ -44,21 +45,20 @@ ScopeTable.prototype.deleteVar = function (fqn) {
var lastIndex = fqn.lastIndexOf('.');
var parent = fqn.substring(0, lastIndex);
- if (nowUtil.hasProperty(this.data, parent)) {
-
+ if (nowUtil.hasProperty(this.data, fqn)) {
// Remove from its parent.
var index = this.data[parent].indexOf(fqn.substring(lastIndex + 1));
if (index > -1) {
this.data[parent].splice(index, 1);
}
+ this.deleteChildren(fqn);
+ delete this.data[fqn];
+ delete this.arrays[fqn];
}
- this.deleteChildren(fqn);
- delete this.data[fqn];
- delete this.arrays[fqn];
};
-ScopeTable.prototype.flagAsArray = function (val, len) {
- return (this.arrays[val] = len);
+ScopeTable.prototype.flagAsArray = function (fqn, len) {
+ return (this.arrays[fqn] = len);
};
exports.ScopeTable = ScopeTable;

0 comments on commit c874f0d

Please sign in to comment.
Something went wrong with that request. Please try again.