diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 09d89bd..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: [jimmywarting] -custom: ["https://paypal.me/jimmywarting", "https://jimmy.warting.se/opensource"] diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 51850d7..0000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,23 +0,0 @@ - - -## Purpose - - -## Changes - - -## Additional information - - -___ - - -- [ ] I updated ./docs/CHANGELOG.md with a link to this PR or Issue -- [ ] I updated ./docs/v3-UPGRADE-GUIDE -- [ ] I updated readme -- [ ] I added unit test(s) - -___ - - -- fixes #000 diff --git a/mod.js b/mod.js index 867ee90..7bb40b0 100644 --- a/mod.js +++ b/mod.js @@ -1,7 +1,8 @@ /*! to-sync. MIT License. Jimmy Wärting */ // Use the native Worker if available, otherwise use the polyfill -const Work = globalThis.Worker || await import('whatwg-worker').then(m => m.default) +// const Work = globalThis.Worker || await import('whatwg-worker').then(m => m.default) +const Work = await import('/Users/jimmywarting/git/web-worker/node-worker.js').then(m => m.default) function createWorker (signal) { // Create a shared buffer to communicate with the worker thread @@ -24,6 +25,7 @@ function createWorker (signal) { worker.postMessage({ port: remotePort, code: source, ab }, [remotePort]) return function runSync (...args) { + Atomics.store(int32, 0, 0) // Send the arguments to the worker thread localPort.postMessage(args) // Wait for the worker thread to send the result back @@ -35,6 +37,10 @@ function createWorker (signal) { let bytesLeft = int32[0] const ok = int32[1] + if (bytesLeft === -1) { + return new Uint8Array(0) + } + // Allocate a new Uint8Array to store the result const result = new Uint8Array(bytesLeft) let offset = 0 diff --git a/package.json b/package.json index e1dc1e6..a429c3f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "await-sync", - "version": "1.0.1", + "version": "1.0.2", "description": "Perform async work synchronously using web worker and SharedArrayBuffer", "main": "mod.js", "type": "module", @@ -50,6 +50,7 @@ }, "devDependencies": { "make-synchronous": "^1.0.0", - "synckit": "^0.8.5" + "synckit": "^0.8.5", + "tinylet": "^0.1.0" } } diff --git a/test/bench.js b/test/bench.js index 1f42013..d85b9cb 100644 --- a/test/bench.js +++ b/test/bench.js @@ -3,7 +3,7 @@ import { Buffer } from 'node:buffer' import { createWorker } from '../mod.js' import makeSynchronous from 'make-synchronous' import { createSyncFn } from 'synckit' - +import { redlet } from 'tinylet' // the worker path must be absolute const workerPath = new URL('./synkit-worker.js', import.meta.url).toString().slice(7) @@ -21,10 +21,17 @@ const jim = createWorker()(async path => { return fs.readFile(new URL(path)) }) +// Runs in a worker thread and uses Atomics.wait() to block the current thread. +const redletReader = redlet(async (path) => { + const fs = await import('fs/promises') + return fs.readFile(new URL(path)) +}) + const control = Buffer.from(readFileSync(new URL(path))).toString() -console.assert(Buffer.from(awaitSync(path)).toString() === control, 'should return the same data') -console.assert(Buffer.from(jim(path)).toString() === control, 'should return the same data') -console.assert(Buffer.from(sin(path)).toString() === control, 'should return the same data') +// console.assert(Buffer.from(awaitSync(path)).toString() === control, 'should return the same data') +// console.assert(Buffer.from(jim(path)).toString() === control, 'should return the same data') +// console.assert(Buffer.from(sin(path)).toString() === control, 'should return the same data') +// console.assert(Buffer.from(redletReader(path)).toString() === control, 'should return the same data') let i @@ -33,19 +40,30 @@ console.time('fs.readFileSync') while (i--) readFileSync(new URL(path)) console.timeEnd('fs.readFileSync') +globalThis?.gc() + +i = 100 +console.time('redletReader') +while (i--) redletReader(path) +console.timeEnd('redletReader') + +globalThis?.gc() + i = 100 console.time('synkit') while (i--) awaitSync(path) console.timeEnd('synkit') +globalThis?.gc() + i = 100 -console.time('to-sync') +console.time('await-sync') while (i--) jim(path) -console.timeEnd('to-sync') +console.timeEnd('await-sync') + +globalThis?.gc() i = 100 console.time('make-syncronous') while (i--) sin(path) console.timeEnd('make-syncronous') - -process.exit() diff --git a/test/spec.js b/test/spec.js index c2b1761..e09421c 100644 --- a/test/spec.js +++ b/test/spec.js @@ -10,7 +10,18 @@ const fn = awaitSync(async function (pkg) { return textEncoder.encode(str) }, r => new TextDecoder().decode(r)) +const returnsEmptyData = awaitSync(async function () { + return new Uint8Array(0) +}) + +console.assert(returnsEmptyData().byteLength === 0, 'empty byteLength should be 0') + const pkg = fn(new URL('../package.json', import.meta.url) + '') ctrl.abort() const json = JSON.parse(pkg) -console.assert(json.name === 'await-sync', 'should return the same data') + +if (json.name === 'await-sync') { + console.log('test completed') +} else { + throw new Error('test failed') +} diff --git a/worker.js b/worker.js index fdb4f16..1472ad5 100644 --- a/worker.js +++ b/worker.js @@ -8,10 +8,15 @@ addEventListener('message', async evt => { const int32 = new Int32Array(ab, 0, 2) /** @param {Uint8Array} buf */ - const write2 = buf => { + const write = buf => { let bytesLeft = buf.byteLength let offset = 0 + if (bytesLeft === 0) { + int32[0] = -1 + Atomics.notify(int32, 0) + } + while (bytesLeft > 0) { int32[0] = bytesLeft const chunkSize = Math.min(bytesLeft, data.byteLength) @@ -24,8 +29,9 @@ addEventListener('message', async evt => { } } - const blob = new Blob([code], { type: 'text/javascript' }) - const url = URL.createObjectURL(blob) + // const blob = new Blob([code], { type: 'text/javascript' }) + // const url = URL.createObjectURL(blob) + const url = "data:text/javascript," + encodeURIComponent(code) const { default: fn } = await import(url) port.onmessage = async function onmessage (evt) { @@ -47,6 +53,6 @@ addEventListener('message', async evt => { }) int32[1] = ok - write2(u8) + write(u8) } })