Make boot() return (optional) initialGestalts instead of having a separate argument to spawn(). Fixes failing test case for initial actor route signalling.
This commit is contained in:
parent
85c6c228a3
commit
5621685052
|
@ -76,7 +76,7 @@ $(document).ready(function () {
|
||||||
// Monitor connection, notifying connectivity changes
|
// Monitor connection, notifying connectivity changes
|
||||||
state: "crashed", // start with this to avoid spurious initial message print
|
state: "crashed", // start with this to avoid spurious initial message print
|
||||||
boot: function () {
|
boot: function () {
|
||||||
World.updateRoutes([sub(["broker_state", __], 0, 1)]);
|
return [sub(["broker_state", __], 0, 1)];
|
||||||
},
|
},
|
||||||
handleEvent: function (e) {
|
handleEvent: function (e) {
|
||||||
if (e.type === "routes") {
|
if (e.type === "routes") {
|
||||||
|
@ -94,7 +94,7 @@ $(document).ready(function () {
|
||||||
World.spawn({
|
World.spawn({
|
||||||
// Actual chat functionality
|
// Actual chat functionality
|
||||||
boot: function () {
|
boot: function () {
|
||||||
World.updateRoutes(this.subscriptions());
|
return this.subscriptions();
|
||||||
},
|
},
|
||||||
nym: function () { return $("#nym").val(); },
|
nym: function () { return $("#nym").val(); },
|
||||||
currentStatus: function () { return $("#status").val(); },
|
currentStatus: function () { return $("#status").val(); },
|
||||||
|
|
|
@ -13,15 +13,18 @@ $(document).ready(function () {
|
||||||
Minimart.RoutingTableWidget.spawnRoutingTableWidget("#spy-holder", "spy");
|
Minimart.RoutingTableWidget.spawnRoutingTableWidget("#spy-holder", "spy");
|
||||||
|
|
||||||
World.spawn({
|
World.spawn({
|
||||||
|
boot: function () {
|
||||||
|
return [pub(["DOM", "#clicker-holder", "clicker",
|
||||||
|
["button", ["span", [["style", "font-style: italic"]], "Click me!"]]]),
|
||||||
|
pub("bump_count"),
|
||||||
|
sub(["jQuery", "button.clicker", "click", __])];
|
||||||
|
},
|
||||||
handleEvent: function (e) {
|
handleEvent: function (e) {
|
||||||
if (e.type === "message" && e.message[0] === "jQuery") {
|
if (e.type === "message" && e.message[0] === "jQuery") {
|
||||||
World.send("bump_count");
|
World.send("bump_count");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [pub(["DOM", "#clicker-holder", "clicker",
|
});
|
||||||
["button", ["span", [["style", "font-style: italic"]], "Click me!"]]]),
|
|
||||||
pub("bump_count"),
|
|
||||||
sub(["jQuery", "button.clicker", "click", __])]);
|
|
||||||
|
|
||||||
World.spawn({
|
World.spawn({
|
||||||
counter: 0,
|
counter: 0,
|
||||||
|
|
|
@ -29,6 +29,13 @@ $(document).ready(function () {
|
||||||
Minimart.RoutingTableWidget.spawnRoutingTableWidget("#spy-holder", "spy"); // local
|
Minimart.RoutingTableWidget.spawnRoutingTableWidget("#spy-holder", "spy"); // local
|
||||||
|
|
||||||
World.spawn({
|
World.spawn({
|
||||||
|
boot: function () {
|
||||||
|
return [pub(domWrap("#clicker-holder", localId + "-clicker",
|
||||||
|
["button", ["span", [["style", "font-style: italic"]],
|
||||||
|
"Click me! (" + localId + ")"]])),
|
||||||
|
pub("bump_count"),
|
||||||
|
sub(jQueryWrap("button."+localId+"-clicker", "click", __))];
|
||||||
|
},
|
||||||
handleEvent: function (e) {
|
handleEvent: function (e) {
|
||||||
console.log(JSON.stringify(e));
|
console.log(JSON.stringify(e));
|
||||||
if (e.type === "message"
|
if (e.type === "message"
|
||||||
|
@ -40,11 +47,7 @@ $(document).ready(function () {
|
||||||
World.send("bump_count");
|
World.send("bump_count");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [pub(domWrap("#clicker-holder", localId + "-clicker",
|
});
|
||||||
["button", ["span", [["style", "font-style: italic"]],
|
|
||||||
"Click me! (" + localId + ")"]])),
|
|
||||||
pub("bump_count"),
|
|
||||||
sub(jQueryWrap("button."+localId+"-clicker", "click", __))]);
|
|
||||||
|
|
||||||
World.spawn({
|
World.spawn({
|
||||||
counter: 0,
|
counter: 0,
|
||||||
|
|
|
@ -12,6 +12,9 @@ $(document).ready(function () {
|
||||||
|
|
||||||
World.spawn({
|
World.spawn({
|
||||||
name: 'GestaltDisplay',
|
name: 'GestaltDisplay',
|
||||||
|
boot: function () {
|
||||||
|
return [sub(__, 0, 10), pub(__, 0, 10)];
|
||||||
|
},
|
||||||
handleEvent: function (e) {
|
handleEvent: function (e) {
|
||||||
if (e.type === "routes") {
|
if (e.type === "routes") {
|
||||||
var gd = document.getElementById('gestalt-display');
|
var gd = document.getElementById('gestalt-display');
|
||||||
|
@ -21,7 +24,7 @@ $(document).ready(function () {
|
||||||
gd.appendChild(t);
|
gd.appendChild(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [sub(__, 0, 10), pub(__, 0, 10)]);
|
});
|
||||||
|
|
||||||
World.spawn(new Actor(function () {
|
World.spawn(new Actor(function () {
|
||||||
this.counter = 0;
|
this.counter = 0;
|
||||||
|
|
14
src/actor.js
14
src/actor.js
|
@ -13,8 +13,9 @@ function Actor(bootfn) {
|
||||||
try {
|
try {
|
||||||
Actor._chunks = [];
|
Actor._chunks = [];
|
||||||
bootfn.call(this);
|
bootfn.call(this);
|
||||||
finalizeActor(this, Actor._chunks);
|
var initialGestalt = finalizeActor(this, Actor._chunks);
|
||||||
Actor._chunks = oldChunks;
|
Actor._chunks = oldChunks;
|
||||||
|
return [initialGestalt];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Actor._chunks = oldChunks;
|
Actor._chunks = oldChunks;
|
||||||
throw e;
|
throw e;
|
||||||
|
@ -123,7 +124,7 @@ function finalizeActor(behavior, chunks) {
|
||||||
var compiledProjections = {};
|
var compiledProjections = {};
|
||||||
var previousObjs = {};
|
var previousObjs = {};
|
||||||
|
|
||||||
behavior.updateRoutes = function () {
|
behavior._computeRoutes = function () {
|
||||||
var newRoutes = Route.emptyGestalt;
|
var newRoutes = Route.emptyGestalt;
|
||||||
for (var i = 0; i < chunks.length; i++) {
|
for (var i = 0; i < chunks.length; i++) {
|
||||||
var chunk = chunks[i];
|
var chunk = chunks[i];
|
||||||
|
@ -159,7 +160,11 @@ function finalizeActor(behavior, chunks) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
World.updateRoutes([newRoutes]);
|
return newRoutes;
|
||||||
|
};
|
||||||
|
|
||||||
|
behavior.updateRoutes = function () {
|
||||||
|
World.updateRoutes([this._computeRoutes()]);
|
||||||
};
|
};
|
||||||
|
|
||||||
behavior.handleEvent = function (e) {
|
behavior.handleEvent = function (e) {
|
||||||
|
@ -254,7 +259,8 @@ function finalizeActor(behavior, chunks) {
|
||||||
if (chunk.options.removed) { behavior[chunk.options.removed] = []; }
|
if (chunk.options.removed) { behavior[chunk.options.removed] = []; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
behavior.updateRoutes();
|
|
||||||
|
return behavior._computeRoutes();
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -17,9 +17,7 @@ function spawnDOMDriver(domWrapFunction, jQueryWrapFunction) {
|
||||||
fragmentClass,
|
fragmentClass,
|
||||||
fragmentSpec,
|
fragmentSpec,
|
||||||
domWrapFunction,
|
domWrapFunction,
|
||||||
jQueryWrapFunction),
|
jQueryWrapFunction));
|
||||||
[sub(domWrapFunction(selector, fragmentClass, fragmentSpec)),
|
|
||||||
sub(domWrapFunction(selector, fragmentClass, fragmentSpec), 0, 1)]);
|
|
||||||
};
|
};
|
||||||
World.spawn(d);
|
World.spawn(d);
|
||||||
}
|
}
|
||||||
|
@ -40,12 +38,14 @@ function DOMFragment(selector, fragmentClass, fragmentSpec, domWrapFunction, jQu
|
||||||
DOMFragment.prototype.boot = function () {
|
DOMFragment.prototype.boot = function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
var monitoring =
|
var monitoring =
|
||||||
sub(this.domWrapFunction(self.selector, self.fragmentClass, self.fragmentSpec), 1, 2);
|
sub(self.domWrapFunction(self.selector, self.fragmentClass, self.fragmentSpec), 1, 2);
|
||||||
|
|
||||||
World.spawn(new World(function () {
|
World.spawn(new World(function () {
|
||||||
Minimart.JQuery.spawnJQueryDriver(self.selector+" > ."+self.fragmentClass,
|
Minimart.JQuery.spawnJQueryDriver(self.selector+" > ."+self.fragmentClass,
|
||||||
1,
|
1,
|
||||||
self.jQueryWrapFunction);
|
self.jQueryWrapFunction);
|
||||||
World.spawn({
|
World.spawn({
|
||||||
|
boot: function () { return [monitoring] },
|
||||||
handleEvent: function (e) {
|
handleEvent: function (e) {
|
||||||
if (e.type === "routes") {
|
if (e.type === "routes") {
|
||||||
var level = e.gestalt.getLevel(1, 0); // find participant peers
|
var level = e.gestalt.getLevel(1, 0); // find participant peers
|
||||||
|
@ -54,8 +54,11 @@ DOMFragment.prototype.boot = function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [monitoring]);
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
return [sub(self.domWrapFunction(self.selector, self.fragmentClass, self.fragmentSpec)),
|
||||||
|
sub(self.domWrapFunction(self.selector, self.fragmentClass, self.fragmentSpec), 0, 1)]
|
||||||
};
|
};
|
||||||
|
|
||||||
DOMFragment.prototype.handleEvent = function (e) {
|
DOMFragment.prototype.handleEvent = function (e) {
|
||||||
|
|
|
@ -18,9 +18,7 @@ function spawnJQueryDriver(baseSelector, metaLevel, wrapFunction) {
|
||||||
selector,
|
selector,
|
||||||
eventName,
|
eventName,
|
||||||
metaLevel,
|
metaLevel,
|
||||||
wrapFunction),
|
wrapFunction));
|
||||||
[pub(wrapFunction(selector, eventName, __), metaLevel),
|
|
||||||
pub(wrapFunction(selector, eventName, __), metaLevel, 1)]);
|
|
||||||
};
|
};
|
||||||
World.spawn(d);
|
World.spawn(d);
|
||||||
}
|
}
|
||||||
|
@ -47,6 +45,11 @@ function JQueryEventRouter(baseSelector, selector, eventName, metaLevel, wrapFun
|
||||||
this.handler);
|
this.handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JQueryEventRouter.prototype.boot = function () {
|
||||||
|
return [pub(this.wrapFunction(this.selector, this.eventName, __), this.metaLevel),
|
||||||
|
pub(this.wrapFunction(this.selector, this.eventName, __), this.metaLevel, 1)];
|
||||||
|
};
|
||||||
|
|
||||||
JQueryEventRouter.prototype.handleEvent = function (e) {
|
JQueryEventRouter.prototype.handleEvent = function (e) {
|
||||||
if (e.type === "routes" && e.gestalt.isEmpty()) {
|
if (e.type === "routes" && e.gestalt.isEmpty()) {
|
||||||
this.computeNodes().off(this.eventName, this.handler);
|
this.computeNodes().off(this.eventName, this.handler);
|
||||||
|
|
|
@ -19,10 +19,8 @@ function pub(pattern, metaLevel, level) {
|
||||||
return Route.simpleGestalt(true, pattern, metaLevel, level);
|
return Route.simpleGestalt(true, pattern, metaLevel, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
function spawn(behavior, initialGestalts) {
|
function spawn(behavior) {
|
||||||
return { type: "spawn",
|
return { type: "spawn", behavior: behavior };
|
||||||
behavior: behavior,
|
|
||||||
initialGestalt: Route.gestaltUnion(initialGestalts || []) };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateRoutes(gestalts) {
|
function updateRoutes(gestalts) {
|
||||||
|
@ -85,8 +83,8 @@ World.updateRoutes = function (gestalts) {
|
||||||
World.current().enqueueAction(World.activePid(), updateRoutes(gestalts));
|
World.current().enqueueAction(World.activePid(), updateRoutes(gestalts));
|
||||||
};
|
};
|
||||||
|
|
||||||
World.spawn = function (behavior, initialGestalts) {
|
World.spawn = function (behavior) {
|
||||||
World.current().enqueueAction(World.activePid(), spawn(behavior, initialGestalts));
|
World.current().enqueueAction(World.activePid(), spawn(behavior));
|
||||||
};
|
};
|
||||||
|
|
||||||
World.exit = function (exn) {
|
World.exit = function (exn) {
|
||||||
|
@ -226,13 +224,18 @@ World.prototype.performAction = function (pid, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case "spawn":
|
case "spawn":
|
||||||
var pid = World.nextPid++;
|
var pid = World.nextPid++;
|
||||||
var newGestalt = action.initialGestalt.label(pid);
|
var entry = { gestalt: Route.emptyGestalt, behavior: action.behavior };
|
||||||
this.processTable[pid] = { gestalt: newGestalt, behavior: action.behavior };
|
this.processTable[pid] = entry;
|
||||||
if (action.behavior.boot) {
|
if (entry.behavior.boot) {
|
||||||
this.asChild(pid, function () { action.behavior.boot() });
|
var initialGestalts = this.asChild(pid, function () { return entry.behavior.boot() });
|
||||||
|
if (initialGestalts) {
|
||||||
|
entry.gestalt = Route.gestaltUnion(initialGestalts).label(pid);
|
||||||
|
}
|
||||||
this.markPidRunnable(pid);
|
this.markPidRunnable(pid);
|
||||||
}
|
}
|
||||||
this.applyAndIssueRoutingUpdate(Route.emptyGestalt, newGestalt, pid);
|
if (!Route.emptyGestalt.equals(entry.gestalt)) {
|
||||||
|
this.applyAndIssueRoutingUpdate(Route.emptyGestalt, entry.gestalt, pid);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "routes":
|
case "routes":
|
||||||
if (pid in this.processTable) {
|
if (pid in this.processTable) {
|
||||||
|
@ -315,6 +318,11 @@ World.prototype.dispatchEvent = function (e) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
World.prototype.boot = function () {
|
||||||
|
// Needed in order for the new World to be marked as "runnable", so
|
||||||
|
// its initial actions get performed.
|
||||||
|
};
|
||||||
|
|
||||||
World.prototype.handleEvent = function (e) {
|
World.prototype.handleEvent = function (e) {
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
case "routes":
|
case "routes":
|
||||||
|
@ -436,8 +444,8 @@ DemandMatcher.prototype.debugState = function () {
|
||||||
|
|
||||||
DemandMatcher.prototype.boot = function () {
|
DemandMatcher.prototype.boot = function () {
|
||||||
var observerLevel = 1 + Math.max(this.demandLevel, this.supplyLevel);
|
var observerLevel = 1 + Math.max(this.demandLevel, this.supplyLevel);
|
||||||
World.updateRoutes([sub(this.demandPattern, this.metaLevel, observerLevel),
|
return [sub(this.demandPattern, this.metaLevel, observerLevel),
|
||||||
pub(this.supplyPattern, this.metaLevel, observerLevel)]);
|
pub(this.supplyPattern, this.metaLevel, observerLevel)];
|
||||||
};
|
};
|
||||||
|
|
||||||
DemandMatcher.prototype.handleEvent = function (e) {
|
DemandMatcher.prototype.handleEvent = function (e) {
|
||||||
|
|
|
@ -12,7 +12,7 @@ function Spy(label, useJson, observationLevel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Spy.prototype.boot = function () {
|
Spy.prototype.boot = function () {
|
||||||
World.updateRoutes([sub(__, 0, this.observationLevel), pub(__, 0, this.observationLevel)]);
|
return [sub(__, 0, this.observationLevel), pub(__, 0, this.observationLevel)];
|
||||||
};
|
};
|
||||||
|
|
||||||
Spy.prototype.handleEvent = function (e) {
|
Spy.prototype.handleEvent = function (e) {
|
||||||
|
|
|
@ -17,8 +17,8 @@ function WakeDetector(period) {
|
||||||
|
|
||||||
WakeDetector.prototype.boot = function () {
|
WakeDetector.prototype.boot = function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
World.updateRoutes([pub(this.message)]);
|
|
||||||
this.timerId = setInterval(World.wrap(function () { self.trigger(); }), this.period);
|
this.timerId = setInterval(World.wrap(function () { self.trigger(); }), this.period);
|
||||||
|
return [pub(this.message)];
|
||||||
};
|
};
|
||||||
|
|
||||||
WakeDetector.prototype.handleEvent = function (e) {};
|
WakeDetector.prototype.handleEvent = function (e) {};
|
||||||
|
|
|
@ -47,10 +47,11 @@ describe("configurationTrace", function() {
|
||||||
it("should yield an appropriate trace", function () {
|
it("should yield an appropriate trace", function () {
|
||||||
checkTrace(function (trace) {
|
checkTrace(function (trace) {
|
||||||
World.spawn({
|
World.spawn({
|
||||||
|
boot: function () { return [sub(__)] },
|
||||||
handleEvent: function (e) {
|
handleEvent: function (e) {
|
||||||
trace(e);
|
trace(e);
|
||||||
}
|
}
|
||||||
}, [sub(__)]);
|
});
|
||||||
World.send(123);
|
World.send(123);
|
||||||
World.send(234);
|
World.send(234);
|
||||||
}, [Minimart.updateRoutes([]),
|
}, [Minimart.updateRoutes([]),
|
||||||
|
@ -64,9 +65,15 @@ describe("nonempty initial routes", function () {
|
||||||
it("should be immediately signalled to the process", function () {
|
it("should be immediately signalled to the process", function () {
|
||||||
// Specifically, no Minimart.updateRoutes([]) first.
|
// Specifically, no Minimart.updateRoutes([]) first.
|
||||||
checkTrace(function (trace) {
|
checkTrace(function (trace) {
|
||||||
World.spawn({ handleEvent: function (e) {
|
World.spawn({
|
||||||
World.spawn({ handleEvent: trace }, [sub(["A", __], 0, 1)])
|
boot: function () { return [pub(["A", __])] },
|
||||||
}}, [pub(["A", __])]);
|
handleEvent: function (e) {
|
||||||
|
World.spawn({
|
||||||
|
boot: function () { return [sub(["A", __], 0, 1)] },
|
||||||
|
handleEvent: trace
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}, [Minimart.updateRoutes([pub(["A", __]).label(1)])]);
|
}, [Minimart.updateRoutes([pub(["A", __]).label(1)])]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -74,7 +81,9 @@ describe("nonempty initial routes", function () {
|
||||||
describe("actor with nonempty initial routes", function () {
|
describe("actor with nonempty initial routes", function () {
|
||||||
it("shouldn't see initial empty conversational context", function () {
|
it("shouldn't see initial empty conversational context", function () {
|
||||||
checkTrace(function (trace) {
|
checkTrace(function (trace) {
|
||||||
World.spawn({ handleEvent: function (e) {
|
World.spawn({
|
||||||
|
boot: function () { return [pub(["A", __])] },
|
||||||
|
handleEvent: function (e) {
|
||||||
World.spawn(new Actor(function () {
|
World.spawn(new Actor(function () {
|
||||||
Actor.observeAdvertisers(
|
Actor.observeAdvertisers(
|
||||||
function () { return ["A", __] },
|
function () { return ["A", __] },
|
||||||
|
@ -83,7 +92,8 @@ describe("actor with nonempty initial routes", function () {
|
||||||
trace(["isPresent", this.isPresent]);
|
trace(["isPresent", this.isPresent]);
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
}}, [pub(["A", __])]);
|
}
|
||||||
|
});
|
||||||
}, [["isPresent", true]]);
|
}, [["isPresent", true]]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -297,6 +297,13 @@ describe("matcher equality", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("gestalt equality", function () {
|
describe("gestalt equality", function () {
|
||||||
|
it("should distinguish emptyGestalt reliably", function () {
|
||||||
|
expect(r.simpleGestalt(false, r.__, 0, 10)
|
||||||
|
.union(r.simpleGestalt(true, r.__, 0, 10))
|
||||||
|
.equals(r.emptyGestalt))
|
||||||
|
.to.be(false);
|
||||||
|
});
|
||||||
|
|
||||||
it("should not rely on object identity", function () {
|
it("should not rely on object identity", function () {
|
||||||
expect(r.simpleGestalt(false, "A", 0, 0).union(r.simpleGestalt(true, "B", 0, 0))
|
expect(r.simpleGestalt(false, "A", 0, 0).union(r.simpleGestalt(true, "B", 0, 0))
|
||||||
.equals(r.simpleGestalt(false, "A", 0, 0).union(r.simpleGestalt(true, "B", 0, 0))))
|
.equals(r.simpleGestalt(false, "A", 0, 0).union(r.simpleGestalt(true, "B", 0, 0))))
|
||||||
|
|
Loading…
Reference in New Issue