import { QuickJSWorker } from "../dist"; const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); describe("Event adapter compatibility", () => { test("on('message') can be removed with off()", async () => { const received: any[] = []; const worker = new QuickJSWorker(); const cb = (msg: any) => received.push(msg); try { worker.on("message", cb); await worker.eval(`postMessage({ a: 1 })`); await sleep(20); expect(received).toEqual([{ a: 1 }]); worker.off("message", cb); await worker.eval(`postMessage({ a: 2 })`); await sleep(20); expect(received).toEqual([{ a: 1 }]); } finally { await worker.close(); } }); test("off('message') without a callback clears all message listeners", async () => { const received: any[] = []; const worker = new QuickJSWorker(); try { worker.on("message", (msg: any) => received.push(["a", msg])); worker.on("message", (msg: any) => received.push(["b", msg])); worker.off("message"); await worker.eval(`postMessage({ a: 1 })`); await sleep(20); expect(received).toEqual([]); } finally { await worker.close(); } }); test("message listeners are deduped and subscriber errors are swallowed", async () => { const seen: any[] = []; const worker = new QuickJSWorker(); const cb = (msg: any) => { seen.push(msg); throw new Error("handler boom"); }; try { worker.on("message", cb); worker.on("message", cb); worker.on("message", (msg: any) => seen.push({ tail: msg })); await worker.eval(`postMessage({ n: 1 })`); await worker.eval(`postMessage({ n: 2 })`); await sleep(40); expect(seen).toEqual([ { n: 1 }, { tail: { n: 1 } }, { n: 2 }, { tail: { n: 2 } }, ]); } finally { await worker.close(); } }); test("on('runtime') can be removed with off()", async () => { const hits: string[] = []; const worker = new QuickJSWorker(); const cb = (event: any) => hits.push(event.kind); try { worker.on("runtime", cb); await worker.eval("1 + 1"); expect(hits).toContain("eval.begin"); expect(hits).toContain("eval.end"); worker.off("runtime", cb); hits.length = 0; await worker.eval("2 + 2"); expect(hits).toEqual([]); } finally { await worker.close(); } }); test("on('error') can be removed with off()", async () => { const hits: string[] = []; const worker = new QuickJSWorker(); const cb = (event: any) => hits.push(event.kind); try { worker.on("error", cb); await expect(worker.eval(`throw new Error("boom-1")`)).rejects.toBeTruthy(); expect(hits).toEqual(["error.thrown"]); worker.off("error", cb); hits.length = 0; await expect(worker.eval(`throw new Error("boom-2")`)).rejects.toBeTruthy(); expect(hits).toEqual([]); } finally { await worker.close(); } }); test("on('close') can be removed with off() and close is only delivered once", async () => { const hits: string[] = []; const worker = new QuickJSWorker(); const cb = () => hits.push("close"); worker.on("close", cb); worker.off("close", cb); await worker.close(); expect(hits).toEqual([]); const worker2 = new QuickJSWorker(); try { worker2.on("close", () => hits.push("close-2")); await worker2.close(); await worker2.close(); expect(hits).toEqual(["close-2"]); } finally { if (!worker2.isClosed()) await worker2.close(); } }); });