##// END OF EJS Templates
working on typings
working on typings

File last commit:

r5:83fa5814462d default
r8:80cb5668e4a7 default
Show More
LifetimeManager.ts
211 lines | 6.0 KiB | video/mp2t | TypeScriptLexer
/ src / main / ts / LifetimeManager.ts
cin
Working on container builder
r5 import { IActivationContext, IDestroyable, ILifetime } from "./interfaces";
cin
initial commit
r0 import { ActivationContext } from "./ActivationContext";
cin
working on fluent configuration
r1 import { argumentNotNull, isDestroyable } from "./traits";
cin
initial commit
r0
cin
working on fluent configuration
r1 const safeCall = (item: () => void) => {
cin
initial commit
r0 try {
item();
} catch {
// silence!
}
cin
working on fluent configuration
r1 };
cin
initial commit
r0
cin
working on fluent configuration
r1 const emptyLifetime = Object.freeze({
cin
initial commit
r0 has() {
return false;
},
initialize() {
},
get() {
throw new Error("The specified item isn't registered with this lifetime manager");
},
store() {
// does nothing
},
toString() {
return `[object EmptyLifetime]`;
}
});
cin
working on fluent configuration
r1 const unknownLifetime = Object.freeze({
cin
initial commit
r0 has() {
return false;
},
initialize() {
throw new Error("Can't call initialize on the unknown lifetime object");
},
get() {
throw new Error("The lifetime object isn't initialized");
},
store() {
throw new Error("Can't store a value in the unknown lifetime object");
},
toString() {
return `[object UnknownLifetime]`;
}
});
let nextId = 0;
cin
working on fluent configuration
r1 const singletons: { [K:string]: unknown} = {};
cin
initial commit
r0
export class LifetimeManager implements IDestroyable {
private _cleanup: (() => void)[] = [];
cin
working on fluent configuration
r1 private readonly _cache: {[K: string]: unknown} = {};
cin
initial commit
r0 private _destroyed = false;
cin
working on fluent configuration
r1 private readonly _pending: {[K: string]: unknown} = {};
cin
initial commit
r0
cin
working on fluent configuration
r1 create<T>(): ILifetime<T> {
cin
initial commit
r0 const id = ++nextId;
return {
cin
working on fluent configuration
r1 has: () => id in this._cache,
get: () => {
const t = this._cache[id];
if (t === undefined)
throw new Error(`The item with with the key ${id} isn't found`);
return t as T;
cin
initial commit
r0 },
cin
working on fluent configuration
r1 initialize: () => {
if (this._pending[id])
throw Error(`Cyclic reference detected: the item with the key ${id} is already activating.`);
this._pending[id] = true;
cin
initial commit
r0 },
cin
working on fluent configuration
r1 store: (item: T, cleanup?: (item: T) => void) => {
cin
initial commit
r0 argumentNotNull(id, "id");
argumentNotNull(item, "item");
cin
working on fluent configuration
r1 if (id in this._cache)
cin
initial commit
r0 throw new Error(`The item with with the key ${id} already registered with this lifetime manager`);
cin
working on fluent configuration
r1 delete this._pending[id];
cin
initial commit
r0
cin
working on fluent configuration
r1 this._cache[id] = item;
cin
initial commit
r0
cin
working on fluent configuration
r1 if (this._destroyed)
cin
initial commit
r0 throw new Error("Lifetime manager is destroyed");
if (cleanup) {
cin
working on fluent configuration
r1 this._cleanup.push(() => cleanup(item));
cin
initial commit
r0 } else if (isDestroyable(item)) {
cin
working on fluent configuration
r1 this._cleanup.push(() => item.destroy());
cin
initial commit
r0 }
}
};
}
destroy() {
if (!this._destroyed) {
this._destroyed = true;
this._cleanup.forEach(safeCall);
this._cleanup.length = 0;
}
}
cin
working on fluent configuration
r1 static empty<T>(): ILifetime<T> {
cin
initial commit
r0 return emptyLifetime;
}
cin
working on fluent configuration
r1 static hierarchyLifetime<T>() {
let _lifetime: ILifetime<T> = unknownLifetime;
cin
initial commit
r0 return {
cin
Working on container builder
r5 initialize(context: IActivationContext<object>) {
cin
initial commit
r0 if (_lifetime !== unknownLifetime)
throw new Error("Cyclic reference activation detected");
cin
working on fluent configuration
r1 _lifetime = context.createContainerLifetime<T>();
cin
initial commit
r0 },
get() {
return _lifetime.get();
},
has() {
return _lifetime.has();
},
cin
working on fluent configuration
r1 store(item: T, cleanup?: (item: T) => void) {
cin
initial commit
r0 return _lifetime.store(item, cleanup);
},
toString() {
cin
working on fluent configuration
r1 return `[object HierarchyLifetime, has=${String(this.has())}]`;
cin
initial commit
r0 }
};
}
cin
working on fluent configuration
r1 static contextLifetime<T>() {
let _lifetime: ILifetime<T> = unknownLifetime;
cin
initial commit
r0 return {
cin
working on fluent configuration
r1 initialize(context: ActivationContext<object>) {
cin
initial commit
r0 if (_lifetime !== unknownLifetime)
throw new Error("Cyclic reference detected");
_lifetime = context.createLifetime();
},
get() {
return _lifetime.get();
},
has() {
return _lifetime.has();
},
cin
working on fluent configuration
r1 store(item: T) {
cin
initial commit
r0 _lifetime.store(item);
},
toString() {
cin
working on fluent configuration
r1 return `[object ContextLifetime, has=${String(this.has())}]`;
cin
initial commit
r0 }
};
}
cin
working on fluent configuration
r1 static singletonLifetime<T>(typeId: string) {
argumentNotNull(typeId, "typeId");
cin
initial commit
r0 let pending = false;
return {
has() {
return typeId in singletons;
},
get() {
if (!this.has())
throw new Error(`The instance ${typeId} doesn't exists`);
cin
working on fluent configuration
r1 return singletons[typeId] as T;
cin
initial commit
r0 },
initialize() {
if (pending)
throw new Error("Cyclic reference detected");
pending = true;
},
cin
working on fluent configuration
r1 store(item: T) {
cin
initial commit
r0 singletons[typeId] = item;
pending = false;
},
toString() {
cin
working on fluent configuration
r1 return `[object SingletonLifetime, has=${String(this.has())}, typeId=${typeId}]`;
cin
initial commit
r0 }
};
}
cin
working on fluent configuration
r1 static containerLifetime<T>(container: { createLifetime<X>(): ILifetime<X>}) {
let _lifetime: ILifetime<T> = unknownLifetime;
cin
initial commit
r0 return {
cin
working on fluent configuration
r1 initialize() {
cin
initial commit
r0 if (_lifetime !== unknownLifetime)
throw new Error("Cyclic reference detected");
cin
working on fluent configuration
r1 _lifetime = container.createLifetime();
cin
initial commit
r0 },
get() {
return _lifetime.get();
},
has() {
return _lifetime.has();
},
cin
working on fluent configuration
r1 store(item: T) {
cin
initial commit
r0 _lifetime.store(item);
},
toString() {
cin
working on fluent configuration
r1 return `[object ContainerLifetime, has=${String(_lifetime.has())}]`;
cin
initial commit
r0 }
};
}
}