diff --git a/.changeset/nice-fireants-add.md b/.changeset/nice-fireants-add.md new file mode 100644 index 00000000..09710524 --- /dev/null +++ b/.changeset/nice-fireants-add.md @@ -0,0 +1,5 @@ +--- +"@inversifyjs/core": major +--- + +Renamed `BindingService.remove` to `removeAllByServiceId`. diff --git a/.changeset/red-ads-raise.md b/.changeset/red-ads-raise.md new file mode 100644 index 00000000..5e0e7d94 --- /dev/null +++ b/.changeset/red-ads-raise.md @@ -0,0 +1,5 @@ +--- +"@inversifyjs/core": major +--- + +Renamed `BindingService.removeByModule` to `removeAllByModuleId`. diff --git a/packages/container/libraries/container/src/container/services/Container.spec.ts b/packages/container/libraries/container/src/container/services/Container.spec.ts index 04788495..e1710f3d 100644 --- a/packages/container/libraries/container/src/container/services/Container.spec.ts +++ b/packages/container/libraries/container/src/container/services/Container.spec.ts @@ -55,7 +55,7 @@ describe(Container.name, () => { > as jest.Mocked; bindingServiceMock = { get: jest.fn(), - remove: jest.fn(), + removeAllByServiceId: jest.fn(), set: jest.fn(), } as Partial> as jest.Mocked; deactivationServiceMock = { @@ -996,9 +996,11 @@ describe(Container.name, () => { ); }); - it('should call bindingService.remove()', () => { - expect(bindingServiceMock.remove).toHaveBeenCalledTimes(1); - expect(bindingServiceMock.remove).toHaveBeenCalledWith( + it('should call bindingService.removeAllByServiceId()', () => { + expect(bindingServiceMock.removeAllByServiceId).toHaveBeenCalledTimes( + 1, + ); + expect(bindingServiceMock.removeAllByServiceId).toHaveBeenCalledWith( serviceIdentifierFixture, ); }); diff --git a/packages/container/libraries/container/src/container/services/Container.ts b/packages/container/libraries/container/src/container/services/Container.ts index 06121e88..7ec40547 100644 --- a/packages/container/libraries/container/src/container/services/Container.ts +++ b/packages/container/libraries/container/src/container/services/Container.ts @@ -12,6 +12,7 @@ import { BindingScope, bindingScopeValues, BindingService, + DeactivationParams, DeactivationsService, getClassMetadata, GetOptions, @@ -175,7 +176,7 @@ export class Container { serviceIdentifier: ServiceIdentifier, options?: IsBoundOptions, ): boolean { - const bindings: Binding[] | undefined = + const bindings: Iterable> | undefined = this.#bindingService.get(serviceIdentifier); if (bindings === undefined) { @@ -193,9 +194,13 @@ export class Container { bindingMetadata.tags.set(options.tag.key, options.tag.value); } - return bindings.some((binding: Binding): boolean => - binding.isSatisfiedBy(bindingMetadata), - ); + for (const binding of bindings) { + if (binding.isSatisfiedBy(bindingMetadata)) { + return true; + } + } + + return false; } public async load(...modules: ContainerModule[]): Promise { @@ -227,21 +232,12 @@ export class Container { public async unbind(serviceIdentifier: ServiceIdentifier): Promise { await resolveServiceDeactivations( - { - getBindings: ( - serviceIdentifier: ServiceIdentifier, - ): Binding[] | undefined => - this.#bindingService.get(serviceIdentifier), - getClassMetadata, - getDeactivations: ( - serviceIdentifier: ServiceIdentifier, - ) => this.#deactivationService.get(serviceIdentifier), - }, + this.#buildDeactivationParams(), serviceIdentifier, ); this.#activationService.removeAllByServiceId(serviceIdentifier); - this.#bindingService.remove(serviceIdentifier); + this.#bindingService.removeAllByServiceId(serviceIdentifier); this.#deactivationService.removeAllByServiceId(serviceIdentifier); } @@ -284,6 +280,19 @@ export class Container { }; } + #buildDeactivationParams(): DeactivationParams { + return { + getBindings: ( + serviceIdentifier: ServiceIdentifier, + ): Iterable> | undefined => + this.#bindingService.get(serviceIdentifier), + getClassMetadata, + getDeactivations: ( + serviceIdentifier: ServiceIdentifier, + ) => this.#deactivationService.get(serviceIdentifier), + }; + } + #buildPlanResult( isMultiple: boolean, serviceIdentifier: ServiceIdentifier, diff --git a/packages/container/libraries/core/src/binding/fixtures/ConstantValueBindingFixtures.ts b/packages/container/libraries/core/src/binding/fixtures/ConstantValueBindingFixtures.ts index 018d5a92..c76b94dd 100644 --- a/packages/container/libraries/core/src/binding/fixtures/ConstantValueBindingFixtures.ts +++ b/packages/container/libraries/core/src/binding/fixtures/ConstantValueBindingFixtures.ts @@ -40,4 +40,18 @@ export class ConstantValueBindingFixtures { }, }; } + + public static get withModuleIdUndefined(): ConstantValueBinding { + return { + ...ConstantValueBindingFixtures.any, + moduleId: undefined, + }; + } + + public static get withModuleId(): ConstantValueBinding { + return { + ...ConstantValueBindingFixtures.any, + moduleId: 1, + }; + } } diff --git a/packages/container/libraries/core/src/binding/services/ActivationsService.spec.ts b/packages/container/libraries/core/src/binding/services/ActivationsService.spec.ts index f3ba9876..0846b083 100644 --- a/packages/container/libraries/core/src/binding/services/ActivationsService.spec.ts +++ b/packages/container/libraries/core/src/binding/services/ActivationsService.spec.ts @@ -152,7 +152,7 @@ describe(ActivationsService.name, () => { }); }); - describe('.removeAllByModule', () => { + describe('.removeAllByModuleId', () => { let moduleIdFixture: number; beforeAll(() => { diff --git a/packages/container/libraries/core/src/binding/services/BindingService.spec.ts b/packages/container/libraries/core/src/binding/services/BindingService.spec.ts index faf9f620..39e721d6 100644 --- a/packages/container/libraries/core/src/binding/services/BindingService.spec.ts +++ b/packages/container/libraries/core/src/binding/services/BindingService.spec.ts @@ -1,163 +1,281 @@ -import { beforeAll, describe, expect, it } from '@jest/globals'; +import { afterAll, beforeAll, describe, expect, it, jest } from '@jest/globals'; +jest.mock('../../common/models/OneToManyMapStar'); + +import { ServiceIdentifier } from '@inversifyjs/common'; + +import { OneToManyMapStar } from '../../common/models/OneToManyMapStar'; +import { ConstantValueBindingFixtures } from '../fixtures/ConstantValueBindingFixtures'; import { Binding } from '../models/Binding'; -import { bindingScopeValues } from '../models/BindingScope'; -import { bindingTypeValues } from '../models/BindingType'; -import { BindingService } from './BindingService'; +import { BindingRelation, BindingService } from './BindingService'; describe(BindingService.name, () => { + let bindingMapsMock: jest.Mocked< + OneToManyMapStar, BindingRelation> + >; + + let parentBindingService: BindingService; + let bindingService: BindingService; + + beforeAll(() => { + bindingMapsMock = new OneToManyMapStar, BindingRelation>({ + moduleId: { + isOptional: true, + }, + serviceId: { + isOptional: false, + }, + }) as jest.Mocked, BindingRelation>>; + + parentBindingService = new BindingService(undefined); + + bindingService = new BindingService(parentBindingService); + }); + describe('.get', () => { - let bindingFixture: Binding; + let serviceIdFixture: ServiceIdentifier; beforeAll(() => { - bindingFixture = { - cache: { - isRight: false, - value: undefined, - }, - id: 2, - isSatisfiedBy: (): boolean => true, - moduleId: 1, - onActivation: undefined, - onDeactivation: undefined, - scope: bindingScopeValues.Singleton, - serviceIdentifier: 'service-identifier-fixture', - type: bindingTypeValues.ConstantValue, - value: Symbol(), - }; + serviceIdFixture = 'service-identifier'; }); - describe('having a BindingService with existing bindings with no parent', () => { - describe('when called', () => { - let bindingServiceImplementation: BindingService; + describe('when called, and bindingMaps.get() returns undefined and parent bindingMaps.get() returns Iterable', () => { + let bindingFixture: Binding; - let result: unknown; + let result: unknown; - beforeAll(() => { - bindingServiceImplementation = new BindingService(undefined); + beforeAll(() => { + bindingFixture = Symbol() as unknown as Binding; - bindingServiceImplementation.set(bindingFixture); + bindingMapsMock.get + .mockReturnValueOnce(undefined) + .mockReturnValueOnce([bindingFixture]); - result = bindingServiceImplementation.get( - bindingFixture.serviceIdentifier, - ); - }); + result = bindingService.get(serviceIdFixture); + }); - it('should return Binding[]', () => { - expect(result).toStrictEqual([bindingFixture]); - }); + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should call bindingMaps.get()', () => { + expect(bindingMapsMock.get).toHaveBeenCalledTimes(2); + expect(bindingMapsMock.get).toHaveBeenNthCalledWith( + 1, + 'serviceId', + serviceIdFixture, + ); + expect(bindingMapsMock.get).toHaveBeenNthCalledWith( + 2, + 'serviceId', + serviceIdFixture, + ); + }); + + it('should return Binding[]', () => { + expect(result).toStrictEqual([bindingFixture]); }); }); - describe('having a BindingService with non existing bindings with no parent', () => { - describe('when called', () => { - let bindingServiceImplementation: BindingService; + describe('when called, and bindingMaps.get() returns Iterable', () => { + let bindingFixture: Binding; - let result: unknown; + let result: unknown; - beforeAll(() => { - bindingServiceImplementation = new BindingService(undefined); + beforeAll(() => { + bindingFixture = Symbol() as unknown as Binding; - result = bindingServiceImplementation.get( - bindingFixture.serviceIdentifier, - ); - }); + bindingMapsMock.get.mockReturnValueOnce([bindingFixture]); - it('should return undefined', () => { - expect(result).toBeUndefined(); - }); + result = bindingService.get(serviceIdFixture); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should call bindingMaps.get()', () => { + expect(bindingMapsMock.get).toHaveBeenCalledTimes(1); + expect(bindingMapsMock.get).toHaveBeenCalledWith( + 'serviceId', + serviceIdFixture, + ); + }); + + it('should return BindingActivation[]', () => { + expect(result).toStrictEqual([bindingFixture]); }); }); + }); - describe('having a BindingService with parent with existing bindings', () => { - describe('when called', () => { - let bindingServiceImplementation: BindingService; - let parentBindingServiceImplementation: BindingService; + describe('.getByModuleId', () => { + let moduleIdFixture: number; - let result: unknown; + beforeAll(() => { + moduleIdFixture = 1; + }); - beforeAll(() => { - parentBindingServiceImplementation = new BindingService(undefined); - parentBindingServiceImplementation.set(bindingFixture); + describe('when called, and bindingMaps.get() returns undefined and parent bindingMaps.get() returns Iterable', () => { + let bindingFixture: Binding; - bindingServiceImplementation = new BindingService( - parentBindingServiceImplementation, - ); + let result: unknown; - result = bindingServiceImplementation.get( - bindingFixture.serviceIdentifier, - ); - }); + beforeAll(() => { + bindingFixture = Symbol() as unknown as Binding; - it('should return Binding[]', () => { - expect(result).toStrictEqual([bindingFixture]); - }); + bindingMapsMock.get + .mockReturnValueOnce(undefined) + .mockReturnValueOnce([bindingFixture]); + + result = bindingService.getByModuleId(moduleIdFixture); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should call bindingMaps.get()', () => { + expect(bindingMapsMock.get).toHaveBeenCalledTimes(2); + expect(bindingMapsMock.get).toHaveBeenNthCalledWith( + 1, + 'moduleId', + moduleIdFixture, + ); + expect(bindingMapsMock.get).toHaveBeenNthCalledWith( + 2, + 'moduleId', + moduleIdFixture, + ); + }); + + it('should return Binding[]', () => { + expect(result).toStrictEqual([bindingFixture]); }); }); - describe('having a BindingService with parent with non existing bindings', () => { - describe('when called, with non existing bindings', () => { - let bindingServiceImplementation: BindingService; - let parentBindingServiceImplementation: BindingService; + describe('when called, and bindingMaps.get() returns Iterable', () => { + let bindingFixture: Binding; - let result: unknown; + let result: unknown; - beforeAll(() => { - parentBindingServiceImplementation = new BindingService(undefined); + beforeAll(() => { + bindingFixture = Symbol() as unknown as Binding; - bindingServiceImplementation = new BindingService( - parentBindingServiceImplementation, - ); + bindingMapsMock.get.mockReturnValueOnce([bindingFixture]); - result = bindingServiceImplementation.get( - bindingFixture.serviceIdentifier, - ); - }); + result = bindingService.getByModuleId(moduleIdFixture); + }); - it('should return undefined', () => { - expect(result).toBeUndefined(); - }); + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should call bindingMaps.get()', () => { + expect(bindingMapsMock.get).toHaveBeenCalledTimes(1); + expect(bindingMapsMock.get).toHaveBeenCalledWith( + 'moduleId', + moduleIdFixture, + ); + }); + + it('should return BindingActivation[]', () => { + expect(result).toStrictEqual([bindingFixture]); }); }); }); - describe('.remove', () => { - let bindingFixture: Binding; + describe('.removeAllByModuleId', () => { + let moduleIdFixture: number; beforeAll(() => { - bindingFixture = { - cache: { - isRight: false, - value: undefined, - }, - id: 2, - isSatisfiedBy: (): boolean => true, - moduleId: 1, - onActivation: undefined, - onDeactivation: undefined, - scope: bindingScopeValues.Singleton, - serviceIdentifier: Symbol(), - type: bindingTypeValues.ConstantValue, - value: Symbol(), - }; + moduleIdFixture = 3; }); - describe('when called, with existing bindings', () => { - let bindingServiceImplementation: BindingService; + describe('when called', () => { + let result: unknown; beforeAll(() => { - bindingServiceImplementation = new BindingService(undefined); + result = bindingService.removeAllByModuleId(moduleIdFixture); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should call bindingMaps.removeByRelation()', () => { + expect(bindingMapsMock.removeByRelation).toHaveBeenCalledTimes(1); + expect(bindingMapsMock.removeByRelation).toHaveBeenCalledWith( + 'moduleId', + moduleIdFixture, + ); + }); + + it('should return undefined', () => { + expect(result).toBeUndefined(); + }); + }); + }); + + describe('.removeAllByServiceId', () => { + let serviceIdFixture: ServiceIdentifier; + + beforeAll(() => { + serviceIdFixture = 'service-id'; + }); + + describe('when called', () => { + let result: unknown; + + beforeAll(() => { + result = bindingService.removeAllByServiceId(serviceIdFixture); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should call bindingMaps.removeByRelation()', () => { + expect(bindingMapsMock.removeByRelation).toHaveBeenCalledTimes(1); + expect(bindingMapsMock.removeByRelation).toHaveBeenCalledWith( + 'serviceId', + serviceIdFixture, + ); + }); - bindingServiceImplementation.set(bindingFixture); - bindingServiceImplementation.remove(bindingFixture.serviceIdentifier); + it('should return undefined', () => { + expect(result).toBeUndefined(); }); + }); + }); - describe('when called .get()', () => { + describe('.set', () => { + describe('having a binding with no container id', () => { + let bindingFixture: Binding; + + beforeAll(() => { + bindingFixture = ConstantValueBindingFixtures.withModuleIdUndefined; + }); + + describe('when called', () => { let result: unknown; beforeAll(() => { - result = bindingServiceImplementation.get( - bindingFixture.serviceIdentifier, + result = bindingService.set(bindingFixture); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should call bindingMaps.set()', () => { + const expectedRelation: BindingRelation = { + serviceId: bindingFixture.serviceIdentifier, + }; + + expect(bindingMapsMock.set).toHaveBeenCalledTimes(1); + expect(bindingMapsMock.set).toHaveBeenCalledWith( + bindingFixture, + expectedRelation, ); }); @@ -166,47 +284,35 @@ describe(BindingService.name, () => { }); }); }); - }); - describe('.removeByModule', () => { - let bindingFixture: Binding; - - beforeAll(() => { - bindingFixture = { - cache: { - isRight: false, - value: undefined, - }, - id: 2, - isSatisfiedBy: (): boolean => true, - moduleId: 1, - onActivation: undefined, - onDeactivation: undefined, - scope: bindingScopeValues.Singleton, - serviceIdentifier: Symbol(), - type: bindingTypeValues.ConstantValue, - value: Symbol(), - }; - }); - - describe('when called, with existing bindings', () => { - let bindingServiceImplementation: BindingService; + describe('having a binding with container id', () => { + let bindingFixture: Binding; beforeAll(() => { - bindingServiceImplementation = new BindingService(undefined); - - bindingServiceImplementation.set(bindingFixture); - bindingServiceImplementation.removeByModule( - bindingFixture.moduleId as number, - ); + bindingFixture = ConstantValueBindingFixtures.withModuleId; }); - describe('when called .get()', () => { + describe('when called', () => { let result: unknown; beforeAll(() => { - result = bindingServiceImplementation.get( - bindingFixture.serviceIdentifier, + result = bindingService.set(bindingFixture); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should call bindingMaps.set()', () => { + const expectedRelation: BindingRelation = { + moduleId: bindingFixture.moduleId as number, + serviceId: bindingFixture.serviceIdentifier, + }; + + expect(bindingMapsMock.set).toHaveBeenCalledTimes(1); + expect(bindingMapsMock.set).toHaveBeenCalledWith( + bindingFixture, + expectedRelation, ); }); diff --git a/packages/container/libraries/core/src/binding/services/BindingService.ts b/packages/container/libraries/core/src/binding/services/BindingService.ts index 04c66ca0..3dcc11ca 100644 --- a/packages/container/libraries/core/src/binding/services/BindingService.ts +++ b/packages/container/libraries/core/src/binding/services/BindingService.ts @@ -1,122 +1,80 @@ import { ServiceIdentifier } from '@inversifyjs/common'; +import { OneToManyMapStar } from '../../common/models/OneToManyMapStar'; import { Binding } from '../models/Binding'; +enum BindingRelationKind { + moduleId = 'moduleId', + serviceId = 'serviceId', +} + +export interface BindingRelation { + [BindingRelationKind.moduleId]?: number; + [BindingRelationKind.serviceId]: ServiceIdentifier; +} + export class BindingService { - readonly #idToBindingMap: Map[]>; - readonly #moduleIdToIdToBindingMap: Map< - number, - Map> - >; + readonly #bindingMaps: OneToManyMapStar, BindingRelation>; + readonly #parent: BindingService | undefined; constructor(parent: BindingService | undefined) { - this.#idToBindingMap = new Map(); - this.#moduleIdToIdToBindingMap = new Map(); + this.#bindingMaps = new OneToManyMapStar, BindingRelation>( + { + moduleId: { + isOptional: true, + }, + serviceId: { + isOptional: false, + }, + }, + ); + this.#parent = parent; } - public get( + public get( serviceIdentifier: ServiceIdentifier, - ): Binding[] | undefined { - return (this.#idToBindingMap.get(serviceIdentifier) ?? - this.#parent?.get(serviceIdentifier)) as Binding[] | undefined; + ): Iterable> | undefined { + return ( + (this.#bindingMaps.get( + BindingRelationKind.serviceId, + serviceIdentifier, + ) as Iterable> | undefined) ?? + this.#parent?.get(serviceIdentifier) + ); } - public remove(serviceIdentifier: ServiceIdentifier): void { - const serviceBindings: Binding[] | undefined = - this.#idToBindingMap.get(serviceIdentifier); - - this.#idToBindingMap.delete(serviceIdentifier); - - if (serviceBindings !== undefined) { - this.#removeBindingsFromModuleMap(serviceBindings); - } + public getByModuleId( + moduleId: number, + ): Iterable> | undefined { + return ( + (this.#bindingMaps.get(BindingRelationKind.moduleId, moduleId) as + | Iterable> + | undefined) ?? this.#parent?.getByModuleId(moduleId) + ); } - public removeByModule(moduleId: number): void { - const moduleBindings: Map> | undefined = - this.#moduleIdToIdToBindingMap.get(moduleId); - - if (moduleBindings === undefined) { - return; - } - - this.#moduleIdToIdToBindingMap.delete(moduleId); - - this.#removeBindingsFromIdMap(moduleBindings.values()); + public removeAllByModuleId(moduleId: number): void { + this.#bindingMaps.removeByRelation(BindingRelationKind.moduleId, moduleId); } - public set(binding: Binding): void { - this.#setIdToBindingMapBinding(binding); - this.#setModuleIdToIdToBindingMapBinding(binding); + public removeAllByServiceId(serviceId: ServiceIdentifier): void { + this.#bindingMaps.removeByRelation( + BindingRelationKind.serviceId, + serviceId, + ); } - #removeBindingsFromIdMap(bindings: Iterable>): void { - for (const binding of bindings) { - let serviceBindings: Binding[] | undefined = - this.#idToBindingMap.get(binding.serviceIdentifier); - - if (serviceBindings !== undefined) { - serviceBindings = serviceBindings.filter( - (serviceBinding: Binding): boolean => - serviceBinding.id !== binding.id, - ); - - if (serviceBindings.length === 0) { - this.#idToBindingMap.delete(binding.serviceIdentifier); - } else { - this.#idToBindingMap.set(binding.serviceIdentifier, serviceBindings); - } - } - } - } - - #removeBindingsFromModuleMap(bindings: Iterable>): void { - for (const binding of bindings) { - if (binding.moduleId !== undefined) { - const moduleBindings: Map> | undefined = - this.#moduleIdToIdToBindingMap.get(binding.moduleId); - - if (moduleBindings !== undefined) { - moduleBindings.delete(binding.id); - - if (moduleBindings.size === 0) { - this.#moduleIdToIdToBindingMap.delete(binding.moduleId); - } - } - } - } - } - - #setIdToBindingMapBinding(binding: Binding): void { - let serviceBindings: Binding[] | undefined = - this.#idToBindingMap.get(binding.serviceIdentifier); - - if (serviceBindings === undefined) { - serviceBindings = []; - } - - serviceBindings.push(binding as Binding); - - this.#idToBindingMap.set(binding.serviceIdentifier, serviceBindings); - } - - #setModuleIdToIdToBindingMapBinding( - binding: Binding, - ): void { - if (binding.moduleId === undefined) { - return; - } - - let moduleBindingsMap: Map> | undefined = - this.#moduleIdToIdToBindingMap.get(binding.moduleId); + public set(binding: Binding): void { + const relation: BindingRelation = { + [BindingRelationKind.serviceId]: binding.serviceIdentifier, + }; - if (moduleBindingsMap === undefined) { - moduleBindingsMap = new Map(); - this.#moduleIdToIdToBindingMap.set(binding.moduleId, moduleBindingsMap); + if (binding.moduleId !== undefined) { + relation[BindingRelationKind.moduleId] = binding.moduleId; } - moduleBindingsMap.set(binding.id, binding as Binding); + this.#bindingMaps.set(binding as Binding, relation); } } diff --git a/packages/container/libraries/core/src/planning/calculations/buildFilteredServiceBindings.ts b/packages/container/libraries/core/src/planning/calculations/buildFilteredServiceBindings.ts index 6d1d66c0..c25ae244 100644 --- a/packages/container/libraries/core/src/planning/calculations/buildFilteredServiceBindings.ts +++ b/packages/container/libraries/core/src/planning/calculations/buildFilteredServiceBindings.ts @@ -23,8 +23,9 @@ export function buildFilteredServiceBindings( const serviceIdentifier: ServiceIdentifier = options?.customServiceIdentifier ?? bindingMetadata.serviceIdentifier; - const serviceBindings: Binding[] = - params.getBindings(serviceIdentifier) ?? []; + const serviceBindings: Binding[] = [ + ...(params.getBindings(serviceIdentifier) ?? []), + ]; return serviceBindings.filter((binding: Binding): boolean => binding.isSatisfiedBy(bindingMetadata), diff --git a/packages/container/libraries/core/src/planning/models/BasePlanParams.ts b/packages/container/libraries/core/src/planning/models/BasePlanParams.ts index 1308e0dc..89b05a85 100644 --- a/packages/container/libraries/core/src/planning/models/BasePlanParams.ts +++ b/packages/container/libraries/core/src/planning/models/BasePlanParams.ts @@ -6,7 +6,7 @@ import { ClassMetadata } from '../../metadata/models/ClassMetadata'; export interface BasePlanParams { getBindings: ( serviceIdentifier: ServiceIdentifier, - ) => Binding[] | undefined; + ) => Iterable> | undefined; getClassMetadata: (type: Newable) => ClassMetadata; servicesBranch: Set; } diff --git a/packages/container/libraries/core/src/resolution/actions/resolveBindingDeactivations.ts b/packages/container/libraries/core/src/resolution/actions/resolveBindingDeactivations.ts index 4c1ab1f8..fd0061cd 100644 --- a/packages/container/libraries/core/src/resolution/actions/resolveBindingDeactivations.ts +++ b/packages/container/libraries/core/src/resolution/actions/resolveBindingDeactivations.ts @@ -9,23 +9,23 @@ export function resolveBindingDeactivations( serviceIdentifier: ServiceIdentifier, value: Resolved, ): void | Promise { - const activations: Iterable> | undefined = + const deactivations: Iterable> | undefined = params.getDeactivations(serviceIdentifier); - if (activations === undefined) { + if (deactivations === undefined) { return undefined; } if (isPromise(value)) { return resolveBindingDeactivationsFromIteratorAsync( value, - activations[Symbol.iterator](), + deactivations[Symbol.iterator](), ); } return resolveBindingDeactivationsFromIterator( value, - activations[Symbol.iterator](), + deactivations[Symbol.iterator](), ); } diff --git a/packages/container/libraries/core/src/resolution/actions/resolveServiceDeactivations.ts b/packages/container/libraries/core/src/resolution/actions/resolveServiceDeactivations.ts index 96eb03b5..95681f1b 100644 --- a/packages/container/libraries/core/src/resolution/actions/resolveServiceDeactivations.ts +++ b/packages/container/libraries/core/src/resolution/actions/resolveServiceDeactivations.ts @@ -19,7 +19,8 @@ export function resolveServiceDeactivations( params: DeactivationParams, serviceIdentifier: ServiceIdentifier, ): void | Promise { - const bindings: Binding[] | undefined = params.getBindings(serviceIdentifier); + const bindings: Iterable | undefined = + params.getBindings(serviceIdentifier); if (bindings === undefined) { return; @@ -67,13 +68,20 @@ export function resolveServiceDeactivations( } function filterSinglentonScopedBindings( - bindings: Binding[], + bindings: Iterable, ): SingletonScopedBinding[] { - return bindings.filter( - (binding: Binding): binding is SingletonScopedBinding => + const filteredBindings: SingletonScopedBinding[] = []; + + for (const binding of bindings) { + if ( isScopedBinding(binding) && - binding.scope === bindingScopeValues.Singleton, - ); + binding.scope === bindingScopeValues.Singleton + ) { + filteredBindings.push(binding as SingletonScopedBinding); + } + } + + return filteredBindings; } function resolveBindingPreDestroy( diff --git a/packages/container/libraries/core/src/resolution/models/DeactivationParams.ts b/packages/container/libraries/core/src/resolution/models/DeactivationParams.ts index c8b0fedd..507d994a 100644 --- a/packages/container/libraries/core/src/resolution/models/DeactivationParams.ts +++ b/packages/container/libraries/core/src/resolution/models/DeactivationParams.ts @@ -7,7 +7,7 @@ import { ClassMetadata } from '../../metadata/models/ClassMetadata'; export interface DeactivationParams { getBindings: ( serviceIdentifier: ServiceIdentifier, - ) => Binding[] | undefined; + ) => Iterable> | undefined; getClassMetadata: (type: Newable) => ClassMetadata; getDeactivations: ( serviceIdentifier: ServiceIdentifier,