From 0c6dc45c85e86cdb0e87c80a4a7c7cb3417781d4 Mon Sep 17 00:00:00 2001 From: Vikram Subramanian Date: Thu, 26 Apr 2018 06:25:30 -0700 Subject: [PATCH] fix(core): avoid eager providers re-initialization (#23559) Fix a corner case where eager providers were getting constructed twice if the provider was requested before the initialization of the NgModule is complete. PR Close #23559 --- packages/core/src/view/ng_module.ts | 5 +++- .../test/linker/ng_module_integration_spec.ts | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/packages/core/src/view/ng_module.ts b/packages/core/src/view/ng_module.ts index 20f4ef060d..4a7d6a19ad 100644 --- a/packages/core/src/view/ng_module.ts +++ b/packages/core/src/view/ng_module.ts @@ -68,7 +68,10 @@ export function initNgModule(data: NgModuleData) { for (let i = 0; i < def.providers.length; i++) { const provDef = def.providers[i]; if (!(provDef.flags & NodeFlags.LazyProvider)) { - providers[i] = _createProviderInstance(data, provDef); + // Make sure the provider has not been already initialized outside this loop. + if (providers[i] === undefined) { + providers[i] = _createProviderInstance(data, provDef); + } } } } diff --git a/packages/core/test/linker/ng_module_integration_spec.ts b/packages/core/test/linker/ng_module_integration_spec.ts index 70194daa79..0ef56663cb 100644 --- a/packages/core/test/linker/ng_module_integration_spec.ts +++ b/packages/core/test/linker/ng_module_integration_spec.ts @@ -883,6 +883,35 @@ function declareTests({useJit}: {useJit: boolean}) { expect(createModule(MyModule).injector.get('eager1')).toBe('v1: v2'); }); + + it('eager providers should get initialized only once', () => { + @Injectable() + class MyService1 { + public innerService: MyService2; + constructor(injector: Injector) { + // Create MyService2 before it it's initialized by TestModule. + this.innerService = injector.get(MyService2); + } + } + + @Injectable() + class MyService2 { + constructor() {} + } + + @NgModule({ + providers: [MyService1, MyService2], + }) + class TestModule { + constructor(public service1: MyService1, public service2: MyService2) {} + } + + const moduleRef = createModule(TestModule, injector); + const module = moduleRef.instance; + + // MyService2 should not get initialized twice. + expect(module.service1.innerService).toBe(module.service2); + }); }); it('should throw when no provider defined', () => {