diff --git a/demos/worker/sum-systemjs-worker.js b/demos/worker/sum-systemjs-worker.js index ebecdce3c..d1ab41337 100644 --- a/demos/worker/sum-systemjs-worker.js +++ b/demos/worker/sum-systemjs-worker.js @@ -2,4 +2,7 @@ import {sum} from "./sum.js" export function onmessage(e) { postMessage(sum(e.data)); -} \ No newline at end of file +} + + + diff --git a/src/worker/meta-worker.js b/src/worker/meta-worker.js index ab8fda2e5..94c9793b3 100644 --- a/src/worker/meta-worker.js +++ b/src/worker/meta-worker.js @@ -9,9 +9,10 @@ self.lively4url = self.location.origin + path.join("/"); importScripts("./livelyworker.js") onmessage = function(evt) { - // console.log("metaworker initial onmessage", evt) + + console.log("metaworker initial onmessage", evt) if (evt.data.message == "load") { - // console.log("meta worker load " + evt.data.url) + console.log("meta worker load " + evt.data.url) System.import("src/plugin-babel.js").then(() => { System.import("src/client/preferences.js").then((mod) => { var Preferences = mod.default @@ -21,9 +22,25 @@ onmessage = function(evt) { System.import(evt.data.url).then((m) => { postMessage({message: "loaded"}) - self.onmessage = (...args) => { - // console.log("metaworker custom onmessage", args) - m.onmessage(...args) + self.onmessage = async (evt) => { + console.log("metaworker onmessage", evt) + + if(m.onrequest && evt.data && evt.data.message === "systemjs-worker-request") { + try { + let result = await m.onrequest(evt.data) + // console.log("ON MESSAGE result " + result) + return postMessage({message: "systemjs-worker-response", + name: evt.data.name, id: evt.data.id, response: result}) + } catch(e) { + return postMessage({message: "systemjs-worker-response", + name: "error", id: evt.data.id, response: "" + e}) + } + } + + console.log("metaworker custom onmessage", evt) + if (m.onmessage) { + m.onmessage(evt) + } } }).catch((err) => { console.log("meta worker error ", err) diff --git a/src/worker/systemjs-worker.js b/src/worker/systemjs-worker.js index 8459d7b50..adc2bd85f 100644 --- a/src/worker/systemjs-worker.js +++ b/src/worker/systemjs-worker.js @@ -4,15 +4,24 @@ import Preferences from "src/client/preferences.js" export var workers + + export default class SystemjsWorker { static get workers() { if (!workers) workers = new Set() return workers } + + newId() { + return this.idCounter++ + } + constructor(url) { /*MD The meta-worker is the actual worker, that is generic will load the actual systemjs module, which contains the client code MD*/ + this.idCounter = 1 + this.resolveRequestForId = new Map() this.metaworker = new Worker("src/worker/meta-worker.js"); /*MD ## bootstrap onmessage MD*/ // console.log("sytemjs-worker new: " + url) @@ -21,7 +30,7 @@ export default class SystemjsWorker { setTimeout(() => { - if (!isLoaded) reject("timeout") + if (!isLoaded) reject("timeout while loading systemjs") }, 10000) // 10s then timeout? /*MD ### Setup: install a message for loading, that will be rpelaced later MD*/ @@ -35,9 +44,16 @@ export default class SystemjsWorker { // console.log("worker loaded", url) /*MD ### Important: here the actual client message is installed MD*/ - this.metaworker.onmessage = (msg) => { + this.metaworker.onmessage = (evt) => { + console.log("systemjs-worker.js ON MESSAGE", evt) + let msg = evt.data + // check if we handle it ourself + if (msg && msg.message === "systemjs-worker-response") { + return this.handleRequest(msg) + } + // console.log(`systemjs-worker.js metaworker.onmessage (${url})` ) - this.onmessage(msg) + this.onmessage(evt) } isLoaded = true resolve(true) // worker should accept postMessages now... @@ -54,6 +70,31 @@ export default class SystemjsWorker { onmessage(evt) { // do nothing } + + handleRequest(msg) { + console.log("handleRequest ", msg) + var resolve = this.resolveRequestForId.get(msg.id) + if (!resolve) { + throw new Error("No resolve func for message " + msg.name + ", " + msg.id + ", " + msg.response) + } + this.resolveRequestForId.set(msg.id, null) + resolve(msg.response) + } + + async request(name, data, timeout=1000) { + + var id = this.newId() + var promise = new Promise((resolve, reject) => { + this.resolveRequestForId.set(id, resolve) + this.postMessage({message: "systemjs-worker-request", id: id, name: name, arguments: data}) + var start = performance.now() + setTimeout(() => { + var unhandledRequestResolve = this.resolveRequestForId.get(id) + if (unhandledRequestResolve) reject({error: "request timeout after " + (performance.now() - start) + "ms"}) + }, timeout) + }) + return promise + } terminate() { this.metaworker.terminate() diff --git a/test/worker/systemjs-worker-test-sum-request-worker.js b/test/worker/systemjs-worker-test-sum-request-worker.js new file mode 100644 index 000000000..e03e25fe7 --- /dev/null +++ b/test/worker/systemjs-worker-test-sum-request-worker.js @@ -0,0 +1,26 @@ + + + +export async function onrequest(msg) { + if (msg.name === "sum") { + var array = msg.arguments + let result = array[0] + array[1] + + return result + } + throw new Error("request not understood: " + msg) +} + + +// export function onmessage(evt) { +// if(evt.data && evt.data.message === "systemjs-worker-request") { +// if (evt.data.name === "sum") { +// var array = evt.data.arguments +// let result = array[0] + array[1] +// // console.log("ON MESSAGE result " + result) +// return postMessage({message: "systemjs-worker-response", name: evt.data.name, id: evt.data.id, response: result}) +// } +// return postMessage({error: "unhandled systemjs-worker-request " + evt}) +// } +// return postMessage({error: "could not handle message " + evt}) +// } \ No newline at end of file diff --git a/test/worker/systemjs-worker-test-sum-worker.js b/test/worker/systemjs-worker-test-sum-worker.js new file mode 100644 index 000000000..bf142e3e5 --- /dev/null +++ b/test/worker/systemjs-worker-test-sum-worker.js @@ -0,0 +1,7 @@ + + +export function onmessage(evt) { + let result = evt.data[0] + evt.data[1] + + postMessage(result) +} \ No newline at end of file diff --git a/test/worker/systemjs-worker-test.js b/test/worker/systemjs-worker-test.js new file mode 100644 index 000000000..40fbab30f --- /dev/null +++ b/test/worker/systemjs-worker-test.js @@ -0,0 +1,54 @@ + +import SystemjsWorker from "src/worker/systemjs-worker.js" + +import {expect} from 'src/external/chai.js'; + +describe('SystemJSWorker', () => { + + + describe('onmessage and postMessage', () => { + let myworker + before(async () => { + myworker = new SystemjsWorker(lively4url + "/test/worker/systemjs-worker-test-sum-worker.js") + + await myworker.loaded + }) + + it('sums', async () => { + var wasrun = false + myworker.onmessage = (evt) => { + wasrun = true + expect(evt.data).equals(7) + } + myworker.postMessage([3, 4]); + + await lively.sleep(1) // not directly connected yet + + expect(wasrun, "wasrun").equals(true) + + }) + after(() => { + myworker.terminate() + }) + + }) + + describe('request', () => { + let myworker + before(async () => { + myworker = new SystemjsWorker(lively4url + "/test/worker/systemjs-worker-test-sum-request-worker.js") + + await myworker.loaded + }) + + it('sums', async () => { + + var result = await myworker.request("sum", [3, 4]); + + // expect(result, "result").equals(7) + }) + after(() => { + myworker.terminate() + }) + }) +}); \ No newline at end of file