Web Worker support, based on js-marketplace

This commit is contained in:
Tony Garnock-Jones 2017-09-16 20:24:12 +01:00
parent 96331e0cfd
commit 2a5d8ebdd4
7 changed files with 138 additions and 7 deletions

View File

@ -0,0 +1,7 @@
all: index.expanded.js worker.expanded.js
%.expanded.js: %.js
../../bin/syndicatec $< > $@ || (rm -f $@; false)
clean:
rm -f *.expanded.js

View File

@ -0,0 +1,15 @@
<!doctype html>
<html>
<head>
<title>Syndicate: DOM WebWorker Example</title>
<meta charset="utf-8">
<script src="../../dist/syndicate.js"></script>
<script src="index.expanded.js"></script>
</head>
<body>
<h1>DOM WebWorker example</h1>
<div id="counter-holder"></div>
<div id="clicker-holder"></div>
<pre id="spy-holder"></pre>
</body>
</html>

View File

@ -0,0 +1,22 @@
document.addEventListener('DOMContentLoaded', function () {
ground dataspace G {
Syndicate.UI.spawnUIDriver();
spawn {
var ui = new Syndicate.UI.Anchor();
during Syndicate.observe('bump_count') { // wait for the worker to boot and start listening
assert ui.html('#clicker-holder',
'<button><span style="font-style: italic">Click me!</span></button>');
}
on message Syndicate.UI.globalEvent('#clicker-holder > button', 'click', _) {
:: 'bump_count';
}
}
Syndicate.Dataspace.spawn(new Syndicate.Worker('worker.expanded.js'));
}
G.dataspace.setOnStateChange(function (mux, patch) {
document.getElementById('spy-holder').innerText = Syndicate.prettyTrie(mux.routingTable);
});
});

View File

@ -0,0 +1,19 @@
importScripts("../../dist/syndicate.js");
var G = new Syndicate.WorkerGround(function () {
spawn {
var ui = new Syndicate.UI.Anchor();
field this.counter = 0;
assert ui.html('#counter-holder', '<div><p>The current count is: '+this.counter+'</p></div>')
metalevel 1;
on message 'bump_count'
metalevel 1
{
this.counter++;
}
}
});
G.startStepping();

View File

@ -48,6 +48,6 @@ module.exports.Actor = require("./actor.js");
// module.exports.Spy = require("./spy.js").Spy;
// module.exports.WakeDetector = require("./wake-detector.js").WakeDetector;
// var Worker = require("./worker.js");
// module.exports.Worker = Worker.Worker;
// module.exports.WorkerGround = Worker.WorkerGround;
var Worker = require("./worker.js");
module.exports.Worker = Worker.Worker;
module.exports.WorkerGround = Worker.WorkerGround;

View File

@ -1,11 +1,10 @@
var randomId;
if ((typeof window !== 'undefined') &&
(typeof window.crypto !== 'undefined') &&
(typeof window.crypto.getRandomValues !== 'undefined')) {
function browserCryptoObject(crypto) {
if (typeof crypto.getRandomValues === 'undefined') return false;
randomId = function (byteCount, hexOutput) {
var buf = new Uint8Array(byteCount);
window.crypto.getRandomValues(buf);
crypto.getRandomValues(buf);
if (hexOutput) {
var encoded = [];
for (var i = 0; i < buf.length; i++) {
@ -17,7 +16,24 @@ if ((typeof window !== 'undefined') &&
return btoa(String.fromCharCode.apply(null, buf)).replace(/=/g,'');
}
};
return true;
}
if ((typeof window !== 'undefined') &&
(typeof window.crypto !== 'undefined') &&
browserCryptoObject(window.crypto)) {
// We are in the main page, and window.crypto is available, and
// browserCryptoObject has installed a suitable randomId. Do
// nothing.
} else if ((typeof self !== 'undefined') &&
(typeof self.crypto !== 'undefined') &&
browserCryptoObject(self.crypto)) {
// We are in a web worker, and self.crypto is available, and
// browserCryptoObject has installed a suitable randomId. Do
// nothing.
} else {
// See if we're in node.js.
var crypto;
try {
crypto = require('crypto');

52
js/src/worker.js Normal file
View File

@ -0,0 +1,52 @@
/* Web Worker interface */
var Ground = require("./ground.js").Ground;
var Util = require("./util.js");
var Codec = require("./codec.js");
var Dataspace = require("./dataspace.js").Dataspace;
var BuiltinWorker = typeof window !== 'undefined' && window.Worker;
///////////////////////////////////////////////////////////////////////////
function Worker(scriptUrl) {
this.scriptUrl = scriptUrl;
this.w = new BuiltinWorker(scriptUrl);
}
Worker.prototype.boot = function () {
this.w.onmessage = Dataspace.wrap(function (e) {
console.log("Received from worker", JSON.stringify(e.data));
Dataspace.enqueueAction(Codec.decodeAction(e.data));
});
};
Worker.prototype.handleEvent = function (e) {
console.log("Sending to worker", JSON.stringify(Codec.encodeEvent(e)));
this.w.postMessage(Codec.encodeEvent(e));
};
///////////////////////////////////////////////////////////////////////////
function WorkerGround(bootFn) {
var self = this;
Ground.call(this, bootFn);
onmessage = function (e) {
console.log("Received from main page", JSON.stringify(e.data));
self.dataspace.handleEvent(Codec.decodeEvent(e.data));
self.startStepping();
};
}
WorkerGround.prototype = Util.extend({}, Ground.prototype);
WorkerGround.prototype.enqueueAction = function (pid, action) {
console.log("Sending to main page", JSON.stringify(Codec.encodeAction(action)));
postMessage(Codec.encodeAction(action));
console.log("Sent to main page");
};
///////////////////////////////////////////////////////////////////////////
module.exports.Worker = Worker;
module.exports.WorkerGround = WorkerGround;