From c8f9c9d9ea37f6f7edd5a6b4e52bb7c239570218 Mon Sep 17 00:00:00 2001 From: modeco80 Date: Sun, 8 Sep 2024 18:53:07 -0400 Subject: [PATCH] make the webworker typed for type safety --- client/src/index.ts | 61 ++++++++++++++++++++------------------ client/src/typed_worker.ts | 18 +++++++++++ 2 files changed, 50 insertions(+), 29 deletions(-) create mode 100644 client/src/typed_worker.ts diff --git a/client/src/index.ts b/client/src/index.ts index c2a180d..635c0fd 100644 --- a/client/src/index.ts +++ b/client/src/index.ts @@ -3,8 +3,10 @@ import { GetKeySym } from "./key"; import { MouseState } from "./mouse"; import { PlayerConfiguredMessage, + PlayerInputMessage, PlayerOutputMessage, } from "./player_worker_messages"; +import { TypedWorker } from "./typed_worker"; class Client { private uri: string; @@ -21,7 +23,8 @@ class Client { ) as HTMLDivElement; private webSocket: WebSocket; - private player: Worker | null = null; + private player: TypedWorker | null = + null; private mouse = new MouseState(); @@ -127,40 +130,40 @@ class Client { if (this.player == null) { let offscreen = this.canvas.transferControlToOffscreen(); - this.player = new Worker(new URL("./player_worker.ts", import.meta.url), { - type: "module", - }); + this.player = new TypedWorker( + new URL("./player_worker.ts", import.meta.url), + { + type: "module", + } + ); - this.player.addEventListener( - "message", - (message: MessageEvent) => { - switch (message.data.type) { - case "configured": { - // set the message - let configMessage = message.data as PlayerConfiguredMessage; - let hwLabelElement = document.getElementById( - "hw-label" - ) as HTMLSpanElement; + this.player.onMessage = (message: PlayerOutputMessage) => { + switch (message.type) { + case "configured": { + // set the message + let configMessage = message as PlayerConfiguredMessage; + let hwLabelElement = document.getElementById( + "hw-label" + ) as HTMLSpanElement; - if (configMessage.usingHwDecode) { - if (!hwLabelElement.classList.contains("hw-good")) { - hwLabelElement.classList.add("hw-good"); - hwLabelElement.innerText = "IS :)"; - } - } else { - if (!hwLabelElement.classList.contains("hw-bad")) { - hwLabelElement.classList.add("hw-bad"); - hwLabelElement.innerText = "is NOT :("; - } + if (configMessage.usingHwDecode) { + if (!hwLabelElement.classList.contains("hw-good")) { + hwLabelElement.classList.add("hw-good"); + hwLabelElement.innerText = "IS :)"; + } + } else { + if (!hwLabelElement.classList.contains("hw-bad")) { + hwLabelElement.classList.add("hw-bad"); + hwLabelElement.innerText = "is NOT :("; } } } } - ); + }; // Send the init message to the worker to give it // access to the canvas - this.player.postMessage( + this.player.post( { type: "init", canvas: offscreen, @@ -185,13 +188,13 @@ class Client { } OnWSOpen() { - this.player?.postMessage({ + this.player?.post({ type: "init-decoder", }); } OnWSClosed() { - this.player?.postMessage({ + this.player?.post({ type: "shutdown-decoder", }); @@ -203,7 +206,7 @@ class Client { OnWSMessage(ev: MessageEvent) { // Video data is binary if (typeof ev.data !== "string") { - this.player?.postMessage( + this.player?.post( { type: "data", data: ev.data as ArrayBuffer, diff --git a/client/src/typed_worker.ts b/client/src/typed_worker.ts new file mode 100644 index 0000000..a77270b --- /dev/null +++ b/client/src/typed_worker.ts @@ -0,0 +1,18 @@ +// It's like Worker but typed. +export class TypedWorker { + private worker; + public onMessage: null | ((m: TOutput) => void) = null; + + constructor(uri: URL | string, opts?: WorkerOptions) { + this.worker = new Worker(uri, opts); + let self = this; + this.worker.addEventListener("message", (m: MessageEvent) => { + if (self.onMessage) self.onMessage(m.data); + }); + } + + post(msg: M, transfer?: Transferable[]) { + if (transfer) this.worker.postMessage(msg, transfer); + else this.worker.postMessage(msg); + } +}