diff --git a/djx/src/main/ts/tsx/Scope.ts b/djx/src/main/ts/tsx/Scope.ts --- a/djx/src/main/ts/tsx/Scope.ts +++ b/djx/src/main/ts/tsx/Scope.ts @@ -6,38 +6,50 @@ 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 _cleanup: (() => void)[] = []; + private readonly _pending: (() => void)[] = []; + + private _disposed = false; static readonly dummy: IScope = { own() { } }; own(target: (() => void) | IDestroyable | IRemovable | Unsubscribable) { if (target instanceof Function) { - this._cleanup.push(target); + this._own(target); } else if (isDestroyable(target)) { - this._cleanup.push(() => target.destroy()); + this._own(() => target.destroy()); } else if (isRemovable(target)) { - this._cleanup.push(() => target.remove()); + this._own(() => target.remove()); } else if (isUnsubscribable(target)) { - this._cleanup.push(() => target.unsubscribe()); + this._own(() => target.unsubscribe()); } } + private _own(target: () => void) { + if (this._disposed) + guard(target); + else + this._pending.push(target); + } + clean() { - const guard = (cb: () => void) => { - try { - cb(); - } catch { - // guard - } - }; - - this._cleanup.forEach(guard); - this._cleanup.length = 0; + this._pending.forEach(guard); + this._pending.length = 0; } destroy() { - this.clean(); + if (!this._disposed) { + this._disposed = true; + this.clean(); + } } } \ No newline at end of file