defmodule QuickBEAM.WorkerAPI do @moduledoc false @worker_bootstrap """ globalThis.self = globalThis; self.postMessage = function(data) { Beam.call("__worker_post", data); }; Object.defineProperty(self, "onmessage", { set(handler) { Beam.onMessage(msg => handler({ data: msg })); }, configurable: true, }); """ @spec spawn_worker([String.t()], pid()) :: integer() def spawn_worker([script], parent_pid) do worker_id = System.unique_integer([:positive]) {:ok, child} = QuickBEAM.start( handlers: %{ "__worker_post" => fn [data] -> send(parent_pid, {:worker_msg, worker_id, data}) nil end } ) send(parent_pid, {:worker_register, worker_id, child}) QuickBEAM.eval(child, @worker_bootstrap) Task.start(fn -> try do case QuickBEAM.eval(child, script) do {:ok, _} -> :ok {:error, err} -> send(parent_pid, {:worker_error, worker_id, err}) end catch :exit, {:normal, _} -> :ok :exit, :normal -> :ok end end) worker_id end @spec post_to_child(list(), pid()) :: nil def post_to_child([worker_id, data], parent_pid) do send(parent_pid, {:worker_post_to_child, worker_id, data}) nil end @spec terminate_worker([integer()], pid()) :: nil def terminate_worker([worker_id], parent_pid) do send(parent_pid, {:worker_terminate, worker_id}) nil end end