From e778ed4724ac391c83964c0f4cbfbc6fdb7565c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Pintos=20L=C3=B3pez?= Date: Thu, 14 Nov 2024 14:21:13 +0100 Subject: [PATCH 1/2] style: update test with right description --- test/bugs/issue_1518.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bugs/issue_1518.test.ts b/test/bugs/issue_1518.test.ts index 5ce5d50d..8dc7baa3 100644 --- a/test/bugs/issue_1518.test.ts +++ b/test/bugs/issue_1518.test.ts @@ -2,7 +2,7 @@ import { expect } from 'chai'; import { Container } from '../../src/inversify'; -describe('Issue 1515', () => { +describe('Issue 1518', () => { it('should not throw on deactivating undefined singleton values', () => { const container: Container = new Container(); const symbol: symbol = Symbol.for('foo'); From 09ab31077dda86d573c21eca9eb953779663b7ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Pintos=20L=C3=B3pez?= Date: Thu, 14 Nov 2024 14:22:04 +0100 Subject: [PATCH 2/2] fix: update BindingToSyntax.toService() to resolve async dependencies --- CHANGELOG.md | 1 + src/syntax/binding_to_syntax.ts | 11 +++++--- test/bugs/issue_1564.test.ts | 46 +++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 test/bugs/issue_1564.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index bc486003..2567c89f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed ### Fixed +- Fixed container to properly resolve async `.toService` bindings. ## [6.1.4] diff --git a/src/syntax/binding_to_syntax.ts b/src/syntax/binding_to_syntax.ts index e4017290..1016e1d2 100644 --- a/src/syntax/binding_to_syntax.ts +++ b/src/syntax/binding_to_syntax.ts @@ -116,9 +116,14 @@ class BindingToSyntax implements interfaces.BindingToSyntax { } public toService(service: interfaces.ServiceIdentifier): void { - this.toDynamicValue((context: interfaces.Context) => - context.container.get(service), - ); + this.toDynamicValue((context: interfaces.Context): T | Promise => { + try { + return context.container.get(service); + } catch (_error: unknown) { + // This is a performance degradation in this edge case, we do need to improve the internal resolution architecture in order to solve this properly. + return context.container.getAsync(service); + } + }); } } diff --git a/test/bugs/issue_1564.test.ts b/test/bugs/issue_1564.test.ts new file mode 100644 index 00000000..eb1d1285 --- /dev/null +++ b/test/bugs/issue_1564.test.ts @@ -0,0 +1,46 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; + +import { Container, inject, injectable } from '../../src/inversify'; + +describe('Issue 1564', () => { + it('should not throw on getting async services bound using "toService"', async () => { + @injectable() + class Database { + constructor() { + console.log('new Database'); + } + } + + @injectable() + class Service1 { + constructor(@inject(Database) public database: Database) { + console.log('new Service1'); + } + } + + @injectable() + class Service2 { + constructor(@inject(Service1) public service1: Service1) { + console.log('new Service2'); + } + } + + const container: Container = new Container({ defaultScope: 'Request' }); + + container.bind(Database).toDynamicValue(async () => { + console.log('connecting to db...'); + return new Database(); + }); + + container.bind(Service1).toSelf(); + container.bind(Service2).toSelf(); + + container.bind('services').toService(Service1); + container.bind('services').toService(Service2); + + const result: unknown[] = await container.getAllAsync('services'); + + expect(result).to.have.length(2); + }); +});