fix(ivy): directiveInject should fall back to inject (#29948)
If a component has its definition set by defineComponent (as opposed to JIT getter), then it will generate a factory that uses directiveInject() to retrieve its dependencies. This can be problematic in test code because tests could use the injection utility before bootstrapping the component, and directiveInject() relies on the view having been created. This commit tweaks directiveInject() to fall back to inject() if the view has not been created. This will allow injection to work in tests even if it is called before the component is bootstrapped. PR Close #29948
This commit is contained in:
parent
ca2462cff7
commit
d9c39dcab0
|
@ -6,6 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {InjectFlags, InjectionToken, resolveForwardRef} from '../../di';
|
||||
import {ɵɵinject} from '../../di/injector_compatibility';
|
||||
import {Type} from '../../interface/type';
|
||||
import {getOrCreateInjectable, injectAttributeImpl} from '../di';
|
||||
import {TContainerNode, TElementContainerNode, TElementNode} from '../interfaces/node';
|
||||
|
@ -40,9 +41,14 @@ export function ɵɵdirectiveInject<T>(token: Type<T>| InjectionToken<T>, flags:
|
|||
export function ɵɵdirectiveInject<T>(
|
||||
token: Type<T>| InjectionToken<T>, flags = InjectFlags.Default): T|null {
|
||||
token = resolveForwardRef(token);
|
||||
const lView = getLView();
|
||||
// Fall back to inject() if view hasn't been created. This situation can happen in tests
|
||||
// if inject utilities are used before bootstrapping.
|
||||
if (lView == null) return ɵɵinject(token, flags);
|
||||
|
||||
return getOrCreateInjectable<T>(
|
||||
getPreviousOrParentTNode() as TElementNode | TContainerNode | TElementContainerNode,
|
||||
getLView(), token, flags);
|
||||
getPreviousOrParentTNode() as TElementNode | TContainerNode | TElementContainerNode, lView,
|
||||
token, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import {Component, Directive, Inject, Injectable, InjectionToken} from '@angular/core';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {TestBed, async, inject} from '@angular/core/testing';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {onlyInIvy} from '@angular/private/testing';
|
||||
|
||||
|
@ -271,5 +271,16 @@ describe('providers', () => {
|
|||
const myCompInstance = fixture.debugElement.query(By.css('div')).injector.get(MyDir);
|
||||
expect(myCompInstance.svc.value).toEqual('some value');
|
||||
});
|
||||
|
||||
describe('injection without bootstrapping', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({declarations: [MyComp], providers: [MyComp, MyService]});
|
||||
});
|
||||
|
||||
it('should support injecting without bootstrapping',
|
||||
async(inject([MyComp, MyService], (comp: MyComp, service: MyService) => {
|
||||
expect(comp.svc.value).toEqual('some value');
|
||||
})));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -359,6 +359,9 @@
|
|||
{
|
||||
"name": "_c9"
|
||||
},
|
||||
{
|
||||
"name": "_currentInjector"
|
||||
},
|
||||
{
|
||||
"name": "_currentNamespace"
|
||||
},
|
||||
|
@ -902,6 +905,9 @@
|
|||
{
|
||||
"name": "injectElementRef"
|
||||
},
|
||||
{
|
||||
"name": "injectInjectorOnly"
|
||||
},
|
||||
{
|
||||
"name": "injectRootLimpMode"
|
||||
},
|
||||
|
@ -1355,6 +1361,9 @@
|
|||
{
|
||||
"name": "ɵɵgetCurrentView"
|
||||
},
|
||||
{
|
||||
"name": "ɵɵinject"
|
||||
},
|
||||
{
|
||||
"name": "ɵɵinterpolation1"
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue