Skip to content

Commit 980b9f8

Browse files
author
Thiago Bustamante
committed
Fix OnlyInstantiableByContainer
1 parent e7df1d7 commit 980b9f8

File tree

8 files changed

+30
-42
lines changed

8 files changed

+30
-42
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "typescript-ioc",
3-
"version": "3.0.1",
3+
"version": "3.0.2",
44
"description": "A Lightweight annotation-based dependency injection container for typescript.",
55
"author": "Thiago da Rosa de Bustamante <trbustamante@gmail.com>",
66
"scripts": {

src/container/container-binding-config.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,9 @@ export class IoCBindConfig implements Config {
8282
if (!this.iocScope) {
8383
this.scope(Scope.Local);
8484
}
85-
if (this.decoratedConstructor) {
86-
return this.getContainerManagedInstance(context);
87-
} else {
88-
return this.iocScope.resolve(this.iocFactory, this.source, context);
89-
}
90-
}
91-
92-
private getContainerManagedInstance(context: BuildContext) {
93-
InjectorHandler.unblockInstantiation(this.source);
85+
InjectorHandler.unblockInstantiation();
9486
const instance = this.iocScope.resolve(this.iocFactory, this.source, context);
95-
InjectorHandler.blockInstantiation(this.source);
87+
InjectorHandler.blockInstantiation();
9688
return instance;
9789
}
9890

src/container/injection-handler.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,35 @@ import { InstanceFactory } from './container-types';
22
import { BuildContext } from '../model';
33

44
const BUILD_CONTEXT_KEY = '__BuildContext';
5-
const BLOCK_INSTANTIATION_KEY = '__block_Instantiation';
65
const IOC_WRAPPER_CLASS = 'ioc_wrapper';
76

87
/**
98
* Utility class to handle injection behavior on class decorations.
109
*/
1110
export class InjectorHandler {
1211
public static constructorNameRegEx = /function (\w*)/;
12+
private static instantiationsBlocked = true;
13+
1314

1415
public static instrumentConstructor(source: Function) {
1516
let newConstructor: any;
1617
// tslint:disable-next-line:class-name
1718
newConstructor = class ioc_wrapper extends (source as FunctionConstructor) {
1819
constructor(...args: Array<any>) {
1920
super(...args);
20-
InjectorHandler.assertInstantiable(source);
21+
InjectorHandler.assertInstantiable();
2122
}
2223
};
2324
newConstructor['__parent'] = source;
24-
InjectorHandler.blockInstantiation(source);
2525
return newConstructor;
2626
}
2727

28-
public static blockInstantiation(source: Function) {
29-
source[BLOCK_INSTANTIATION_KEY] = true;
28+
public static blockInstantiation() {
29+
InjectorHandler.instantiationsBlocked = true;
3030
}
3131

32-
public static unblockInstantiation(source: Function) {
33-
source[BLOCK_INSTANTIATION_KEY] = false;
32+
public static unblockInstantiation() {
33+
InjectorHandler.instantiationsBlocked = false;
3434
}
3535

3636
public static getConstructorFromType(target: Function): FunctionConstructor {
@@ -92,8 +92,8 @@ export class InjectorHandler {
9292
}
9393
}
9494

95-
private static assertInstantiable(target: any) {
96-
if (target[BLOCK_INSTANTIATION_KEY]) {
95+
private static assertInstantiable() {
96+
if (InjectorHandler.instantiationsBlocked) {
9797
throw new TypeError('Can not instantiate it. The instantiation is blocked for this class. ' +
9898
'Ask Container for it, using Container.get');
9999
}

test/integration/ioc-container-tests.spec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,17 @@ describe('@OnlyInstantiableByContainer decorator', () => {
443443
expect(instance).toBeDefined();
444444
});
445445

446+
it('should allow Container instantiation of Singleton classes with instrumented parent.', () => {
447+
@OnlyInstantiableByContainer
448+
class First { }
449+
450+
@OnlyInstantiableByContainer
451+
class Second extends First { }
452+
453+
const instance: First = Container.get(Second);
454+
expect(instance).toBeDefined();
455+
});
456+
446457
it('should allow scope change to Local from Singleton.', () => {
447458
Container.bind(SingletonInstantiation).scope(Scope.Local);
448459
const instance: SingletonInstantiation = Container.get(SingletonInstantiation);

test/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"removeComments": true,
1919
"sourceMap": true,
2020
"strictNullChecks": false,
21-
"target": "es5"
21+
"target": "es6"
2222
},
2323
"include": [
2424
"**/*.spec.ts"

test/unit/container/container-binding-config.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,9 @@ describe('IoCBindConfig', () => {
141141
bindConfig.instrumentConstructor();
142142

143143
expect(bindConfig.getInstance(buildContext)).toEqual(instance);
144-
expect(mockInjectorBlockInstantiation).toBeCalledWith(MyBaseType);
144+
expect(mockInjectorBlockInstantiation).toBeCalled();
145145
expect(bindConfig.iocScope.resolve).toBeCalledWith(bindConfig.iocFactory, MyBaseType, buildContext);
146-
expect(mockInjectorUnBlockInstantiation).toBeCalledWith(MyBaseType);
146+
expect(mockInjectorUnBlockInstantiation).toBeCalledWith();
147147
});
148148
});
149149

test/unit/container/injection-handler.spec.ts

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,27 @@ describe('InjectorHandler', () => {
99
const newConstructor = InjectorHandler.instrumentConstructor(MyBaseType);
1010
expect(newConstructor.name).toEqual('ioc_wrapper');
1111
expect(newConstructor['__parent']).toEqual(MyBaseType);
12-
expect((MyBaseType as any)['__block_Instantiation']).toBeTruthy();
1312
});
1413

1514
it('should keep creating valid instances for the baseType', () => {
1615
class MyBaseType { }
1716
const newConstructor = InjectorHandler.instrumentConstructor(MyBaseType);
18-
InjectorHandler.unblockInstantiation(MyBaseType);
17+
InjectorHandler.unblockInstantiation();
1918
expect(new newConstructor()).toBeInstanceOf(MyBaseType);
19+
InjectorHandler.blockInstantiation();
2020
});
2121
});
2222

2323
describe('blockInstantiation()', () => {
24-
it('should configure the constructor as non instantiable', () => {
25-
class MyBaseType { }
26-
InjectorHandler.blockInstantiation(MyBaseType);
27-
expect((MyBaseType as any)['__block_Instantiation']).toBeTruthy();
28-
});
29-
3024
it('should avoid that instrumented constructor create instances', () => {
3125
class MyBaseType { }
3226
const newConstructor = InjectorHandler.instrumentConstructor(MyBaseType);
33-
InjectorHandler.blockInstantiation(MyBaseType);
27+
InjectorHandler.blockInstantiation();
3428
expect(() => new newConstructor())
3529
.toThrow(new TypeError('Can not instantiate it. The instantiation is blocked for this class. Ask Container for it, using Container.get'));
3630
});
3731
});
3832

39-
describe('unblockInstantiation()', () => {
40-
it('should configure the constructor as instantiable', () => {
41-
class MyBaseType { }
42-
InjectorHandler.blockInstantiation(MyBaseType);
43-
InjectorHandler.unblockInstantiation(MyBaseType);
44-
expect((MyBaseType as any)['__block_Instantiation']).toBeFalsy();
45-
});
46-
});
47-
4833
describe('injectContext()', () => {
4934
it('should inject the context as a hidden property into the target', () => {
5035
class MyBaseType { }

0 commit comments

Comments
 (0)