Skip to content

Commit

Permalink
Added wrapping of objects when testing for properties. Added hasPrope…
Browse files Browse the repository at this point in the history
…rty() to nowUtil.
  • Loading branch information
steveWang committed May 27, 2011
1 parent 74f8822 commit 38e25bc
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 220 deletions.
102 changes: 55 additions & 47 deletions lib/clientGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ exports.ClientGroup = function ClientGroup(nowCore, socket, groupName){
this.on('disconnect', func);
};

// Store function is called by the proxy object upon variables changes
// Key contains the top level key of the change (ex 'x' if now.x or a child of it was changed)
// Val contains the new value
// Callback contains a callback for use in proxy internals
// Changes contains a key value map of fqn's to new values
// Store function is called by the proxy object upon variables changes.
// Key contains the top level key of the change (ex 'x' if now.x or
// a child of it was changed).
// Val contains the new value.
// Callback contains a callback for use in proxy internals.
// Changes contains a key value map of fqn's to new values.
var store = {
set: function(key, val, callback, changes){

Expand All @@ -46,35 +47,36 @@ exports.ClientGroup = function ClientGroup(nowCore, socket, groupName){
}

function processChanges(key, val, changes){
var currScopes = [];

// Create multicallers for the current group
var data = nowUtil.decycle(val, "now."+key, [function(fqn, func){
var multiCaller = generateMultiCaller(fqn);
nowUtil.createVarAtFqn(fqn, nowScope, multiCaller);
return nowUtil.serializeFunction(fqn, func);
}]);

// Send the changes to everybody in the group
for(var clientId in groupScopes){
socket.clients[clientId].send({type: 'replaceVar', data: {key: key, value: data[0]}});
}

// Put all relevant nowCore.scopes in array so we traverse only once
for(var i in groupScopes) {
currScopes.push(groupScopes[i]);
}
// Don't forget the default scope of the server, which is merged into scopes of new users of group
currScopes.push(defaultScope);

nowUtil.mergeChanges(currScopes, changes);
var currScopes = [];

// Create multicallers for the current group
var data = nowUtil.decycle(val, "now."+key, [function(fqn, func){
var multiCaller = generateMultiCaller(fqn);
nowUtil.createVarAtFqn(fqn, nowScope, multiCaller);
return nowUtil.serializeFunction(fqn, func);
}]);

// Send the changes to everybody in the group
for(var clientId in groupScopes){
socket.clients[clientId].send({type: 'replaceVar', data: {key: key, value: data[0]}});
}

// Put all relevant nowCore.scopes in array so we traverse only once
for(var i in groupScopes) {
currScopes.push(groupScopes[i]);
}
// Don't forget the default scope of the server, which is merged
// into scopes of new users of group
currScopes.push(defaultScope);

nowUtil.mergeChanges(currScopes, changes);

// If is `everyone`, add multicallers to all groups for the change
if(isSuperGroup){
var obj = {};
obj[key] = val;
nowUtil.multiMergeFunctionsToMulticallers(nowCore.groups, obj);
}
// If is `everyone`, add multicallers to all groups for the change
if(isSuperGroup){
var obj = {};
obj[key] = val;
nowUtil.multiMergeFunctionsToMulticallers(nowCore.groups, obj);
}

return data;
}
Expand All @@ -88,32 +90,36 @@ exports.ClientGroup = function ClientGroup(nowCore, socket, groupName){

// Add a clientId to the group, if it isn't already there
function addUser(clientId){
if(Object.prototype.hasOwnProperty.call(nowCore.scopes, clientId)){
if(nowUtil.hasProperty(nowCore.scopes, clientId)){

if(!isSuperGroup){

// If not a super group, merge functions in the new user's scope to the group scope
// If not a super group, merge functions in the new user's
// scope to the group scope
nowUtil.multiMergeFunctionsToMulticallers([this], nowCore.scopes[clientId]);

// Add the group to the user's list of groups
nowCore.clientGroups[clientId][groupName] = this;

// Merge the items in the group's default scope to the proxy, triggering a replaceVar to the client for any changes
// Merge the items in the group's default scope to the proxy,
// triggering a replaceVar to the client for any changes
nowUtil.mergeScopes(nowCore.proxies[clientId], defaultScope);
} else {

// Merge default scope to the user's scope, not triggering a replaceVar to the client. The user already gets the replaceVar in initalizeScope

// Merge default scope to the user's scope, not triggering a
// replaceVar to the client. The user already gets the
// replaceVar in initalizeScope
nowUtil.mergeScopes(nowCore.scopes[clientId], defaultScope);

}

// Add user's scope reference to this users groupScopes
groupScopes[clientId] = nowCore.scopes[clientId];

this.count++;

nowUtil.debug(groupName+" addUser", "adding " + clientId);

// Emit the connect event, along with this.now and this.user
this.emit.apply({_events: this._events, now: nowCore.proxies[clientId], user:nowCore.userObjects[clientId]}, ['connect', clientId]);
} else {
Expand All @@ -123,7 +129,7 @@ exports.ClientGroup = function ClientGroup(nowCore, socket, groupName){
};

function removeUser(clientId){
if(Object.prototype.hasOwnProperty.call(groupScopes, clientId)){
if(nowUtil.hasProperty(groupScopes, clientId)){
nowUtil.debug(groupName+" removeUser", "removing " + clientId);

this.count--;
Expand All @@ -133,13 +139,15 @@ exports.ClientGroup = function ClientGroup(nowCore, socket, groupName){

// Delete this clientId from clientGroups
delete nowCore.clientGroups[clientId][groupName];

// Delete the reference from groupScopes after disconnect event, so any changes can still be made in groupScopes event handler

// Delete the reference from groupScopes after disconnect event,
// so any changes can still be made in groupScopes event handler
delete groupScopes[clientId];
}
};

// Generate the multicaller function, a special function that calls functions at a particular fqn for some group of users
// Generate the multicaller function, a special function that calls
// functions at a particular fqn for some group of users
function generateMultiCaller(fqn){
nowUtil.debug("generateMultiCaller", fqn);

Expand All @@ -165,7 +173,7 @@ exports.ClientGroup = function ClientGroup(nowCore, socket, groupName){

// Return boolean whether group contains a particular clientId
function hasClient(clientId) {
return Object.prototype.hasOwnProperty.call(groupScopes, clientId);
return nowUtil.hasProperty(groupScopes, clientId);
};


Expand Down
4 changes: 2 additions & 2 deletions lib/fileServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ function serveFile(filename, request, response, options){
var options = options || {};

// Write file from cache if possible
if(Object.prototype.hasOwnProperty.call(fileCache, filename)) {
if(nowUtil.hasProperty(fileCache, filename)) {
response.writeHead(200);
response.write(fileCache[filename]);
response.end();
} else {
if(filename.indexOf("/now.js") !== -1) {

// Write file from cache if possible
if(Object.prototype.hasOwnProperty.call(nowFileCache, request.headers.host)) {
if(nowUtil.hasProperty(nowFileCache, request.headers.host)) {

// Write file from cache
response.writeHead(200, {'content-type': 'text/javascript'});
Expand Down
28 changes: 14 additions & 14 deletions lib/now.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ var nowCore = {

// Search (only at top level) of args for functions parameters, and replace with wrapper remote call function
for(var i, ii = theArgs.length; i < ii; i++){
if(Object.prototype.hasOwnProperty.call(theArgs[i], 'type') && theArgs[i].type === 'function'){
if(nowUtil.hasProperty(theArgs[i], 'type') && theArgs[i].type === 'function'){
theArgs[i] = nowCore.constructRemoteFunction(client, theArgs[i].fqn);
}
}
Expand Down Expand Up @@ -84,7 +84,7 @@ var nowCore = {
// Handle variable vale changes in this callback

// If not on blacklist do changes
if(!Object.prototype.hasOwnProperty.call(nowCore.watchersBlacklist[client.sessionId], fqn)){
if(!nowUtil.hasProperty(nowCore.watchersBlacklist[client.sessionId], fqn)){
nowUtil.debug("clientScopeWatcherVariableChanged", fqn + " => " + newVal);
if(oldVal && typeof oldVal === "object") {
var oldFqns = nowUtil.getAllChildFqns(oldVal, fqn);
Expand Down Expand Up @@ -132,7 +132,7 @@ var nowCore = {
}
}

if(Object.prototype.hasOwnProperty.call(data.value, "type") && data.value.type === 'function') {
if(nowUtil.hasProperty(data.value, "type") && data.value.type === 'function') {
data.value = nowCore.constructRemoteFunction(client, data.value.fqn);
newVal = data.value;
}
Expand Down Expand Up @@ -163,7 +163,7 @@ var nowCore = {
var theArgs = Array.prototype.slice.call(arguments);

for(var i in theArgs){
if(typeof theArgs[i] === 'function' && Object.prototype.hasOwnProperty.call(theArgs, i)){
if(typeof theArgs[i] === 'function' && nowUtil.hasProperty(theArgs, i)){
var closureId = "closure" + "_" + theArgs[i].name + "_" + nowUtil.generateRandomString(10);
nowCore.closures[closureId] = theArgs[i];
theArgs[i] = {type: 'function', fqn: closureId};
Expand Down Expand Up @@ -252,38 +252,38 @@ var nowLib = {
this.traverseObject = function(path, obj, arrayBlacklist, objClone) {
// Prevent new array items from being double counted
for(var key in obj){
if(Object.prototype.hasOwnProperty.call(obj, key)){
if(nowUtil.hasProperty(obj, key)){
var fqn = path+"."+key;
// Ignore ready function
if(Object.prototype.hasOwnProperty.call(badNames, fqn)) {
if(nowUtil.hasProperty(badNames, fqn)) {
continue;
}
if(isIE && !nowUtil.isArray(obj) && typeof obj[key] !== "object" && Object.prototype.hasOwnProperty.call(objClone, key) && obj[key] !== objClone[key]) {
if(isIE && !nowUtil.isArray(obj) && typeof obj[key] !== "object" && nowUtil.hasProperty(objClone, key) && obj[key] !== objClone[key]) {
this.variableChanged(key, fqn, objClone[key], obj[key]);
objClone[key] = nowUtil.shallowCopy(obj[key]);
}
if(!Object.prototype.hasOwnProperty.call(this.data.watchedKeys, fqn)) {
if(!nowUtil.hasProperty(this.data.watchedKeys, fqn)) {
if(!isIE){
nowUtil.watch(obj, key, fqn, this.variableChanged);
} else {
objClone[key] = nowUtil.shallowCopy(obj[key]);
}
if(!Object.prototype.hasOwnProperty.call(arrayBlacklist, fqn)) {
if(!nowUtil.hasProperty(arrayBlacklist, fqn)) {
this.variableChanged(key, fqn, "", obj[key]);
}
this.data.watchedKeys[fqn] = true;
}

if(obj[key] && typeof obj[key] === 'object') {
if(nowUtil.isArray(obj[key])) {
if(Object.prototype.hasOwnProperty.call(this.data.hashedArrays, fqn)){
if(nowUtil.hasProperty(this.data.hashedArrays, fqn)){
var diff = this.compareArray(this.data.hashedArrays[fqn], obj[key]);
if(diff === false) {
// Replace the whole array
this.variableChanged(key, fqn, this.data.hashedArrays[fqn], obj[key]);
} else if(diff !== true) {
for(var i in diff) {
if(Object.prototype.hasOwnProperty.call(diff, i)){
if(nowUtil.hasProperty(diff, i)){
arrayBlacklist[fqn+"."+i] = true;
this.variableChanged(i, fqn+"."+i, this.data.hashedArrays[fqn][i], diff[i]);
}
Expand All @@ -292,7 +292,7 @@ var nowLib = {
}
this.data.hashedArrays[fqn] = obj[key].slice(0);
}
if(isIE && (!Object.prototype.hasOwnProperty.call(objClone, key) || !(typeof objClone[key] === "object"))) {
if(isIE && (!nowUtil.hasProperty(objClone, key) || !(typeof objClone[key] === "object"))) {
if(nowUtil.isArray(obj[key])) {
objClone[key] = [];
} else {
Expand Down Expand Up @@ -332,7 +332,7 @@ var nowLib = {
var modified = false;
if(newArr.length >= oldArr.length) {
for(var i in newArr) {
if(!Object.prototype.hasOwnProperty.call(oldArr, i) || newArr[i] !== oldArr[i]) {
if(!nowUtil.hasProperty(oldArr, i) || newArr[i] !== oldArr[i]) {
result[i] = newArr[i];
modified = true;
}
Expand All @@ -347,7 +347,7 @@ var nowLib = {
handleNewConnection: function(client){
client.on('message', function(message){
var messageObj = message;
if(Object.prototype.hasOwnProperty.call(messageObj, "type") && Object.prototype.hasOwnProperty.call(nowCore.messageHandlers, messageObj.type)) {
if(nowUtil.hasProperty(messageObj, "type") && nowUtil.hasProperty(nowCore.messageHandlers, messageObj.type)) {
nowCore.messageHandlers[messageObj.type](client, messageObj.data);
}
});
Expand Down
Loading

0 comments on commit 38e25bc

Please sign in to comment.