fix(ivy): reorder provider type checks to align with VE (#34433)
The ordering matters because we don't currently throw if multiple configurations are provided (i.e. provider has *both* useExisting and useFactory). We should actually throw an error in this case, but to avoid another breaking change in v9, this PR simply aligns the Ivy behavior with ViewEngine. PR Close #34433
This commit is contained in:
parent
835ed0f35f
commit
357a0733c7
|
@ -482,10 +482,10 @@ export function providerToFactory(
|
||||||
} else {
|
} else {
|
||||||
if (isValueProvider(provider)) {
|
if (isValueProvider(provider)) {
|
||||||
factory = () => resolveForwardRef(provider.useValue);
|
factory = () => resolveForwardRef(provider.useValue);
|
||||||
} else if (isExistingProvider(provider)) {
|
|
||||||
factory = () => ɵɵinject(resolveForwardRef(provider.useExisting));
|
|
||||||
} else if (isFactoryProvider(provider)) {
|
} else if (isFactoryProvider(provider)) {
|
||||||
factory = () => provider.useFactory(...injectArgs(provider.deps || []));
|
factory = () => provider.useFactory(...injectArgs(provider.deps || []));
|
||||||
|
} else if (isExistingProvider(provider)) {
|
||||||
|
factory = () => ɵɵinject(resolveForwardRef(provider.useExisting));
|
||||||
} else {
|
} else {
|
||||||
const classRef = resolveForwardRef(
|
const classRef = resolveForwardRef(
|
||||||
provider &&
|
provider &&
|
||||||
|
|
|
@ -1901,4 +1901,36 @@ describe('di', () => {
|
||||||
|
|
||||||
expect(fixture.nativeElement.textContent.trim()).toBe('2 (transformed) items');
|
expect(fixture.nativeElement.textContent.trim()).toBe('2 (transformed) items');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: https://angular-team.atlassian.net/browse/FW-1779
|
||||||
|
it('should prioritize useFactory over useExisting', () => {
|
||||||
|
abstract class Base {}
|
||||||
|
@Directive({selector: '[dirA]'})
|
||||||
|
class DirA implements Base {
|
||||||
|
}
|
||||||
|
@Directive({selector: '[dirB]'})
|
||||||
|
class DirB implements Base {
|
||||||
|
}
|
||||||
|
|
||||||
|
const PROVIDER = {provide: Base, useExisting: DirA, useFactory: () => new DirB()};
|
||||||
|
|
||||||
|
@Component({selector: 'child', template: '', providers: [PROVIDER]})
|
||||||
|
class Child {
|
||||||
|
constructor(readonly base: Base) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({template: `<div dirA> <child></child> </div>`})
|
||||||
|
class App {
|
||||||
|
@ViewChild(DirA) dirA !: DirA;
|
||||||
|
@ViewChild(Child) child !: Child;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fixture = TestBed.configureTestingModule({declarations: [DirA, DirB, App, Child]})
|
||||||
|
.createComponent(App);
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.componentInstance.dirA)
|
||||||
|
.not.toEqual(
|
||||||
|
fixture.componentInstance.child.base,
|
||||||
|
'should not get dirA from parent, but create new dirB from the useFactory provider');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue