import { IDestroyable, IRemovable } from "@implab/core-amd/interfaces"; import { isDestroyable, isRemovable } from "@implab/core-amd/safe"; import { isUnsubscribable, Unsubscribable } from "../observable"; export interface IScope { own(target: (() => void) | IDestroyable | IRemovable | Unsubscribable): void; } const guard = (cb: () => void) => { try { cb(); } catch { // guard } }; export class Scope implements IDestroyable, IScope { private readonly _pending: (() => void)[] = []; private _disposed = false; static readonly dummy: IScope = { own() { } }; own(target: (() => void) | IDestroyable | IRemovable | Unsubscribable) { if (target instanceof Function) { this._own(target); } else if (isDestroyable(target)) { this._own(() => target.destroy()); } else if (isRemovable(target)) { this._own(() => target.remove()); } else if (isUnsubscribable(target)) { this._own(() => target.unsubscribe()); } } private _own(target: () => void) { if (this._disposed) guard(target); else this._pending.push(target); } clean() { this._pending.forEach(guard); this._pending.length = 0; } destroy() { if (!this._disposed) { this._disposed = true; this.clean(); } } }