git.iko.soy/rowtype-yoga/purescript-web-proletarian
on main help sign in
feat: add disposable worker subscriptions and failure hooks
commit369ed371156d260775aab87fb69c9e81911b922e authorMark <mark.eibes@gmail.com> dateSat 12 Sep 2026, 20:08 (1 month ago) parent0ee3de0
5 files changed+48−13
README.md+2−2 src/Yoga/WebBoss.js+13−4 src/Yoga/WebBoss.purs+6−2 src/Yoga/WebWorker.js+22−4 src/Yoga/WebWorker.purs+5−1
README.md+2−2
@@ -24,7 +24,7 @@ import Yoga.WebProletarian.Types (Worker)
2424import Yoga.WebWorker (postMessageToBoss, subscribe)
2525
2626main ∷ Effect Unit
27−main = subscribe (\(i :: Int) -> postMessageToBoss (show i))
27+main = void $ subscribe (\(i :: Int) -> postMessageToBoss (show i))
2828
2929foreign import newWorker ∷ Effect (Worker Int String)
3030```
@@ -66,7 +66,7 @@ import Worker.Echo as Echo
6666main :: Effect Unit
6767main = do
6868 worker ← Echo.newWorker
69− worker # onMessageFromWorker \msg -> do
69+ void $ worker # onMessageFromWorker \msg -> do
7070 Console.log msg
7171 worker # terminate
7272 worker # postMessageToWorker 42
src/Yoga/WebBoss.js+13−4
@@ -1,10 +1,19 @@
11export const onMessageFromWorker = handler => worker => () => {
2− worker.onmessage = (msg => handler(msg.data)())
3−}
2+ const listener = event => handler(event.data)();
3+ worker.addEventListener("message", listener);
4+ return () => worker.removeEventListener("message", listener);
5+};
46
57export const onErrorFromWorker = handler => worker => () => {
6− worker.addEventListener("error", e => handler(e.message)())
7−}
8+ const listener = event => handler(event)();
9+ worker.addEventListener("error", listener);
10+ return () => worker.removeEventListener("error", listener);
11+};
12+
13+export const onMessageErrorFromWorker = handler => worker => () => {
14+ worker.addEventListener("messageerror", handler);
15+ return () => worker.removeEventListener("messageerror", handler);
16+};
817
918export const postMessageToWorker = msg => worker => () => worker.postMessage(msg)
1019
src/Yoga/WebBoss.purs+6−2
@@ -3,14 +3,18 @@ module Yoga.WebBoss where
33import Prelude
44
55import Effect (Effect)
6+import Web.HTML.Event.ErrorEvent (ErrorEvent)
67import Yoga.WebProletarian.Transferable (Transferable)
78import Yoga.WebProletarian.Types (Worker)
89
910foreign import onMessageFromWorker
10− ∷ ∀ toWorker toBoss. (toBoss → Effect Unit) → Worker toWorker toBoss → Effect Unit
11+ ∷ ∀ toWorker toBoss. (toBoss → Effect Unit) → Worker toWorker toBoss → Effect (Effect Unit)
1112
1213foreign import onErrorFromWorker
13− ∷ ∀ toWorker toBoss. (String → Effect Unit) → Worker toWorker toBoss → Effect Unit
14+ ∷ ∀ toWorker toBoss. (ErrorEvent → Effect Unit) → Worker toWorker toBoss → Effect (Effect Unit)
15+
16+foreign import onMessageErrorFromWorker
17+ ∷ ∀ toWorker toBoss. Effect Unit → Worker toWorker toBoss → Effect (Effect Unit)
1418
1519foreign import postMessageToWorker ∷ ∀ toBoss toWorker. toWorker → Worker toWorker toBoss → Effect Unit
1620
src/Yoga/WebWorker.js+22−4
@@ -1,10 +1,28 @@
11export const subscribe = handler => () => {
2− addEventListener("message", (event) => {
3− handler(event.data)();
4− })
5−}
2+ const listener = event => handler(event.data)();
3+ addEventListener("message", listener);
4+ return () => removeEventListener("message", listener);
5+};
66
77export const quit = () => close()
88
99export const postMessageToBoss = data => () => postMessage(data)
1010
11+export const onFailure = handler => () => {
12+ const onError = event => {
13+ event.preventDefault();
14+ handler(event.message || "Worker execution failed")();
15+ };
16+ const onRejection = event => {
17+ event.preventDefault();
18+ const reason = event.reason;
19+ handler(reason instanceof Error ? reason.message : String(reason))();
20+ };
21+ addEventListener("error", onError);
22+ addEventListener("unhandledrejection", onRejection);
23+ return () => {
24+ removeEventListener("error", onError);
25+ removeEventListener("unhandledrejection", onRejection);
26+ };
27+};
28+
src/Yoga/WebWorker.purs+5−1
@@ -3,9 +3,13 @@ module Yoga.WebWorker where
33import Prelude
44import Effect (Effect)
55
6−foreign import subscribe :: forall toWorker. (toWorker -> Effect Unit) -> Effect Unit
6+foreign import subscribe :: forall toWorker. (toWorker -> Effect Unit) -> Effect (Effect Unit)
77
88foreign import quit :: Effect Unit
99
1010foreign import postMessageToBoss :: forall toBoss. toBoss -> Effect Unit
1111
12+-- | Handle worker-global exceptions and rejected promises. Installing this
13+-- | handler consumes their default reporting; disposing restores it.
14+foreign import onFailure :: (String -> Effect Unit) -> Effect (Effect Unit)
15+