make the webworker typed for type safety

This commit is contained in:
Lily Tsuru 2024-09-08 18:53:07 -04:00
parent e58a765cfa
commit c8f9c9d9ea
2 changed files with 50 additions and 29 deletions

View file

@ -3,8 +3,10 @@ import { GetKeySym } from "./key";
import { MouseState } from "./mouse"; import { MouseState } from "./mouse";
import { import {
PlayerConfiguredMessage, PlayerConfiguredMessage,
PlayerInputMessage,
PlayerOutputMessage, PlayerOutputMessage,
} from "./player_worker_messages"; } from "./player_worker_messages";
import { TypedWorker } from "./typed_worker";
class Client { class Client {
private uri: string; private uri: string;
@ -21,7 +23,8 @@ class Client {
) as HTMLDivElement; ) as HTMLDivElement;
private webSocket: WebSocket; private webSocket: WebSocket;
private player: Worker | null = null; private player: TypedWorker<PlayerInputMessage, PlayerOutputMessage> | null =
null;
private mouse = new MouseState(); private mouse = new MouseState();
@ -127,40 +130,40 @@ class Client {
if (this.player == null) { if (this.player == null) {
let offscreen = this.canvas.transferControlToOffscreen(); let offscreen = this.canvas.transferControlToOffscreen();
this.player = new Worker(new URL("./player_worker.ts", import.meta.url), { this.player = new TypedWorker<PlayerInputMessage, PlayerOutputMessage>(
type: "module", new URL("./player_worker.ts", import.meta.url),
}); {
type: "module",
}
);
this.player.addEventListener( this.player.onMessage = (message: PlayerOutputMessage) => {
"message", switch (message.type) {
(message: MessageEvent<PlayerOutputMessage>) => { case "configured": {
switch (message.data.type) { // set the message
case "configured": { let configMessage = message as PlayerConfiguredMessage;
// set the message let hwLabelElement = document.getElementById(
let configMessage = message.data as PlayerConfiguredMessage; "hw-label"
let hwLabelElement = document.getElementById( ) as HTMLSpanElement;
"hw-label"
) as HTMLSpanElement;
if (configMessage.usingHwDecode) { if (configMessage.usingHwDecode) {
if (!hwLabelElement.classList.contains("hw-good")) { if (!hwLabelElement.classList.contains("hw-good")) {
hwLabelElement.classList.add("hw-good"); hwLabelElement.classList.add("hw-good");
hwLabelElement.innerText = "IS :)"; hwLabelElement.innerText = "IS :)";
} }
} else { } else {
if (!hwLabelElement.classList.contains("hw-bad")) { if (!hwLabelElement.classList.contains("hw-bad")) {
hwLabelElement.classList.add("hw-bad"); hwLabelElement.classList.add("hw-bad");
hwLabelElement.innerText = "is NOT :("; hwLabelElement.innerText = "is NOT :(";
}
} }
} }
} }
} }
); };
// Send the init message to the worker to give it // Send the init message to the worker to give it
// access to the canvas // access to the canvas
this.player.postMessage( this.player.post(
{ {
type: "init", type: "init",
canvas: offscreen, canvas: offscreen,
@ -185,13 +188,13 @@ class Client {
} }
OnWSOpen() { OnWSOpen() {
this.player?.postMessage({ this.player?.post({
type: "init-decoder", type: "init-decoder",
}); });
} }
OnWSClosed() { OnWSClosed() {
this.player?.postMessage({ this.player?.post({
type: "shutdown-decoder", type: "shutdown-decoder",
}); });
@ -203,7 +206,7 @@ class Client {
OnWSMessage(ev: MessageEvent<string | ArrayBuffer>) { OnWSMessage(ev: MessageEvent<string | ArrayBuffer>) {
// Video data is binary // Video data is binary
if (typeof ev.data !== "string") { if (typeof ev.data !== "string") {
this.player?.postMessage( this.player?.post(
{ {
type: "data", type: "data",
data: ev.data as ArrayBuffer, data: ev.data as ArrayBuffer,

View file

@ -0,0 +1,18 @@
// It's like Worker but typed.
export class TypedWorker<TInput, TOutput> {
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<TOutput>) => {
if (self.onMessage) self.onMessage(m.data);
});
}
post<M extends TInput>(msg: M, transfer?: Transferable[]) {
if (transfer) this.worker.postMessage(msg, transfer);
else this.worker.postMessage(msg);
}
}