Wrap a function to always run in this context.
The function to wrap
A function with the same signature/overloads, but which will run in this context when called. (Note: signal dependency tracking will be disabled for the duration of the call, as if it had been wrapped with peek().)
Note that if the supplied function has any custom properties, they will not be available on the returned function at runtime, even though TypeScript will act as if they are present at compile time. This is because the only way to copy all overloads of a function signature is to copy the exact type (as TypeScript has no way to generically say, "this is a function with all the same overloads, but none of the properties").
Subscribe a sink to a stream, starting a task that ends when the stream does (and can be canceled to unsubscribe).
This is basically shorthand for start<void>(work => void src(sink, work, inlet)) -- i.e. a quick way to subscribe to a finite and/or pausable stream.
a Task that can be used to detect the stream end/error, or end()ed to close it early.
ReadonlyendRelease all resources held by the task or context.
Arrange for all cleanup functions and result consumers added to the context (via release, must, do, etc.) be called in the appropriate order. When the call to end() returns, all child tasks will have been notified of their cancellation. (But not all of their cleanups or result consumers may have run yet, in the event that another task's end() is in progress when this method is called.)
If any cleanup callbacks throw exceptions, they're sent to
root.asyncThrow(), which by default converts them to unhandled promise
rejections. This ensures all of the callbacks will be run, even if one
throws an error. (And none of the errors will be missed.)
Note: this method is a bound function, so you can pass it as a callback to another task, event source, etc.
Invoke a function in this context, such that calling the global must function will add cleanup callbacks to it, start will create child tasks of it, etc. (Note: signal dependency tracking is disabled for the duration of the call, as if it had been wrapped with peek().)
The result of calling fn(...args)
Start a subtask in the context using the given ActivityFn or Eventual value.
ctx.start(activity) is roughly shorthand for calling
ctx.starting(activity).task(), or
ctx.starting().exec(activity).task(). That is,
it creates a new Work of the appropriate type, .exec()s the
activity in it, and returns the Task that will provide the work's
result.
However, unlike with .starting(), if the activity is an
Uneventful-supplied Task, the passed-in task is returned
unchanged rather than starting a new task.
If the activity is a function and it throws a synchronous error before
.start() returns, the new task will be canceled and the error rethrown.
The type of result the task will eventually produce. Defaults
to never if not given, meaning that the task will never end itself
(except via an error), and will only end when it is canceled or one of
its parent contexts ends or resets.
Create the Work of a new task, optionally starting activities in it
.starting(a1, a2, ...) is roughly equivalent to .start(work => work.exec(a1).exec(a2)...), except that the work is returned instead
of the task.
Zero or more activities for the new task's Work to .exec(). The first one to complete the task (via return/throw) will determine the overall task result; all others will be canceled.
If any of the startables synchronously completes (or throws a synchronous error) during the initial setup, the remaining startables will not be run. As with .start(), a synchronous error also cancels the partially-initialized task.
A Work context you can customize to set up its .task() or .future() with.
Set up a callback to receive unhandled errors from subtasks.
Setting an async-catch handler allows you to create robust parent tasks that log or report errors and restart either a single task or an entire group of them, in the event a subtask malfunctions in a way that's not caught elsewhere.
Either an error-receiving callback, or null. If null,
asyncThrow()n will "crash" the scope (i.e. throw() if it's a task) and
possibly be forwarded up to parent scopes as another asyncThrow(). If a
callback is given, it's called with this bound to the relevant context
instance when the scope asyncThrow()s.
Report an unhandled error from a child task.
If the context has an .asyncCatch() handler set, it will be called with the error, otherwise the context/task will end with the supplied error. If the error then isn't handled by a listener on the associated Future, the error will cascade to an asyncThrow on the context's parent context, until the root context and its asyncCatch handler are reached. (Which defaults to creating an unhandled promise rejection.)
Note: application code should not normally need to call this method directly, as it's automatically invoked on a task's parent if the task fails and has no error listeners. (That is, if a task's future isn't awaited by anything, listened to by anything, and has no onError handlers, and the task throw()s, then the error is automatically asyncThrow()n to the task's parent context.)
The error thrown by the child task
Create a checkpoint as a child context
(The new context will not automaticaly end when the parent does, but unhandled async errors will propagate to the parent if you don't give it an explicit asyncCatch handler.)
Returns true if the context is cleaning up due to completion, cancellation, or checkpoint .reset().
Cleanups added to the context while it is being cleaned up will be run later, after the caller returns (possibly in a different microtask). A context ended by return, throw, or cancellation will remain in a perpetual state of cleaning up, but a checkpoint that is .reset() will go back to returning false from this method once the reset completes.
Add a cleanup callback to be run when the context is ended or reset. (Non-function values are ignored.) If the context has already ended, the callback will be invoked asynchronously in the next microtask. Cleanup functions are run in LIFO order, after any Context.release() callbacks (including those of the context's children), but before any Future observers are run if the context is a task scope.
Generally speaking, this method is used within a task, state, reactive function, or other cleanup context to arrange for used resources to be cleaned up, or to undo other state that was only supposed to be active while the task, state, or effect was active.
Optionalcleanup: OptionalCleanupCreate a mutual-cleanup link with a resource that might be stopped or terminated in some way before the context ends. (Like a child process, a server connection, etc.)
If a task uses a lot of such resources, using Context.must callbacks to trigger each one would result in an ever growing number of callbacks (and uncollectable references to the no-longer-usable resources). So this method lets you remove a cleanup function when it's no longer needed: when the resource is closed or finished, invoking the callback returned by this method will remove the cleanup callback from the context, allowing the resource to be freed before the context cleans up, without accumulating an endless number of callbacks in the context. (Uneventful also uses this mechanism internally to link child contexts to their parents, so that serially-spawning subtasks don't leak cleanup callbacks.)
In order to ensure that all such "child" contexts, resources, and activities are marked as canceled before any side effects (such as events, callbacks or I/O operations) can occur, Uneventful prioritizes all release callbacks to run before any other callbacks of any kind. Since release callbacks are used for child tasks, this means that the entire context subtree is notified immediately of cancellation, before any other actions are taken. This ensures that no "stray" operations can continue, unaware that their context is cleaning up or ended.
This means, however, that release callbacks must do only simple actions that can't result in arbitrary code being synchronously run. (Some safe examples would be setting flags, cancelling event subscriptions, removing things from internal queues, etc.) Synchronously triggering events or other callbacks, however, runs the risk of that code doing things it wouldn't have done if it knew its context were canceled.
(Note that if you still need such actions to happen, your release callback can always add a new .Context.must() or .Future.do() callback at that point, and the callback will then get done during a later phase of cleanup, without losing the benefits of the mutual-cleanup process.)
A callback that should be used to remove the passed-in cleanup callback from the context, if the resource is disposed of before the context cleans up.
A cancellable cleanup context with configurable error-reporting scope