*/
let isWorkerReady: boolean = false
let isWorkerListening: boolean = false
+let tasks: Map<string, Parameters<ConstructorParameters<PromiseConstructor>[0]>> = new Map()
let worker: Worker | NodeWorker
let url: string
init()
}
+function onresult (msg: { data: Record<string, unknown> }): void {
+ const { data } = msg
+ if (data.url !== url) return
+ if (!('id' in data) || typeof data.id !== 'string') return
+
+ const executor = tasks.get(data.id)
+ if (executor == null) return
+ const [ok, err] = executor
+
+ const { result } = data
+ console.log('received result from worker')
+ if (typeof result !== 'boolean' && typeof result !== 'string' && !isBytes(result)) {
+ err('Invalid return type')
+ }
+ ok(result)
+}
+
// Check that the worker is running and listening before sending messages
async function start (): Promise<void> {
if (!isWorkerReady) init()
if (!isWorkerListening) {
return new Promise(async (resolve, reject): Promise<void> => {
const onstarted = (msg: { data: Record<string, unknown> }): void => {
- const { data } = msg
- if (data.url !== url) return
- const { result } = data
+ if (msg.data.url !== url) return
+ const { result } = msg.data
if (result === 'started') {
console.log('worker started successfully')
+ BROWSER: { (worker as Worker).onmessage = onresult }
+ NODE: { (worker as NodeWorker).on('message', onresult) }
isWorkerListening = true
resolve()
} else {
}
console.log(`starting worker`)
const id = crypto.randomUUID()
+ const data = { url, id, action: 'start' }
BROWSER: {
worker = worker as Worker
worker.onerror = reject
worker.onmessage = onstarted
- worker.postMessage({ url, id, action: 'start' })
+ worker.postMessage(data)
}
NODE: {
worker = worker as unknown as NodeWorker
worker.on('error', reject)
worker.on('message', onstarted)
- worker.postMessage({ data: { url, id, action: 'start' } })
+ worker.postMessage({ data })
}
})
}
}
// Send command and relevant data to nano25519 worker
-async function dispatch (data: { [key: string]: string | ArrayBuffer | Uint8Array<ArrayBuffer> }): Promise<boolean | string | Uint8Array<ArrayBuffer>> {
- return new Promise((resolve, reject) => {
- const id = crypto.randomUUID()
- const transfer: ArrayBuffer[] = []
- for (let k of Object.keys(data)) {
- if (isBytes(data[k])) {
- data[k] = data[k].buffer.slice()
- transfer.push(data[k])
- }
- }
- const onresult = (msg: { data: Record<string, unknown> }): void => {
- const { data } = msg
- if (data.url !== url) return
- if (data.id !== id) return
- const { result } = data
- console.log('received result from worker')
- if (typeof result !== 'boolean' && typeof result !== 'string' && !isBytes(result)) {
- return reject('Invalid return type')
- }
- resolve(result)
- }
- console.log('sending data to worker')
- data.url = url
- data.id = id
- BROWSER: {
- worker = worker as Worker
- worker.onerror = reject
- worker.onmessage = onresult
- worker.postMessage(data, transfer)
- }
- NODE: {
- worker = worker as unknown as NodeWorker
- worker.on('error', reject)
- worker.on('message', onresult)
- worker.postMessage({ data }, transfer)
+async function dispatch (data: Record<string, string | ArrayBuffer | Uint8Array<ArrayBuffer>>): Promise<unknown> {
+ const id = crypto.randomUUID()
+ const transfer: ArrayBuffer[] = []
+ for (let k of Object.keys(data)) {
+ if (isBytes(data[k])) {
+ data[k] = data[k].buffer.slice()
+ transfer.push(data[k])
}
+ }
+ console.log('sending data to worker')
+ data.url = url
+ data.id = id
+ return new Promise((resolve, reject) => {
+ tasks.set(id, [resolve, reject])
+ console.log('tasks', tasks)
+ BROWSER: { (worker as Worker).postMessage(data, transfer) }
+ NODE: { (worker as NodeWorker).postMessage({ data }, transfer) }
})
}
})
}
-export async function run (data: Record<"action", "derive"> & Record<string, string | Uint8Array<ArrayBuffer>>): Promise<string | Uint8Array<ArrayBuffer>>
-export async function run (data: Record<"action", "sign"> & Record<string, string | Uint8Array<ArrayBuffer>>): Promise<string | Uint8Array<ArrayBuffer>>
-export async function run (data: Record<"action", "verify"> & Record<string, string | Uint8Array<ArrayBuffer>>): Promise<boolean>
-export async function run (data: Record<string, string | Uint8Array<ArrayBuffer>>): Promise<boolean | string | Uint8Array<ArrayBuffer>> {
+export async function run (data: Record<'action', 'derive'> & Record<string, string | Uint8Array<ArrayBuffer>>): Promise<string | Uint8Array<ArrayBuffer>>
+export async function run (data: Record<'action', 'sign'> & Record<string, string | Uint8Array<ArrayBuffer>>): Promise<string | Uint8Array<ArrayBuffer>>
+export async function run (data: Record<'action', 'verify'> & Record<string, string | Uint8Array<ArrayBuffer>>): Promise<boolean>
+export async function run (data: Record<'action', 'derive' | 'sign' | 'verify'> & Record<string, string | Uint8Array<ArrayBuffer>>): Promise<boolean | string | Uint8Array<ArrayBuffer>> {
try {
await start()
} catch (err: any) {
}
try {
const result = await dispatch(data)
- if (typeof result === 'string' && !/^([0-9a-f]{64}|[0-9a-f]{128})$/i.test(result)) {
- throw new Error('Invalid result')
+ switch (data.action) {
+ case 'derive': {
+ if ((isBytes(result) && result.byteLength === 32) || (typeof result === 'string' && /^[0-9a-f]{64}$/i.test(result))) {
+ return result
+ } else {
+ throw new Error('derive result invalid')
+ }
+ }
+ case 'sign': {
+ if ((isBytes(result) && result.byteLength === 64) || (typeof result === 'string' && /^[0-9a-f]{128}$/i.test(result))) {
+ return result
+ } else {
+ throw new Error('sign result invalid')
+ }
+ }
+ case 'verify': {
+ if (typeof result === 'boolean') {
+ return result
+ } else {
+ throw new Error('verify result invalid')
+ }
+ }
}
- return result
} catch (err: any) {
try {
await stop()