fix(core): support ngInjectableDef on types with inherited ɵprov (#33732)

The `ngInjectableDef` property was renamed to `ɵprov`, but core must
still support both because there are published libraries that use the
older term.

We are only interested in such properties that are defined directly on
the type being injected, not on base classes. So there is a check that
the defintion is specifically for the given type.

Previously if you tried to inject a class that had `ngInjectableDef` but
also inherited `ɵprov` then the check would fail on the `ɵprov` property
and never even try the `ngInjectableDef` property resulting in a failed
injection.

This commit fixes this by attempting to find each of the properties
independently.

Fixes https://github.com/angular/ngcc-validation/pull/526

PR Close #33732
This commit is contained in:
Pete Bacon Darwin
2019-11-11 15:01:58 +00:00
committed by Kara Erickson
parent 2f0b8bc541
commit 641c671bac
4 changed files with 48 additions and 8 deletions

View File

@ -160,6 +160,32 @@ describe('ngInjectableDef Bazel Integration', () => {
expect(() => TestBed.inject(ChildService).value).toThrowError(/ChildService/);
});
it('uses legacy `ngInjectable` property even if it inherits from a class that has `ɵprov` property',
() => {
@Injectable({
providedIn: 'root',
useValue: new ParentService('parent'),
})
class ParentService {
constructor(public value: string) {}
}
// ChildServices exteds ParentService but does not have @Injectable
class ChildService extends ParentService {
constructor(value: string) { super(value); }
static ngInjectableDef = {
providedIn: 'root',
factory: () => new ChildService('child'),
token: ChildService,
};
}
TestBed.configureTestingModule({});
// We are asserting that system throws an error, rather than taking the inherited
// annotation.
expect(TestBed.inject(ChildService).value).toEqual('child');
});
it('NgModule injector understands requests for INJECTABLE', () => {
TestBed.configureTestingModule({
providers: [{provide: 'foo', useValue: 'bar'}],