fix(ivy): set proper implementation for module injector (#28667)

Prior to this change we used current injector implementation for module injector, which was causing problems and produces circular dependencies in case the same token is referenced (with @SkipSelf flag) in the `deps` array. The origin of the problem was that once `directiveInject` implementation becomes active, it was used for module injector as well, thus searching deps in Component/Directive DI scope. This fix sets `injectInjectorOnly` implementation for module injector to resolve the problem.

PR Close #28667
This commit is contained in:
Andrew Kushnir
2019-02-12 09:46:39 -08:00
committed by Miško Hevery
parent 5cafd44654
commit 553f80ff46
4 changed files with 259 additions and 571 deletions

View File

@ -10,6 +10,7 @@ import {ChangeDetectorRef as ViewEngine_ChangeDetectorRef} from '../change_detec
import {InjectionToken} from '../di/injection_token';
import {Injector} from '../di/injector';
import {inject} from '../di/injector_compatibility';
import {InjectFlags} from '../di/interface/injector';
import {Type} from '../interface/type';
import {ComponentFactory as viewEngine_ComponentFactory, ComponentRef as viewEngine_ComponentRef} from '../linker/component_factory';
import {ComponentFactoryResolver as viewEngine_ComponentFactoryResolver} from '../linker/component_factory_resolver';
@ -77,8 +78,8 @@ export const SCHEDULER = new InjectionToken<((fn: () => void) => void)>('SCHEDUL
function createChainedInjector(rootViewInjector: Injector, moduleInjector: Injector): Injector {
return {
get: <T>(token: Type<T>| InjectionToken<T>, notFoundValue?: T): T => {
const value = rootViewInjector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR);
get: <T>(token: Type<T>| InjectionToken<T>, notFoundValue?: T, flags?: InjectFlags): T => {
const value = rootViewInjector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as T, flags);
if (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR ||
notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) {
@ -90,7 +91,7 @@ function createChainedInjector(rootViewInjector: Injector, moduleInjector: Injec
return value;
}
return moduleInjector.get(token, notFoundValue);
return moduleInjector.get(token, notFoundValue, flags);
}
};
}

View File

@ -392,10 +392,18 @@ export function getOrCreateInjectable<T>(
if ((flags & (InjectFlags.Self | InjectFlags.Host)) === 0) {
const moduleInjector = lView[INJECTOR];
if (moduleInjector) {
return moduleInjector.get(token, notFoundValue, flags & InjectFlags.Optional);
} else {
return injectRootLimpMode(token, notFoundValue, flags & InjectFlags.Optional);
// switch to `injectInjectorOnly` implementation for module injector, since module injector
// should not have access to Component/Directive DI scope (that may happen through
// `directiveInject` implementation)
const previousInjectImplementation = setInjectImplementation(undefined);
try {
if (moduleInjector) {
return moduleInjector.get(token, notFoundValue, flags & InjectFlags.Optional);
} else {
return injectRootLimpMode(token, notFoundValue, flags & InjectFlags.Optional);
}
} finally {
setInjectImplementation(previousInjectImplementation);
}
}
if (flags & InjectFlags.Optional) {