bern-target-api 0.1.0

Interface between the Bern compiler and independent UI target modules
Documentation

function startScriptHost(host) {
  const contexts = new Map();
  const source = `onmessage = async ({data: {id, source}}) => {
    try { const value = await (0, eval)(source); postMessage(JSON.stringify({id, value: value === undefined ? null : value})); }
    catch (error) { postMessage(JSON.stringify({id, error: String(error)})); }
  };`;
  const url = URL.createObjectURL(new Blob([source], {type: "text/javascript"}));
  host.exports.bern_script_start();
  const complete = json => host.withBytes(new TextEncoder().encode(json), (ptr, len) => host.exports.bern_script_complete(ptr, len));
  const timer = setInterval(() => {
    const batch = new TextDecoder().decode(host.buffer("bern_script_poll", performance.now()));
    if (!batch) return;
    for (const request of JSON.parse(batch)) {
      if (request.source === null) { contexts.get(request.context)?.terminate(); contexts.delete(request.context); continue; }
      try {
        let worker = contexts.get(request.context);
        if (!worker) {
          worker = new Worker(url); contexts.set(request.context, worker);
          worker.onmessage = ({data}) => complete(data);
          worker.onerror = () => stop();
        }
        worker.postMessage(request);
      } catch (error) { complete(JSON.stringify({id: request.id, error: String(error)})); }
    }
  }, 16);
  const stop = () => {
    clearInterval(timer); for (const worker of contexts.values()) worker.terminate();
    contexts.clear(); URL.revokeObjectURL(url); host.exports.bern_script_stop();
  };
  addEventListener("pagehide", event => { if (!event.persisted) stop(); });
  return stop;
}