async function workersStarted () {
return new Promise(async (ready, fail): Promise<void> => {
+ const id = crypto.randomUUID()
const resolutions = []
for (const w of workers) {
resolutions.push(new Promise((resolve, reject): void => {
w.onerror = reject
w.onmessage = (msg) => {
const { data } = msg
- if (data.url === url) {
+ if (data.url === url && data.id === id) {
data.result === 'started' ? resolve(data) : reject(data)
}
}
- w.postMessage({ start: true, url })
+ w.postMessage({ url, id, start: true })
}))
}
Promise.all(resolutions).then(ready).catch(fail)
async function dispatch (): Promise<bigint> {
return new Promise((resolve, reject) => {
+ const id = crypto.randomUUID()
const seed = crypto.getRandomValues(new BigUint64Array(workers.length))
const attempts = []
for (let i = 0; i < workers.length; i++) {
w.onerror = err
w.onmessage = (msg) => {
const { data } = msg
- if (data.url === url) {
+ if (data.url === url && data.id === id) {
logger.log(`received result ${typeof data.result} "${data.result}" from worker ${i}`)
found(data.result)
}
}
- logger.log(`sending data to worker ${i}`, { ...data, url })
- w.postMessage({ ...data, url })
+ logger.log(`sending data to worker ${i}`, { url, id, ...data })
+ w.postMessage({ url, id, ...data })
}))
}
Promise.all(attempts)
async function workersStopped (): Promise<boolean> {
return new Promise(stopped => {
+ const id = crypto.randomUUID()
try {
const attempts = []
for (let i = 0; i < workers.length; i++) {
w.onerror = reject
w.onmessage = (msg) => {
const { data } = msg
- if (data.url === url) {
+ if (data.url === url && data.id === id) {
data.result === 'stopped' ? resolve(true) : reject(i)
}
}
- w.postMessage({ stop: true, url })
+ w.postMessage({ url, id, stop: true })
}))
}
Promise.allSettled(attempts).then(results => {
}
}
- async function handleMessage (msg: any): Promise<void> {
- if (msg?.data?.url !== self.location.href) return
- let result: any = null
+ async function handleMessage (msg: unknown): Promise<void> {
+ if (msg == null
+ || typeof msg !== 'object'
+ || !('data' in msg)
+ || msg.data == null
+ || typeof msg.data !== 'object'
+ || !('url' in msg.data)
+ || typeof msg.data.url !== 'string'
+ || !('id' in msg.data)
+ || typeof msg.data.id !== 'string'
+ ) return
+
+ const data = msg.data
+ const { url, id } = data
+ if (url !== self.location.href) return
+
+ let result: undefined | string
+
try {
- const { data } = msg
if (!isReady) await setup()
const hashArray = new BigUint64Array(4)
const hashView = new DataView(hashArray.buffer)
- if (data.start) {
+ if ('start' in data && data.start) {
result = 'started'
- } else if (data.stop) {
+ } else if ('stop' in data && data.stop) {
removeEventListener('message', handleMessage)
result = 'stopped'
- } else {
+ } else if ('seed' in data
+ && typeof data.seed === 'string'
+ && 'difficulty' in data
+ && typeof data.difficulty === 'string'
+ && 'hash' in data
+ && typeof data.hash === 'string'
+ ) {
const seed = BigInt(`0x${data.seed}`)
const difficulty = BigInt(`0x${data.difficulty}`)
for (let i = 0; i < data.hash.length; i += 16) {
workView.setBigUint64(0, work, true)
result = workArray[0].toString(16).padStart(16, '0')
}
- } catch (err: unknown) {
- if (typeof err === 'object' && err != null) {
- const e = err as Record<string, unknown>
- if (typeof e.message === 'string' && e.message.includes('divide by zero')) {
- result = ''
- } else {
- result = e.message
- }
+ } catch (e: unknown) {
+ if (e != null && typeof e === 'object' && 'message' in e && typeof e.message === 'string') {
+ result = e.message.includes('divide by zero') ? '' : e.message
} else {
- result = JSON.stringify(err)
+ result = JSON.stringify(e)
}
} finally {
- if (result != null) {
- postMessage({ result, url: self.location.href })
+ if (result !== undefined) {
+ postMessage({ url, id, result })
}
addEventListener('message', handleMessage)
}