Something went wrong. Try again.
MIRROR: javascript for 🐜's, a tiny runtime with big ambitions ant.themackabu.dev
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110import { test, testDeep, summary } from './helpers.js';import { Worker, MessageChannel, isMainThread, parentPort, workerData, receiveMessageOnPort, setEnvironmentData, getEnvironmentData, moveMessagePortToContext} from 'node:worker_threads';
console.log('Worker Threads Tests\n');
async function run() { test('isMainThread in main context', isMainThread, true); test('parentPort is null in main context', parentPort, null); test('workerData is null in main context', workerData, null);
const ch1 = new MessageChannel(); test('MessageChannel has port1', typeof ch1.port1, 'object'); test('MessageChannel has port2', typeof ch1.port2, 'object');
ch1.port1.postMessage({ hello: 'queue' }); const queued = receiveMessageOnPort(ch1.port2); testDeep('receiveMessageOnPort returns message envelope', queued, { message: { hello: 'queue' } }); test('receiveMessageOnPort returns undefined when empty', receiveMessageOnPort(ch1.port2), undefined);
const ch2 = new MessageChannel(); const seen = []; ch2.port1.postMessage('queued-before-listener'); ch2.port2.on('message', msg => { seen.push(`on:${msg}`); }); ch2.port2.once('message', msg => { seen.push(`once:${msg}`); }); ch2.port1.postMessage('next'); ch2.port1.postMessage('final'); testDeep('MessagePort delivers asynchronously', seen, []); await new Promise(resolve => setTimeout(resolve, 20)); testDeep('MessagePort queue drains in FIFO order', seen, ['on:queued-before-listener', 'once:queued-before-listener', 'on:next', 'on:final']);
let onmessageData = undefined; ch2.port2.onmessage = event => { onmessageData = event.data; }; ch2.port1.postMessage('event-data'); await new Promise(resolve => setTimeout(resolve, 20)); test('MessagePort onmessage receives event.data', onmessageData, 'event-data'); ch2.port1.close();
const moved = moveMessagePortToContext(ch2.port1, globalThis); test('moveMessagePortToContext returns same port', moved, ch2.port1);
const shared = { answer: 42, ok: true }; setEnvironmentData('shared-key', shared); testDeep('getEnvironmentData in main context', getEnvironmentData('shared-key'), shared);
const workerUrl = new URL('./worker_threads.worker.mjs', import.meta.url); const payload = { hello: 'world', n: 42, arr: [1, 2, 3] };
const worker = new Worker(workerUrl, { workerData: payload }); test('Worker constructor returns object', typeof worker, 'object'); test('Worker has once method', typeof worker.once, 'function'); test('Worker has terminate method', typeof worker.terminate, 'function');
worker.unref(); worker.ref();
const message = await new Promise((resolve, reject) => { worker.once('message', resolve); worker.once('exit', code => { if (code !== 0) reject(new Error(`worker exited early with code ${code}`)); }); });
test('worker replied success flag', message.ok, true); test('worker isMainThread false in worker context', message.isMainThread, false); test('worker has parentPort in worker context', message.hasParentPort, true); testDeep('workerData round-trip', message.workerData, payload); testDeep('worker getEnvironmentData snapshot', message.environmentData, shared);
const exitCode = await worker.terminate(); test('terminate resolves to numeric exit code', typeof exitCode, 'number');
const ropeCount = 220_000; const ropeWorkers = Array.from( { length: 4 }, () => new Worker(workerUrl, { workerData: { ropeStress: ropeCount } }) ); const ropeResults = await Promise.all(ropeWorkers.map(current => new Promise((resolve, reject) => { current.once('message', resolve); current.once('exit', code => { if (code !== 0) reject(new Error(`rope worker exited early with code ${code}`)); }); }) )); test('concurrent worker rope GC', ropeResults.every(result => result.ok && result.length === ropeCount + 13 && result.tail === 'xxxx' ), true); await Promise.all(ropeWorkers.map(current => current.terminate()));
summary();}
void run();