|
|
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();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|