From a24bc467c115590510f2d5fb8244ebc88d2856c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jimmy=20Wa=CC=88rting?= Date: Fri, 7 Jul 2023 23:55:14 +0200 Subject: [PATCH 1/4] fix: make it run in nodejs --- mod.js | 4 +++- package.json | 3 ++- test/bench.js | 34 ++++++++++++++++++++++++++-------- test/spec.js | 7 ++++++- worker.js | 9 +++++---- 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/mod.js b/mod.js index 867ee90..e921ada 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 diff --git a/package.json b/package.json index e1dc1e6..ecc87f3 100644 --- a/package.json +++ b/package.json @@ -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..c9b8513 100644 --- a/test/spec.js +++ b/test/spec.js @@ -13,4 +13,9 @@ const fn = awaitSync(async function (pkg) { 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..f0d6609 100644 --- a/worker.js +++ b/worker.js @@ -8,7 +8,7 @@ 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 @@ -24,8 +24,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 +48,6 @@ addEventListener('message', async evt => { }) int32[1] = ok - write2(u8) + write(u8) } }) From 0b0c8ea258e38def641a45472616c80681dc87a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jimmy=20Wa=CC=88rting?= Date: Sat, 8 Jul 2023 01:00:33 +0200 Subject: [PATCH 2/4] Handle 0 byte length --- mod.js | 4 ++++ test/spec.js | 6 ++++++ worker.js | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/mod.js b/mod.js index e921ada..7bb40b0 100644 --- a/mod.js +++ b/mod.js @@ -37,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/test/spec.js b/test/spec.js index c9b8513..e09421c 100644 --- a/test/spec.js +++ b/test/spec.js @@ -10,6 +10,12 @@ 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) diff --git a/worker.js b/worker.js index f0d6609..1472ad5 100644 --- a/worker.js +++ b/worker.js @@ -12,6 +12,11 @@ addEventListener('message', async evt => { 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) From 96a4f1d70c437c75fed9edac68900fac54e14e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jimmy=20Wa=CC=88rting?= Date: Sat, 8 Jul 2023 01:02:39 +0200 Subject: [PATCH 3/4] rm unnecessary files --- .github/FUNDING.yml | 2 -- .github/PULL_REQUEST_TEMPLATE.md | 23 ----------------------- 2 files changed, 25 deletions(-) delete mode 100644 .github/FUNDING.yml delete mode 100644 .github/PULL_REQUEST_TEMPLATE.md 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 From b5a537c025811912f9ba916d80402d5eddb6ec47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jimmy=20Wa=CC=88rting?= Date: Sat, 8 Jul 2023 01:02:59 +0200 Subject: [PATCH 4/4] bump vers --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ecc87f3..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",