Skip to content

jsxtools/explicit-resource-management

Repository files navigation

Explicit Resource Management Polyfills

Concise, clear polyfills for the TC39 Explicit Resource Management proposal, providing DisposableStack, AsyncDisposableStack, and SuppressedError.

Installation

npm install @jsxtools/explicit-resource-management

Usage

import { DisposableStack, AsyncDisposableStack, SuppressedError } from "@jsxtools/explicit-resource-management";

// Sync disposal
const stack = new DisposableStack();

const file = stack.use(openFile("example.txt"));
stack.defer(() => console.log("Cleanup complete"));

// Resources are disposed in reverse order
stack.dispose();

// Async disposal
const asyncStack = new AsyncDisposableStack();

const connection = asyncStack.use(await openConnection());
asyncStack.defer(async () => console.log("Async cleanup complete"));

await asyncStack.disposeAsync();

API

DisposableStack

A stack-based container for synchronous disposable resources.

Methods

  • use<T>(value: T): T - Adds a disposable resource (with Symbol.dispose) to the stack
  • adopt<T>(value: T, onDispose: (value: T) => void): T - Adds a non-disposable resource with a cleanup callback
  • defer(onDispose: () => void): void - Adds a cleanup callback to be called on disposal
  • move(): DisposableStack - Moves all resources to a new stack and marks this one as disposed
  • dispose(): void - Disposes all resources in reverse order

Properties

  • disposed: boolean - Whether the stack has been disposed

AsyncDisposableStack

A stack-based container for asynchronous disposable resources.

Methods

  • use<T>(value: T): T - Adds a disposable resource (with Symbol.asyncDispose or Symbol.dispose)
  • adopt<T>(value: T, onDisposeAsync: (value: T) => Promise<void>): T - Adds a resource with async cleanup
  • defer(onDisposeAsync: () => Promise<void>): void - Adds an async cleanup callback
  • move(): AsyncDisposableStack - Moves all resources to a new stack
  • disposeAsync(): Promise<void> - Disposes all resources asynchronously in reverse order

Properties

  • disposed: boolean - Whether the stack has been disposed

SuppressedError

An error type used to chain multiple errors that occur during resource disposal.

const error = new SuppressedError(new Error("disposal error"), new Error("suppressed error"), "optional message");

console.log(error.error); // Error: disposal error
console.log(error.suppressed); // Error: suppressed error

Features

  • ✅ Spec-compliant implementation of DisposableStack and AsyncDisposableStack
  • ✅ Proper error aggregation with SuppressedError
  • ✅ TypeScript support with full type definitions
  • ✅ Zero dependencies (assumes Symbol.dispose and Symbol.asyncDispose exist)
  • ✅ Concise, readable implementation (~230 lines total)

Requirements

This polyfill assumes that Symbol.dispose and Symbol.asyncDispose are already available in your environment. If they are not, you'll need to polyfill them first:

Symbol.dispose ??= Symbol("Symbol.dispose");
Symbol.asyncDispose ??= Symbol("Symbol.asyncDispose");

License

MIT-0

About

Polyfill for TC39 Explicit Resource Management (using and await using)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors