mirror of
https://github.com/simplex-chat/simplexmq.git
synced 2026-03-29 10:10:06 +00:00
fix worker message race: wait for ready signal before posting messages
This commit is contained in:
@@ -28,10 +28,27 @@ class WorkerBackend implements CryptoBackend {
|
||||
private pending = new Map<number, PendingRequest>()
|
||||
private nextId = 1
|
||||
private progressCb: ((done: number, total: number) => void) | null = null
|
||||
private ready: Promise<void>
|
||||
|
||||
constructor() {
|
||||
this.worker = new Worker(new URL('./crypto.worker.ts', import.meta.url), {type: 'module'})
|
||||
this.worker.onmessage = (e) => this.handleMessage(e.data)
|
||||
let rejectReady: (e: Error) => void
|
||||
this.ready = new Promise((resolve, reject) => {
|
||||
rejectReady = reject
|
||||
this.worker.onmessage = (e) => {
|
||||
if (e.data?.type === 'ready') {
|
||||
this.worker.onmessage = (e) => this.handleMessage(e.data)
|
||||
resolve()
|
||||
} else {
|
||||
reject(new Error('Worker: unexpected first message'))
|
||||
}
|
||||
}
|
||||
})
|
||||
this.worker.onerror = (e) => {
|
||||
rejectReady(new Error('Worker failed to load: ' + e.message))
|
||||
for (const p of this.pending.values()) p.reject(new Error('Worker error: ' + e.message))
|
||||
this.pending.clear()
|
||||
}
|
||||
}
|
||||
|
||||
private handleMessage(msg: {id: number, type: string, [k: string]: any}) {
|
||||
@@ -49,7 +66,8 @@ class WorkerBackend implements CryptoBackend {
|
||||
}
|
||||
}
|
||||
|
||||
private send(msg: Record<string, any>, transfer?: Transferable[]): Promise<any> {
|
||||
private async send(msg: Record<string, any>, transfer?: Transferable[]): Promise<any> {
|
||||
await this.ready
|
||||
const id = this.nextId++
|
||||
return new Promise((resolve, reject) => {
|
||||
this.pending.set(id, {resolve, reject})
|
||||
|
||||
@@ -256,9 +256,9 @@ async function handleCleanup(id: number) {
|
||||
// ── Message dispatch ────────────────────────────────────────────
|
||||
|
||||
self.onmessage = async (e: MessageEvent) => {
|
||||
await initPromise
|
||||
const msg = e.data
|
||||
try {
|
||||
await initPromise
|
||||
switch (msg.type) {
|
||||
case 'encrypt':
|
||||
await handleEncrypt(msg.id, msg.data, msg.fileName)
|
||||
@@ -302,3 +302,6 @@ const initPromise = (async () => {
|
||||
await sodium.ready
|
||||
await sweepStale()
|
||||
})()
|
||||
|
||||
// Signal main thread that the worker is ready to receive messages
|
||||
initPromise.then(() => self.postMessage({type: 'ready'}), () => {})
|
||||
|
||||
Reference in New Issue
Block a user