Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
0dfd71e
feat: Implement `Symbol.asyncDispose` on tasks to enable `await using…
joshamaju Jan 5, 2026
d884d25
Corrects formatting
joshamaju Jan 5, 2026
805ad9d
refactor: move `Symbol.dispose` from `Future` to `Task` interface.
joshamaju Jan 6, 2026
370541a
refactor: simplify Task's asyncDispose method implementation
joshamaju Jan 6, 2026
18e228d
refactor: remove await from task halt in test
joshamaju Jan 6, 2026
9bc8f78
refactor: relocate task error handler to outside `await using` block …
joshamaju Jan 6, 2026
2681228
fix: provide async dispose types
joshamaju Jan 9, 2026
d1acb33
feat: adds automatic scope closing for createScope
joshamaju Jan 9, 2026
6e40c44
roll back formatting changes
cowboyd Jan 14, 2026
7906f51
Move `AsyncDisposable` into `ScopeInternal`
cowboyd Jan 14, 2026
10a2f26
docs: adds documentation for `AsyncDisposable` support for `Task` and…
joshamaju Jan 15, 2026
1436bf0
feat: adds support for both normal variable assignment and destructur…
joshamaju Feb 6, 2026
2be74e4
refactor: update type definitions for createScope and improve test ca…
joshamaju Feb 9, 2026
ff59169
Merge branch 'v4' into native-disposable-resource
joshamaju Feb 9, 2026
9d889b7
chore: fix formating
joshamaju Feb 9, 2026
b736ceb
chore: fix formating
joshamaju Feb 9, 2026
3ef5fde
Merge branch 'native-disposable-resource' of https://github.com/josha…
joshamaju Feb 9, 2026
3a0fa1a
Merge branch 'native-disposable-resource' of https://github.com/josha…
joshamaju Feb 9, 2026
efb2591
Merge branch 'native-disposable-resource' of https://github.com/josha…
joshamaju Feb 9, 2026
8a0c134
✨ Explicit Resource Management for Task and Scope
joshamaju Jan 5, 2026
80f6b93
Merge branch 'native-disposable-resource' of https://github.com/josha…
joshamaju Feb 15, 2026
a0227b9
Add using() API with runtime validation and tests
joshamaju Feb 15, 2026
a8fd70c
chore: format
joshamaju Feb 15, 2026
72eefeb
chore: format
joshamaju Feb 15, 2026
669c458
Merge branch 'native-disposable-resource' of https://github.com/josha…
joshamaju Feb 15, 2026
f08cf53
Revert "Add using() API with runtime validation and tests"
joshamaju Feb 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions lib/task.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// <reference lib="esnext" />
// deno-lint-ignore-file no-unsafe-finally
import { DelimiterContext, ErrorContext } from "./delimiter.ts";
import { createCoroutine } from "./coroutine.ts";
Expand Down Expand Up @@ -74,6 +75,12 @@ export function createTask<T>(options: TaskOptions<T>): NewTask<T> {
enumerable: false,
value: "Task",
},
[Symbol.asyncDispose]: {
enumerable: false,
value: async function () {
return await this.halt();
},
},
}) as Task<T>;

let boundary = owner.expect(ErrorContext);
Expand Down
9 changes: 6 additions & 3 deletions lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ export interface Operation<T> {
* things, if the operation resolves synchronously, it will continue within the
* same tick of the run loop.
*/
export interface Future<T> extends Operation<T>, Promise<T> {}
export interface Future<T> extends Operation<T>, Promise<T> {
[Symbol.dispose](): void;
}

/**
* A handle to a concurrently running operation that lets you either use the
Expand Down Expand Up @@ -334,8 +336,9 @@ export interface Scope {
* Analogous to the built in [`Awaited`](https://www.typescriptlang.org/docs/handbook/utility-types.html#awaitedtype) type.
* `Yielded<Operation<T>> === T`
*/
export type Yielded<T extends Operation<unknown>> = T extends
Operation<infer TYield> ? TYield
export type Yielded<T extends Operation<unknown>> = T extends Operation<
infer TYield
> ? TYield
: never;

// low-level private apis.
Expand Down
49 changes: 46 additions & 3 deletions test/run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import {

describe("run()", () => {
it("can run an operation", async () => {
await expect(run(function* () {
return "hello";
})).resolves.toEqual("hello");
await expect(
run(function* () {
return "hello";
}),
).resolves.toEqual("hello");
});

it("can compose multiple promises via generator", async () => {
Expand Down Expand Up @@ -318,4 +320,45 @@ describe("run()", () => {
await expect(task).rejects.toHaveProperty("message", "boom!");
await expect(task.halt()).resolves.toBe(undefined);
});

it("can be disposed with 'await using'", async () => {
let halted = false;

let task = run(function* () {
try {
yield* suspend();
} finally {
halted = true;
}
});

{
await using _ = task;
}

expect(halted).toEqual(true);
});

it("should throw when 'halt' is invoked after 'await using'", async () => {
let halted = false;
let error: Error | undefined;

let task = run(function* () {
try {
yield* suspend();
} finally {
halted = true;
}
});

{
await using _ = task;
_.catch((e) => error = e);
await _.halt();
}

expect(error).toBeDefined();
expect(error?.message).toEqual("halted");
expect(halted).toEqual(true);
});
});
Loading