ECMAScript: Explicit resource management

Note

These are only built-ins for Explicit Resource Management; the using syntax requires transpiler support.

Modules

es.disposable-stack.constructor, es.iterator.dispose, es.async-disposable-stack.constructor, es.async-iterator.async-dispose, es.suppressed-error.constructor, es.symbol.async-dispose, es.symbol.dispose.

Built-ins signatures

class Symbol {
  static asyncDispose: @@asyncDispose;
  static dispose: @@dispose;
}

class DisposableStack {
  constructor(): DisposableStack;
  readonly attribute disposed: boolean;
  dispose(): undefined;
  use(value: Disposable): value;
  adopt(value: object, onDispose: Function): value;
  defer(onDispose: Function): undefined;
  move(): DisposableStack;
  @@dispose(): undefined;
  @@toStringTag: 'DisposableStack';
}

class AsyncDisposableStack {
  constructor(): AsyncDisposableStack;
  readonly attribute disposed: boolean;
  disposeAsync(): Promise<undefined>;
  use(value: AsyncDisposable | Disposable): value;
  adopt(value: object, onDispose: Function): value;
  defer(onDispose: Function): undefined;
  move(): AsyncDisposableStack;
  @@asyncDispose(): Promise<undefined>;
  @@toStringTag: 'AsyncDisposableStack';
}

class SuppressedError extends Error {
  constructor(error: any, suppressed: any, message?: string): SuppressedError;
  error: any;
  suppressed: any;
  message: string;
}

class Iterator {
  @@dispose(): undefined;
}

class AsyncIterator {
  @@asyncDispose(): Promise<undefined>;
}

Entry points

{ core-js, @core-js/pure }/es|stable|actual|full/disposable-stack
{ core-js, @core-js/pure }/es|stable|actual|full/async-disposable-stack
{ core-js, @core-js/pure }/es|stable|actual|full/suppressed-error
{ core-js, @core-js/pure }/es|stable|actual|full/symbol/async-dispose
{ core-js, @core-js/pure }/es|stable|actual|full/symbol/dispose

Examples

const stack = new DisposableStack();
stack.use({
  [Symbol.dispose]() {
    console.log('resource disposed');
  },
});
stack.defer(() => console.log('deferred cleanup'));
stack.adopt(42, value => console.log(`${ value } released`));

stack.disposed; // => false
stack.dispose(); // => '42 released', 'deferred cleanup', 'resource disposed'
stack.disposed; // => true

const failing = new DisposableStack();
failing.defer(() => {
  throw new Error('first');
});
failing.defer(() => {
  throw new Error('second');
});
try {
  failing.dispose();
} catch (error) {
  error instanceof SuppressedError; // => true
  error.error.message;              // => 'first'
  error.suppressed.message;         // => 'second'
}

const asyncStack = new AsyncDisposableStack();
asyncStack.defer(async () => console.log('async cleanup'));
await asyncStack.disposeAsync(); // => 'async cleanup'

function * gen() {
  try {
    yield 1;
  } finally {
    console.log('iterator closed');
  }
}
const iterator = gen();
iterator.next();
iterator[Symbol.dispose](); // => 'iterator closed'