Something went wrong. Try again.
Offload functions to worker threads with shared memory primitives for Node.js.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131import { describe, it } from 'node:test';import assert from 'node:assert/strict';import { workers } from 'moroutine';import { fail, failType, failCause } from './fixtures/math.ts';import { failAfterType } from './fixtures/stream-gen.ts';
describe('error handling', () => { it('rejects with error from dedicated worker', async () => { await assert.rejects(async () => fail('boom').then((x) => x), { message: 'boom', }); });
it('rejects with error from pool worker', async () => { await using run = workers(1); await assert.rejects(() => run(fail('pool boom')), { message: 'pool boom', }); });
it('preserves stack trace pointing to worker source via cause', async () => { await using run = workers(1); try { await run(fail('stack check')); assert.fail('should have thrown'); } catch (err) { assert.ok(err instanceof Error); const cause = err.cause as Error; assert.ok(cause instanceof Error); assert.match(cause.stack!, /fixtures\/math\.ts/); } });
it('preserves built-in error subclass identity', async () => { await using run = workers(1); try { await run(failType('type check')); assert.fail('should have thrown'); } catch (err) { assert.ok(err instanceof TypeError); assert.equal((err as Error).message, 'type check'); } });
it('preserves error cause (nested through wrapper)', async () => { await using run = workers(1); try { await run(failCause('with cause')); assert.fail('should have thrown'); } catch (err) { assert.ok(err instanceof Error); // outer wrapper has the worker error as cause; worker error has RangeError as its cause const workerErr = (err as Error).cause as Error; assert.ok(workerErr instanceof Error); assert.ok(workerErr.cause instanceof RangeError); assert.equal((workerErr.cause as Error).message, 'root cause'); } });
it('preserves error details on dedicated worker', async () => { try { await failType('dedicated type'); assert.fail('should have thrown'); } catch (err) { assert.ok(err instanceof TypeError); const cause = (err as Error).cause as Error; assert.match(cause.stack!, /fixtures\/math\.ts/); } });
it('main-thread stack includes run() caller', async () => { await using run = workers(1);
async function someCaller() { await run(fail('trace check')); }
try { await someCaller(); assert.fail('should have thrown'); } catch (err) { assert.ok(err instanceof Error); assert.match((err as Error).stack!, /someCaller/); } });
it('main-thread stack includes exec() caller', async () => { await using run = workers(1);
async function someCaller() { await run.workers[0].exec(fail('exec trace check')); }
try { await someCaller(); assert.fail('should have thrown'); } catch (err) { assert.ok(err instanceof Error); assert.match((err as Error).stack!, /someCaller/); } });
it('main-thread stack includes await-task caller on dedicated worker', async () => { async function someCaller() { await fail('dedicated trace check'); }
try { await someCaller(); assert.fail('should have thrown'); } catch (err) { assert.ok(err instanceof Error); assert.match((err as Error).stack!, /someCaller/); } });
it('preserves error details on streaming task', async () => { await using run = workers(1); try { for await (const _ of run(failAfterType(2))) { // consume yields until error } assert.fail('should have thrown'); } catch (err) { assert.ok(err instanceof TypeError); assert.equal((err as Error).message, 'stream type error'); assert.match((err as Error).stack!, /fixtures\/stream-gen\.ts/); } });});