import { describe, it } from 'node:test'; import assert from 'node:assert/strict'; import { workers } from 'moroutine'; import { makeCtx, makeMultiplierCtx, readCtx, addWithCtx, prefixValue } from './fixtures/context.ts'; describe('task-arg caching', () => { it('task arg is resolved on the worker', async () => { const ctx = makeCtx('hello'); const run = workers(1); try { const result = await run(readCtx(ctx)); assert.equal(result.value, 'hello'); } finally { run[Symbol.dispose](); } }); it('task arg is cached — same task evaluated once per worker', async () => { const ctx = makeCtx('test'); const run = workers(1); try { const r1 = await run(readCtx(ctx)); const r2 = await run(readCtx(ctx)); // Same workerInitId means ctx was only evaluated once assert.equal(r1.workerInitId, r2.workerInitId); assert.equal(r1.value, 'test'); } finally { run[Symbol.dispose](); } }); it('different workers each evaluate the task independently', async () => { const ctx = makeCtx('test'); const run = workers(2); try { const r1 = await run(readCtx(ctx)); const r2 = await run(readCtx(ctx)); // Each worker's initCount starts at 0, so both get workerInitId=1 assert.equal(r1.workerInitId, 1); assert.equal(r2.workerInitId, 1); } finally { run[Symbol.dispose](); } }); it('task arg works alongside regular args', async () => { const ctx = makeMultiplierCtx(3); const run = workers(1); try { const result = await run(addWithCtx(ctx, 2, 5)); assert.equal(result, 21); // (2 + 5) * 3 } finally { run[Symbol.dispose](); } }); it('nested task args resolve recursively', async () => { // makeCtx('hello') is a task-arg passed to prefixValue // prefixValue itself is the outer task dispatched to the worker // The worker must resolve makeCtx first, then call prefixValue with the result const ctx = makeCtx('hello'); const run = workers(1); try { const result = await run(prefixValue(ctx, '>>> ')); assert.equal(result, '>>> hello'); } finally { run[Symbol.dispose](); } }); });