uneventful 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/call-or-wait-DORP7nkp.mjs +112 -0
- package/dist/call-or-wait-DORP7nkp.mjs.map +1 -0
- package/dist/{call-or-wait-COAmx32w.mjs → jobutils-CmHay7sf.mjs} +21 -119
- package/dist/jobutils-CmHay7sf.mjs.map +1 -0
- package/dist/mod.d.ts +63 -5
- package/dist/mod.mjs +7 -5
- package/dist/mod.mjs.map +1 -1
- package/dist/shared.d.ts +109 -0
- package/dist/shared.mjs +53 -0
- package/dist/shared.mjs.map +1 -0
- package/dist/signals.d.ts +25 -4
- package/dist/signals.mjs +16 -5
- package/dist/signals.mjs.map +1 -1
- package/dist/{utils-P0JEpWXG.mjs → utils-DnMz1K-o.mjs} +14 -7
- package/dist/utils-DnMz1K-o.mjs.map +1 -0
- package/dist/utils.d.ts +64 -26
- package/dist/utils.mjs +1 -1
- package/package.json +8 -2
- package/dist/call-or-wait-COAmx32w.mjs.map +0 -1
- package/dist/utils-P0JEpWXG.mjs.map +0 -1
package/dist/mod.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.mjs","sources":["../src/async.ts","../src/sources.ts","../src/sinks.ts","../src/operators.ts"],"sourcesContent":["import { Request, Yielding } from \"./types.ts\";\nimport { rejecter, resolve, resolver } from \"./results.ts\"\n\n/**\n * Convert a (possible) promise to something you can `yield *to()` in a job\n *\n * Much like `await valueOrPromiseLike` in an async function, using `yield\n * *to(valueOrPromiseLike)` in a {@link Job}'s generator function will return\n * the value or the result of the promise/promise-like object.\n *\n * @category Scheduling\n */\nexport function *to<T>(p: Promise<T> | PromiseLike<T> | T): Yielding<T> {\n return yield (res: Request<T>) => Promise.resolve(p).then(resolver(res), rejecter(res));\n}\n\n/**\n * Pause the job for the specified time in ms, e.g. `yield *sleep(1000)` to wait\n * one second.\n *\n * @category Scheduling\n */\nexport function *sleep(ms: number): Yielding<void> {\n try {\n var id: ReturnType<typeof setTimeout>;\n yield r => {\n id = setTimeout(() => { id = undefined; resolve(r, void 0); }, ms);\n }\n } finally {\n if (id) clearTimeout(id);\n }\n}\n","import { defer } from \"./defer.ts\";\nimport { type Stream, IsStream, backpressure, Sink, Connection, Backpressure, throttle, Inlet, Source } from \"./streams.ts\";\nimport { getJob, detached } from \"./tracking.ts\";\nimport { must, start } from \"./jobutils.ts\";\nimport { DisposeFn } from \"./types.ts\";\nimport { isCancel, isError, isUnhandled, markHandled, noop } from \"./results.ts\";\n\n/**\n * A function that emits events, with a .source they're emitted from\n *\n * Created using {@link emitter}.\n *\n * @category Types and Interfaces\n */\nexport interface Emitter<T> {\n /** Call the emitter to emit events on its .source */\n (val: T): void;\n /** An event source that receives the events */\n source: Source<T>;\n /** Close all current subscribers' connections */\n end: () => void;\n /** Close all current subscribers' connections with an error */\n throw: (e: any) => void;\n};\n\n/**\n * Create an event source and a function to emit events on it\n *\n * (Note: you must specify the event type (e.g. `emitter<number>()`), since\n * there's nothing else to infer it from.)\n *\n * @returns A function that emits events, with a .source property they're\n * emitted on.\n *\n * @category Stream Producers\n */\nexport function emitter<T>(): Emitter<T> {\n const emit = mockSource<T>();\n emit.source = share(emit.source);\n return emit;\n}\n\n/**\n * A stream that immediately closes\n *\n * @category Stream Producers\n */\nexport function empty(): Source<never> {\n return (_, conn) => (conn?.return(), IsStream);\n}\n\n/**\n * Convert an async iterable to an event source\n *\n * Each time the resulting source is subscribed to, it will emit an event for\n * each item output by the iterator, then end the stream. Pause/resume is\n * supported.\n *\n * @category Stream Producers\n */\nexport function fromAsyncIterable<T>(iterable: AsyncIterable<T>): Source<T> {\n return (sink, conn=start(), inlet) => {\n const ready = backpressure(inlet);\n const iter = iterable[Symbol.asyncIterator]();\n if (iter.return) must(() => iter.return());\n return ready(next), IsStream;\n function next() {\n iter.next().then(({value, done}) => {\n if (done) conn.return(); else ready(() => {\n if (sink(value), ready()) next(); else ready(next);\n })\n }, e => conn.throw(e));\n }\n }\n}\n\n/**\n * Create an event source from an element, window, or other event target\n *\n * You can manually override the expected event type using a type parameter,\n * e.g. `fromDomEvent<CustomEvent>(someTarget, \"custom-event\")`.\n *\n * @param target an HTMLElement, Window, Document, or other EventTarget.\n * @param type the name of the event to add a listener for\n * @param options a boolean capture option, or an object of event listener\n * options\n * @returns a source that can be subscribed or piped, issuing events from the\n * target of the specified type.\n *\n * @category Stream Producers\n */\nexport function fromDomEvent<T extends HTMLElement, K extends keyof HTMLElementEventMap>(\n target: T, type: K, options?: boolean | AddEventListenerOptions\n): Source<HTMLElementEventMap[K]>;\nexport function fromDomEvent<T extends Window, K extends keyof WindowEventMap>(\n target: T, type: K, options?: boolean | AddEventListenerOptions\n): Source<WindowEventMap[K]>;\nexport function fromDomEvent<T extends Document, K extends keyof DocumentEventMap>(\n target: T, type: K, options?: boolean | AddEventListenerOptions\n): Source<DocumentEventMap[K]>;\nexport function fromDomEvent<T extends Event>(\n target: EventTarget, type: string, options?: boolean | AddEventListenerOptions\n): Source<T>\nexport function fromDomEvent<T extends EventTarget, K extends string>(\n target: T, type: K, options?: boolean | AddEventListenerOptions\n): Source<Event> {\n return (sink) => {\n function push(v: Event) { sink(v); }\n target.addEventListener(type, push, options);\n must(() => target.removeEventListener(type, push, options));\n return IsStream;\n }\n}\n\n/**\n * Convert an iterable to a synchronous event source\n *\n * Each time the resulting source is subscribed to, it will emit an event for\n * each item in the iterator, then close the connection. Pause/resume is\n * supported.\n *\n * @category Stream Producers\n */\nexport function fromIterable<T>(iterable: Iterable<T>): Source<T> {\n return (sink, conn=start(), inlet) => {\n const ready = backpressure(inlet);\n const iter = iterable[Symbol.iterator]();\n if (iter.return) must(() => iter.return());\n return ready(loop), IsStream;\n function loop() {\n try {\n for(;;) {\n const {value, done} = iter.next();\n if (done) return conn.return();\n if (sink(value), !ready()) return ready(loop);\n }\n } catch (e) {\n conn.throw(e);\n }\n }\n }\n}\n\n/**\n * Convert a Promise to an event source\n *\n * Each time the resulting source is subscribed to, it will emit an event for\n * the result of the promise, then close the connection. (Unless the promise is\n * rejected, in which case the connection throws and closes each time the source\n * is subscribed.) Non-native promises and non-promise values are converted\n * using Promise.resolve().\n *\n * @category Stream Producers\n */\nexport function fromPromise<T>(promise: Promise<T>|PromiseLike<T>|T): Source<T> {\n return (sink, conn) => {\n const job = getJob();\n Promise.resolve(promise).then(\n v => void (job.result() || (sink(v), conn?.return())),\n e => void (job.result() || conn?.throw(e))\n )\n return IsStream;\n }\n}\n\n/**\n * Create an event source from an arbitrary subscribe/unsubscribe function\n *\n * The supplied \"subscribe\" function will be passed a 1-argument callback and\n * must return an unsubscribe function. The callback should be called with\n * events of the appropriate type, and the unsubscribe function will be called\n * when the connection is closed.\n *\n * (Note: it's okay if the act of subscribing causes an immediate callback, as\n * the subscribe function will be called in a separate microtask.)\n *\n * @category Stream Producers\n */\nexport function fromSubscribe<T>(subscribe: (cb: (val: T) => void) => DisposeFn): Source<T> {\n return (sink) => {\n const f = getJob().must(() => sink = noop);\n return defer(() => f.must(subscribe(v => { sink(v); }))), IsStream;\n }\n}\n\n/**\n * Create a source that emits a single given value\n *\n * @category Stream Producers\n */\nexport function fromValue<T>(val: T): Source<T> {\n return (sink, conn) => {\n must(() => { sink = noop; conn = undefined; })\n return defer(() => { sink(val); conn?.return(); }), IsStream;\n }\n}\n\n/**\n * Create an event source that issues a number every `ms` milliseconds (starting\n * with 0 after the first interval passes).\n *\n * @category Stream Producers\n */\nexport function interval(ms: number): Source<number> {\n return (sink) => {\n let idx = 0, id = setInterval(() => sink(idx++), ms);\n return must(() => clearInterval(id)), IsStream;\n }\n}\n\n/**\n * Create a dynamic source that is created each time it's subscribed\n *\n * @param factory A function returning a source of the desired type. It will be\n * called whenever the lazy() stream is subscribed, and its result subscribed to.\n *\n * @returns A stream of the same type as the factory function returns\n *\n * @category Stream Producers\n */\nexport function lazy<T>(factory: () => Stream<T>): Source<T> {\n return (sink, conn, inlet) => factory()(sink, conn, inlet)\n}\n\n/**\n * An {@link Emitter} with a ready() method, that only supports a single active\n * subscriber. (Useful for testing stream operators and sinks.)\n *\n * Created using {@link mockSource}().\n *\n * @category Types and Interfaces\n */\nexport interface MockSource<T> extends Emitter<T> {\n ready: Backpressure\n}\n\n/**\n * Like {@link emitter}, but with a ready() backpressure method. It also only\n * supports a single active subscriber. (Useful for testing stream operators\n * and sinks.)\n *\n * @category Stream Producers\n */\nexport function mockSource<T>(): MockSource<T> {\n let write: Sink<T>, outlet: Connection, ready: Backpressure;\n const emit: MockSource<T> = (val: T) => { if (write) write(val); };\n emit.source = (sink, conn, inlet) => {\n write = sink; outlet = conn; ready = backpressure(inlet);\n must(() => write = outlet = ready = undefined);\n return IsStream;\n };\n emit.end = () => outlet?.return();\n emit.throw = (e: any) => outlet?.throw(e);\n emit.ready = (cb?: () => any) => ready(cb);\n return emit;\n}\n\n/**\n * A stream that never emits or closes\n *\n * @category Stream Producers\n */\nexport function never(): Source<never> {\n return () => IsStream;\n}\n\n/**\n * Wrap a source to allow multiple subscribers to the same underlying stream\n *\n * The input source will be susbcribed when the output has at least one\n * subscriber, and unsubscribed when the output has no subscribers. The input\n * will be paused when any subscriber pauses, and will only be resumed when all\n * subscribers are unpaused. All subscribers are closed or thrown if the input\n * source closes or throws.\n *\n * (Generally speaking, you should place the share call as late in your\n * pipelines as possible, if you use it at all. It adds some overhead that is\n * wasted if the stream doesn't have multiple subscribers, and may be redundant\n * if an upstream source is already shared. It's mainly useful if there is a\n * lot of mapping, filtering, or other complicated processing taking place\n * upstream of the share, and you know for a fact there will be enough\n * subscribers to make it a bottleneck. You should probably also consider\n * putting some {@link slack}() either upstream or downstream of the share, if\n * the upstream supports backpressure.)\n *\n * @category Stream Operators\n */\nexport function share<T>(source: Stream<T>): Source<T> {\n let uplink: Connection;\n const\n links = new Set<[sink: Sink<T>, conn: Connection]>,\n inlets = new Map<Inlet, number>(), // refcounts of incoming inlets\n t = throttle(), // the actual onReady queue\n multi: Inlet = {\n // A multi-connection inlet that requires all downstreams to be ready\n isOpen() { return !uplink?.result(); },\n isReady() {\n if (this.isOpen()) {\n for (const [i] of inlets) if (!i.isReady()) return (t.pause(), false);\n return true;\n }\n t.pause();\n return false;\n },\n onReady(cb, job) {\n if (this.isOpen()) {\n t.onReady(cb, job);\n for (const [i] of inlets) i.isReady() || i.onReady(produce, job);\n }\n return this;\n }\n }\n ;\n function produce() { multi.isReady() && t.resume(); }\n\n return (sink, conn=start(), inlet) => {\n const self: [Sink<T>, Connection] = [sink, conn];\n links.add(self);\n if (inlet) inlets.set(inlet, 1+(inlets.get(inlet) || 0));\n conn.must(() => {\n links.delete(self);\n if (inlet) {\n inlets.set(inlet, inlets.get(inlet)-1);\n if (!inlets.get(inlet)) inlets.delete(inlet);\n }\n if (!links.size) uplink?.end();\n else if (multi.isReady() && !t.isReady()) defer(produce);\n });\n if (links.size === 1) {\n uplink = detached.connect(source, v => {\n for(const [s, c] of links) try { s(v) } catch(e) { c.throw(e); };\n }, multi).do(r => {\n uplink = undefined;\n if (isCancel(r)) return;\n if (isUnhandled(r)) markHandled(r);\n for(const [_, c] of links) isError(r) ? c.throw(r.err) : c.return();\n })\n }\n return IsStream;\n }\n}\n","import { Job, RecalcSource, Request, Suspend, Yielding } from \"./types.ts\"\nimport { defer } from \"./defer.ts\";\nimport { Connection, Inlet, Sink, Stream, connect, pipe, throttle } from \"./streams.ts\";\nimport { resolve, isError, markHandled, fulfillPromise, rejecter, resolver } from \"./results.ts\";\nimport { restarting, start, must } from \"./jobutils.ts\";\nimport { isFunction } from \"./utils.ts\";\nimport { Signal, until } from \"./signals.ts\"; // the until is needed for documentation link\nimport { callOrWait, mustBeSourceOrSignal } from \"./call-or-wait.ts\";\nimport { current } from \"./ambient.ts\";\n\n/**\n * The result type returned from calls to {@link Each}.next()\n *\n * @category Types and Interfaces\n */\nexport type EachResult<T> = {\n /** The value provided by the source being iterated */\n item: T;\n\n /**\n * A suspend callback that must be `yield`-ed before the next call to the\n * iterator's .next() method. (That is, you must `yield next` it exactly once\n * per loop pass. See {@link each}() for more details.)\n */\n next: Suspend<void>;\n}\n\n/**\n * The iterable returned by `yield *` {@link each}()\n *\n * @category Types and Interfaces\n */\nexport type Each<T> = IterableIterator<EachResult<T>>\n\n/**\n * Asynchronously iterate over an event source\n *\n * Usage:\n *\n * ```ts\n * for (const {item: event, next} of yield *each(mouseMove)) {\n * console.log(event.clientX, event.clientY);\n * yield next; // required exactly once per iteration, even/w continue!\n * }\n * ```\n *\n * each(eventSource) yield-returns an iterator of `{item, next}` pairs. The\n * item is the data supplied by the event source, and `next` is a\n * {@link Suspend}\\<void\\> that advances the iterator to the next item. It\n * *must* be yielded exactly once per loop iteration. If you use `continue` to\n * shortcut the loop body, you must `yield next` *before* doing so.\n *\n * The for-loop will end if the source ends, errors, or is canceled. The source\n * is paused while the loop body is running, and resumed when the `yield next`\n * happens. If events arrive anyway (e.g. because the source doesn't support\n * pausing), they will be ignored unless you pipe the source through the\n * {@link slack}() operator to provide a buffer. If the for-loop is exited\n * early for any reason (or the iterator's `.return()` is called), the source is\n * unsubscribed and the iteration ended.\n *\n * @category Stream Consumers\n */\nexport function *each<T>(src: Stream<T>): Yielding<Each<T>> {\n let yielded = false, waiter: Request<void>;\n const result: IteratorYieldResult<EachResult<T>> = {value: {item: undefined as T, next}, done: false};\n const t = throttle(), conn = connect(src, v => {\n t.pause();\n if (!waiter || conn.result()) return;\n result.value.item = v;\n resolve(waiter, waiter = void 0);\n }, t).do(r => {\n // Prevent unhandled throws from here - it'll be seen by the next `yield\n // next`, or in the next microtask if `yield next` is already running.\n if (isError(r)) markHandled(r);\n if (waiter) { defer(next.bind(null, waiter)); waiter = undefined; }\n });\n\n // Wait for first value to arrive (and get put in result) before returning the iterator\n t.pause(); yield next;\n return {\n [Symbol.iterator]() { return this; },\n next() {\n if (!yielded) throw new Error(\"Must `yield next` in loop\");\n yielded = false;\n return result;\n },\n return() { conn.end(); return {value: undefined, done: true}; },\n }\n function next(r: Request<void>) {\n if (waiter) throw new Error(\"Multiple `yield next` in loop\");\n yielded = true;\n if (conn.result()) {\n result.value = undefined;\n (result as IteratorResult<any>).done = true;\n fulfillPromise(resolver(r), rejecter(r), conn.result())\n } else {\n waiter = r;\n t.resume();\n }\n }\n}\n\n/**\n * An object that can be waited on with `yield *until()`, by calling its\n * \"uneventful.until\" method. (This mostly exists to allow Signals to optimize\n * their until() implementation, but is also open for extensions.)\n *\n * @category Types and Interfaces\n */\nexport interface UntilMethod<T> {\n /** Return an async op to resume once a truthy value is available */\n \"uneventful.until\"(): Yielding<T>\n}\n\n/**\n * An object that can be waited on with `yield *next()`, by calling its\n * \"uneventful.next\" method. (This mostly exists to allow Signals to optimize\n * their next() implementation, but is also open for extensions.)\n *\n * @category Types and Interfaces\n */\nexport interface NextMethod<T> {\n /** Return an async op to resume with the \"next\" (i.e. not current) value produced */\n \"uneventful.next\"(): Yielding<T>\n};\n\n/**\n * Wait for and return the next value (or error) from a data source (when\n * processed with `yield *` within a {@link Job}).\n *\n * This differs from {@link until}() in that it waits for the *next* value\n * (truthy or not!), and it never resumes immediately for signals, but instead\n * waits for the signal to *change*. (Also, it does not support zero-argument\n * functions, unless you wrap them with {@link cached}() first.)\n *\n * @param source The source to wait on, which can be:\n * - An object with an `\"uneventful.next\"` method returning a {@link Yielding}\n * (in which case the result will be the the result of calling that method)\n * - A {@link Signal} or {@link Source} (in which case the job resumes on the\n * next value it produces)\n *\n * (Note: if the supplied source is a function with a non-zero `.length`, it is\n * assumed to be a {@link Source}.)\n *\n * @returns a Yieldable that when processed with `yield *` in a job, will return\n * the triggered event, or signal value. An error is thrown if event stream\n * throws or closes early, or the signal throws.\n *\n * @category Stream Consumers\n * @category Scheduling\n */\nexport function next<T>(source: NextMethod<T> | Stream<T>): Yielding<T> {\n return callOrWait<T>(source, \"uneventful.next\", waitAny, mustBeSourceOrSignal);\n}\n\nfunction waitAny<T>(job: Job<T>, v: T) { job.return(v); }\n\n/**\n * Run a {@link restarting}() callback for each value produced by a source.\n *\n * With each event that occurs, any previous callback run is cleaned up before\n * the new one begins. (And the last run is cleaned up when the connection or\n * job ends.)\n *\n * This function is almost the exact opposite of {@link each}(), in that the\n * stream is never paused (unless you do so manually via a throttle or inlet),\n * and if the \"loop body\" (callback job) is still running when a new value\n * arrives, forEach() restarts the job instead of dropping the value.\n *\n * @param src An event source (i.e. a {@link Source} or {@link Signal})\n * @param sink A callback that receives values from the source\n * @param inlet An optional throttle or inlet that will be used to pause the\n * source (if it's a signal or supports backpressure)\n * @returns a {@link Connection} that can be used to detect the stream\n * end/error, or ended to close it early.\n *\n * @category Stream Consumers\n */\nexport function forEach<T>(src: Stream<T>, sink: Sink<T>, inlet?: Inlet): Connection;\n/**\n * When called without a source, return a callback suitable for use w/{@link pipe}().\n * e.g.:\n *\n * ```ts\n * pipe(someSource, ..., forEach(v => { doSomething(v); }), optionalInlet));\n * ```\n *\n */\nexport function forEach<T>(sink: Sink<T>, inlet?: Inlet): (src: Stream<T>) => Connection;\nexport function forEach<T>(\n src: Stream<T>|Sink<T>, sink?: Sink<T>|Inlet, inlet?: Inlet\n): Connection | ((src: Stream<T>) => Connection) {\n if (isFunction(sink)) return start(j => {\n (src as Stream<T>)(restarting(sink as Sink<T>), j, inlet)\n });\n inlet = sink as Inlet; sink = src as Sink<T>;\n return (src: Stream<T>) => forEach(src, sink as Sink<T>, inlet);\n}\n\n/**\n * Arrange for the current signal or rule to recalculate on demand\n *\n * This lets you interop with systems that have a way to query a value and\n * subscribe to changes to it, but not directly produce a signal. (Such as\n * querying the DOM state and using a MutationObserver.)\n *\n * By calling this with a {@link Source} or {@link RecalcSource}, you arrange\n * for it to be subscribed, if and when the call occurs in a rule or a cached\n * function that's in use by a rule (directly or indirectly). When the source\n * emits a value, the signal machinery will invalidate the caching of the\n * function or rule, forcing a recalculation and subsequent rule reruns, if\n * applicable.\n *\n * Note: you should generally only call the 1-argument version of this function\n * with \"static\" sources - i.e. ones that won't change on every call. Otherwise,\n * you will end up creating new signals each time, subscribing and unsubscribing\n * on every call to recalcWhen().\n *\n * If the source needs to reference some object, it's best to use the 2-argument\n * version (i.e. `recalcWhen(someObj, factory)`, where `factory` is a function\n * that takes `someObj` and returns a suitable {@link RecalcSource}.)\n *\n * @remarks\n * recalcWhen is specifically designed so that using it does not pull in any\n * part of Uneventful's signals framework, in the event a program doesn't\n * already use it. This means you can use it in library code to provide signal\n * compatibility, without adding bundle bloat to code that doesn't use signals.\n *\n * @category Signals\n */\n\nexport function recalcWhen(src: RecalcSource): void;\n/**\n * Two-argument variant of recalcWhen\n *\n * In certain circumstances, you may wish to use recalcWhen with a source\n * related to some object. You could call recalcWhen with a closure, but that\n * would create and discard signals on every call. So this 2-argument version\n * lets you avoid that by allowing the use of an arbitrary object as a key,\n * along with a factory function to turn the key into a {@link RecalcSource}.\n *\n * @param key an object to be used as a key\n *\n * @param factory a function that will be called with the key to obtain a\n * {@link RecalcSource}. (Note that this factory function must also be a static\n * function, not a closure, or the same memory thrash issue will occur!)\n */\nexport function recalcWhen<T extends WeakKey>(key: T, factory: (key: T) => RecalcSource): void;\nexport function recalcWhen<T extends WeakKey>(fnOrKey: T | RecalcSource, fn?: (key: T) => RecalcSource) {\n current.cell?.recalcWhen<T>(fnOrKey as T, fn);\n}\n\n/**\n * Find out whether the active signal is being observed, or just queried.\n *\n * If the return value is true, the caller is running within a signal\n * calculation that is being observed by subscribers (such as a rule or stream\n * listener). If the return value is false, the caller is running within a\n * signal calculation that is *not* observed by any subscribers, and the signal\n * will be recalculated whenever it transitions from unobserved to observed.\n *\n * Returns `undefined` if the caller isn't running in a signal calculation.\n *\n * @remarks Note that calling this function within a signal calculation even\n * once adds a *permanent*, implicit dependency to that signal, on whether the\n * signal is being observed. (As does using any job APIs directly.)\n *\n * The assumption here is that if you're checking whether it's observed, it's\n * because you only want to do certain things *while* it's being observed, so\n * the signal needs to be recalculated when it *starts* being observed, so you\n * can do those things. (If you need to undo or clean up those things when the\n * signal is no-longer observed, you can register a cleanup callback via e.g.\n * {@link must}(), or wrap them in a sub-job with start, connect, etc.)\n *\n * @category Signals\n */\nexport function isObserved(): boolean | undefined {\n return current.cell?.isObserved();\n}\n","import { fromIterable } from \"./sources.ts\";\nimport { Connection, IsStream, Source, Sink, Stream, Transformer, backpressure, throttle } from \"./streams.ts\";\nimport { isValue, noop } from \"./results.ts\";\nimport { start } from \"./jobutils.ts\";\n\n/**\n * Output multiple streams' contents in order (from an array/iterable of stream\n * sources)\n *\n * Streams are concatenated in order -- note that this means they need to not be\n * infinite if any subsequent streams are to be processed! The output is closed\n * when all sources are finished or if any source throws (in which case the\n * error propagates to the subscriber).\n *\n * Note: this function is just shorthand for {@link concatAll}({@link fromIterable}(*sources*)).\n *\n * @category Stream Operators\n */\nexport function concat<T>(sources: Stream<T>[] | Iterable<Stream<T>>): Source<T> {\n return concatAll(fromIterable(sources))\n}\n\n/**\n * Flatten a source of sources by emitting their contents in series\n *\n * Streams are concatenated in order -- note that this means they need to not be\n * infinite if any subsequent streams are to be processed! The output is closed\n * when all sources are finished or if any source throws (in which case the\n * error propagates to the subscriber).\n *\n * If you want to switch to a new stream whenever a new source arrives from the\n * input stream, use {@link switchAll} instead.\n *\n * @category Stream Operators\n */\nexport function concatAll<T>(sources: Stream<Stream<T>>): Source<T> {\n return (sink, conn=start(), inlet) => {\n let inner: Connection;\n const inputs: Stream<T>[] = [], t = throttle();\n let outer = conn.connect(sources, s => {\n inputs.push(s); startNext(); t.pause();\n }, t).do(r => {\n outer = undefined\n inputs.length || inner || !isValue(r) || conn.return();\n });\n function startNext() {\n inner ||= conn.connect(inputs.shift(), sink, inlet).do(r => {\n inner = undefined;\n inputs.length ? startNext() : (outer ? t.resume() : !isValue(r) || conn.return());\n });\n }\n return IsStream;\n }\n}\n\n/**\n * Map each value of a stream to a substream, then concatenate the resulting\n * substreams\n *\n * (This is just shorthand for `compose(map(mapper), concatAll)`.)\n *\n * If you want to switch to a new stream whenever a new event arrives on the\n * input stream, use {@link switchMap} instead.\n *\n * @category Stream Operators\n */\nexport function concatMap<T,R>(mapper: (v: T, idx: number) => Stream<R>): Transformer<T,R> {\n return src => concatAll(map(mapper)(src))\n}\n\n\n/**\n * Create a subset of a stream, based on a filter function (like Array.filter)\n *\n * The filter function receives the current index (zero-based) as well as the\n * current value. If it returns truth, the value will be passed to the output,\n * otherwise it will be skipped.\n *\n * If the filter function is typed as a Typescript type guard (i.e. as returning\n * `v is SomeType`), then the resulting source will be typed as\n * Source<SomeType>.\n *\n * @category Stream Operators\n */\nexport function filter<T,R extends T>(filter: (v: T, idx: number) => v is R): Transformer<T,R>;\nexport function filter<T>(filter: (v: T, idx: number) => boolean): Transformer<T>;\nexport function filter<T>(filter: (v: T, idx: number) => boolean): Transformer<T> {\n return src => (sink, conn, inlet) => {\n let idx = 0; return src(v => filter(v, idx++) && sink(v), conn, inlet);\n }\n}\n\n/**\n * Replace each value in a stream using a function (like Array.map)\n *\n * The mapping function receives the current index (zero-based) as well as the\n * current value.\n *\n * @category Stream Operators\n */\nexport function map<T,R>(mapper: (v: T, idx: number) => R): Transformer<T,R> {\n return src => (sink, conn, inlet) => {\n let idx = 0; return src(v => sink(mapper(v, idx++)), conn, inlet);\n }\n}\n\n/**\n * Create an event source by merging an array or iterable of event sources.\n *\n * The resulting source issues events whenever any of the input sources do, and\n * closes once they all do (or throws if any of them do).\n *\n * @category Stream Operators\n */\nexport function merge<T>(sources: Stream<T>[] | Iterable<Stream<T>>): Source<T> {\n return mergeAll(fromIterable(sources));\n}\n\n/**\n * Create an event source by merging sources from a stream of event sources\n *\n * The resulting source issues events whenever any of the input sources do, and\n * closes once they all do (or throws if any of them do).\n *\n * @category Stream Operators\n */\nexport function mergeAll<T>(sources: Stream<Stream<T>>): Source<T> {\n return (sink, conn=start(), inlet) => {\n const uplinks: Set<Connection> = new Set;\n let outer = conn.connect(sources, (s) => {\n const c = conn.connect(s, sink, inlet).do(r => {\n uplinks.delete(c);\n uplinks.size || outer || !isValue(r) || conn.return();\n });\n uplinks.add(c);\n }).do(r => {\n outer = undefined;\n uplinks.size || !isValue(r) || conn.return();\n });\n return IsStream;\n }\n}\n\n/**\n * Create an event source by merging sources created by mapping events to sources\n *\n * The resulting source issues events whenever any of the input sources do, and\n * closes once they all do (or throws if any of them do).\n *\n * (Note: this is just shorthand for `compose(map(mapper), mergeAll)`.)\n *\n * @category Stream Operators\n */\nexport function mergeMap<T,R>(mapper: (v: T, idx: number) => Stream<R>): Transformer<T,R> {\n return src => mergeAll(map(mapper)(src));\n}\n\n/**\n * Skip the first N items from a source\n *\n * (Equivalent to {@link skipWhile}() with a function that checks the index is < n.)\n *\n * @category Stream Operators\n */\nexport function skip<T>(n: number): Transformer<T> {\n return skipWhile((_, i) => i<n);\n}\n\n/**\n * Skip items from a stream until another source produces a value.\n *\n * If the notifier closes without producing a value, the output will\n * be empty. If the notifier throws, so will the output.\n *\n * @category Stream Operators\n */\nexport function skipUntil<T>(notifier: Stream<any>): Transformer<T> {\n return src => (sink, conn=start(), inlet) => {\n let taking = false;\n const c = conn.connect(notifier, () => { taking = true; c.end(); });\n return src(v => taking && sink(v), conn, inlet);\n }\n}\n\n/**\n * Skip items from a stream until a given condition is false, then output all\n * remaining items. The condition function is not called again once it returns\n * false.\n *\n * @category Stream Operators\n */\nexport function skipWhile<T>(condition: (v: T, index: number) => boolean) : Transformer<T> {\n return src => (sink, conn, inlet) => {\n let idx = 0, met = false;\n return src(v => (met ||= !condition(v, idx++)) && sink(v), conn, inlet);\n };\n}\n\n/**\n * Add job control and buffering to a stream\n *\n * This lets you block events from a stream that can't be paused, or allow for\n * some slack for a source that can sometimes get ahead of its sink.\n *\n * @param size The number of items to buffer when the sink is busy (i.e., the\n * sink is running or the connection is paused). If positive, the most recent N\n * items are kept (a \"sliding\" buffer), and if negative, the oldest N item are\n * kept (a \"dropping\" buffer). If zero, no items are buffered, and items are\n * dropped if received while the sink is busy.\n *\n * @param dropped Optional: a callback that will receive items when they are\n * dropped. (Useful for testing, performance instrumentation, error logging,\n * etc.)\n *\n * @category Stream Operators\n */\nexport function slack<T>(size: number, dropped: Sink<T> = noop): Transformer<T> {\n const max = Math.abs(size);\n return src => (sink, conn=start(), inlet) => {\n const buffer: T[] = [], ready = backpressure(inlet);\n let paused = false, draining = false;\n const t = throttle();\n conn.connect(src, v => {\n buffer.push(v);\n if (!draining && ready()) return drain();\n while (buffer.length > max) { dropped((size < 0) ? buffer.pop() : buffer.shift()); }\n if (buffer.length === max) { t.pause(); paused = true; }\n if (buffer.length) ready(drain);\n }, t).do(r => {\n if (isValue(r)) conn.return();\n });\n\n function drain() {\n draining = true;\n try {\n while(buffer.length) {\n sink(buffer.shift());\n if (paused && ready()) {\n paused = false; t.resume();\n }\n if (buffer.length && !ready()) {\n return ready(drain);\n }\n }\n } finally {\n draining = false;\n }\n }\n return IsStream;\n }\n}\n\n/**\n * Flatten a source of sources by emitting their contents until a new one\n * arrives.\n *\n * As each source arrives from the input stream, its values are sent to the\n * output, closing the previous one (if any). The output is closed when both\n * the input stream and the most-recently-arrived stream are finished. Errors\n * propagate to the output if any stream throws.\n *\n * (If you want to send *all* the values of each stream to the output without\n * stopping, input stream, use {@link concatAll} or {@link mergeAll} instead.)\n *\n * @category Stream Operators\n */\nexport function switchAll<T>(sources: Stream<Stream<T>>): Source<T> {\n return (sink, conn=start(), inlet) => {\n let inner: Connection;\n let outer = conn.connect(sources, s => {\n inner?.end();\n inner = conn.connect(s, sink, inlet).do(r => {\n inner = undefined;\n outer || !isValue(r) || conn.return();\n });\n }).do(r => {\n outer = undefined;\n inner || !isValue(r) || conn.return();\n });\n return IsStream;\n }\n}\n\n/**\n * Map each value of a stream to a substream, then output the resulting\n * substreams until a new value arrives.\n *\n * (This is just shorthand for `compose(map(mapper),`{@link switchAll `switchAll)`}.)\n *\n * (If you want to send *all* the values of each stream to the output without\n * stopping, input stream, use {@link concatMap} or {@link mergeMap} instead.)\n *\n * @category Stream Operators\n */\nexport function switchMap<T,R>(mapper: (v: T, idx: number) => Stream<R>): Transformer<T,R> {\n return src => switchAll(map(mapper)(src))\n}\n\n/**\n * Take the first N items from a source\n *\n * (Equivalent to {@link takeWhile}() with a function that checks the index is < n.)\n *\n * @category Stream Operators\n */\nexport function take<T>(n: number): Transformer<T> {\n return takeWhile((_, i) => i<n);\n}\n\n/**\n * Take items from a source until another source produces a value.\n *\n * If the notifier closes without producing a value, this will output all\n * elements of the input. But if the notifier throws, so will the output.\n *\n * @category Stream Operators\n */\nexport function takeUntil<T>(notifier: Stream<any>): Transformer<T> {\n return src => (sink, conn=start(), inlet) => {\n conn.connect(notifier, () => conn.return());\n return src(sink, conn, inlet);\n }\n}\n\n/**\n * Take items from a stream until a given condition is false, then close the\n * output. The condition function is not called again after it returns false.\n *\n * If the condition function is typed as a Typescript type guard (i.e. as\n * returning `v is SomeType`), then the resulting source will be typed as\n * Source<SomeType>.\n *\n * @category Stream Operators\n */\nexport function takeWhile<T,R extends T>(condition: (v: T, idx: number) => v is R): Transformer<T,R>;\nexport function takeWhile<T>(condition: (v: T, idx: number) => boolean): Transformer<T>;\nexport function takeWhile<T>(condition: (v: T, index: number) => boolean) : Transformer<T> {\n return src => (sink, conn, inlet) => {\n let idx = 0;\n return src(v => condition(v, idx++) ? sink(v) : conn?.return(), conn, inlet);\n };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mod.mjs","sources":["../src/async.ts","../src/sources.ts","../src/sinks.ts","../src/operators.ts"],"sourcesContent":["import { Request, Yielding } from \"./types.ts\";\nimport { rejecter, resolve, resolver } from \"./results.ts\"\n\n/**\n * Convert a (possible) promise to something you can `yield *to()` in a job\n *\n * Much like `await valueOrPromiseLike` in an async function, using `yield\n * *to(valueOrPromiseLike)` in a {@link Job}'s generator function will return\n * the value or the result of the promise/promise-like object.\n *\n * @category Scheduling\n */\nexport function *to<T>(p: Promise<T> | PromiseLike<T> | T): Yielding<T> {\n return yield (res: Request<T>) => Promise.resolve(p).then(resolver(res), rejecter(res));\n}\n\n/**\n * Pause the job for the specified time in ms, e.g. `yield *sleep(1000)` to wait\n * one second.\n *\n * @category Scheduling\n */\nexport function *sleep(ms: number): Yielding<void> {\n try {\n var id: ReturnType<typeof setTimeout>;\n yield r => {\n id = setTimeout(() => { id = undefined; resolve(r, void 0); }, ms);\n }\n } finally {\n if (id) clearTimeout(id);\n }\n}\n","import { defer } from \"./defer.ts\";\nimport { type Stream, IsStream, backpressure, Sink, Connection, Backpressure, throttle, Inlet, Source } from \"./streams.ts\";\nimport { getJob, root } from \"./tracking.ts\";\nimport { must, start } from \"./jobutils.ts\";\nimport { DisposeFn } from \"./types.ts\";\nimport { isCancel, isError, isUnhandled, markHandled, noop } from \"./results.ts\";\n\n/**\n * A function that emits events, with a .source they're emitted from\n *\n * Created using {@link emitter}.\n *\n * @category Types and Interfaces\n */\nexport interface Emitter<T> {\n /** Call the emitter to emit events on its .source */\n (val: T): void;\n /** An event source that receives the events */\n source: Source<T>;\n /** Close all current subscribers' connections */\n end: () => void;\n /** Close all current subscribers' connections with an error */\n throw: (e: any) => void;\n};\n\n/**\n * Create an event source and a function to emit events on it\n *\n * (Note: you must specify the event type (e.g. `emitter<number>()`), since\n * there's nothing else to infer it from.)\n *\n * @returns A function that emits events, with a .source property they're\n * emitted on.\n *\n * @category Stream Producers\n */\nexport function emitter<T>(): Emitter<T> {\n const emit = mockSource<T>();\n emit.source = share(emit.source);\n return emit;\n}\n\n/**\n * A stream that immediately closes\n *\n * @category Stream Producers\n */\nexport function empty(): Source<never> {\n return (_, conn) => (conn?.return(), IsStream);\n}\n\n/**\n * Convert an async iterable to an event source\n *\n * Each time the resulting source is subscribed to, it will emit an event for\n * each item output by the iterator, then end the stream. Pause/resume is\n * supported.\n *\n * @category Stream Producers\n */\nexport function fromAsyncIterable<T>(iterable: AsyncIterable<T>): Source<T> {\n return (sink, conn=start(), inlet) => {\n const ready = backpressure(inlet);\n const iter = iterable[Symbol.asyncIterator]();\n if (iter.return) must(() => iter.return());\n return ready(next), IsStream;\n function next() {\n iter.next().then(({value, done}) => {\n if (done) conn.return(); else ready(() => {\n if (sink(value), ready()) next(); else ready(next);\n })\n }, e => conn.throw(e));\n }\n }\n}\n\n/**\n * Create an event source from an element, window, or other event target\n *\n * You can manually override the expected event type using a type parameter,\n * e.g. `fromDomEvent<CustomEvent>(someTarget, \"custom-event\")`.\n *\n * @param target an HTMLElement, Window, Document, or other EventTarget.\n * @param type the name of the event to add a listener for\n * @param options a boolean capture option, or an object of event listener\n * options\n * @returns a source that can be subscribed or piped, issuing events from the\n * target of the specified type.\n *\n * @category Stream Producers\n */\nexport function fromDomEvent<T extends HTMLElement, K extends keyof HTMLElementEventMap>(\n target: T, type: K, options?: boolean | AddEventListenerOptions\n): Source<HTMLElementEventMap[K]>;\nexport function fromDomEvent<T extends Window, K extends keyof WindowEventMap>(\n target: T, type: K, options?: boolean | AddEventListenerOptions\n): Source<WindowEventMap[K]>;\nexport function fromDomEvent<T extends Document, K extends keyof DocumentEventMap>(\n target: T, type: K, options?: boolean | AddEventListenerOptions\n): Source<DocumentEventMap[K]>;\nexport function fromDomEvent<T extends Event>(\n target: EventTarget, type: string, options?: boolean | AddEventListenerOptions\n): Source<T>\nexport function fromDomEvent<T extends EventTarget, K extends string>(\n target: T, type: K, options?: boolean | AddEventListenerOptions\n): Source<Event> {\n return (sink) => {\n function push(v: Event) { sink(v); }\n target.addEventListener(type, push, options);\n must(() => target.removeEventListener(type, push, options));\n return IsStream;\n }\n}\n\n/**\n * Convert an iterable to a synchronous event source\n *\n * Each time the resulting source is subscribed to, it will emit an event for\n * each item in the iterator, then close the connection. Pause/resume is\n * supported.\n *\n * @category Stream Producers\n */\nexport function fromIterable<T>(iterable: Iterable<T>): Source<T> {\n return (sink, conn=start(), inlet) => {\n const ready = backpressure(inlet);\n const iter = iterable[Symbol.iterator]();\n if (iter.return) must(() => iter.return());\n return ready(loop), IsStream;\n function loop() {\n try {\n for(;;) {\n const {value, done} = iter.next();\n if (done) return conn.return();\n if (sink(value), !ready()) return ready(loop);\n }\n } catch (e) {\n conn.throw(e);\n }\n }\n }\n}\n\n/**\n * Convert a Promise to an event source\n *\n * Each time the resulting source is subscribed to, it will emit an event for\n * the result of the promise, then close the connection. (Unless the promise is\n * rejected, in which case the connection throws and closes each time the source\n * is subscribed.) Non-native promises and non-promise values are converted\n * using Promise.resolve().\n *\n * @category Stream Producers\n */\nexport function fromPromise<T>(promise: Promise<T>|PromiseLike<T>|T): Source<T> {\n return (sink, conn) => {\n const job = getJob();\n Promise.resolve(promise).then(\n v => void (job.result() || (sink(v), conn?.return())),\n e => void (job.result() || conn?.throw(e))\n )\n return IsStream;\n }\n}\n\n/**\n * Create an event source from an arbitrary subscribe/unsubscribe function\n *\n * The supplied \"subscribe\" function will be passed a 1-argument callback and\n * must return an unsubscribe function. The callback should be called with\n * events of the appropriate type, and the unsubscribe function will be called\n * when the connection is closed.\n *\n * (Note: it's okay if the act of subscribing causes an immediate callback, as\n * the subscribe function will be called in a separate microtask.)\n *\n * @category Stream Producers\n */\nexport function fromSubscribe<T>(subscribe: (cb: (val: T) => void) => DisposeFn): Source<T> {\n return (sink) => {\n const f = getJob().must(() => sink = noop);\n return defer(() => f.must(subscribe(v => { sink(v); }))), IsStream;\n }\n}\n\n/**\n * Create a source that emits a single given value\n *\n * @category Stream Producers\n */\nexport function fromValue<T>(val: T): Source<T> {\n return (sink, conn) => {\n must(() => { sink = noop; conn = undefined; })\n return defer(() => { sink(val); conn?.return(); }), IsStream;\n }\n}\n\n/**\n * Create an event source that issues a number every `ms` milliseconds (starting\n * with 0 after the first interval passes).\n *\n * @category Stream Producers\n */\nexport function interval(ms: number): Source<number> {\n return (sink) => {\n let idx = 0, id = setInterval(() => sink(idx++), ms);\n return must(() => clearInterval(id)), IsStream;\n }\n}\n\n/**\n * Create a dynamic source that is created each time it's subscribed\n *\n * @param factory A function returning a source of the desired type. It will be\n * called whenever the lazy() stream is subscribed, and its result subscribed to.\n *\n * @returns A stream of the same type as the factory function returns\n *\n * @category Stream Producers\n */\nexport function lazy<T>(factory: () => Stream<T>): Source<T> {\n return (sink, conn, inlet) => factory()(sink, conn, inlet)\n}\n\n/**\n * An {@link Emitter} with a ready() method, that only supports a single active\n * subscriber. (Useful for testing stream operators and sinks.)\n *\n * Created using {@link mockSource}().\n *\n * @category Types and Interfaces\n */\nexport interface MockSource<T> extends Emitter<T> {\n ready: Backpressure\n}\n\n/**\n * Like {@link emitter}, but with a ready() backpressure method. It also only\n * supports a single active subscriber. (Useful for testing stream operators\n * and sinks.)\n *\n * @category Stream Producers\n */\nexport function mockSource<T>(): MockSource<T> {\n let write: Sink<T>, outlet: Connection, ready: Backpressure;\n const emit: MockSource<T> = (val: T) => { if (write) write(val); };\n emit.source = (sink, conn, inlet) => {\n write = sink; outlet = conn; ready = backpressure(inlet);\n must(() => write = outlet = ready = undefined);\n return IsStream;\n };\n emit.end = () => outlet?.return();\n emit.throw = (e: any) => outlet?.throw(e);\n emit.ready = (cb?: () => any) => ready(cb);\n return emit;\n}\n\n/**\n * A stream that never emits or closes\n *\n * @category Stream Producers\n */\nexport function never(): Source<never> {\n return () => IsStream;\n}\n\n/**\n * Wrap a source to allow multiple subscribers to the same underlying stream\n *\n * The input source will be susbcribed when the output has at least one\n * subscriber, and unsubscribed when the output has no subscribers. The input\n * will be paused when any subscriber pauses, and will only be resumed when all\n * subscribers are unpaused. All subscribers are closed or thrown if the input\n * source closes or throws.\n *\n * (Generally speaking, you should place the share call as late in your\n * pipelines as possible, if you use it at all. It adds some overhead that is\n * wasted if the stream doesn't have multiple subscribers, and may be redundant\n * if an upstream source is already shared. It's mainly useful if there is a\n * lot of mapping, filtering, or other complicated processing taking place\n * upstream of the share, and you know for a fact there will be enough\n * subscribers to make it a bottleneck. You should probably also consider\n * putting some {@link slack}() either upstream or downstream of the share, if\n * the upstream supports backpressure.)\n *\n * @category Stream Operators\n */\nexport function share<T>(source: Stream<T>): Source<T> {\n let uplink: Connection;\n const\n links = new Set<[sink: Sink<T>, conn: Connection]>,\n inlets = new Map<Inlet, number>(), // refcounts of incoming inlets\n t = throttle(), // the actual onReady queue\n multi: Inlet = {\n // A multi-connection inlet that requires all downstreams to be ready\n isOpen() { return !uplink?.result(); },\n isReady() {\n if (this.isOpen()) {\n for (const [i] of inlets) if (!i.isReady()) return (t.pause(), false);\n return true;\n }\n t.pause();\n return false;\n },\n onReady(cb, job) {\n if (this.isOpen()) {\n t.onReady(cb, job);\n for (const [i] of inlets) i.isReady() || i.onReady(produce, job);\n }\n return this;\n }\n }\n ;\n function produce() { multi.isReady() && t.resume(); }\n\n return (sink, conn=start(), inlet) => {\n const self: [Sink<T>, Connection] = [sink, conn];\n links.add(self);\n if (inlet) inlets.set(inlet, 1+(inlets.get(inlet) || 0));\n conn.must(() => {\n links.delete(self);\n if (inlet) {\n inlets.set(inlet, inlets.get(inlet)-1);\n if (!inlets.get(inlet)) inlets.delete(inlet);\n }\n if (!links.size) uplink?.end();\n else if (multi.isReady() && !t.isReady()) defer(produce);\n });\n if (links.size === 1) {\n uplink = root.connect(source, v => {\n for(const [s, c] of links) try { s(v) } catch(e) { c.throw(e); };\n }, multi).do(r => {\n uplink = undefined;\n if (isCancel(r)) return;\n if (isUnhandled(r)) markHandled(r);\n for(const [_, c] of links) isError(r) ? c.throw(r.err) : c.return();\n })\n }\n return IsStream;\n }\n}\n","import { Job, RecalcSource, Request, Suspend, Yielding } from \"./types.ts\"\nimport { defer } from \"./defer.ts\";\nimport { Connection, Inlet, Sink, Stream, connect, pipe, throttle } from \"./streams.ts\";\nimport { resolve, isError, markHandled, fulfillPromise, rejecter, resolver } from \"./results.ts\";\nimport { restarting, start, must } from \"./jobutils.ts\";\nimport { isFunction } from \"./utils.ts\";\nimport { Signal, until, cached } from \"./signals.ts\"; // the until and cached are needed for documentation links\nimport { callOrWait, mustBeSourceOrSignal } from \"./call-or-wait.ts\";\nimport { current } from \"./ambient.ts\";\n\n/**\n * The result type returned from calls to {@link Each}.next()\n *\n * @category Types and Interfaces\n */\nexport type EachResult<T> = {\n /** The value provided by the source being iterated */\n item: T;\n\n /**\n * A suspend callback that must be `yield`-ed before the next call to the\n * iterator's .next() method. (That is, you must `yield next` it exactly once\n * per loop pass. See {@link each}() for more details.)\n */\n next: Suspend<void>;\n}\n\n/**\n * The iterable returned by `yield *` {@link each}()\n *\n * @category Types and Interfaces\n */\nexport type Each<T> = IterableIterator<EachResult<T>>\n\n/**\n * Asynchronously iterate over an event source\n *\n * Usage:\n *\n * ```ts\n * for (const {item: event, next} of yield *each(mouseMove)) {\n * console.log(event.clientX, event.clientY);\n * yield next; // required exactly once per iteration, even/w continue!\n * }\n * ```\n *\n * each(eventSource) yield-returns an iterator of `{item, next}` pairs. The\n * item is the data supplied by the event source, and `next` is a\n * {@link Suspend}\\<void\\> that advances the iterator to the next item. It\n * *must* be yielded exactly once per loop iteration. If you use `continue` to\n * shortcut the loop body, you must `yield next` *before* doing so.\n *\n * The for-loop will end if the source ends, errors, or is canceled. The source\n * is paused while the loop body is running, and resumed when the `yield next`\n * happens. If events arrive anyway (e.g. because the source doesn't support\n * pausing), they will be ignored unless you pipe the source through the\n * {@link slack}() operator to provide a buffer. If the for-loop is exited\n * early for any reason (or the iterator's `.return()` is called), the source is\n * unsubscribed and the iteration ended.\n *\n * @category Stream Consumers\n */\nexport function *each<T>(src: Stream<T>): Yielding<Each<T>> {\n let yielded = false, waiter: Request<void>;\n const result: IteratorYieldResult<EachResult<T>> = {value: {item: undefined as T, next}, done: false};\n const t = throttle(), conn = connect(src, v => {\n t.pause();\n if (!waiter || conn.result()) return;\n result.value.item = v;\n resolve(waiter, waiter = void 0);\n }, t).do(r => {\n // Prevent unhandled throws from here - it'll be seen by the next `yield\n // next`, or in the next microtask if `yield next` is already running.\n if (isError(r)) markHandled(r);\n if (waiter) { defer(next.bind(null, waiter)); waiter = undefined; }\n });\n\n // Wait for first value to arrive (and get put in result) before returning the iterator\n t.pause(); yield next;\n return {\n [Symbol.iterator]() { return this; },\n next() {\n if (!yielded) throw new Error(\"Must `yield next` in loop\");\n yielded = false;\n return result;\n },\n return() { conn.end(); return {value: undefined, done: true}; },\n }\n function next(r: Request<void>) {\n if (waiter) throw new Error(\"Multiple `yield next` in loop\");\n yielded = true;\n if (conn.result()) {\n result.value = undefined;\n (result as IteratorResult<any>).done = true;\n fulfillPromise(resolver(r), rejecter(r), conn.result())\n } else {\n waiter = r;\n t.resume();\n }\n }\n}\n\n/**\n * An object that can be waited on with `yield *until()`, by calling its\n * \"uneventful.until\" method. (This mostly exists to allow Signals to optimize\n * their until() implementation, but is also open for extensions.)\n *\n * @category Types and Interfaces\n */\nexport interface UntilMethod<T> {\n /** Return an async op to resume once a truthy value is available */\n \"uneventful.until\"(): Yielding<T>\n}\n\n/**\n * An object that can be waited on with `yield *next()`, by calling its\n * \"uneventful.next\" method. (This mostly exists to allow Signals to optimize\n * their next() implementation, but is also open for extensions.)\n *\n * @category Types and Interfaces\n */\nexport interface NextMethod<T> {\n /** Return an async op to resume with the \"next\" (i.e. not current) value produced */\n \"uneventful.next\"(): Yielding<T>\n};\n\n/**\n * Wait for and return the next value (or error) from a data source (when\n * processed with `yield *` within a {@link Job}).\n *\n * This differs from {@link until}() in that it waits for the *next* value\n * (truthy or not!), and it never resumes immediately for signals, but instead\n * waits for the signal to *change*. (Also, it does not support zero-argument\n * functions, unless you wrap them with {@link cached}() first.)\n *\n * @param source The source to wait on, which can be:\n * - An object with an `\"uneventful.next\"` method returning a {@link Yielding}\n * (in which case the result will be the the result of calling that method)\n * - A {@link Signal} or {@link Source} (in which case the job resumes on the\n * next value it produces)\n *\n * (Note: if the supplied source is a function with a non-zero `.length`, it is\n * assumed to be a {@link Source}.)\n *\n * @returns a Yieldable that when processed with `yield *` in a job, will return\n * the triggered event, or signal value. An error is thrown if event stream\n * throws or closes early, or the signal throws.\n *\n * @category Stream Consumers\n * @category Scheduling\n */\nexport function next<T>(source: NextMethod<T> | Stream<T>): Yielding<T> {\n return callOrWait<T>(source, \"uneventful.next\", waitAny, mustBeSourceOrSignal);\n}\n\nfunction waitAny<T>(job: Job<T>, v: T) { job.return(v); }\n\n/**\n * Run a {@link restarting}() callback for each value produced by a source.\n *\n * With each event that occurs, any previous callback run is cleaned up before\n * the new one begins. (And the last run is cleaned up when the connection or\n * job ends.)\n *\n * This function is almost the exact opposite of {@link each}(), in that the\n * stream is never paused (unless you do so manually via a throttle or inlet),\n * and if the \"loop body\" (callback job) is still running when a new value\n * arrives, forEach() restarts the job instead of dropping the value.\n *\n * @param src An event source (i.e. a {@link Source} or {@link Signal})\n * @param sink A callback that receives values from the source\n * @param inlet An optional throttle or inlet that will be used to pause the\n * source (if it's a signal or supports backpressure)\n * @returns a {@link Connection} that can be used to detect the stream\n * end/error, or ended to close it early.\n *\n * @category Stream Consumers\n */\nexport function forEach<T>(src: Stream<T>, sink: Sink<T>, inlet?: Inlet): Connection;\n/**\n * When called without a source, return a callback suitable for use w/{@link pipe}().\n * e.g.:\n *\n * ```ts\n * pipe(someSource, ..., forEach(v => { doSomething(v); }), optionalInlet));\n * ```\n *\n */\nexport function forEach<T>(sink: Sink<T>, inlet?: Inlet): (src: Stream<T>) => Connection;\nexport function forEach<T>(\n src: Stream<T>|Sink<T>, sink?: Sink<T>|Inlet, inlet?: Inlet\n): Connection | ((src: Stream<T>) => Connection) {\n if (isFunction(sink)) return start(j => {\n (src as Stream<T>)(restarting(sink as Sink<T>), j, inlet)\n });\n inlet = sink as Inlet; sink = src as Sink<T>;\n return (src: Stream<T>) => forEach(src, sink as Sink<T>, inlet);\n}\n\n/**\n * Arrange for the current signal or rule to recalculate on demand\n *\n * This lets you interop with systems that have a way to query a value and\n * subscribe to changes to it, but not directly produce a signal. (Such as\n * querying the DOM state and using a MutationObserver.)\n *\n * By calling this with a {@link Source} or {@link RecalcSource}, you arrange\n * for it to be subscribed, if and when the call occurs in a rule or a cached\n * function that's in use by a rule (directly or indirectly). When the source\n * emits a value, the signal machinery will invalidate the caching of the\n * function or rule, forcing a recalculation and subsequent rule reruns, if\n * applicable.\n *\n * Note: you should generally only call the 1-argument version of this function\n * with \"static\" sources - i.e. ones that won't change on every call. Otherwise,\n * you will end up creating new signals each time, subscribing and unsubscribing\n * on every call to recalcWhen().\n *\n * If the source needs to reference some object, it's best to use the 2-argument\n * version (i.e. `recalcWhen(someObj, factory)`, where `factory` is a function\n * that takes `someObj` and returns a suitable {@link RecalcSource}.)\n *\n * @remarks\n * recalcWhen is specifically designed so that using it does not pull in any\n * part of Uneventful's signals framework, in the event a program doesn't\n * already use it. This means you can use it in library code to provide signal\n * compatibility, without adding bundle bloat to code that doesn't use signals.\n *\n * @category Signals\n */\n\nexport function recalcWhen(src: RecalcSource): void;\n/**\n * Two-argument variant of recalcWhen\n *\n * In certain circumstances, you may wish to use recalcWhen with a source\n * related to some object. You could call recalcWhen with a closure, but that\n * would create and discard signals on every call. So this 2-argument version\n * lets you avoid that by allowing the use of an arbitrary object as a key,\n * along with a factory function to turn the key into a {@link RecalcSource}.\n *\n * @param key an object to be used as a key\n *\n * @param factory a function that will be called with the key to obtain a\n * {@link RecalcSource}. (Note that this factory function must also be a static\n * function, not a closure, or the same memory thrash issue will occur!)\n */\nexport function recalcWhen<T extends WeakKey>(key: T, factory: (key: T) => RecalcSource): void;\nexport function recalcWhen<T extends WeakKey>(fnOrKey: T | RecalcSource, fn?: (key: T) => RecalcSource) {\n current.cell?.recalcWhen<T>(fnOrKey as T, fn);\n}\n\n/**\n * Find out whether the active signal is being observed, or just queried.\n *\n * If the return value is true, the caller is running within a signal\n * calculation that is being observed by subscribers (such as a rule or stream\n * listener). If the return value is false, the caller is running within a\n * signal calculation that is *not* observed by any subscribers, and the signal\n * will be recalculated whenever it transitions from unobserved to observed.\n *\n * Returns `undefined` if the caller isn't running in a signal calculation.\n *\n * @remarks Note that calling this function within a signal calculation even\n * once adds a *permanent*, implicit dependency to that signal, on whether the\n * signal is being observed. (As does using any job APIs directly.)\n *\n * The assumption here is that if you're checking whether it's observed, it's\n * because you only want to do certain things *while* it's being observed, so\n * the signal needs to be recalculated when it *starts* being observed, so you\n * can do those things. (If you need to undo or clean up those things when the\n * signal is no-longer observed, you can register a cleanup callback via e.g.\n * {@link must}(), or wrap them in a sub-job with start, connect, etc.)\n *\n * @category Signals\n */\nexport function isObserved(): boolean | undefined {\n return current.cell?.isObserved();\n}\n","import { fromIterable } from \"./sources.ts\";\nimport { Connection, IsStream, Source, Sink, Stream, Transformer, backpressure, throttle } from \"./streams.ts\";\nimport { isValue, noop } from \"./results.ts\";\nimport { start } from \"./jobutils.ts\";\n\n/**\n * Output multiple streams' contents in order (from an array/iterable of stream\n * sources)\n *\n * Streams are concatenated in order -- note that this means they need to not be\n * infinite if any subsequent streams are to be processed! The output is closed\n * when all sources are finished or if any source throws (in which case the\n * error propagates to the subscriber).\n *\n * Note: this function is just shorthand for {@link concatAll}({@link fromIterable}(*sources*)).\n *\n * @category Stream Operators\n */\nexport function concat<T>(sources: Stream<T>[] | Iterable<Stream<T>>): Source<T> {\n return concatAll(fromIterable(sources))\n}\n\n/**\n * Flatten a source of sources by emitting their contents in series\n *\n * Streams are concatenated in order -- note that this means they need to not be\n * infinite if any subsequent streams are to be processed! The output is closed\n * when all sources are finished or if any source throws (in which case the\n * error propagates to the subscriber).\n *\n * If you want to switch to a new stream whenever a new source arrives from the\n * input stream, use {@link switchAll} instead.\n *\n * @category Stream Operators\n */\nexport function concatAll<T>(sources: Stream<Stream<T>>): Source<T> {\n return (sink, conn=start(), inlet) => {\n let inner: Connection;\n const inputs: Stream<T>[] = [], t = throttle();\n let outer = conn.connect(sources, s => {\n inputs.push(s); startNext(); t.pause();\n }, t).do(r => {\n outer = undefined\n inputs.length || inner || !isValue(r) || conn.return();\n });\n function startNext() {\n inner ||= conn.connect(inputs.shift(), sink, inlet).do(r => {\n inner = undefined;\n inputs.length ? startNext() : (outer ? t.resume() : !isValue(r) || conn.return());\n });\n }\n return IsStream;\n }\n}\n\n/**\n * Map each value of a stream to a substream, then concatenate the resulting\n * substreams\n *\n * (This is just shorthand for `compose(map(mapper), concatAll)`.)\n *\n * If you want to switch to a new stream whenever a new event arrives on the\n * input stream, use {@link switchMap} instead.\n *\n * @category Stream Operators\n */\nexport function concatMap<T,R>(mapper: (v: T, idx: number) => Stream<R>): Transformer<T,R> {\n return src => concatAll(map(mapper)(src))\n}\n\n\n/**\n * Create a subset of a stream, based on a filter function (like Array.filter)\n *\n * The filter function receives the current index (zero-based) as well as the\n * current value. If it returns truth, the value will be passed to the output,\n * otherwise it will be skipped.\n *\n * If the filter function is typed as a Typescript type guard (i.e. as returning\n * `v is SomeType`), then the resulting source will be typed as\n * Source<SomeType>.\n *\n * @category Stream Operators\n */\nexport function filter<T,R extends T>(filter: (v: T, idx: number) => v is R): Transformer<T,R>;\nexport function filter<T>(filter: (v: T, idx: number) => boolean): Transformer<T>;\nexport function filter<T>(filter: (v: T, idx: number) => boolean): Transformer<T> {\n return src => (sink, conn, inlet) => {\n let idx = 0; return src(v => filter(v, idx++) && sink(v), conn, inlet);\n }\n}\n\n/**\n * Replace each value in a stream using a function (like Array.map)\n *\n * The mapping function receives the current index (zero-based) as well as the\n * current value.\n *\n * @category Stream Operators\n */\nexport function map<T,R>(mapper: (v: T, idx: number) => R): Transformer<T,R> {\n return src => (sink, conn, inlet) => {\n let idx = 0; return src(v => sink(mapper(v, idx++)), conn, inlet);\n }\n}\n\n/**\n * Create an event source by merging an array or iterable of event sources.\n *\n * The resulting source issues events whenever any of the input sources do, and\n * closes once they all do (or throws if any of them do).\n *\n * @category Stream Operators\n */\nexport function merge<T>(sources: Stream<T>[] | Iterable<Stream<T>>): Source<T> {\n return mergeAll(fromIterable(sources));\n}\n\n/**\n * Create an event source by merging sources from a stream of event sources\n *\n * The resulting source issues events whenever any of the input sources do, and\n * closes once they all do (or throws if any of them do).\n *\n * @category Stream Operators\n */\nexport function mergeAll<T>(sources: Stream<Stream<T>>): Source<T> {\n return (sink, conn=start(), inlet) => {\n const uplinks: Set<Connection> = new Set;\n let outer = conn.connect(sources, (s) => {\n const c = conn.connect(s, sink, inlet).do(r => {\n uplinks.delete(c);\n uplinks.size || outer || !isValue(r) || conn.return();\n });\n uplinks.add(c);\n }).do(r => {\n outer = undefined;\n uplinks.size || !isValue(r) || conn.return();\n });\n return IsStream;\n }\n}\n\n/**\n * Create an event source by merging sources created by mapping events to sources\n *\n * The resulting source issues events whenever any of the input sources do, and\n * closes once they all do (or throws if any of them do).\n *\n * (Note: this is just shorthand for `compose(map(mapper), mergeAll)`.)\n *\n * @category Stream Operators\n */\nexport function mergeMap<T,R>(mapper: (v: T, idx: number) => Stream<R>): Transformer<T,R> {\n return src => mergeAll(map(mapper)(src));\n}\n\n/**\n * Skip the first N items from a source\n *\n * (Equivalent to {@link skipWhile}() with a function that checks the index is < n.)\n *\n * @category Stream Operators\n */\nexport function skip<T>(n: number): Transformer<T> {\n return skipWhile((_, i) => i<n);\n}\n\n/**\n * Skip items from a stream until another source produces a value.\n *\n * If the notifier closes without producing a value, the output will\n * be empty. If the notifier throws, so will the output.\n *\n * @category Stream Operators\n */\nexport function skipUntil<T>(notifier: Stream<any>): Transformer<T> {\n return src => (sink, conn=start(), inlet) => {\n let taking = false;\n const c = conn.connect(notifier, () => { taking = true; c.end(); });\n return src(v => taking && sink(v), conn, inlet);\n }\n}\n\n/**\n * Skip items from a stream until a given condition is false, then output all\n * remaining items. The condition function is not called again once it returns\n * false.\n *\n * @category Stream Operators\n */\nexport function skipWhile<T>(condition: (v: T, index: number) => boolean) : Transformer<T> {\n return src => (sink, conn, inlet) => {\n let idx = 0, met = false;\n return src(v => (met ||= !condition(v, idx++)) && sink(v), conn, inlet);\n };\n}\n\n/**\n * Add job control and buffering to a stream\n *\n * This lets you block events from a stream that can't be paused, or allow for\n * some slack for a source that can sometimes get ahead of its sink.\n *\n * @param size The number of items to buffer when the sink is busy (i.e., the\n * sink is running or the connection is paused). If positive, the most recent N\n * items are kept (a \"sliding\" buffer), and if negative, the oldest N item are\n * kept (a \"dropping\" buffer). If zero, no items are buffered, and items are\n * dropped if received while the sink is busy.\n *\n * @param dropped Optional: a callback that will receive items when they are\n * dropped. (Useful for testing, performance instrumentation, error logging,\n * etc.)\n *\n * @category Stream Operators\n */\nexport function slack<T>(size: number, dropped: Sink<T> = noop): Transformer<T> {\n const max = Math.abs(size);\n return src => (sink, conn=start(), inlet) => {\n const buffer: T[] = [], ready = backpressure(inlet);\n let paused = false, draining = false;\n const t = throttle();\n conn.connect(src, v => {\n buffer.push(v);\n if (!draining && ready()) return drain();\n while (buffer.length > max) { dropped((size < 0) ? buffer.pop() : buffer.shift()); }\n if (buffer.length === max) { t.pause(); paused = true; }\n if (buffer.length) ready(drain);\n }, t).do(r => {\n if (isValue(r)) conn.return();\n });\n\n function drain() {\n draining = true;\n try {\n while(buffer.length) {\n sink(buffer.shift());\n if (paused && ready()) {\n paused = false; t.resume();\n }\n if (buffer.length && !ready()) {\n return ready(drain);\n }\n }\n } finally {\n draining = false;\n }\n }\n return IsStream;\n }\n}\n\n/**\n * Flatten a source of sources by emitting their contents until a new one\n * arrives.\n *\n * As each source arrives from the input stream, its values are sent to the\n * output, closing the previous one (if any). The output is closed when both\n * the input stream and the most-recently-arrived stream are finished. Errors\n * propagate to the output if any stream throws.\n *\n * (If you want to send *all* the values of each stream to the output without\n * stopping, input stream, use {@link concatAll} or {@link mergeAll} instead.)\n *\n * @category Stream Operators\n */\nexport function switchAll<T>(sources: Stream<Stream<T>>): Source<T> {\n return (sink, conn=start(), inlet) => {\n let inner: Connection;\n let outer = conn.connect(sources, s => {\n inner?.end();\n inner = conn.connect(s, sink, inlet).do(r => {\n inner = undefined;\n outer || !isValue(r) || conn.return();\n });\n }).do(r => {\n outer = undefined;\n inner || !isValue(r) || conn.return();\n });\n return IsStream;\n }\n}\n\n/**\n * Map each value of a stream to a substream, then output the resulting\n * substreams until a new value arrives.\n *\n * (This is just shorthand for `compose(map(mapper),`{@link switchAll `switchAll)`}.)\n *\n * (If you want to send *all* the values of each stream to the output without\n * stopping, input stream, use {@link concatMap} or {@link mergeMap} instead.)\n *\n * @category Stream Operators\n */\nexport function switchMap<T,R>(mapper: (v: T, idx: number) => Stream<R>): Transformer<T,R> {\n return src => switchAll(map(mapper)(src))\n}\n\n/**\n * Take the first N items from a source\n *\n * (Equivalent to {@link takeWhile}() with a function that checks the index is < n.)\n *\n * @category Stream Operators\n */\nexport function take<T>(n: number): Transformer<T> {\n return takeWhile((_, i) => i<n);\n}\n\n/**\n * Take items from a source until another source produces a value.\n *\n * If the notifier closes without producing a value, this will output all\n * elements of the input. But if the notifier throws, so will the output.\n *\n * @category Stream Operators\n */\nexport function takeUntil<T>(notifier: Stream<any>): Transformer<T> {\n return src => (sink, conn=start(), inlet) => {\n conn.connect(notifier, () => conn.return());\n return src(sink, conn, inlet);\n }\n}\n\n/**\n * Take items from a stream until a given condition is false, then close the\n * output. The condition function is not called again after it returns false.\n *\n * If the condition function is typed as a Typescript type guard (i.e. as\n * returning `v is SomeType`), then the resulting source will be typed as\n * Source<SomeType>.\n *\n * @category Stream Operators\n */\nexport function takeWhile<T,R extends T>(condition: (v: T, idx: number) => v is R): Transformer<T,R>;\nexport function takeWhile<T>(condition: (v: T, idx: number) => boolean): Transformer<T>;\nexport function takeWhile<T>(condition: (v: T, index: number) => boolean) : Transformer<T> {\n return src => (sink, conn, inlet) => {\n let idx = 0;\n return src(v => condition(v, idx++) ? sink(v) : conn?.return(), conn, inlet);\n };\n}\n"],"names":[],"mappings":"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"}
|
package/dist/shared.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Y as Yielding } from './types-N2ua11te.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tools for sharing tasks, values, services, etc., especially across job
|
|
5
|
+
* boundaries.
|
|
6
|
+
*
|
|
7
|
+
* @module uneventful/shared
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Wrap a factory function to create a singleton service accessor
|
|
12
|
+
*
|
|
13
|
+
* The returned function, when called, will run the factory in a new job and
|
|
14
|
+
* cache the result. The job the factory ran in will end when the {@link root}
|
|
15
|
+
* job does, after which the cached result will be cleared.
|
|
16
|
+
*
|
|
17
|
+
* @param factory A function returning whatever result you want to share: a
|
|
18
|
+
* value, a function, an object, etc. It will be called at most once per root
|
|
19
|
+
* job lifetime, in a job that is an immediate child of the root job.
|
|
20
|
+
*
|
|
21
|
+
* (Note: if your factory is a native generator function, it is automatically
|
|
22
|
+
* wrapped with {@link fork}() so that its job will not end when the generator
|
|
23
|
+
* ends, and the result can be waited on by multiple callers. If your factory
|
|
24
|
+
* is *not* a native generator function but still returns a generator to produce
|
|
25
|
+
* an async result, you should wrap that generator with {@link fork} before
|
|
26
|
+
* returning it.)
|
|
27
|
+
*
|
|
28
|
+
* @remarks Note that if you want your code to be testable with {@link newRoot},
|
|
29
|
+
* you should avoid storing the *result* of calling the service accessor
|
|
30
|
+
* anywhere it can outlive the root job, since you will otherwise end up with a
|
|
31
|
+
* stale reference to the previous service instance *and* fail to initialize the
|
|
32
|
+
* new instance.
|
|
33
|
+
*
|
|
34
|
+
* Your services can detect this scenario, however, by having the factory wrap
|
|
35
|
+
* its return value with {@link expiring}(), which will make any access to a
|
|
36
|
+
* saved service value throw a TypeError after the root job ends. (Note that
|
|
37
|
+
* such a thing should not be necessary in your production builds, however,
|
|
38
|
+
* since at runtime you will normally only ever have one root job.)
|
|
39
|
+
*/
|
|
40
|
+
declare function service<T>(factory: () => T): () => T;
|
|
41
|
+
/**
|
|
42
|
+
* Proxy an object so it "expires" (becomes inaccessible) with the calling job.
|
|
43
|
+
*
|
|
44
|
+
* Any attempts to use the returned object after the job ends or restarts (other
|
|
45
|
+
* than to check its `typeof`) will result in a TypeError.
|
|
46
|
+
*
|
|
47
|
+
* Note: your runtime environment must support `Proxy.revocable()`.
|
|
48
|
+
*/
|
|
49
|
+
declare function expiring<T extends object>(obj: T): T;
|
|
50
|
+
/**
|
|
51
|
+
* Wrap a generator, generator function, or generator method to run in parallel
|
|
52
|
+
* and have a result that can be waited on in parallel as well.
|
|
53
|
+
*
|
|
54
|
+
* Normally, when you `yield *` to a generator in a job function, you're
|
|
55
|
+
* *pausing* the current function until that generator is finished. And
|
|
56
|
+
* normally, this is what you *want*, because you're not trying to do things in
|
|
57
|
+
* parallel. But if you *do* want to do things in parallel, you need `fork`.
|
|
58
|
+
*
|
|
59
|
+
* Generators also can't normally be *waited on* in parallel either: if multiple
|
|
60
|
+
* jobs try to wait on an unfinished generator, the most likely result is an
|
|
61
|
+
* error or data corruption. (Because the extra `yield *` operations will make
|
|
62
|
+
* the generator think it's received data it was waiting for, causing all kinds
|
|
63
|
+
* of havoc.)
|
|
64
|
+
*
|
|
65
|
+
* So if you want a generator to either *run* in parallel or be *waited on* in
|
|
66
|
+
* parallel (or both), you need to `fork` it: either on the consuming side by
|
|
67
|
+
* wrapping a generator with `fork()`, or on the producing side by wrapping a
|
|
68
|
+
* generator function (or decorating a generator method).
|
|
69
|
+
*
|
|
70
|
+
* When called with a generator, `fork` returns a wrapped generator; when called
|
|
71
|
+
* with a function, it returns a wrapped version of the function that will fork
|
|
72
|
+
* its results. And when used as a decorator (`@fork`, compatible with both
|
|
73
|
+
* TC39 and legacy decorator protocols), it wraps a method to fork its result as
|
|
74
|
+
* well.
|
|
75
|
+
*
|
|
76
|
+
* It is safe to call `fork()` more than once on the same generator, or to
|
|
77
|
+
* `fork()` an already-forked generator: the result will always be the same as
|
|
78
|
+
* the original fork.
|
|
79
|
+
*
|
|
80
|
+
* @remarks Note that while you can *also* make a generator run or be waitable
|
|
81
|
+
* in parallel using e.g. `start()`, the critical difference is in when resource
|
|
82
|
+
* cleanup happens. If you `start()` the generator (or wrap the generator
|
|
83
|
+
* function with `task`), its resources will be cleaned up when the generator
|
|
84
|
+
* function exits.
|
|
85
|
+
*
|
|
86
|
+
* With `yield*`, however (with or without `fork`), the resources are cleaned up
|
|
87
|
+
* when the original *calling* job ends. And this is what you want when the
|
|
88
|
+
* generator's return value is some kind of resource using other active
|
|
89
|
+
* resources (such as event listeners rules, etc.) that need to *remain* active
|
|
90
|
+
* for the caller.
|
|
91
|
+
*
|
|
92
|
+
* (If you're familiar with the Effection framework, you may recognize this as
|
|
93
|
+
* the difference between "actions" and "resources": in Uneventful we use
|
|
94
|
+
* `start()` or `task()` for generators that return the result of an action, and
|
|
95
|
+
* `fork` for generators that return a resource that will be owned by the
|
|
96
|
+
* calling job.)
|
|
97
|
+
*/
|
|
98
|
+
declare function fork<T>(gen: Yielding<T>): Yielding<T>;
|
|
99
|
+
declare function fork<T, F extends (...args: any[]) => Yielding<T>>(genFunc: F): F;
|
|
100
|
+
/** @hidden TC39 decorator */
|
|
101
|
+
declare function fork<T, F extends (...args: any[]) => Yielding<T>>(genFunc: F, ctx: {
|
|
102
|
+
kind: "method";
|
|
103
|
+
}): F;
|
|
104
|
+
/** @hidden legacy decorator */
|
|
105
|
+
declare function fork<T, F extends (...args: any[]) => Yielding<T>, D extends {
|
|
106
|
+
value?: F;
|
|
107
|
+
}>(clsOrProto: any, name: string | symbol, desc: D): D;
|
|
108
|
+
|
|
109
|
+
export { expiring, fork, service };
|
package/dist/shared.mjs
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { c as root, m as must, s as start, n as noop } from './jobutils-CmHay7sf.mjs';
|
|
2
|
+
import { a as isGeneratorFunction, b as decorateMethod, i as isFunction, c as apply, s as setMap } from './utils-DnMz1K-o.mjs';
|
|
3
|
+
|
|
4
|
+
function service(factory) {
|
|
5
|
+
let known = false, value = void 0;
|
|
6
|
+
if (isGeneratorFunction(factory))
|
|
7
|
+
factory = fork(factory);
|
|
8
|
+
return () => {
|
|
9
|
+
if (known)
|
|
10
|
+
return value;
|
|
11
|
+
root.start(() => {
|
|
12
|
+
value = factory();
|
|
13
|
+
known = true;
|
|
14
|
+
must(() => {
|
|
15
|
+
value = void 0;
|
|
16
|
+
known = false;
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
return value;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function expiring(obj) {
|
|
23
|
+
const p = Proxy.revocable(obj, {});
|
|
24
|
+
must(p.revoke);
|
|
25
|
+
return p.proxy;
|
|
26
|
+
}
|
|
27
|
+
function fork(genOrFunc, ...args) {
|
|
28
|
+
if (args.length)
|
|
29
|
+
return decorateMethod(fork, genOrFunc, ...args);
|
|
30
|
+
if (isFunction(genOrFunc))
|
|
31
|
+
return function(...args2) {
|
|
32
|
+
return fork(apply(genOrFunc, this, args2));
|
|
33
|
+
};
|
|
34
|
+
else {
|
|
35
|
+
if (forks.has(genOrFunc))
|
|
36
|
+
return forks.get(genOrFunc);
|
|
37
|
+
const job = start();
|
|
38
|
+
start(function* run() {
|
|
39
|
+
try {
|
|
40
|
+
job.return(yield* genOrFunc);
|
|
41
|
+
} catch (e) {
|
|
42
|
+
job.throw(e);
|
|
43
|
+
}
|
|
44
|
+
yield noop;
|
|
45
|
+
});
|
|
46
|
+
const it = { [Symbol.iterator]: job[Symbol.iterator].bind(job) };
|
|
47
|
+
return setMap(forks, it, setMap(forks, genOrFunc, it));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const forks = /* @__PURE__ */ new WeakMap();
|
|
51
|
+
|
|
52
|
+
export { expiring, fork, service };
|
|
53
|
+
//# sourceMappingURL=shared.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.mjs","sources":["../src/shared.ts"],"sourcesContent":["/**\n * Tools for sharing tasks, values, services, etc., especially across job\n * boundaries.\n *\n * @module uneventful/shared\n */\n\nimport { must, start } from \"./jobutils.ts\";\nimport { noop } from \"./results.ts\";\nimport { root, newRoot } from \"./tracking.ts\";\nimport { JobIterator, Yielding } from \"./types.ts\";\nimport { apply, decorateMethod, isFunction, isGeneratorFunction, setMap } from \"./utils.ts\";\n\n/**\n * Wrap a factory function to create a singleton service accessor\n *\n * The returned function, when called, will run the factory in a new job and\n * cache the result. The job the factory ran in will end when the {@link root}\n * job does, after which the cached result will be cleared.\n *\n * @param factory A function returning whatever result you want to share: a\n * value, a function, an object, etc. It will be called at most once per root\n * job lifetime, in a job that is an immediate child of the root job.\n *\n * (Note: if your factory is a native generator function, it is automatically\n * wrapped with {@link fork}() so that its job will not end when the generator\n * ends, and the result can be waited on by multiple callers. If your factory\n * is *not* a native generator function but still returns a generator to produce\n * an async result, you should wrap that generator with {@link fork} before\n * returning it.)\n *\n * @remarks Note that if you want your code to be testable with {@link newRoot},\n * you should avoid storing the *result* of calling the service accessor\n * anywhere it can outlive the root job, since you will otherwise end up with a\n * stale reference to the previous service instance *and* fail to initialize the\n * new instance.\n *\n * Your services can detect this scenario, however, by having the factory wrap\n * its return value with {@link expiring}(), which will make any access to a\n * saved service value throw a TypeError after the root job ends. (Note that\n * such a thing should not be necessary in your production builds, however,\n * since at runtime you will normally only ever have one root job.)\n */\nexport function service<T>(factory: () => T): () => T {\n let known = false, value: T = undefined;\n if (isGeneratorFunction<JobIterator<any>>(factory)) factory = fork(factory)\n return () => {\n if (known) return value\n root.start(() => {\n value = factory()\n known = true\n must(() => { value = undefined; known = false; })\n })\n return value\n }\n}\n\n/**\n * Proxy an object so it \"expires\" (becomes inaccessible) with the calling job.\n *\n * Any attempts to use the returned object after the job ends or restarts (other\n * than to check its `typeof`) will result in a TypeError.\n *\n * Note: your runtime environment must support `Proxy.revocable()`.\n */\nexport function expiring<T extends object>(obj: T): T {\n const p = Proxy.revocable(obj, {})\n must(p.revoke)\n return p.proxy\n}\n\n/**\n * Wrap a generator, generator function, or generator method to run in parallel\n * and have a result that can be waited on in parallel as well.\n *\n * Normally, when you `yield *` to a generator in a job function, you're\n * *pausing* the current function until that generator is finished. And\n * normally, this is what you *want*, because you're not trying to do things in\n * parallel. But if you *do* want to do things in parallel, you need `fork`.\n *\n * Generators also can't normally be *waited on* in parallel either: if multiple\n * jobs try to wait on an unfinished generator, the most likely result is an\n * error or data corruption. (Because the extra `yield *` operations will make\n * the generator think it's received data it was waiting for, causing all kinds\n * of havoc.)\n *\n * So if you want a generator to either *run* in parallel or be *waited on* in\n * parallel (or both), you need to `fork` it: either on the consuming side by\n * wrapping a generator with `fork()`, or on the producing side by wrapping a\n * generator function (or decorating a generator method).\n *\n * When called with a generator, `fork` returns a wrapped generator; when called\n * with a function, it returns a wrapped version of the function that will fork\n * its results. And when used as a decorator (`@fork`, compatible with both\n * TC39 and legacy decorator protocols), it wraps a method to fork its result as\n * well.\n *\n * It is safe to call `fork()` more than once on the same generator, or to\n * `fork()` an already-forked generator: the result will always be the same as\n * the original fork.\n *\n * @remarks Note that while you can *also* make a generator run or be waitable\n * in parallel using e.g. `start()`, the critical difference is in when resource\n * cleanup happens. If you `start()` the generator (or wrap the generator\n * function with `task`), its resources will be cleaned up when the generator\n * function exits.\n *\n * With `yield*`, however (with or without `fork`), the resources are cleaned up\n * when the original *calling* job ends. And this is what you want when the\n * generator's return value is some kind of resource using other active\n * resources (such as event listeners rules, etc.) that need to *remain* active\n * for the caller.\n *\n * (If you're familiar with the Effection framework, you may recognize this as\n * the difference between \"actions\" and \"resources\": in Uneventful we use\n * `start()` or `task()` for generators that return the result of an action, and\n * `fork` for generators that return a resource that will be owned by the\n * calling job.)\n */\nexport function fork<T>(gen: Yielding<T>): Yielding<T>\nexport function fork<T, F extends (...args: any[]) => Yielding<T>>(genFunc: F): F\n/** @hidden TC39 decorator */\nexport function fork<T, F extends (...args: any[]) => Yielding<T>>(genFunc: F, ctx: {kind: \"method\"}): F\n/** @hidden legacy decorator */\nexport function fork<T, F extends (...args: any[]) => Yielding<T>, D extends {value?: F}>(clsOrProto:any, name: string|symbol, desc: D): D\n\n// Implementation\nexport function fork<T, F extends (...args: any[]) => Yielding<T>>(\n genOrFunc:Yielding<T> | ((...args: any[]) => Yielding<T>), ...args: any[]\n) {\n if (args.length) return decorateMethod(fork, genOrFunc, ...args as [any, any]);\n if (isFunction(genOrFunc)) return (function(this: any, ...args: Parameters<F>) {\n return fork(apply(genOrFunc, this, args))\n }) as F; else {\n if (forks.has(genOrFunc)) return forks.get(genOrFunc);\n const job = start<T>();\n start(function *run(){\n try { job.return(yield *genOrFunc); }\n catch(e) { job.throw(e); }\n yield noop; // suspend until canceled\n })\n const it = { [Symbol.iterator]: job[Symbol.iterator].bind(job) }\n return setMap(forks, it, setMap(forks, genOrFunc, it))\n }\n}\n\nconst forks = new WeakMap<Yielding<any>, Yielding<any>>()\n"],"names":[],"mappings":";;;AAIO,SAAS,OAAO,CAAC,OAAO,EAAE;AACjC,EAAE,IAAI,KAAK,GAAG,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC;AACpC,EAAE,IAAI,mBAAmB,CAAC,OAAO,CAAC;AAClC,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;AAC5B,EAAE,OAAO,MAAM;AACf,IAAI,IAAI,KAAK;AACb,MAAM,OAAO,KAAK,CAAC;AACnB,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM;AACrB,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;AACxB,MAAM,KAAK,GAAG,IAAI,CAAC;AACnB,MAAM,IAAI,CAAC,MAAM;AACjB,QAAQ,KAAK,GAAG,KAAK,CAAC,CAAC;AACvB,QAAQ,KAAK,GAAG,KAAK,CAAC;AACtB,OAAO,CAAC,CAAC;AACT,KAAK,CAAC,CAAC;AACP,IAAI,OAAO,KAAK,CAAC;AACjB,GAAG,CAAC;AACJ,CAAC;AACM,SAAS,QAAQ,CAAC,GAAG,EAAE;AAC9B,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACrC,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AACjB,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC;AACjB,CAAC;AACM,SAAS,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,EAAE;AACzC,EAAE,IAAI,IAAI,CAAC,MAAM;AACjB,IAAI,OAAO,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,CAAC;AACpD,EAAE,IAAI,UAAU,CAAC,SAAS,CAAC;AAC3B,IAAI,OAAO,SAAS,GAAG,KAAK,EAAE;AAC9B,MAAM,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;AACjD,KAAK,CAAC;AACN,OAAO;AACP,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;AAC5B,MAAM,OAAO,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAClC,IAAI,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC;AACxB,IAAI,KAAK,CAAC,UAAU,GAAG,GAAG;AAC1B,MAAM,IAAI;AACV,QAAQ,GAAG,CAAC,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC;AACrC,OAAO,CAAC,OAAO,CAAC,EAAE;AAClB,QAAQ,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACrB,OAAO;AACP,MAAM,MAAM,IAAI,CAAC;AACjB,KAAK,CAAC,CAAC;AACP,IAAI,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACrE,IAAI,OAAO,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,GAAG;AACH,CAAC;AACD,MAAM,KAAK,mBAAmB,IAAI,OAAO,EAAE;;;;"}
|
package/dist/signals.d.ts
CHANGED
|
@@ -131,6 +131,9 @@ interface RuleFactory {
|
|
|
131
131
|
*/
|
|
132
132
|
factory(scheduleFn: SchedulerFn): RuleFactory;
|
|
133
133
|
/**
|
|
134
|
+
* @deprecated Use {@link RuleFactory.root} instead
|
|
135
|
+
*
|
|
136
|
+
* ---
|
|
134
137
|
* Create a "detached" or standalone rule, that is not attached to any job.
|
|
135
138
|
*
|
|
136
139
|
* `r.detached(fn)` is shorthand for calling `detached.run(r, fn)`. (Where
|
|
@@ -141,6 +144,17 @@ interface RuleFactory {
|
|
|
141
144
|
* by the rule function arranging to stop itself via {@link rule.stop}().
|
|
142
145
|
*/
|
|
143
146
|
detached(fn: () => OptionalCleanup): DisposeFn;
|
|
147
|
+
/**
|
|
148
|
+
* Create a standalone rule, not attached to the current job.
|
|
149
|
+
*
|
|
150
|
+
* `r.root(fn)` is shorthand for calling `root.run(r, fn)`, where `r` is a
|
|
151
|
+
* {@link RuleFactory} such as `rule`.
|
|
152
|
+
*
|
|
153
|
+
* The created rule will run until the {@link root} job stops, unless
|
|
154
|
+
* explicitly stopped. (Either by calling the returned disposal function or
|
|
155
|
+
* by the rule function arranging to stop itself via {@link rule.stop}().)
|
|
156
|
+
*/
|
|
157
|
+
root(fn: () => OptionalCleanup): DisposeFn;
|
|
144
158
|
/**
|
|
145
159
|
* Change the scheduler used for the currently-executing rule. Throws an
|
|
146
160
|
* error if no rule is running.
|
|
@@ -171,7 +185,7 @@ interface RuleFactory {
|
|
|
171
185
|
* {@link rule.stop}() from within the rule function.
|
|
172
186
|
*
|
|
173
187
|
* Note: this function will throw an error if called without an active job. If
|
|
174
|
-
* you need a standalone rule, use {@link RuleFactory.
|
|
188
|
+
* you need a standalone rule, use {@link RuleFactory.root rule.root}().
|
|
175
189
|
*
|
|
176
190
|
* @param fn The function that will be run each time its dependencies change.
|
|
177
191
|
* The function will be run in a restarted job each time, with any resources
|
|
@@ -327,9 +341,16 @@ interface Writable<T> extends Signal<T> {
|
|
|
327
341
|
* @category Writing
|
|
328
342
|
*/
|
|
329
343
|
readonly set: (val: T) => void;
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
|
|
344
|
+
value: T;
|
|
345
|
+
/**
|
|
346
|
+
* Update the current value with a patch function
|
|
347
|
+
*
|
|
348
|
+
* Note: this reads the signal's current value, which may produce a write
|
|
349
|
+
* conflict or circular dependency if you call it from inside a rule.
|
|
350
|
+
*
|
|
351
|
+
* @category Writing
|
|
352
|
+
*/
|
|
353
|
+
edit(patch: (before: T) => T): void;
|
|
333
354
|
}
|
|
334
355
|
/**
|
|
335
356
|
* A writable signal that can be set to either a value or an expression.
|
package/dist/signals.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { b as
|
|
1
|
+
import { F as swapCtx, G as nullCtx, k as current, H as makeCtx, w as makeJob, c as root, f as isError, e as markHandled, g as getJob, x as detached, o as reject, b as resolve, I as freeCtx } from './jobutils-CmHay7sf.mjs';
|
|
2
|
+
import { b as backpressure, I as IsStream, a as callOrWait } from './call-or-wait-DORP7nkp.mjs';
|
|
3
|
+
import { e as batch, f as arrayEq, d as defer, c as apply, s as setMap, C as CallableObject } from './utils-DnMz1K-o.mjs';
|
|
3
4
|
|
|
4
5
|
const ruleQueues = /* @__PURE__ */ new WeakMap();
|
|
5
6
|
function ruleQueue(scheduleFn = defer) {
|
|
@@ -399,7 +400,10 @@ class Cell {
|
|
|
399
400
|
}
|
|
400
401
|
getJob() {
|
|
401
402
|
this.flags |= 64 /* Stateful */;
|
|
402
|
-
return this.ctx.job ||= makeJob()
|
|
403
|
+
return this.ctx.job ||= makeJob(root, () => {
|
|
404
|
+
this.ctx.job?.end();
|
|
405
|
+
this.ctx.job = void 0;
|
|
406
|
+
});
|
|
403
407
|
}
|
|
404
408
|
updateDemand() {
|
|
405
409
|
demandChanges.delete(this);
|
|
@@ -427,7 +431,7 @@ class Cell {
|
|
|
427
431
|
}
|
|
428
432
|
if (job)
|
|
429
433
|
return;
|
|
430
|
-
job = ctx.job = makeJob().do((r) => {
|
|
434
|
+
job = ctx.job = makeJob(root).do((r) => {
|
|
431
435
|
if (isError(r)) {
|
|
432
436
|
cell.setValue(markHandled(r), true);
|
|
433
437
|
} else {
|
|
@@ -440,7 +444,7 @@ class Cell {
|
|
|
440
444
|
src(write, job);
|
|
441
445
|
} catch (e) {
|
|
442
446
|
job.end();
|
|
443
|
-
|
|
447
|
+
root.asyncThrow(e);
|
|
444
448
|
} finally {
|
|
445
449
|
swapCtx(old);
|
|
446
450
|
}
|
|
@@ -468,6 +472,7 @@ class Cell {
|
|
|
468
472
|
static mkRule(fn, q) {
|
|
469
473
|
const outer = getJob(), cell = Cell.mkCached(() => {
|
|
470
474
|
try {
|
|
475
|
+
cell.getJob();
|
|
471
476
|
const cleanup = fn();
|
|
472
477
|
if (cleanup)
|
|
473
478
|
(cell.ctx.job || cell.getJob()).must(cleanup);
|
|
@@ -520,6 +525,9 @@ class RF extends CallableObject {
|
|
|
520
525
|
detached(fn) {
|
|
521
526
|
return detached.run(this, fn);
|
|
522
527
|
}
|
|
528
|
+
root(fn) {
|
|
529
|
+
return root.run(this, fn);
|
|
530
|
+
}
|
|
523
531
|
setScheduler(scheduleFn) {
|
|
524
532
|
if (currentRule)
|
|
525
533
|
currentRule.setQ(scheduleFn ? ruleQueue(scheduleFn) : defaultQ);
|
|
@@ -619,6 +627,9 @@ class WritableImpl extends SignalImpl {
|
|
|
619
627
|
asReadonly() {
|
|
620
628
|
return new SignalImpl(this._c);
|
|
621
629
|
}
|
|
630
|
+
edit(patch) {
|
|
631
|
+
this.set(patch(this()));
|
|
632
|
+
}
|
|
622
633
|
}
|
|
623
634
|
class ConfigurableImpl extends WritableImpl {
|
|
624
635
|
setf(expr) {
|