refactor(ivy): generate ngFactoryDef for injectables (#32433)
With #31953 we moved the factories for components, directives and pipes into a new field called `ngFactoryDef`, however I decided not to do it for injectables, because they needed some extra logic. These changes set up the `ngFactoryDef` for injectables as well. For reference, the extra logic mentioned above is that for injectables we have two code paths: 1. For injectables that don't configure how they should be instantiated, we create a `factory` that proxies to `ngFactoryDef`: ``` // Source @Injectable() class Service {} // Output class Service { static ngInjectableDef = defineInjectable({ factory: () => Service.ngFactoryFn(), }); static ngFactoryFn: (t) => new (t || Service)(); } ``` 2. For injectables that do configure how they're created, we keep the `ngFactoryDef` and generate the factory based on the metadata: ``` // Source @Injectable({ useValue: DEFAULT_IMPL, }) class Service {} // Output export class Service { static ngInjectableDef = defineInjectable({ factory: () => DEFAULT_IMPL, }); static ngFactoryFn: (t) => new (t || Service)(); } ``` PR Close #32433
This commit is contained in:
@ -16,7 +16,7 @@ import {Type} from '../interface/type';
|
||||
import {assertDefined, assertEqual} from '../util/assert';
|
||||
|
||||
import {getFactoryDef} from './definition';
|
||||
import {NG_ELEMENT_ID} from './fields';
|
||||
import {NG_ELEMENT_ID, NG_FACTORY_DEF} from './fields';
|
||||
import {DirectiveDef, FactoryFn} from './interfaces/definition';
|
||||
import {NO_PARENT_INJECTOR, NodeInjectorFactory, PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags, TNODE, isFactory} from './interfaces/injector';
|
||||
import {AttributeMarker, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType} from './interfaces/node';
|
||||
@ -642,9 +642,11 @@ export function ɵɵgetFactoryOf<T>(type: Type<any>): FactoryFn<T>|null {
|
||||
}) as any;
|
||||
}
|
||||
|
||||
// TODO(crisbeto): unify injectable factories with getFactory.
|
||||
const def = getInjectableDef<T>(typeAny) || getInjectorDef<T>(typeAny);
|
||||
const factory = def && def.factory || getFactoryDef<T>(typeAny);
|
||||
let factory = getFactoryDef<T>(typeAny);
|
||||
if (factory === null) {
|
||||
const injectorDef = getInjectorDef<T>(typeAny);
|
||||
factory = injectorDef && injectorDef.factory;
|
||||
}
|
||||
return factory || null;
|
||||
}
|
||||
|
||||
@ -653,7 +655,7 @@ export function ɵɵgetFactoryOf<T>(type: Type<any>): FactoryFn<T>|null {
|
||||
*/
|
||||
export function ɵɵgetInheritedFactory<T>(type: Type<any>): (type: Type<T>) => T {
|
||||
const proto = Object.getPrototypeOf(type.prototype).constructor as Type<any>;
|
||||
const factory = ɵɵgetFactoryOf<T>(proto);
|
||||
const factory = (proto as any)[NG_FACTORY_DEF] || ɵɵgetFactoryOf<T>(proto);
|
||||
if (factory !== null) {
|
||||
return factory;
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user