"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.disposeSymbol = exports.asyncDisposeSymbol = exports.DisposableStack = exports.AsyncDisposableStack = void 0; exports.unwrapSuppressedErrors = unwrapSuppressedErrors; /** * Well-known `Symbol.dispose`. Resolves to the native well-known symbol when * the runtime ships the explicit resource management proposal; otherwise falls * back to `Symbol.for('Symbol.dispose')`, the same registry symbol used by the * fallback stacks below, so `DisposableStack#use` finds the method. * * Consumers should key dispose methods on this constant — * `class Foo { [disposeSymbol]() {} }` — rather than `Symbol.dispose`, so the * class works on runtimes without the proposal. */ const disposeSymbol = exports.disposeSymbol = typeof Symbol.dispose === 'symbol' ? Symbol.dispose : Symbol.for('Symbol.dispose'); /** * Well-known `Symbol.asyncDispose`. See {@link disposeSymbol} for the * native/fallback resolution rules. */ const asyncDisposeSymbol = exports.asyncDisposeSymbol = typeof Symbol.asyncDispose === 'symbol' ? Symbol.asyncDispose : Symbol.for('Symbol.asyncDispose'); /** Object disposable via {@link disposeSymbol}. Mirrors `Disposable` from `esnext.disposable`. */ /** Object disposable via {@link asyncDisposeSymbol}. Mirrors `AsyncDisposable` from `esnext.disposable`. */ /** * Mirrors the `DisposableStack` interface from `esnext.disposable`, declared * locally so consumers don't need that lib in their TypeScript config. */ /** * Mirrors the `AsyncDisposableStack` interface from `esnext.disposable`, declared * locally so consumers don't need that lib in their TypeScript config. */ const NativeSuppressedError = typeof SuppressedError === 'function' ? SuppressedError : undefined; /** * Builds a `SuppressedError` (native when available, otherwise a compatible * `{ error, suppressed }` Error) so {@link unwrapSuppressedErrors} can flatten * the chain produced when several disposers throw. */ function createSuppressedError(error, suppressed) { if (NativeSuppressedError) { return new NativeSuppressedError(error, suppressed); } const wrapper = /* minify-error-disabled */new Error('An error was suppressed during disposal.'); return Object.assign(wrapper, { name: 'SuppressedError', error, suppressed }); } function assertNotDisposed(disposed) { if (disposed) { throw /* minify-error-disabled */new ReferenceError('MUI X: The disposable stack is disposed.'); } } /** * Minimal fallback for `DisposableStack`, used on runtimes that do not ship the * explicit resource management proposal. Implements the subset of the proposal * MUI X uses — `use`, `adopt`, `defer`, `move`, `dispose`, `disposed` and * `[Symbol.dispose]` — so the `core-js-pure` ponyfill no longer has to be bundled. */ class FallbackDisposableStack { stack = []; isDisposed = false; get disposed() { return this.isDisposed; } use(value) { assertNotDisposed(this.isDisposed); if (value != null) { const method = value[disposeSymbol]; if (typeof method !== 'function') { throw /* minify-error-disabled */new TypeError('MUI X: The value is not disposable.'); } this.stack.push(() => method.call(value)); } return value; } adopt(value, onDispose) { assertNotDisposed(this.isDisposed); this.stack.push(() => onDispose(value)); return value; } defer(onDispose) { assertNotDisposed(this.isDisposed); this.stack.push(onDispose); } move() { assertNotDisposed(this.isDisposed); const next = new FallbackDisposableStack(); next.stack = this.stack; this.stack = []; this.isDisposed = true; return next; } dispose() { if (this.isDisposed) { return; } this.isDisposed = true; let hasError = false; let error; // Dispose in reverse (LIFO) order, aggregating failures into a SuppressedError chain. for (let i = this.stack.length - 1; i >= 0; i -= 1) { try { this.stack[i](); } catch (caught) { error = hasError ? createSuppressedError(caught, error) : caught; hasError = true; } } this.stack = []; if (hasError) { throw error; } } [disposeSymbol]() { this.dispose(); } } /** * Minimal fallback for `AsyncDisposableStack`. See {@link FallbackDisposableStack}; * disposers may return promises and are awaited sequentially in LIFO order. */ class FallbackAsyncDisposableStack { stack = []; isDisposed = false; get disposed() { return this.isDisposed; } use(value) { assertNotDisposed(this.isDisposed); if (value != null) { const record = value; const method = record[asyncDisposeSymbol] ?? record[disposeSymbol]; if (typeof method !== 'function') { throw /* minify-error-disabled */new TypeError('MUI X: The value is not async disposable.'); } this.stack.push(() => method.call(value)); } return value; } adopt(value, onDisposeAsync) { assertNotDisposed(this.isDisposed); this.stack.push(() => onDisposeAsync(value)); return value; } defer(onDisposeAsync) { assertNotDisposed(this.isDisposed); this.stack.push(onDisposeAsync); } move() { assertNotDisposed(this.isDisposed); const next = new FallbackAsyncDisposableStack(); next.stack = this.stack; this.stack = []; this.isDisposed = true; return next; } async disposeAsync() { if (this.isDisposed) { return; } this.isDisposed = true; let hasError = false; let error; for (let i = this.stack.length - 1; i >= 0; i -= 1) { try { // eslint-disable-next-line no-await-in-loop await this.stack[i](); } catch (caught) { error = hasError ? createSuppressedError(caught, error) : caught; hasError = true; } } this.stack = []; if (hasError) { throw error; } } [asyncDisposeSymbol]() { return this.disposeAsync(); } } /** * Spec-compliant `DisposableStack`. Prefers the platform's native class when * present; falls back to a minimal built-in implementation otherwise. */ // eslint-disable-next-line @typescript-eslint/no-redeclare const DisposableStack = exports.DisposableStack = globalThis.DisposableStack ?? FallbackDisposableStack; /** * Spec-compliant `AsyncDisposableStack`. Prefers the platform's native class * when present; falls back to a minimal built-in implementation otherwise. */ // eslint-disable-next-line @typescript-eslint/no-redeclare const AsyncDisposableStack = exports.AsyncDisposableStack = globalThis.AsyncDisposableStack ?? FallbackAsyncDisposableStack; /** * Unwraps a `SuppressedError` chain (as produced by `DisposableStack.dispose()` * when multiple disposers throw) into a flat list, outermost failure first. * Returns `[error]` unchanged if it isn't a `SuppressedError`. */ function unwrapSuppressedErrors(error) { const failures = []; let current = error; while (typeof current === 'object' && current !== null && 'error' in current && 'suppressed' in current) { failures.push(current.error); current = current.suppressed; } failures.push(current); return failures; }