diff --git a/index.js b/index.js index f09300c..acb26e1 100644 --- a/index.js +++ b/index.js @@ -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); + } } }); }); diff --git a/marketplace.js b/marketplace.js index ae93457..9e9c0df 100644 --- a/marketplace.js +++ b/marketplace.js @@ -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;