UNPKG

shelving

Version:

Toolkit for using data in JavaScript.

62 lines (61 loc) 1.77 kB
import { logError } from "./error.js"; import { isObject } from "./object.js"; /** * Temporary polyfill for `Symbol.dipose` value. * @todo Remove this once browsers support `Symbol.dispose` */ Symbol.dispose ??= Symbol("Symbol.dispose"); /** Safely dispose a disposable. */ export function dispose(value) { try { value[Symbol.dispose](); } catch (thrown) { logError(thrown); } } /** Is an unknown value a disposable object? */ export function isDisposable(v) { return isObject(v) && typeof v[Symbol.dispose] === "function"; } /** * Version of `Map` that is disposable. * - If items are `Disposable` they are disposed when they're deleted from the map. * - Set itself is `Disposable` to delete (and dispose) all items when the map itself is disposed. */ export class DisposableMap extends Map { delete(key) { if (this.has(key)) { const value = this.get(key); super.delete(key); if (isDisposable(value)) dispose(value); return true; } return false; } [Symbol.dispose]() { for (const key of this.keys()) this.delete(key); } } /** * Version of `Set` that is disposable. * - If items are `Disposable` they are disposed when they're deleted from the set. * - Set itself is `Disposable` to delete (and dispose) all items when the set itself is disposed. */ export class DisposableSet extends Set { delete(item) { if (this.has(item)) { super.delete(item); if (isDisposable(item)) dispose(item); return true; } return false; } [Symbol.dispose]() { for (const item of this) this.delete(item); } }