or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-lumino--disposable

TypeScript library implementing the disposable pattern for resource management with observable disposal events

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@lumino/disposable@2.1.x

To install, run

npx @tessl/cli install tessl/npm-lumino--disposable@2.1.0

index.mddocs/

Lumino Disposable

Lumino Disposable provides a comprehensive implementation of the disposable pattern for TypeScript/JavaScript applications, enabling proper resource management and cleanup in object-oriented code. It offers core interfaces and concrete implementations that allow developers to create objects that can be properly disposed of when no longer needed, with support for observable disposal events through the Lumino signaling system.

Package Information

  • Package Name: @lumino/disposable
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @lumino/disposable

Core Imports

import {
  IDisposable,
  IObservableDisposable,
  DisposableDelegate,
  ObservableDisposableDelegate,
  DisposableSet,
  ObservableDisposableSet
} from "@lumino/disposable";

For CommonJS:

const {
  IDisposable,
  IObservableDisposable,
  DisposableDelegate,
  ObservableDisposableDelegate,
  DisposableSet,
  ObservableDisposableSet
} = require("@lumino/disposable");

Basic Usage

import {
  DisposableDelegate,
  DisposableSet,
  ObservableDisposableDelegate
} from "@lumino/disposable";

// Create a simple disposable with a callback
const resource = new DisposableDelegate(() => {
  console.log("Resource cleaned up!");
});

// Create an observable disposable that signals when disposed
const observableResource = new ObservableDisposableDelegate(() => {
  console.log("Observable resource cleaned up!");
});

// Listen for disposal events
observableResource.disposed.connect(() => {
  console.log("Disposal event received!");
});

// Manage multiple disposables as a collection
const disposables = new DisposableSet();
disposables.add(resource);
disposables.add(observableResource);

// Dispose all resources at once (in order they were added)
disposables.dispose();

Architecture

Lumino Disposable is built around the disposable pattern with several key components:

  • Core Interfaces: IDisposable and IObservableDisposable define the basic disposable contract
  • Delegate Pattern: DisposableDelegate and ObservableDisposableDelegate wrap callback functions as disposable objects
  • Collection Management: DisposableSet and ObservableDisposableSet manage multiple disposables with ordered disposal
  • Observable Events: Observable variants emit signals when disposed, integrating with the Lumino signaling system
  • Safe Disposal: All dispose methods are safe to call multiple times and maintain proper cleanup order

Capabilities

Core Interfaces

Basic interfaces defining the disposable pattern contract.

/**
 * An object which implements the disposable pattern.
 */
interface IDisposable {
  /**
   * Test whether the object has been disposed.
   * This property is always safe to access.
   */
  readonly isDisposed: boolean;

  /**
   * Dispose of the resources held by the object.
   * If called more than once, subsequent calls are no-ops.
   * It is undefined behavior to use the object after disposal.
   */
  dispose(): void;
}

/**
 * A disposable object with an observable disposed signal.
 */
interface IObservableDisposable extends IDisposable {
  /**
   * A signal emitted when the object is disposed.
   */
  readonly disposed: ISignal<this, void>;
}

Disposable Delegate

Wraps a callback function as a disposable object, allowing functional cleanup code to participate in the disposable pattern.

/**
 * A disposable object which delegates to a callback function.
 */
class DisposableDelegate implements IDisposable {
  /**
   * Construct a new disposable delegate.
   * @param fn - The callback function to invoke on dispose
   */
  constructor(fn: () => void);

  /**
   * Test whether the delegate has been disposed.
   */
  readonly isDisposed: boolean;

  /**
   * Dispose of the delegate and invoke the callback function.
   * Safe to call multiple times.
   */
  dispose(): void;
}

Usage Examples:

import { DisposableDelegate } from "@lumino/disposable";

// Clean up event listeners
const disposable = new DisposableDelegate(() => {
  element.removeEventListener('click', handler);
});

// Clean up timers
const timer = new DisposableDelegate(() => {
  clearInterval(intervalId);
});

// Clean up resources
const resource = new DisposableDelegate(() => {
  connection.close();
  fileHandle.close();
});

// Dispose when done
resource.dispose(); // Callback is invoked
resource.dispose(); // Safe no-op

Observable Disposable Delegate

Observable version of DisposableDelegate that emits a signal when disposed, enabling reactive cleanup patterns.

/**
 * An observable disposable object which delegates to a callback function.
 */
class ObservableDisposableDelegate extends DisposableDelegate implements IObservableDisposable {
  /**
   * A signal emitted when the delegate is disposed.
   */
  readonly disposed: ISignal<this, void>;

