import { buffer, hex, utf8 } from './convert.js'
import { Entropy } from './entropy.js'
+import { Thread } from './thread.js'
const { subtle } = globalThis.crypto
const ERR_MSG = 'Failed to store item in Safe'
export class Safe {
#storage = globalThis.sessionStorage
+ #thread = new Thread(new URL('./placeholder.js', import.meta.url))
/**
* Encrypts data with a password and stores it in the Safe.
--- /dev/null
+// SPDX-FileCopyrightText: 2024 Chris Duncan <chris@zoso.dev>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+if (globalThis.Worker == null) {
+ const { Worker } = await import('node:worker_threads')
+ //@ts-expect-error
+ Worker.prototype.addEventListener = Worker.prototype.addListener
+ //@ts-expect-error
+ globalThis.Worker = Worker
+}
+
+type Task = {
+ data: object,
+ resolve: Function
+}
+
+/**
+* Processes tasks from a queue using a Web Worker.
+*/
+export class Thread {
+ #isAvailable: boolean = true
+ #queue: Task[] = []
+ #task?: Task
+ #worker: Worker
+
+ #post (next: Task) {
+ this.#isAvailable = false
+ this.#task = next
+ this.#worker.postMessage(next.data)
+ }
+
+ constructor (url: string | URL) {
+ this.#worker = new Worker(new URL(url, import.meta.url), { type: 'module' })
+ this.#worker.addEventListener('message', (event) => {
+ const result = event.data ?? event
+ if (this.#task == null) {
+ throw new ReferenceError(`Error resolving Worker result: ${result}`)
+ }
+ const resolve = this.#task.resolve
+ const next = this.#queue.shift()
+ if (next == null) {
+ this.#isAvailable = true
+ } else {
+ this.#post(next)
+ }
+ resolve(result)
+ })
+ }
+
+ async work (data: object): Promise<any> {
+ return new Promise(resolve => {
+ if (this.#isAvailable) {
+ this.#post({ data, resolve })
+ } else {
+ this.#queue.push({ data, resolve })
+ }
+ })
+ }
+}