##// END OF EJS Templates
WIP lifetime services, change target to ES2018
WIP lifetime services, change target to ES2018

File last commit:

r11:dd37d4287c45 default
r11:dd37d4287c45 default
Show More
LifetimeManager.ts
252 lines | 7.3 KiB | video/mp2t | TypeScriptLexer
/ src / main / ts / LifetimeManager.ts
cin
intoruced initial work on ILifetimeSlot
r10 import { IActivationContext, ILifetime, ILifetimeContext, ILifetimeManager, ILifetimeSlot } 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
WIP lifetime services, change target to ES2018
r11 const noop = () => {};
const fail = (message: string) => {
throw new Error(message);
};
cin
intoruced initial work on ILifetimeSlot
r10 const _emptySlot = Object.freeze({
has: () => false,
cin
initial commit
r0
cin
WIP lifetime services, change target to ES2018
r11 initialize: noop,
get: fail("The specified item isn't registered with a lifetime manager"),
cin
initial commit
r0
cin
WIP lifetime services, change target to ES2018
r11 store: noop,
cin
initial commit
r0
cin
WIP lifetime services, change target to ES2018
r11 remove: noop
cin
initial commit
r0 });
cin
intoruced initial work on ILifetimeSlot
r10 const _unknonwSlot = Object.freeze({
has: () => false,
initialize: () => {
cin
initial commit
r0 throw new Error("Can't call initialize on the unknown lifetime object");
},
cin
intoruced initial work on ILifetimeSlot
r10 get: () => {
cin
initial commit
r0 throw new Error("The lifetime object isn't initialized");
},
cin
intoruced initial work on ILifetimeSlot
r10 store: () => {
cin
initial commit
r0 throw new Error("Can't store a value in the unknown lifetime object");
}
});
cin
intoruced initial work on ILifetimeSlot
r10
const pendingSlot = <T>(store: (item: T) => void) => ({
has: () => false,
get: () => {
throw new Error("The value in this slot doesn't exist");
},
initialize: () => {
throw new Error("Cyclic reference detected");
},
store
});
const valueSlot = <T>(value: T, cleanup: (item: T) => void) => ({
has: () => true,
get: () => value,
initialize: () => {
throw new Error("The slot already has a value");
},
store: () => {
throw new Error("The slot already has a value");
}
});
cin
WIP lifetime services, change target to ES2018
r11 const singletons: { [K: string]: unknown } = {};
cin
almost woking typings
r9 export class LifetimeManager implements ILifetimeManager {
cin
initial commit
r0 private _destroyed = false;
cin
intoruced initial work on ILifetimeSlot
r10 private readonly _slots: Record<string, ILifetimeSlot<unknown>> = {};
cin
working on fluent configuration
r1
cin
intoruced initial work on ILifetimeSlot
r10 slot<T>(cookie: string): ILifetimeSlot<T> {
if (cookie in this._slots)
return this._slots[cookie] as ILifetimeSlot<T>;
cin
initial commit
r0
cin
intoruced initial work on ILifetimeSlot
r10 const store = (item: T, cleanup?: (item: T) => void) => {
this._assertNotDestroyed();
this._slots[cookie] = valueSlot(
item,
cleanup ?? isDestroyable(item) ? () => item.destroy() : noop
);
};
cin
initial commit
r0
cin
intoruced initial work on ILifetimeSlot
r10 return {
has: () => false,
get: () => {
throw new Error("The value isn't stored in this slot");
cin
almost woking typings
r9 },
cin
intoruced initial work on ILifetimeSlot
r10 store,
initialize: () => {
this._assertNotDestroyed();
this._slots[cookie] = pendingSlot(store);
cin
initial commit
r0 }
};
}
cin
WIP lifetime services, change target to ES2018
r11 remove(cookie: string) {
delete this._slots[cookie];
}
cin
intoruced initial work on ILifetimeSlot
r10 private _assertNotDestroyed() {
if (this._destroyed)
throw new Error("The lifetime manager is destroyed");
}
cin
initial commit
r0 destroy() {
if (!this._destroyed) {
this._destroyed = true;
cin
WIP lifetime services, change target to ES2018
r11 Object.values(this._slots).forEach(({clean}) => )
cin
initial commit
r0 }
}
cin
almost woking typings
r9 }
export const emptyLifetime = <T>(): ILifetime<T> => {
return _emptyLifetime;
};
cin
initial commit
r0
cin
almost woking typings
r9 export const hierarchyLifetime = <T>(): ILifetime<T> => {
cin
WIP lifetime services, change target to ES2018
r11 // TODO: вот здесь ошибка, при первой активации сервиса будет получен и
// привязан lifetime из дочернего контейнера, при активации через второй
// дочерний контейнера это приведет к ошибке, точнее будет взят экземпляр
// из первого контейнера.
cin
almost woking typings
r9 let _lifetime: ILifetime<T> = _unknownLifetime;
return {
cin
intoruced initial work on ILifetimeSlot
r10 initialize(context: ILifetimeContext) {
cin
almost woking typings
r9 if (_lifetime !== _unknownLifetime)
throw new Error("Cyclic reference activation detected");
cin
initial commit
r0
cin
almost woking typings
r9 _lifetime = context.createContainerLifetime<T>();
},
get() {
return _lifetime.get();
},
has() {
return _lifetime.has();
},
store(item: NonNullable<T>, cleanup?: (item: NonNullable<T>) => void) {
return _lifetime.store(item, cleanup);
},
toString() {
return `[object HierarchyLifetime, has=${String(this.has())}]`;
}
};
};
cin
initial commit
r0
cin
intoruced initial work on ILifetimeSlot
r10 /**
* Creates a lifetime instance bound to the current activation context. This
* lifetime will store the service instance per activation context. Every
* top level service resolution will create a new activation context. This
* context is propagated to subsequent service resolution thus all services
* with context lifetime will be shared among their consumers.
*
* @returns The instance of the lifetime.
*/
cin
almost woking typings
r9 export const contextLifetime = <T>(): ILifetime<T> => {
let _lifetime: ILifetime<T> = _unknownLifetime;
return {
cin
intoruced initial work on ILifetimeSlot
r10 initialize(context: ILifetimeContext) {
cin
almost woking typings
r9 if (_lifetime !== _unknownLifetime)
throw new Error("Cyclic reference detected");
_lifetime = context.createLifetime();
},
get() {
return _lifetime.get();
},
has() {
return _lifetime.has();
},
store(item: NonNullable<T>) {
_lifetime.store(item);
},
toString() {
return `[object ContextLifetime, has=${String(this.has())}]`;
}
};
};
cin
initial commit
r0
cin
intoruced initial work on ILifetimeSlot
r10 /**
* Creates the lifetime for the service which will allow existence only one
* instance with the specified {@linkcode typeId}. If there will be created
* several lifetime instances with same `typeId` in the runtime, they will
* share the same service instance.
*
* @param typeId The identified for the global instance, usually this is a
* fully qualified class name
* @returns The lifetime instance
*/
cin
almost woking typings
r9 export const singletonLifetime = <T>(typeId: string): ILifetime<T> => {
argumentNotNull(typeId, "typeId");
let pending = false;
return {
has() {
return typeId in singletons;
},
get() {
if (!this.has())
throw new Error(`The instance ${typeId} doesn't exists`);
return singletons[typeId] as NonNullable<T>;
},
initialize() {
if (pending)
throw new Error("Cyclic reference detected");
pending = true;
},
store(item: NonNullable<T>) {
singletons[typeId] = item;
pending = false;
},
toString() {
return `[object SingletonLifetime, has=${String(this.has())}, typeId=${typeId}]`;
}
};
};
cin
intoruced initial work on ILifetimeSlot
r10 /** Creates a lifetime bound to the specified container. Using this lifetime
* will create a single service instance per the specified container.
*
* @param container The container which will manage the lifetime for the service
*/
cin
almost woking typings
r9 export const containerLifetime = <T>(container: { createLifetime<X>(): ILifetime<X> }) => {
let _lifetime: ILifetime<T> = _unknownLifetime;
return {
initialize() {
if (_lifetime !== _unknownLifetime)
throw new Error("Cyclic reference detected");
_lifetime = container.createLifetime();
},
get() {
return _lifetime.get();
},
has() {
return _lifetime.has();
},
cin
intoruced initial work on ILifetimeSlot
r10 store(item: NonNullable<T>, cleanup?: (item: NonNullable<T>) => void) {
_lifetime.store(item, cleanup);
cin
almost woking typings
r9 },
toString() {
return `[object ContainerLifetime, has=${String(_lifetime.has())}]`;
}
};
};