  /**
   * Dispose of the delegate, invoke the callback, and emit the disposed signal.
   * Safe to call multiple times.
   */
  dispose(): void;
}

Usage Examples:

import { ObservableDisposableDelegate } from "@lumino/disposable";

const resource = new ObservableDisposableDelegate(() => {
  console.log("Resource cleaned up");
});

// React to disposal
resource.disposed.connect(() => {
  console.log("Disposal event received");
  updateUI();
});

resource.dispose();
// Output: "Resource cleaned up"
// Output: "Disposal event received"

Disposable Set

Manages a collection of disposable items, disposing them in insertion order when the set itself is disposed.

/**
 * An object which manages a collection of disposable items.
 */
class DisposableSet implements IDisposable {
  /**
   * Test whether the set has been disposed.
   */
  readonly isDisposed: boolean;

  /**
   * Dispose of the set and all items it contains.
   * Items are disposed in the order they were added.
   * Safe to call multiple times.
   */
  dispose(): void;

  /**
   * Test whether the set contains a specific item.
   * @param item - The item of interest
   * @returns true if the set contains the item, false otherwise
   */
  contains(item: IDisposable): boolean;

  /**
   * Add a disposable item to the set.
   * If the item is already in the set, this is a no-op.
   * @param item - The item to add to the set
   */
  add(item: IDisposable): void;

  /**
   * Remove a disposable item from the set without disposing it.
   * If the item is not in the set, this is a no-op.
   * @param item - The item to remove from the set
   */
  remove(item: IDisposable): void;

  /**
   * Remove all items from the set without disposing them.
   */
  clear(): void;
}

Usage Examples:

import { DisposableSet, DisposableDelegate } from "@lumino/disposable";

const disposables = new DisposableSet();

// Add individual disposables
disposables.add(new DisposableDelegate(() => cleanup1()));
disposables.add(new DisposableDelegate(() => cleanup2()));

// Check contents
const item = new DisposableDelegate(() => cleanup3());
disposables.add(item);
console.log(disposables.contains(item)); // true

// Remove without disposing
disposables.remove(item);
console.log(disposables.contains(item)); // false

// Dispose all remaining items in order
disposables.dispose();

Observable Disposable Set

Observable version of DisposableSet that emits a signal when the set is disposed.

/**
 * An observable object which manages a collection of disposable items.
 */
class ObservableDisposableSet extends DisposableSet implements IObservableDisposable {
  /**
   * A signal emitted when the set is disposed.
   */
  readonly disposed: ISignal<this, void>;

  /**
   * Dispose of the set, all contained items, and emit the disposed signal.
   * Items are disposed in insertion order.
   * Safe to call multiple times.
   */
  dispose(): void;
}

Static Factory Methods

Factory methods for creating disposable sets from iterables.

namespace DisposableSet {
  /**
   * Create a disposable set from an iterable of items.
   * @param items - The iterable object of interest
   * @returns A new disposable set initialized with the given items
   */
  function from(items: Iterable<IDisposable>): DisposableSet;
}

namespace ObservableDisposableSet {
  /**
   * Create an observable disposable set from an iterable of items.
   * @param items - The iterable object of interest
   * @returns A new observable disposable set initialized with the given items
   */
  function from(items: Iterable<IDisposable>): ObservableDisposableSet;
}

Usage Examples:

import { DisposableSet, ObservableDisposableSet } from "@lumino/disposable";

// Create from array
const items = [
  new DisposableDelegate(() => cleanup1()),
  new DisposableDelegate(() => cleanup2()),
  new DisposableDelegate(() => cleanup3())
];

const set1 = DisposableSet.from(items);
const set2 = ObservableDisposableSet.from(items);

// Listen for disposal on observable set
set2.disposed.connect(() => {
  console.log("All items disposed");
});

set2.dispose(); // Disposes all items in order and emits signal

Types

// Re-exported from @lumino/signaling
interface ISignal<T, U> {
  connect(slot: (sender: T, args: U) => void, thisArg?: any): void;
  disconnect(slot: (sender: T, args: U) => void, thisArg?: any): void;
  emit(args: U): void;
}

Error Handling

The package follows a fail-safe approach:

  • All dispose() methods are safe to call multiple times - subsequent calls are no-ops
  • Adding duplicate items to sets is a no-op
  • Removing non-existent items from sets is a no-op
  • Using objects after disposal results in undefined behavior (as documented)
  • Observable disposal events are emitted synchronously during the dispose() call