New World stack mechanism; bug fixes

This commit is contained in:
Tony Garnock-Jones 2013-10-18 09:58:08 +01:00
parent 5265f42beb
commit 35f17da335
2 changed files with 57 additions and 51 deletions

View File

@ -25,7 +25,6 @@ JQueryDriver.prototype.updateHandlerMap = function (routes) {
handler = (function (selector, eventName) { // JS is broken handler = (function (selector, eventName) { // JS is broken
return World.wrap(function (e) { return World.wrap(function (e) {
World.send(["jQuery", selector, eventName, e]); World.send(["jQuery", selector, eventName, e]);
World.current.startStepping();
}); });
})(selector, eventName); })(selector, eventName);
console.log("jQuery", "installing", selector, eventName); console.log("jQuery", "installing", selector, eventName);
@ -35,7 +34,7 @@ JQueryDriver.prototype.updateHandlerMap = function (routes) {
} }
} }
for (var key in this.handlerMap) { for (var key in this.handlerMap) {
if (hasOwnProperty(this.handlerMap, key) && !hasOwnProperty(newMap, key)) { if (this.handlerMap.hasOwnProperty(key) && !(key in newMap)) {
var keyArray = JSON.parse(key); var keyArray = JSON.parse(key);
var handler = this.handlerMap[key]; var handler = this.handlerMap[key];
var selector = keyArray[0]; var selector = keyArray[0];
@ -58,7 +57,7 @@ JQueryDriver.prototype.handleEvent = function (e) {
}; };
var g = new Ground(function () { var g = new Ground(function () {
console.log('here'); console.log('starting ground boot');
World.spawn(new Spy()); World.spawn(new Spy());
World.spawn(new JQueryDriver()); World.spawn(new JQueryDriver());
World.spawn({ World.spawn({
@ -70,7 +69,12 @@ var g = new Ground(function () {
World.send({msg: 'hello inner world'}, 0); World.send({msg: 'hello inner world'}, 0);
}, },
handleEvent: function (e) { handleEvent: function (e) {
console.log('dummy handleEvent', e); if (e.type === "send" && e.message[0] === "jQuery") {
console.log("got a click");
World.updateRoutes([]);
} else {
console.log('dummy handleEvent', e);
}
} }
}); });
}); });

View File

@ -146,7 +146,7 @@ function filterEvent(e, routes) {
} }
} }
} }
return result.length ? updateRoutes(result) : null; return updateRoutes(result);
case "send": case "send":
for (var i = 0; i < routes.length; i++) { for (var i = 0; i < routes.length; i++) {
var r = routes[i]; var r = routes[i];
@ -180,22 +180,51 @@ function World(bootFn) {
/* Class state / methods */ /* Class state / methods */
World.current = null; // parameter World.stack = [];
World.current = function () {
return World.stack[World.stack.length - 1];
};
World.send = function (m, metaLevel, isFeedback) { World.send = function (m, metaLevel, isFeedback) {
World.current.enqueueAction(sendMessage(m, metaLevel, isFeedback)); World.current().enqueueAction(sendMessage(m, metaLevel, isFeedback));
}; };
World.updateRoutes = function (routes) { World.updateRoutes = function (routes) {
World.current.enqueueAction(updateRoutes(routes)); World.current().enqueueAction(updateRoutes(routes));
}; };
World.spawn = function (behavior, initialRoutes) { World.spawn = function (behavior, initialRoutes) {
World.current.enqueueAction(spawn(behavior, initialRoutes)); World.current().enqueueAction(spawn(behavior, initialRoutes));
};
World.withWorldStack = function (stack, f) {
var oldStack = World.stack;
World.stack = stack;
var result = null;
try {
result = f();
} catch (e) {
World.stack = oldStack;
throw e;
}
World.stack = oldStack;
return result;
}; };
World.wrap = function (f) { World.wrap = function (f) {
return World.current.wrap(f); var savedStack = World.stack.slice();
var savedPid = World.current().activePid;
return function () {
var actuals = arguments;
return World.withWorldStack(savedStack, function () {
var result = World.current().asChild(savedPid, function () {
return f.apply(null, actuals);
});
World.stack[0].startStepping();
return result;
});
};
}; };
/* Instance methods */ /* Instance methods */
@ -204,12 +233,6 @@ World.prototype.enqueueAction = function (action) {
this.processActions.push([this.activePid, action]); this.processActions.push([this.activePid, action]);
}; };
World.prototype.enqueueActions = function (pid, actions) {
for (var i = 0; i < actions.length; i++) {
this.processActions.push([pid, actions[i]]);
}
};
World.prototype.isQuiescent = function () { World.prototype.isQuiescent = function () {
return this.eventQueue.length === 0 && this.processActions.length === 0; return this.eventQueue.length === 0 && this.processActions.length === 0;
}; };
@ -239,9 +262,8 @@ World.prototype.stopStepping = function () {
}; };
World.prototype.asChild = function (pid, f) { World.prototype.asChild = function (pid, f) {
var oldWorld = World.current; World.stack.push(this);
var result = null; var result = null;
World.current = this;
this.activePid = pid; this.activePid = pid;
try { try {
result = f(); result = f();
@ -249,24 +271,17 @@ World.prototype.asChild = function (pid, f) {
this.kill(pid, e); this.kill(pid, e);
} }
this.activePid = null; this.activePid = null;
World.current = oldWorld; if (World.stack.pop() !== this) {
throw { message: "Internal error: World stack imbalance" };
}
return result; return result;
}; };
World.prototype.wrap = function (f) {
var savedWorld = this;
var savedPid = this.activePid;
return function () {
var actuals = arguments;
return savedWorld.asChild(savedPid, function () { return f.apply(null, actuals) });
};
};
World.prototype.kill = function (pid, exn) { World.prototype.kill = function (pid, exn) {
if (exn && exn.stack) { if (exn && exn.stack) {
console.log("Killed process", pid, exn, exn.stack); console.log("Killed process", pid, exn, exn.stack);
} else { } else {
console.log("Killed process", pid); console.log("Killed process", pid, exn);
} }
delete this.processTable[pid]; delete this.processTable[pid];
this.issueRoutingUpdate(); this.issueRoutingUpdate();
@ -311,7 +326,11 @@ World.prototype.performAction = function (pid, action) {
this.issueRoutingUpdate(); this.issueRoutingUpdate();
break; break;
case "routes": case "routes":
this.processTable[pid].routes = action.routes; if (pid in this.processTable) {
// it may not be: this might be the routing update from a
// kill of the process
this.processTable[pid].routes = action.routes;
}
this.issueRoutingUpdate(); this.issueRoutingUpdate();
break; break;
case "send": case "send":
@ -373,33 +392,16 @@ World.prototype.handleEvent = function (e) {
function Ground(bootFn) { function Ground(bootFn) {
var self = this; var self = this;
this.stepperId = null; this.stepperId = null;
this.wrap(function () { World.withWorldStack([this], function () {
self.world = new World(bootFn); self.world = new World(bootFn);
})(); });
} }
Ground.prototype.wrap = function (f) {
var self = this;
return function () {
var oldWorld = World.current;
var result = null;
World.current = self;
try {
result = f();
} catch (e) {
World.current = oldWorld;
throw e;
}
World.current = oldWorld;
return result;
};
};
Ground.prototype.step = function () { Ground.prototype.step = function () {
var self = this; var self = this;
return this.wrap(function () { return World.withWorldStack([this], function () {
return self.world.step(); return self.world.step();
})(); });
}; };
Ground.prototype.startStepping = World.prototype.startStepping; Ground.prototype.startStepping = World.prototype.startStepping;