diff --git a/lib/lift.ts b/lib/lift.ts index 76a48818..f93d8c9c 100644 --- a/lib/lift.ts +++ b/lib/lift.ts @@ -1,3 +1,4 @@ +import { shift } from "./deps.ts"; import { type Operation } from "./types.ts"; /** @@ -16,20 +17,17 @@ import { type Operation } from "./types.ts"; * @returns a function returning an operation that invokes `fn` when evaluated */ export function lift( - fn: Fn, -): LiftedFn { + fn: (...args: TArgs) => TReturn, +): (...args: TArgs) => Operation { return (...args: TArgs) => { return ({ - [Symbol.iterator]() { - let value = fn(...args); - return { next: () => ({ done: true, value }) }; + *[Symbol.iterator]() { + return yield () => { + return shift(function* (k) { + k({ ok: true, value: fn(...args) }); + }); + }; }, }); }; } - -type Fn = (...args: TArgs) => TReturn; - -type LiftedFn = ( - ...args: TArgs -) => Operation; diff --git a/test/lift.test.ts b/test/lift.test.ts new file mode 100644 index 00000000..d2240296 --- /dev/null +++ b/test/lift.test.ts @@ -0,0 +1,23 @@ +import { createSignal, each, lift, run, sleep, spawn } from "../mod.ts"; +import { describe, expect, it } from "./suite.ts"; + +describe("lift", () => { + it("safely does not continue if the call stops the operation", async () => { + let reached = false; + + await run(function* () { + let signal = createSignal(); + + yield* spawn(function* () { + yield* sleep(0); + yield* lift(signal.close)(); + + reached = true; + }); + + for (let _ of yield* each(signal)); + }); + + expect(reached).toBe(false); + }); +});