From 980b9f87e6f73bb3a0d139729f8060662450a6a1 Mon Sep 17 00:00:00 2001 From: Thiago Bustamante Date: Thu, 27 Feb 2020 22:22:55 -0300 Subject: [PATCH] Fix OnlyInstantiableByContainer --- package-lock.json | 2 +- package.json | 2 +- src/container/container-binding-config.ts | 12 ++--------- src/container/injection-handler.ts | 18 ++++++++-------- test/integration/ioc-container-tests.spec.ts | 11 ++++++++++ test/tsconfig.json | 2 +- .../container-binding-config.spec.ts | 4 ++-- test/unit/container/injection-handler.spec.ts | 21 +++---------------- 8 files changed, 30 insertions(+), 42 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1b82d36..6bbdd82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "typescript-ioc", - "version": "3.0.1", + "version": "3.0.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index f31cb06..46afa38 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "typescript-ioc", - "version": "3.0.1", + "version": "3.0.2", "description": "A Lightweight annotation-based dependency injection container for typescript.", "author": "Thiago da Rosa de Bustamante ", "scripts": { diff --git a/src/container/container-binding-config.ts b/src/container/container-binding-config.ts index fe4c1a5..88f8193 100644 --- a/src/container/container-binding-config.ts +++ b/src/container/container-binding-config.ts @@ -82,17 +82,9 @@ export class IoCBindConfig implements Config { if (!this.iocScope) { this.scope(Scope.Local); } - if (this.decoratedConstructor) { - return this.getContainerManagedInstance(context); - } else { - return this.iocScope.resolve(this.iocFactory, this.source, context); - } - } - - private getContainerManagedInstance(context: BuildContext) { - InjectorHandler.unblockInstantiation(this.source); + InjectorHandler.unblockInstantiation(); const instance = this.iocScope.resolve(this.iocFactory, this.source, context); - InjectorHandler.blockInstantiation(this.source); + InjectorHandler.blockInstantiation(); return instance; } diff --git a/src/container/injection-handler.ts b/src/container/injection-handler.ts index eef2d6c..a02e33e 100644 --- a/src/container/injection-handler.ts +++ b/src/container/injection-handler.ts @@ -2,7 +2,6 @@ import { InstanceFactory } from './container-types'; import { BuildContext } from '../model'; const BUILD_CONTEXT_KEY = '__BuildContext'; -const BLOCK_INSTANTIATION_KEY = '__block_Instantiation'; const IOC_WRAPPER_CLASS = 'ioc_wrapper'; /** @@ -10,6 +9,8 @@ const IOC_WRAPPER_CLASS = 'ioc_wrapper'; */ export class InjectorHandler { public static constructorNameRegEx = /function (\w*)/; + private static instantiationsBlocked = true; + public static instrumentConstructor(source: Function) { let newConstructor: any; @@ -17,20 +18,19 @@ export class InjectorHandler { newConstructor = class ioc_wrapper extends (source as FunctionConstructor) { constructor(...args: Array) { super(...args); - InjectorHandler.assertInstantiable(source); + InjectorHandler.assertInstantiable(); } }; newConstructor['__parent'] = source; - InjectorHandler.blockInstantiation(source); return newConstructor; } - public static blockInstantiation(source: Function) { - source[BLOCK_INSTANTIATION_KEY] = true; + public static blockInstantiation() { + InjectorHandler.instantiationsBlocked = true; } - public static unblockInstantiation(source: Function) { - source[BLOCK_INSTANTIATION_KEY] = false; + public static unblockInstantiation() { + InjectorHandler.instantiationsBlocked = false; } public static getConstructorFromType(target: Function): FunctionConstructor { @@ -92,8 +92,8 @@ export class InjectorHandler { } } - private static assertInstantiable(target: any) { - if (target[BLOCK_INSTANTIATION_KEY]) { + private static assertInstantiable() { + if (InjectorHandler.instantiationsBlocked) { throw new TypeError('Can not instantiate it. The instantiation is blocked for this class. ' + 'Ask Container for it, using Container.get'); } diff --git a/test/integration/ioc-container-tests.spec.ts b/test/integration/ioc-container-tests.spec.ts index e2939c9..0aaef9e 100644 --- a/test/integration/ioc-container-tests.spec.ts +++ b/test/integration/ioc-container-tests.spec.ts @@ -443,6 +443,17 @@ describe('@OnlyInstantiableByContainer decorator', () => { expect(instance).toBeDefined(); }); + it('should allow Container instantiation of Singleton classes with instrumented parent.', () => { + @OnlyInstantiableByContainer + class First { } + + @OnlyInstantiableByContainer + class Second extends First { } + + const instance: First = Container.get(Second); + expect(instance).toBeDefined(); + }); + it('should allow scope change to Local from Singleton.', () => { Container.bind(SingletonInstantiation).scope(Scope.Local); const instance: SingletonInstantiation = Container.get(SingletonInstantiation); diff --git a/test/tsconfig.json b/test/tsconfig.json index 6a11ef0..07f63b3 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -18,7 +18,7 @@ "removeComments": true, "sourceMap": true, "strictNullChecks": false, - "target": "es5" + "target": "es6" }, "include": [ "**/*.spec.ts" diff --git a/test/unit/container/container-binding-config.spec.ts b/test/unit/container/container-binding-config.spec.ts index f1399d2..f07cd5e 100644 --- a/test/unit/container/container-binding-config.spec.ts +++ b/test/unit/container/container-binding-config.spec.ts @@ -141,9 +141,9 @@ describe('IoCBindConfig', () => { bindConfig.instrumentConstructor(); expect(bindConfig.getInstance(buildContext)).toEqual(instance); - expect(mockInjectorBlockInstantiation).toBeCalledWith(MyBaseType); + expect(mockInjectorBlockInstantiation).toBeCalled(); expect(bindConfig.iocScope.resolve).toBeCalledWith(bindConfig.iocFactory, MyBaseType, buildContext); - expect(mockInjectorUnBlockInstantiation).toBeCalledWith(MyBaseType); + expect(mockInjectorUnBlockInstantiation).toBeCalledWith(); }); }); diff --git a/test/unit/container/injection-handler.spec.ts b/test/unit/container/injection-handler.spec.ts index 202bf09..fb42789 100644 --- a/test/unit/container/injection-handler.spec.ts +++ b/test/unit/container/injection-handler.spec.ts @@ -9,42 +9,27 @@ describe('InjectorHandler', () => { const newConstructor = InjectorHandler.instrumentConstructor(MyBaseType); expect(newConstructor.name).toEqual('ioc_wrapper'); expect(newConstructor['__parent']).toEqual(MyBaseType); - expect((MyBaseType as any)['__block_Instantiation']).toBeTruthy(); }); it('should keep creating valid instances for the baseType', () => { class MyBaseType { } const newConstructor = InjectorHandler.instrumentConstructor(MyBaseType); - InjectorHandler.unblockInstantiation(MyBaseType); + InjectorHandler.unblockInstantiation(); expect(new newConstructor()).toBeInstanceOf(MyBaseType); + InjectorHandler.blockInstantiation(); }); }); describe('blockInstantiation()', () => { - it('should configure the constructor as non instantiable', () => { - class MyBaseType { } - InjectorHandler.blockInstantiation(MyBaseType); - expect((MyBaseType as any)['__block_Instantiation']).toBeTruthy(); - }); - it('should avoid that instrumented constructor create instances', () => { class MyBaseType { } const newConstructor = InjectorHandler.instrumentConstructor(MyBaseType); - InjectorHandler.blockInstantiation(MyBaseType); + InjectorHandler.blockInstantiation(); expect(() => new newConstructor()) .toThrow(new TypeError('Can not instantiate it. The instantiation is blocked for this class. Ask Container for it, using Container.get')); }); }); - describe('unblockInstantiation()', () => { - it('should configure the constructor as instantiable', () => { - class MyBaseType { } - InjectorHandler.blockInstantiation(MyBaseType); - InjectorHandler.unblockInstantiation(MyBaseType); - expect((MyBaseType as any)['__block_Instantiation']).toBeFalsy(); - }); - }); - describe('injectContext()', () => { it('should inject the context as a hidden property into the target', () => { class MyBaseType { }