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
return World.wrap(function (e) {
World.send(["jQuery", selector, eventName, e]);
World.current.startStepping();
});
})(selector, eventName);
console.log("jQuery", "installing", selector, eventName);
@ -35,7 +34,7 @@ JQueryDriver.prototype.updateHandlerMap = function (routes) {
}
}
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 handler = this.handlerMap[key];
var selector = keyArray[0];
@ -58,7 +57,7 @@ JQueryDriver.prototype.handleEvent = function (e) {
};
var g = new Ground(function () {
console.log('here');
console.log('starting ground boot');
World.spawn(new Spy());
World.spawn(new JQueryDriver());
World.spawn({
@ -70,7 +69,12 @@ var g = new Ground(function () {
World.send({msg: 'hello inner world'}, 0);
},
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":
for (var i = 0; i < routes.length; i++) {
var r = routes[i];
@ -180,22 +180,51 @@ function World(bootFn) {
/* 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.current.enqueueAction(sendMessage(m, metaLevel, isFeedback));
World.current().enqueueAction(sendMessage(m, metaLevel, isFeedback));
};
World.updateRoutes = function (routes) {
World.current.enqueueAction(updateRoutes(routes));
World.current().enqueueAction(updateRoutes(routes));
};
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) {
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 */
@ -204,12 +233,6 @@ World.prototype.enqueueAction = function (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 () {
return this.eventQueue.length === 0 && this.processActions.length === 0;
};
@ -239,9 +262,8 @@ World.prototype.stopStepping = function () {
};
World.prototype.asChild = function (pid, f) {
var oldWorld = World.current;
World.stack.push(this);
var result = null;
World.current = this;
this.activePid = pid;
try {
result = f();
@ -249,24 +271,17 @@ World.prototype.asChild = function (pid, f) {
this.kill(pid, e);
}
this.activePid = null;
World.current = oldWorld;
if (World.stack.pop() !== this) {
throw { message: "Internal error: World stack imbalance" };
}
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) {
if (exn && exn.stack) {
console.log("Killed process", pid, exn, exn.stack);
} else {
console.log("Killed process", pid);
console.log("Killed process", pid, exn);
}
delete this.processTable[pid];
this.issueRoutingUpdate();
@ -311,7 +326,11 @@ World.prototype.performAction = function (pid, action) {
this.issueRoutingUpdate();
break;
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();
break;
case "send":
@ -373,33 +392,16 @@ World.prototype.handleEvent = function (e) {
function Ground(bootFn) {
var self = this;
this.stepperId = null;
this.wrap(function () {
World.withWorldStack([this], function () {
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 () {
var self = this;
return this.wrap(function () {
return World.withWorldStack([this], function () {
return self.world.step();
})();
});
};
Ground.prototype.startStepping = World.prototype.startStepping;