]> zoso.dev Git - libnemo.git/commitdiff
Restore Node.js polyfills for worker support.
authorChris Duncan <chris@zoso.dev>
Wed, 4 Dec 2024 05:02:08 +0000 (21:02 -0800)
committerChris Duncan <chris@zoso.dev>
Wed, 4 Dec 2024 05:02:08 +0000 (21:02 -0800)
src/lib/bip44-ckd.ts
src/lib/nano-nacl.ts
src/lib/pool.ts
src/lib/pow.ts

index 1dfb0f0f020fa2f834434b6ce3e4a265cc825bc3..3aa91efbfb48970369b0b1c070399164555c8630 100644 (file)
@@ -6,7 +6,18 @@ type ExtendedKey = {
        chainCode: DataView
 }
 
-const b = () => {
+const b = async () => {
+       /**
+       * Polyfill for window methods which do not exist when executing Node.js tests.
+       */
+       if (typeof Window === 'undefined') {
+               const { isMainThread, parentPort } = await import('node:worker_threads')
+               if (!isMainThread && parentPort) {
+                       var addEventListener = Object.getPrototypeOf(parentPort).addListener.bind(parentPort)
+                       var postMessage = Object.getPrototypeOf(parentPort).postMessage.bind(parentPort)
+               }
+       }
+
        const BIP44_COIN_NANO = 165
        const BIP44_PURPOSE = 44
        const HARDENED_OFFSET = 0x80000000
@@ -15,14 +26,15 @@ const b = () => {
        /**
        * Listens for messages from a calling function.
        */
-       addEventListener('message', (message) => {
-               const data = JSON.parse(new TextDecoder().decode(message.data ?? message))
-               process(data).then(results => {
-                       const buf = new TextEncoder().encode(JSON.stringify(results)).buffer
-                       //@ts-expect-error
-                       postMessage(buf, [buf])
+       if (addEventListener != null) {
+               addEventListener('message', (message: any): void => {
+                       const data = JSON.parse(new TextDecoder().decode(message.data ?? message))
+                       process(data).then(results => {
+                               const buf = new TextEncoder().encode(JSON.stringify(results)).buffer
+                               postMessage(buf, [buf])
+                       })
                })
-       })
+       }
 
        async function process (data: any[]): Promise<any[]> {
                return new Promise(async (resolve) => {
@@ -110,7 +122,7 @@ const b = () => {
        return { nanoCKD }
 }
 
-export const Bip44Ckd = b()
+export const Bip44Ckd = await b()
 
 const start = b.toString().indexOf('{') + 1
 const end = b.toString().lastIndexOf('return')
index 7e04d58cf45ef728da63c469942a07e36aad6649..e57e8362e140c74411348eab427f27efd3da1821 100644 (file)
@@ -17,19 +17,31 @@ import { Blake2b } from './blake2b.js'
 // See for details: https://docs.nano.org/integration-guides/the-basics/\r
 // Original source commit: https://github.com/dchest/tweetnacl-js/blob/71df1d6a1d78236ca3e9f6c788786e21f5a651a6/nacl-fast.js\r
 \r
-const n = () => {\r
+const n = async () => {\r
        /**\r
-       * Listens for messages from a calling function.\r
+       * Polyfill for window methods which do not exist when executing Node.js tests.\r
        */\r
-       addEventListener('message', message => {\r
-               const data = JSON.parse(new TextDecoder().decode(message.data ?? message))\r
-               for (const d of data) {\r
-                       d.publicKey = convert(d.privateKey)\r
+       if (typeof Window === 'undefined') {\r
+               const { isMainThread, parentPort } = await import('node:worker_threads')\r
+               if (!isMainThread && parentPort) {\r
+                       var addEventListener = Object.getPrototypeOf(parentPort).addListener.bind(parentPort)\r
+                       var postMessage = Object.getPrototypeOf(parentPort).postMessage.bind(parentPort)\r
                }\r
-               const buf = new TextEncoder().encode(JSON.stringify(data)).buffer\r
-               //@ts-expect-error\r
-               postMessage(buf, [buf])\r
-       })\r
+       }\r
+\r
+       /**\r
+       * Listens for messages from a calling function.\r
+       */\r
+       if (addEventListener != null) {\r
+               addEventListener('message', (message: any): void => {\r
+                       const data = JSON.parse(new TextDecoder().decode(message.data ?? message))\r
+                       for (const d of data) {\r
+                               d.publicKey = convert(d.privateKey)\r
+                       }\r
+                       const buf = new TextEncoder().encode(JSON.stringify(data)).buffer\r
+                       postMessage(buf, [buf])\r
+               })\r
+       }\r
 \r
        const gf = function (init?: number[]): Float64Array {\r
                const r = new Float64Array(16)\r
@@ -850,7 +862,7 @@ const n = () => {
        return { sign, open, detached, verify, convert }\r
 }\r
 \r
-export const NanoNaCl = n()\r
+export const NanoNaCl = await n()\r
 \r
 const start = n.toString().indexOf('{') + 1\r
 const end = n.toString().lastIndexOf('return')\r
index 5524879b3dc68fb7fb4271a01e72950cfd09e63a..336c5c1e4cbf6a9f39dbb2c1e6483162e656af0e 100644 (file)
@@ -36,7 +36,11 @@ export class Pool {
        }
 
        constructor (fn: string) {
-               this.#url = URL.createObjectURL(new Blob([fn], { type: 'text/javascript' }))
+               if (typeof Window === 'undefined') {
+                       this.#url = fn
+               } else {
+                       this.#url = URL.createObjectURL(new Blob([fn], { type: 'text/javascript' }))
+               }
                for (let i = this.#cores; i > 0; i--) {
                        const thread = {
                                isBusy: false,
@@ -104,6 +108,10 @@ export class Pool {
        }
 
        dismiss (): void {
-               URL.revokeObjectURL(this.#url)
+               if (typeof Window === 'undefined') {
+                       this.#threads.forEach(thread => thread.worker.terminate())
+               } else {
+                       URL.revokeObjectURL(this.#url)
+               }
        }
 }
index 94cc3dcef53831337299d83b2ccf09b68116ed30..9065386b5dfa27604d1fa11dc02543f7a148aa09 100644 (file)
@@ -1,27 +1,39 @@
 // SPDX-FileCopyrightText: 2024 Chris Duncan <chris@zoso.dev>
 // SPDX-License-Identifier: GPL-3.0-or-later
 
-const p = () => {
+const p = async () => {
+       /**
+       * Polyfill for window methods which do not exist when executing Node.js tests.
+       */
+       if (typeof Window === 'undefined') {
+               const { isMainThread, parentPort } = await import('node:worker_threads')
+               if (!isMainThread && parentPort) {
+                       var addEventListener = Object.getPrototypeOf(parentPort).addListener.bind(parentPort)
+                       var postMessage = Object.getPrototypeOf(parentPort).postMessage.bind(parentPort)
+               }
+       }
+
        const SEND_THRESHOLD = '0xfffffff8'
        /**
        * Listens for messages from a calling function.
        */
-       addEventListener('message', message => {
-               const data = JSON.parse(new TextDecoder().decode(message.data ?? message))
-               for (const d of data) {
-                       if (d === 'stop') {
-                               close()
-                               postMessage(new ArrayBuffer(0))
-                       } else {
-                               find(d.hash, d.threshold ?? SEND_THRESHOLD).then(nonce => {
-                                       d.work = nonce
-                                       const buf = new TextEncoder().encode(JSON.stringify(data)).buffer
-                                       //@ts-expect-error
-                                       postMessage(buf, [buf])
-                               })
+       if (addEventListener != null) {
+               addEventListener('message', (message: any): void => {
+                       const data = JSON.parse(new TextDecoder().decode(message.data ?? message))
+                       for (const d of data) {
+                               if (d === 'stop') {
+                                       close()
+                                       postMessage(new ArrayBuffer(0))
+                               } else {
+                                       find(d.hash, d.threshold ?? SEND_THRESHOLD).then(nonce => {
+                                               d.work = nonce
+                                               const buf = new TextEncoder().encode(JSON.stringify(data)).buffer
+                                               postMessage(buf, [buf])
+                                       })
+                               }
                        }
-               }
-       })
+               })
+       }
 
        async function find (hash: string, threshold: string = SEND_THRESHOLD): Promise<string> {
                return new Promise<string>(resolve => {
@@ -364,7 +376,7 @@ const p = () => {
        return { find }
 }
 
-export const Pow = p()
+export const Pow = await p()
 
 const start = p.toString().indexOf('{') + 1
 const end = p.toString().lastIndexOf('return')