Some modularity; general cleanup of codebase
This commit is contained in:
parent
4239c1ea33
commit
7bab9be492
27 changed files with 4390 additions and 1732 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,6 +1,5 @@
|
|||
private-key.pem
|
||||
server-cert.pem
|
||||
MarketplaceChat.app.zip
|
||||
MarketplaceChat.app/
|
||||
scratch/
|
||||
_site/
|
||||
node_modules/
|
||||
|
|
41
Makefile
41
Makefile
|
@ -1,21 +1,8 @@
|
|||
APP_NAME=MarketplaceChat.app
|
||||
LIB_SOURCES=\
|
||||
route.js \
|
||||
marketplace.js \
|
||||
spy.js \
|
||||
dom-driver.js \
|
||||
jquery-driver.js \
|
||||
routing-table-widget.js \
|
||||
routing-table-widget.css \
|
||||
wake-detector.js \
|
||||
websocket-driver.js
|
||||
APP_SOURCES=\
|
||||
examples/chat/index.html \
|
||||
examples/chat/index.js \
|
||||
examples/chat/style.css
|
||||
RESOURCES=$(wildcard examples/chat/app-resources/*)
|
||||
all:
|
||||
npm run build
|
||||
|
||||
all: $(APP_NAME).zip
|
||||
deps:
|
||||
npm install .
|
||||
|
||||
keys: private-key.pem server-cert.pem
|
||||
|
||||
|
@ -31,23 +18,3 @@ server-cert.pem: private-key.pem
|
|||
|
||||
clean-keys:
|
||||
rm -f private-key.pem server-cert.pem
|
||||
|
||||
$(APP_NAME).zip: $(APP_NAME)
|
||||
zip -r $@ $<
|
||||
|
||||
$(APP_NAME): $(APP_SOURCES) $(LIB_SOURCES)
|
||||
echo RESOURCES $(RESOURCES)
|
||||
rm -rf $@
|
||||
mkdir -p $@/Contents/MacOS
|
||||
mkdir -p $@/Contents/Resources
|
||||
cp examples/chat/app-resources/Info.plist $@/Contents
|
||||
cp examples/chat/app-resources/boot.sh $@/Contents/MacOS
|
||||
cp examples/chat/app-resources/app.icns $@/Contents/Resources
|
||||
cp -r third-party $@/Contents/Resources
|
||||
cp $(LIB_SOURCES) $@/Contents/Resources
|
||||
mkdir -p $@/Contents/Resources/examples/chat
|
||||
cp $(APP_SOURCES) $@/Contents/Resources/examples/chat
|
||||
chmod a+x $@/Contents/MacOS/boot.sh
|
||||
|
||||
clean:
|
||||
rm -rf $(APP_NAME) $(APP_NAME).zip
|
||||
|
|
|
@ -14,7 +14,7 @@ To install the Racket server:
|
|||
|
||||
To run the Racket server:
|
||||
|
||||
- `racket server.rkt` from the base directory of this repository.
|
||||
racket -l minimart/examples/broker
|
||||
|
||||
The Racket server listens for tunnelled Network Calculus events via
|
||||
websocket on ports 8000 (HTTP) and 8443 (HTTPS, if you have a
|
||||
|
|
1
dist/README.md
vendored
Normal file
1
dist/README.md
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
Directory for build products, checked in to the repo for ease-of-use.
|
2650
dist/minimart.js
vendored
Normal file
2650
dist/minimart.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
dist/minimart.min.js
vendored
Normal file
2
dist/minimart.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -3,33 +3,15 @@
|
|||
<head>
|
||||
<title>JS Marketplace: Chat Example</title>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<link href="../../third-party/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../third-party/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet">
|
||||
<link href="style.css" rel="stylesheet">
|
||||
<!-- <script src="../../third-party/bootstrap/js/bootstrap.min.js"></script> -->
|
||||
<script src="../../third-party/jquery-2.0.3.min.js"></script>
|
||||
|
||||
<script src="../../route.js"></script>
|
||||
<script src="../../marketplace.js"></script>
|
||||
<script src="../../spy.js"></script>
|
||||
<script src="../../dom-driver.js"></script>
|
||||
|
||||
<script src="../../routing-table-widget.js"></script>
|
||||
<link href="../../routing-table-widget.css" rel="stylesheet">
|
||||
|
||||
<script src="../../jquery-driver.js"></script>
|
||||
<script src="../../wake-detector.js"></script>
|
||||
<script src="../../websocket-driver.js"></script>
|
||||
<script src="../../dist/minimart.js"></script>
|
||||
<script src="index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<!-- <div class="row-fluid"> -->
|
||||
<!-- <div class="span12"> -->
|
||||
<!-- <h1>JS Marketplace</h1> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<form class="form-horizontal" name="nym_form">
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
var Route = Minimart.Route;
|
||||
var World = Minimart.World;
|
||||
var sub = Minimart.sub;
|
||||
var pub = Minimart.pub;
|
||||
var __ = Minimart.__;
|
||||
var _$ = Minimart._$;
|
||||
|
||||
function chatEvent(nym, status, utterance, stamp) {
|
||||
return ["chatEvent", nym, status, utterance, stamp || +(new Date())];
|
||||
}
|
||||
|
@ -18,7 +25,7 @@ function outputItem(item) {
|
|||
function updateNymList(g) {
|
||||
var statuses = {};
|
||||
var nymProj = ["broker", 0, ["chatEvent", _$, _$, __, __]];
|
||||
var matchedNyms = route.matcherKeys(g.project(route.compileProjection(nymProj), true, 0, 0));
|
||||
var matchedNyms = Route.matcherKeys(g.project(Route.compileProjection(nymProj), true, 0, 0));
|
||||
for (var i = 0; i < matchedNyms.length; i++) {
|
||||
statuses[matchedNyms[i][0]] = matchedNyms[i][1];
|
||||
}
|
||||
|
@ -55,15 +62,15 @@ $(document).ready(function () {
|
|||
$("#nym_form").submit(function (e) { e.preventDefault(); return false; });
|
||||
if (!($("#nym").val())) { $("#nym").val("nym" + Math.floor(Math.random() * 65536)); }
|
||||
|
||||
G = new Ground(function () {
|
||||
G = new Minimart.Ground(function () {
|
||||
console.log('starting ground boot');
|
||||
// World.spawn(new Spy());
|
||||
spawnJQueryDriver();
|
||||
spawnDOMDriver();
|
||||
spawnRoutingTableWidget("#spy-holder", "spy");
|
||||
Minimart.JQuery.spawnJQueryDriver();
|
||||
Minimart.DOM.spawnDOMDriver();
|
||||
Minimart.RoutingTableWidget.spawnRoutingTableWidget("#spy-holder", "spy");
|
||||
|
||||
World.spawn(new WakeDetector());
|
||||
var wsconn = new WebSocketConnection("broker", $("#wsurl").val(), true);
|
||||
World.spawn(new Minimart.WakeDetector());
|
||||
var wsconn = new Minimart.WebSocket.WebSocketConnection("broker", $("#wsurl").val(), true);
|
||||
World.spawn(wsconn);
|
||||
World.spawn({
|
||||
// Monitor connection, notifying connectivity changes
|
||||
|
@ -74,7 +81,7 @@ $(document).ready(function () {
|
|||
handleEvent: function (e) {
|
||||
if (e.type === "routes") {
|
||||
var states =
|
||||
route.matcherKeys(e.gestalt.project(route.compileProjection([__, _$]),
|
||||
Route.matcherKeys(e.gestalt.project(Route.compileProjection([__, _$]),
|
||||
true, 0, 0));
|
||||
var newState = states.length > 0 ? states[0][0] : "crashed";
|
||||
if (this.state != newState) {
|
||||
|
|
|
@ -3,24 +3,11 @@
|
|||
<head>
|
||||
<title>JS Marketplace: DOM Example</title>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<link href="../../third-party/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="../../third-party/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet">
|
||||
<link href="style.css" rel="stylesheet">
|
||||
<!-- <script src="../../third-party/bootstrap/js/bootstrap.min.js"></script> -->
|
||||
<script src="../../third-party/jquery-2.0.3.min.js"></script>
|
||||
|
||||
<script src="../../route.js"></script>
|
||||
<script src="../../marketplace.js"></script>
|
||||
<script src="../../spy.js"></script>
|
||||
<script src="../../dom-driver.js"></script>
|
||||
|
||||
<script src="../../routing-table-widget.js"></script>
|
||||
<link href="../../routing-table-widget.css" rel="stylesheet">
|
||||
|
||||
<script src="../../jquery-driver.js"></script>
|
||||
<script src="../../wake-detector.js"></script>
|
||||
<script src="../../websocket-driver.js"></script>
|
||||
<script src="../../dist/minimart.js"></script>
|
||||
<script src="index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
var G;
|
||||
$(document).ready(function () {
|
||||
G = new Ground(function () {
|
||||
var World = Minimart.World;
|
||||
var sub = Minimart.sub;
|
||||
var pub = Minimart.pub;
|
||||
var __ = Minimart.__;
|
||||
var _$ = Minimart._$;
|
||||
|
||||
G = new Minimart.Ground(function () {
|
||||
console.log('starting ground boot');
|
||||
// World.spawn(new Spy("GROUND", true));
|
||||
spawnDOMDriver();
|
||||
spawnRoutingTableWidget("#spy-holder", "spy");
|
||||
Minimart.DOM.spawnDOMDriver();
|
||||
Minimart.RoutingTableWidget.spawnRoutingTableWidget("#spy-holder", "spy");
|
||||
|
||||
World.spawn({
|
||||
handleEvent: function (e) {
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
<title>JS Marketplace: Smoketest</title>
|
||||
<meta charset="utf-8">
|
||||
<script src="../../third-party/jquery-2.0.3.min.js"></script>
|
||||
<script src="../../route.js"></script>
|
||||
<script src="../../marketplace.js"></script>
|
||||
<script src="../../spy.js"></script>
|
||||
<script src="../../dist/minimart.js"></script>
|
||||
<script src="index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
var G;
|
||||
$(document).ready(function () {
|
||||
G = new Ground(function () {
|
||||
var World = Minimart.World;
|
||||
var sub = Minimart.sub;
|
||||
var pub = Minimart.pub;
|
||||
var __ = Minimart.__;
|
||||
var _$ = Minimart._$;
|
||||
|
||||
G = new Minimart.Ground(function () {
|
||||
console.log('starting ground boot');
|
||||
World.spawn(new Spy("GROUND", true));
|
||||
World.spawn(new Minimart.Spy("GROUND", true));
|
||||
World.spawn({
|
||||
counter: 0,
|
||||
handleEvent: function (e) {},
|
||||
|
|
|
@ -9,16 +9,7 @@
|
|||
<link href="style.css" rel="stylesheet">
|
||||
|
||||
<script src="../../third-party/jquery-2.0.3.min.js"></script>
|
||||
<script src="../../route.js"></script>
|
||||
<script src="../../marketplace.js"></script>
|
||||
<script src="../../spy.js"></script>
|
||||
<script src="../../dom-driver.js"></script>
|
||||
|
||||
<script src="../../routing-table-widget.js"></script>
|
||||
<link href="../../routing-table-widget.css" rel="stylesheet">
|
||||
|
||||
<script src="../../jquery-driver.js"></script>
|
||||
<script src="../../wake-detector.js"></script>
|
||||
<script src="../../dist/minimart.js"></script>
|
||||
<script src="index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// GUI
|
||||
|
||||
var Route = Minimart.Route;
|
||||
var World = Minimart.World;
|
||||
var sub = Minimart.sub;
|
||||
var pub = Minimart.pub;
|
||||
var __ = Minimart.__;
|
||||
var _$ = Minimart._$;
|
||||
|
||||
function piece(text, pos, lo, hi, cls) {
|
||||
return "<span class='"+cls+"'>"+
|
||||
((pos >= lo && pos < hi)
|
||||
|
@ -16,19 +23,19 @@ function spawnGui() {
|
|||
sub(["fieldContents", __, __], 0, 1),
|
||||
sub(["highlight", __], 0, 1)]);
|
||||
},
|
||||
fieldContentsSpec: route.compileProjection(["fieldContents", _$, _$]),
|
||||
highlightSpec: route.compileProjection(["highlight", _$]),
|
||||
fieldContentsSpec: Route.compileProjection(["fieldContents", _$, _$]),
|
||||
highlightSpec: Route.compileProjection(["highlight", _$]),
|
||||
handleEvent: function (e) {
|
||||
switch (e.type) {
|
||||
case "routes":
|
||||
var text = "", pos = 0, highlight = false;
|
||||
// BUG: escape text!
|
||||
var fc = route.matcherKeys(e.gestalt.project(this.fieldContentsSpec, true));
|
||||
var fc = Route.matcherKeys(e.gestalt.project(this.fieldContentsSpec, true));
|
||||
if (fc.length > 0) {
|
||||
text = fc[0][0];
|
||||
pos = fc[0][1];
|
||||
}
|
||||
var hl = route.matcherKeys(e.gestalt.project(this.highlightSpec, true));
|
||||
var hl = Route.matcherKeys(e.gestalt.project(this.highlightSpec, true));
|
||||
if (hl.length > 0) {
|
||||
highlight = hl[0][0];
|
||||
}
|
||||
|
@ -112,7 +119,7 @@ function spawnSearch() {
|
|||
World.spawn({
|
||||
fieldContents: "",
|
||||
highlight: false,
|
||||
fieldContentsSpec: route.compileProjection(["fieldContents", _$, _$]),
|
||||
fieldContentsSpec: Route.compileProjection(["fieldContents", _$, _$]),
|
||||
boot: function () {
|
||||
World.updateRoutes(this.subscriptions());
|
||||
},
|
||||
|
@ -137,7 +144,7 @@ function spawnSearch() {
|
|||
handleEvent: function (e) {
|
||||
switch (e.type) {
|
||||
case "routes":
|
||||
var fc = route.matcherKeys(e.gestalt.project(this.fieldContentsSpec, true));
|
||||
var fc = Route.matcherKeys(e.gestalt.project(this.fieldContentsSpec, true));
|
||||
if (fc.length > 0) {
|
||||
this.fieldContents = fc[0][0];
|
||||
}
|
||||
|
@ -157,10 +164,10 @@ function spawnSearch() {
|
|||
|
||||
var G;
|
||||
$(document).ready(function () {
|
||||
G = new Ground(function () {
|
||||
spawnJQueryDriver();
|
||||
spawnDOMDriver();
|
||||
spawnRoutingTableWidget("#spy-holder", "spy");
|
||||
G = new Minimart.Ground(function () {
|
||||
Minimart.JQuery.spawnJQueryDriver();
|
||||
Minimart.DOM.spawnDOMDriver();
|
||||
Minimart.RoutingTableWidget.spawnRoutingTableWidget("#spy-holder", "spy");
|
||||
|
||||
spawnGui();
|
||||
spawnModel();
|
||||
|
|
22
package.json
Normal file
22
package.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "js-marketplace",
|
||||
"version": "0.0.0",
|
||||
"description": "Network Calculus in the browser",
|
||||
"homepage": "https://github.com/tonyg/js-marketplace",
|
||||
"main": "src/main.js",
|
||||
"scripts": {
|
||||
"clean": "rm -f dist/*",
|
||||
"build-debug": "browserify src/main.js -d -s Minimart -o dist/minimart.js",
|
||||
"build-min": "browserify src/main.js -s Minimart -o dist/_minimart.js && uglifyjs dist/_minimart.js -o dist/minimart.min.js && rm dist/_minimart.js",
|
||||
"build": "npm run build-debug && npm run build-min",
|
||||
"watch": "watchify src/main.js -d -s Minimart -o dist/minimart.js",
|
||||
"prepublish": "npm run build"
|
||||
},
|
||||
"author": "Tony Garnock-Jones <tonyg@ccs.neu.edu>",
|
||||
"devDependencies": {
|
||||
"watchify": "^0.6.1",
|
||||
"uglify-js": "^2.4.12",
|
||||
"browserify": "^3.30.4",
|
||||
"mocha": "^1.17.1"
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
.routing-table li { list-style-type: none; }
|
||||
|
||||
.routing-table .sub .pattern { background-color: lightblue; }
|
||||
.routing-table .sub .level { background-color: lightblue; }
|
||||
.routing-table .pub .pattern { background-color: lightgreen; }
|
||||
.routing-table .pub .level { background-color: lightgreen; }
|
||||
|
||||
.routing-table .route {
|
||||
display: inline-block;
|
||||
height: 2em;
|
||||
}
|
||||
|
||||
.routing-table .route .level { font-style: italic; line-height: 1em; padding: 0 0.5em; }
|
||||
.routing-table .route .polarity { display: none; }
|
||||
.routing-table .route .pattern { padding-right: 0.5em; }
|
||||
|
||||
.routing-table .route:before {
|
||||
content: " ";
|
||||
float: left;
|
||||
}
|
||||
|
||||
.routing-table .pub:before {
|
||||
border-right: 0.6em solid lightgreen;
|
||||
border-top: 0.75em solid transparent;
|
||||
border-bottom: 0.75em solid transparent;
|
||||
}
|
||||
|
||||
.routing-table .sub:before {
|
||||
border-left: 0.6em solid transparent;
|
||||
border-top: 0.75em solid lightblue;
|
||||
border-bottom: 0.75em solid lightblue;
|
||||
}
|
||||
|
||||
.routing-table .route:after {
|
||||
content: " ";
|
||||
float: right;
|
||||
}
|
||||
|
||||
.routing-table .pub:after {
|
||||
border-left: 0.6em solid lightgreen;
|
||||
border-top: 0.75em solid transparent;
|
||||
border-bottom: 0.75em solid transparent;
|
||||
}
|
||||
|
||||
.routing-table .sub:after {
|
||||
border-right: 0.6em solid transparent;
|
||||
border-top: 0.75em solid lightblue;
|
||||
border-bottom: 0.75em solid lightblue;
|
||||
}
|
|
@ -1,7 +1,13 @@
|
|||
// DOM fragment display driver
|
||||
var Minimart = require("./minimart.js");
|
||||
var World = Minimart.World;
|
||||
var sub = Minimart.sub;
|
||||
var pub = Minimart.pub;
|
||||
var __ = Minimart.__;
|
||||
var _$ = Minimart._$;
|
||||
|
||||
function spawnDOMDriver() {
|
||||
var d = new DemandMatcher(["DOM", _$, _$, _$]);
|
||||
var d = new Minimart.DemandMatcher(["DOM", _$, _$, _$]);
|
||||
d.onDemandIncrease = function (captures) {
|
||||
var selector = captures[0];
|
||||
var fragmentClass = captures[1];
|
||||
|
@ -24,7 +30,7 @@ DOMFragment.prototype.boot = function () {
|
|||
var self = this;
|
||||
var monitoring = sub(["DOM", self.selector, self.fragmentClass, self.fragmentSpec], 1, 2);
|
||||
World.spawn(new World(function () {
|
||||
spawnJQueryDriver(self.selector+" > ."+self.fragmentClass, 1);
|
||||
Minimart.JQuery.spawnJQueryDriver(self.selector+" > ."+self.fragmentClass, 1);
|
||||
World.spawn({
|
||||
handleEvent: function (e) {
|
||||
if (e.type === "routes") {
|
||||
|
@ -86,3 +92,7 @@ DOMFragment.prototype.buildNodes = function () {
|
|||
});
|
||||
return nodes;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module.exports.spawnDOMDriver = spawnDOMDriver;
|
13
jquery-driver.js → src/jquery-driver.js
vendored
13
jquery-driver.js → src/jquery-driver.js
vendored
|
@ -1,8 +1,15 @@
|
|||
// JQuery event driver
|
||||
var Minimart = require("./minimart.js");
|
||||
var World = Minimart.World;
|
||||
var sub = Minimart.sub;
|
||||
var pub = Minimart.pub;
|
||||
var __ = Minimart.__;
|
||||
var _$ = Minimart._$;
|
||||
|
||||
function spawnJQueryDriver(baseSelector, metaLevel) {
|
||||
metaLevel = metaLevel || 0;
|
||||
var d = new DemandMatcher(["jQuery", _$, _$, __], metaLevel, {demandSideIsSubscription: true});
|
||||
var d = new Minimart.DemandMatcher(["jQuery", _$, _$, __], metaLevel,
|
||||
{demandSideIsSubscription: true});
|
||||
d.onDemandIncrease = function (captures) {
|
||||
var selector = captures[0];
|
||||
var eventName = captures[1];
|
||||
|
@ -44,3 +51,7 @@ JQueryEventRouter.prototype.computeNodes = function () {
|
|||
return $(this.selector);
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module.exports.spawnJQueryDriver = spawnJQueryDriver;
|
9
src/main.js
Normal file
9
src/main.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
module.exports = require("./minimart.js");
|
||||
|
||||
module.exports.DOM = require("./dom-driver.js");
|
||||
module.exports.JQuery = require("./jquery-driver.js");
|
||||
module.exports.RoutingTableWidget = require("./routing-table-widget.js");
|
||||
module.exports.WebSocket = require("./websocket-driver.js");
|
||||
|
||||
module.exports.Spy = require("./spy.js").Spy;
|
||||
module.exports.WakeDetector = require("./wake-detector.js").WakeDetector;
|
|
@ -1,27 +1,31 @@
|
|||
var Route = require("./route.js");
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: trigger-guards as per minimart
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Events and Actions */
|
||||
|
||||
var __ = route.__;
|
||||
var _$ = route._$;
|
||||
var __ = Route.__;
|
||||
var _$ = Route._$;
|
||||
|
||||
function sub(pattern, metaLevel, level) {
|
||||
return route.simpleGestalt(false, pattern, metaLevel, level);
|
||||
return Route.simpleGestalt(false, pattern, metaLevel, level);
|
||||
}
|
||||
|
||||
function pub(pattern, metaLevel, level) {
|
||||
return route.simpleGestalt(true, pattern, metaLevel, level);
|
||||
return Route.simpleGestalt(true, pattern, metaLevel, level);
|
||||
}
|
||||
|
||||
function spawn(behavior, initialGestalts) {
|
||||
return { type: "spawn",
|
||||
behavior: behavior,
|
||||
initialGestalt: route.gestaltUnion(initialGestalts || []) };
|
||||
initialGestalt: Route.gestaltUnion(initialGestalts || []) };
|
||||
}
|
||||
|
||||
function updateRoutes(gestalts) {
|
||||
return { type: "routes", gestalt: route.gestaltUnion(gestalts) };
|
||||
return { type: "routes", gestalt: Route.gestaltUnion(gestalts) };
|
||||
}
|
||||
|
||||
function pendingRoutingUpdate(aggregate, affectedSubgestalt, knownTarget) {
|
||||
|
@ -49,11 +53,11 @@ function World(bootFn) {
|
|||
this.alive = true;
|
||||
this.eventQueue = [];
|
||||
this.runnablePids = {};
|
||||
this.partialGestalt = route.emptyGestalt; // Only gestalt from local processes
|
||||
this.fullGestalt = route.emptyGestalt ;; // partialGestalt unioned with downwardGestalt
|
||||
this.partialGestalt = Route.emptyGestalt; // Only gestalt from local processes
|
||||
this.fullGestalt = Route.emptyGestalt ;; // partialGestalt unioned with downwardGestalt
|
||||
this.processTable = {};
|
||||
this.tombstones = {};
|
||||
this.downwardGestalt = route.emptyGestalt;
|
||||
this.downwardGestalt = Route.emptyGestalt;
|
||||
this.processActions = [];
|
||||
this.asChild(-1, bootFn, true);
|
||||
}
|
||||
|
@ -134,7 +138,7 @@ World.prototype.enqueueAction = function (pid, action) {
|
|||
World.prototype.isInert = function () {
|
||||
return this.eventQueue.length === 0
|
||||
&& this.processActions.length === 0
|
||||
&& route.is_emptySet(this.runnablePids);
|
||||
&& Route.is_emptySet(this.runnablePids);
|
||||
};
|
||||
|
||||
World.prototype.markPidRunnable = function (pid) {
|
||||
|
@ -183,7 +187,7 @@ World.prototype.kill = function (pid, exn) {
|
|||
p.exitReason = exn;
|
||||
this.tombstones[pid] = p;
|
||||
}
|
||||
this.applyAndIssueRoutingUpdate(p.gestalt, route.emptyGestalt);
|
||||
this.applyAndIssueRoutingUpdate(p.gestalt, Route.emptyGestalt);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -227,7 +231,7 @@ World.prototype.performAction = function (pid, action) {
|
|||
this.asChild(pid, function () { action.behavior.boot() });
|
||||
this.markPidRunnable(pid);
|
||||
}
|
||||
this.applyAndIssueRoutingUpdate(route.emptyGestalt, newGestalt, pid);
|
||||
this.applyAndIssueRoutingUpdate(Route.emptyGestalt, newGestalt, pid);
|
||||
break;
|
||||
case "routes":
|
||||
if (pid in this.processTable) {
|
||||
|
@ -391,8 +395,8 @@ function DemandMatcher(projection, metaLevel, options) {
|
|||
supplyLevel: 0,
|
||||
demandSideIsSubscription: false
|
||||
}, options);
|
||||
this.pattern = route.projectionToPattern(projection);
|
||||
this.projectionSpec = route.compileProjection(projection);
|
||||
this.pattern = Route.projectionToPattern(projection);
|
||||
this.projectionSpec = Route.compileProjection(projection);
|
||||
this.metaLevel = metaLevel | 0;
|
||||
this.demandLevel = options.demandLevel;
|
||||
this.supplyLevel = options.supplyLevel;
|
||||
|
@ -428,12 +432,12 @@ DemandMatcher.prototype.handleGestalt = function (gestalt) {
|
|||
this.demandSideIsSubscription,
|
||||
this.metaLevel,
|
||||
this.supplyLevel);
|
||||
var newDemand = route.arrayToSet(route.matcherKeys(newDemandMatcher));
|
||||
var newSupply = route.arrayToSet(route.matcherKeys(newSupplyMatcher));
|
||||
var demandDelta = route.setSubtract(newDemand, this.currentDemand);
|
||||
var supplyDelta = route.setSubtract(this.currentSupply, newSupply);
|
||||
var demandIncr = route.setSubtract(demandDelta, newSupply);
|
||||
var supplyDecr = route.setIntersect(supplyDelta, newDemand);
|
||||
var newDemand = Route.arrayToSet(Route.matcherKeys(newDemandMatcher));
|
||||
var newSupply = Route.arrayToSet(Route.matcherKeys(newSupplyMatcher));
|
||||
var demandDelta = Route.setSubtract(newDemand, this.currentDemand);
|
||||
var supplyDelta = Route.setSubtract(this.currentSupply, newSupply);
|
||||
var demandIncr = Route.setSubtract(demandDelta, newSupply);
|
||||
var supplyDecr = Route.setIntersect(supplyDelta, newDemand);
|
||||
this.currentDemand = newDemand;
|
||||
this.currentSupply = newSupply;
|
||||
for (var k in demandIncr) this.onDemandIncrease(demandIncr[k]);
|
||||
|
@ -533,3 +537,21 @@ Ground.prototype.enqueueAction = function (pid, action) {
|
|||
console.error("You have sent a message into the outer void.", action);
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module.exports.__ = __;
|
||||
module.exports._$ = _$;
|
||||
|
||||
module.exports.sub = sub;
|
||||
module.exports.pub = pub;
|
||||
module.exports.spawn = spawn;
|
||||
module.exports.updateRoutes = updateRoutes;
|
||||
module.exports.sendMessage = sendMessage;
|
||||
module.exports.shutdownWorld = shutdownWorld;
|
||||
|
||||
module.exports.World = World;
|
||||
module.exports.DemandMatcher = DemandMatcher;
|
||||
module.exports.Deduplicator = Deduplicator;
|
||||
module.exports.Ground = Ground;
|
||||
module.exports.Route = Route;
|
1519
src/route.js
Normal file
1519
src/route.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,11 @@
|
|||
var Minimart = require("./minimart.js");
|
||||
var Route = Minimart.Route;
|
||||
var World = Minimart.World;
|
||||
var sub = Minimart.sub;
|
||||
var pub = Minimart.pub;
|
||||
var __ = Minimart.__;
|
||||
var _$ = Minimart._$;
|
||||
|
||||
function spawnRoutingTableWidget(selector, fragmentClass, observationLevel) {
|
||||
observationLevel = observationLevel || 10;
|
||||
// ^ arbitrary: should be Infinity, when route.js supports it. TODO
|
||||
|
@ -5,8 +13,8 @@ function spawnRoutingTableWidget(selector, fragmentClass, observationLevel) {
|
|||
World.spawn({
|
||||
boot: function () { this.updateState(); },
|
||||
|
||||
state: route.emptyGestalt.serialize(),
|
||||
nextState: route.emptyGestalt.serialize(),
|
||||
state: Route.emptyGestalt.serialize(),
|
||||
nextState: Route.emptyGestalt.serialize(),
|
||||
timer: false,
|
||||
|
||||
localGestalt: (sub( ["DOM", selector, fragmentClass, __], 0, 2)
|
||||
|
@ -18,8 +26,7 @@ function spawnRoutingTableWidget(selector, fragmentClass, observationLevel) {
|
|||
},
|
||||
|
||||
updateState: function () {
|
||||
var elts = ["ul", {"class": "routing-table"},
|
||||
["li", ["pre", route.deserializeGestalt(this.state).pretty()]]];
|
||||
var elts = ["pre", Route.deserializeGestalt(this.state).pretty()];
|
||||
World.updateRoutes([sub(__, 0, observationLevel),
|
||||
pub(__, 0, observationLevel),
|
||||
pub(["DOM", selector, fragmentClass, elts])]);
|
||||
|
@ -45,3 +52,5 @@ function spawnRoutingTableWidget(selector, fragmentClass, observationLevel) {
|
|||
});
|
||||
|
||||
}
|
||||
|
||||
module.exports.spawnRoutingTableWidget = spawnRoutingTableWidget;
|
|
@ -1,4 +1,10 @@
|
|||
// Generic Spy
|
||||
var Minimart = require("./minimart.js");
|
||||
var World = Minimart.World;
|
||||
var sub = Minimart.sub;
|
||||
var pub = Minimart.pub;
|
||||
var __ = Minimart.__;
|
||||
var _$ = Minimart._$;
|
||||
|
||||
function Spy(label, useJson, observationLevel) {
|
||||
this.label = label || "SPY";
|
||||
|
@ -29,3 +35,5 @@ Spy.prototype.handleEvent = function (e) {
|
|||
break;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.Spy = Spy;
|
|
@ -2,6 +2,12 @@
|
|||
// suspension/sleeping!) has caused periodic activities to be
|
||||
// interrupted, and warns others about it
|
||||
// Inspired by http://blog.alexmaccaw.com/javascript-wake-event
|
||||
var Minimart = require("./minimart.js");
|
||||
var World = Minimart.World;
|
||||
var sub = Minimart.sub;
|
||||
var pub = Minimart.pub;
|
||||
var __ = Minimart.__;
|
||||
var _$ = Minimart._$;
|
||||
|
||||
function WakeDetector(period) {
|
||||
this.message = "wake";
|
||||
|
@ -25,3 +31,5 @@ WakeDetector.prototype.trigger = function () {
|
|||
}
|
||||
this.mostRecentTrigger = now;
|
||||
};
|
||||
|
||||
module.exports.WakeDetector = WakeDetector;
|
|
@ -1,3 +1,11 @@
|
|||
var Minimart = require("./minimart.js");
|
||||
var Route = Minimart.Route;
|
||||
var World = Minimart.World;
|
||||
var sub = Minimart.sub;
|
||||
var pub = Minimart.pub;
|
||||
var __ = Minimart.__;
|
||||
var _$ = Minimart._$;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// WebSocket client driver
|
||||
|
||||
|
@ -15,11 +23,11 @@ function WebSocketConnection(label, wsurl, shouldReconnect) {
|
|||
this.wsurl = wsurl;
|
||||
this.shouldReconnect = shouldReconnect ? true : false;
|
||||
this.reconnectDelay = DEFAULT_RECONNECT_DELAY;
|
||||
this.localGestalt = route.emptyGestalt;
|
||||
this.peerGestalt = route.emptyGestalt;
|
||||
this.localGestalt = Route.emptyGestalt;
|
||||
this.peerGestalt = Route.emptyGestalt;
|
||||
this.prevLocalRoutesMessage = null;
|
||||
this.prevPeerRoutesMessage = null;
|
||||
this.deduplicator = new Deduplicator();
|
||||
this.deduplicator = new Minimart.Deduplicator();
|
||||
this.connectionCount = 0;
|
||||
|
||||
this.activityTimestamp = 0;
|
||||
|
@ -58,8 +66,8 @@ WebSocketConnection.prototype.relayGestalt = function () {
|
|||
WebSocketConnection.prototype.aggregateGestalt = function () {
|
||||
var self = this;
|
||||
return this.peerGestalt.transform(function (m, metaLevel) {
|
||||
return route.compilePattern(true,
|
||||
[self.label, metaLevel, route.embeddedMatcher(m)]);
|
||||
return Route.compilePattern(true,
|
||||
[self.label, metaLevel, Route.embeddedMatcher(m)]);
|
||||
}).union(this.relayGestalt());
|
||||
};
|
||||
|
||||
|
@ -88,7 +96,8 @@ WebSocketConnection.prototype.safeSend = function (m) {
|
|||
};
|
||||
|
||||
WebSocketConnection.prototype.sendLocalRoutes = function () {
|
||||
var newLocalRoutesMessage = JSON.stringify(encodeEvent(updateRoutes([this.localGestalt])));
|
||||
var newLocalRoutesMessage =
|
||||
JSON.stringify(encodeEvent(Minimart.updateRoutes([this.localGestalt])));
|
||||
if (this.prevLocalRoutesMessage !== newLocalRoutesMessage) {
|
||||
this.prevLocalRoutesMessage = newLocalRoutesMessage;
|
||||
this.safeSend(newLocalRoutesMessage);
|
||||
|
@ -96,14 +105,14 @@ WebSocketConnection.prototype.sendLocalRoutes = function () {
|
|||
};
|
||||
|
||||
WebSocketConnection.prototype.collectMatchers = function (getAdvertisements, level, g) {
|
||||
var extractMetaLevels = route.compileProjection([this.label, _$, __]);
|
||||
var mls = route.matcherKeys(g.project(extractMetaLevels, getAdvertisements, 0, level));
|
||||
var extractMetaLevels = Route.compileProjection([this.label, _$, __]);
|
||||
var mls = Route.matcherKeys(g.project(extractMetaLevels, getAdvertisements, 0, level));
|
||||
for (var i = 0; i < mls.length; i++) {
|
||||
var metaLevel = mls[i][0]; // only one capture in the projection
|
||||
var extractMatchers = route.compileProjection([this.label, metaLevel, _$]);
|
||||
var extractMatchers = Route.compileProjection([this.label, metaLevel, _$]);
|
||||
var m = g.project(extractMatchers, getAdvertisements, 0, level);
|
||||
this.localGestalt = this.localGestalt.union(route.simpleGestalt(getAdvertisements,
|
||||
route.embeddedMatcher(m),
|
||||
this.localGestalt = this.localGestalt.union(Route.simpleGestalt(getAdvertisements,
|
||||
Route.embeddedMatcher(m),
|
||||
metaLevel,
|
||||
level));
|
||||
}
|
||||
|
@ -115,9 +124,9 @@ WebSocketConnection.prototype.handleEvent = function (e) {
|
|||
case "routes":
|
||||
// TODO: GROSS - erasing by pid!
|
||||
var nLevels = e.gestalt.levelCount(0);
|
||||
var relayGestalt = route.fullGestalt(1, nLevels).label(World.activePid());
|
||||
var relayGestalt = Route.fullGestalt(1, nLevels).label(World.activePid());
|
||||
var g = e.gestalt.erasePath(relayGestalt);
|
||||
this.localGestalt = route.emptyGestalt;
|
||||
this.localGestalt = Route.emptyGestalt;
|
||||
for (var level = 0; level < nLevels; level++) {
|
||||
this.collectMatchers(false, level, g);
|
||||
this.collectMatchers(true, level, g);
|
||||
|
@ -129,7 +138,8 @@ WebSocketConnection.prototype.handleEvent = function (e) {
|
|||
var m = e.message;
|
||||
if (m.length && m.length === 3 && m[0] === this.label)
|
||||
{
|
||||
var encoded = JSON.stringify(encodeEvent(sendMessage(m[2], m[1], e.isFeedback)));
|
||||
var encoded = JSON.stringify(encodeEvent(
|
||||
Minimart.sendMessage(m[2], m[1], e.isFeedback)));
|
||||
if (this.deduplicator.accept(encoded)) {
|
||||
this.safeSend(encoded);
|
||||
}
|
||||
|
@ -232,10 +242,17 @@ function encodeEvent(e) {
|
|||
function decodeAction(j) {
|
||||
switch (j[0]) {
|
||||
case "routes":
|
||||
return updateRoutes([route.deserializeGestalt(j[1], function (v) { return true; })]);
|
||||
return Minimart.updateRoutes([
|
||||
Route.deserializeGestalt(j[1], function (v) { return true; })]);
|
||||
case "message":
|
||||
return sendMessage(j[1], j[2], j[3]);
|
||||
return Minimart.sendMessage(j[1], j[2], j[3]);
|
||||
default:
|
||||
throw { message: "Invalid JSON-encoded action: " + JSON.stringify(j) };
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module.exports.WebSocketConnection = WebSocketConnection;
|
||||
module.exports.encodeEvent = encodeEvent;
|
||||
module.exports.decodeAction = decodeAction;
|
Loading…
Reference in a new issue