feat(ivy): support injecting Renderer2 (#25523)

PR Close #25523
This commit is contained in:
Marc Laval 2018-08-16 17:43:29 +02:00 committed by Misko Hevery
parent ccb4a396f0
commit 00f13110be
15 changed files with 93 additions and 6 deletions

View File

@ -75,6 +75,9 @@ export function getConstructorDependencies(
case 'ViewContainerRef': case 'ViewContainerRef':
resolved = R3ResolvedDependencyType.ViewContainerRef; resolved = R3ResolvedDependencyType.ViewContainerRef;
break; break;
case 'Renderer2':
resolved = R3ResolvedDependencyType.Renderer2;
break;
default: default:
// Leave as a Token or Attribute. // Leave as a Token or Attribute.
} }

View File

@ -49,6 +49,7 @@ export class ElementRef {}
export class Injector {} export class Injector {}
export class TemplateRef<T = any> {} export class TemplateRef<T = any> {}
export class ViewContainerRef {} export class ViewContainerRef {}
export class Renderer2 {}
export class ɵNgModuleFactory<T> { export class ɵNgModuleFactory<T> {
constructor(public clazz: T) {} constructor(public clazz: T) {}
} }

View File

@ -448,6 +448,7 @@ describe('ngtsc behavioral tests', () => {
Component, Component,
ElementRef, ElementRef,
Injector, Injector,
Renderer2,
TemplateRef, TemplateRef,
ViewContainerRef, ViewContainerRef,
} from '@angular/core'; } from '@angular/core';
@ -462,6 +463,7 @@ describe('ngtsc behavioral tests', () => {
cdr: ChangeDetectorRef, cdr: ChangeDetectorRef,
er: ElementRef, er: ElementRef,
i: Injector, i: Injector,
r2: Renderer2,
tr: TemplateRef, tr: TemplateRef,
vcr: ViewContainerRef, vcr: ViewContainerRef,
) {} ) {}
@ -474,7 +476,7 @@ describe('ngtsc behavioral tests', () => {
const jsContents = getContents('test.js'); const jsContents = getContents('test.js');
expect(jsContents) expect(jsContents)
.toContain( .toContain(
`factory: function FooCmp_Factory(t) { return new (t || FooCmp)(i0.ɵinjectAttribute("test"), i0.ɵinjectChangeDetectorRef(), i0.ɵinjectElementRef(), i0.ɵdirectiveInject(i0.INJECTOR), i0.ɵinjectTemplateRef(), i0.ɵinjectViewContainerRef()); }`); `factory: function FooCmp_Factory(t) { return new (t || FooCmp)(i0.ɵinjectAttribute("test"), i0.ɵinjectChangeDetectorRef(), i0.ɵinjectElementRef(), i0.ɵdirectiveInject(i0.INJECTOR), i0.ɵinjectRenderer2(), i0.ɵinjectTemplateRef(), i0.ɵinjectViewContainerRef()); }`);
}); });
it('should generate queries for components', () => { it('should generate queries for components', () => {

View File

@ -28,6 +28,7 @@ export class Identifiers {
}; };
static QueryList: o.ExternalReference = {name: 'QueryList', moduleName: CORE}; static QueryList: o.ExternalReference = {name: 'QueryList', moduleName: CORE};
static TemplateRef: o.ExternalReference = {name: 'TemplateRef', moduleName: CORE}; static TemplateRef: o.ExternalReference = {name: 'TemplateRef', moduleName: CORE};
static Renderer2: o.ExternalReference = {name: 'Renderer2', moduleName: CORE};
static CodegenComponentFactoryResolver: o.ExternalReference = { static CodegenComponentFactoryResolver: o.ExternalReference = {
name: 'ɵCodegenComponentFactoryResolver', name: 'ɵCodegenComponentFactoryResolver',
moduleName: CORE, moduleName: CORE,

View File

@ -120,6 +120,11 @@ export enum R3ResolvedDependencyType {
* The dependency is for `ChangeDetectorRef`. * The dependency is for `ChangeDetectorRef`.
*/ */
ChangeDetectorRef = 6, ChangeDetectorRef = 6,
/**
* The dependency is for `Renderer2`.
*/
Renderer2 = 7,
} }
/** /**
@ -285,6 +290,8 @@ function compileInjectDependency(
return o.importExpr(R3.injectViewContainerRef).callFn([]); return o.importExpr(R3.injectViewContainerRef).callFn([]);
case R3ResolvedDependencyType.ChangeDetectorRef: case R3ResolvedDependencyType.ChangeDetectorRef:
return o.importExpr(R3.injectChangeDetectorRef).callFn([]); return o.importExpr(R3.injectChangeDetectorRef).callFn([]);
case R3ResolvedDependencyType.Renderer2:
return o.importExpr(R3.injectRenderer2).callFn([]);
default: default:
return unsupported( return unsupported(
`Unknown R3ResolvedDependencyType: ${R3ResolvedDependencyType[dep.resolved]}`); `Unknown R3ResolvedDependencyType: ${R3ResolvedDependencyType[dep.resolved]}`);
@ -305,6 +312,7 @@ export function dependenciesFromGlobalMetadata(
const templateRef = reflector.resolveExternalReference(Identifiers.TemplateRef); const templateRef = reflector.resolveExternalReference(Identifiers.TemplateRef);
const viewContainerRef = reflector.resolveExternalReference(Identifiers.ViewContainerRef); const viewContainerRef = reflector.resolveExternalReference(Identifiers.ViewContainerRef);
const injectorRef = reflector.resolveExternalReference(Identifiers.Injector); const injectorRef = reflector.resolveExternalReference(Identifiers.Injector);
const renderer2 = reflector.resolveExternalReference(Identifiers.Renderer2);
// Iterate through the type's DI dependencies and produce `R3DependencyMetadata` for each of them. // Iterate through the type's DI dependencies and produce `R3DependencyMetadata` for each of them.
const deps: R3DependencyMetadata[] = []; const deps: R3DependencyMetadata[] = [];
@ -320,6 +328,8 @@ export function dependenciesFromGlobalMetadata(
resolved = R3ResolvedDependencyType.ViewContainerRef; resolved = R3ResolvedDependencyType.ViewContainerRef;
} else if (tokenRef === injectorRef) { } else if (tokenRef === injectorRef) {
resolved = R3ResolvedDependencyType.Injector; resolved = R3ResolvedDependencyType.Injector;
} else if (tokenRef === renderer2) {
resolved = R3ResolvedDependencyType.Renderer2;
} else if (dependency.isAttribute) { } else if (dependency.isAttribute) {
resolved = R3ResolvedDependencyType.Attribute; resolved = R3ResolvedDependencyType.Attribute;
} }

View File

@ -116,6 +116,8 @@ export class Identifiers {
static injectChangeDetectorRef: static injectChangeDetectorRef:
o.ExternalReference = {name: 'ɵinjectChangeDetectorRef', moduleName: CORE}; o.ExternalReference = {name: 'ɵinjectChangeDetectorRef', moduleName: CORE};
static injectRenderer2: o.ExternalReference = {name: 'ɵinjectRenderer2', moduleName: CORE};
static directiveInject: o.ExternalReference = {name: 'ɵdirectiveInject', moduleName: CORE}; static directiveInject: o.ExternalReference = {name: 'ɵdirectiveInject', moduleName: CORE};
static templateRefExtractor: static templateRefExtractor:

View File

@ -25,6 +25,7 @@ export {
injectTemplateRef as ɵinjectTemplateRef, injectTemplateRef as ɵinjectTemplateRef,
injectViewContainerRef as ɵinjectViewContainerRef, injectViewContainerRef as ɵinjectViewContainerRef,
injectChangeDetectorRef as ɵinjectChangeDetectorRef, injectChangeDetectorRef as ɵinjectChangeDetectorRef,
injectRenderer2 as ɵinjectRenderer2,
injectAttribute as ɵinjectAttribute, injectAttribute as ɵinjectAttribute,
getFactoryOf as ɵgetFactoryOf, getFactoryOf as ɵgetFactoryOf,
getInheritedFactory as ɵgetInheritedFactory, getInheritedFactory as ɵgetInheritedFactory,

View File

@ -216,6 +216,7 @@ The goal is for the `@Component` (and friends) to be the compiler of template. S
| `injectElementRef()` | ✅ | ✅ | ✅ | | `injectElementRef()` | ✅ | ✅ | ✅ |
| `injectViewContainerRef()` | ✅ | ✅ | ✅ | | `injectViewContainerRef()` | ✅ | ✅ | ✅ |
| `injectTemplateRef()` | ✅ | ✅ | ✅ | | `injectTemplateRef()` | ✅ | ✅ | ✅ |
| `injectRenderer2()` | ✅ | ✅ | ✅ |
| default `inject()` with no injector | ❌ | ❌ | ❌ | | default `inject()` with no injector | ❌ | ❌ | ❌ |
| sanitization with no injector | ✅ | ✅ | ❌ | | sanitization with no injector | ✅ | ✅ | ❌ |

View File

@ -19,6 +19,7 @@ import {NgModuleRef as viewEngine_NgModuleRef} from '../linker/ng_module_factory
import {TemplateRef as viewEngine_TemplateRef} from '../linker/template_ref'; import {TemplateRef as viewEngine_TemplateRef} from '../linker/template_ref';
import {ViewContainerRef as viewEngine_ViewContainerRef} from '../linker/view_container_ref'; import {ViewContainerRef as viewEngine_ViewContainerRef} from '../linker/view_container_ref';
import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, ViewRef as viewEngine_ViewRef} from '../linker/view_ref'; import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, ViewRef as viewEngine_ViewRef} from '../linker/view_ref';
import {Renderer2} from '../render';
import {Type} from '../type'; import {Type} from '../type';
import {assertDefined, assertGreaterThan, assertLessThan} from './assert'; import {assertDefined, assertGreaterThan, assertLessThan} from './assert';
@ -29,7 +30,7 @@ import {DirectiveDefInternal, RenderFlags} from './interfaces/definition';
import {LInjector} from './interfaces/injector'; import {LInjector} from './interfaces/injector';
import {AttributeMarker, LContainerNode, LElementContainerNode, LElementNode, LNode, LNodeWithLocalRefs, LViewNode, TContainerNode, TElementNode, TNodeFlags, TNodeType} from './interfaces/node'; import {AttributeMarker, LContainerNode, LElementContainerNode, LElementNode, LNode, LNodeWithLocalRefs, LViewNode, TContainerNode, TElementNode, TNodeFlags, TNodeType} from './interfaces/node';
import {LQueries, QueryReadType} from './interfaces/query'; import {LQueries, QueryReadType} from './interfaces/query';
import {Renderer3} from './interfaces/renderer'; import {Renderer3, isProceduralRenderer} from './interfaces/renderer';
import {DIRECTIVES, HOST_NODE, INJECTOR, LViewData, QUERIES, RENDERER, TVIEW, TView} from './interfaces/view'; import {DIRECTIVES, HOST_NODE, INJECTOR, LViewData, QUERIES, RENDERER, TVIEW, TView} from './interfaces/view';
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert'; import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
import {addRemoveViewFromContainer, appendChild, detachView, getChildLNode, getParentLNode, insertView, removeView} from './node_manipulation'; import {addRemoveViewFromContainer, appendChild, detachView, getChildLNode, getParentLNode, insertView, removeView} from './node_manipulation';
@ -236,6 +237,10 @@ export function injectComponentFactoryResolver(): viewEngine_ComponentFactoryRes
} }
const componentFactoryResolver: ComponentFactoryResolver = new ComponentFactoryResolver(); const componentFactoryResolver: ComponentFactoryResolver = new ComponentFactoryResolver();
export function injectRenderer2(): Renderer2 {
return getOrCreateRenderer2(getOrCreateNodeInjector());
}
/** /**
* Inject static attribute value into directive constructor. * Inject static attribute value into directive constructor.
* *
@ -320,6 +325,17 @@ function getOrCreateHostChangeDetector(currentNode: LViewNode | LElementNode):
.view[DIRECTIVES] ![hostNode.tNode.flags >> TNodeFlags.DirectiveStartingIndexShift]); .view[DIRECTIVES] ![hostNode.tNode.flags >> TNodeFlags.DirectiveStartingIndexShift]);
} }
function getOrCreateRenderer2(di: LInjector): Renderer2 {
const renderer = di.node.view[RENDERER];
if (isProceduralRenderer(renderer)) {
return renderer as Renderer2;
} else {
throw new Error('Cannot inject Renderer2 when the application uses Renderer3!');
}
}
/** /**
* If the node is an embedded view, traverses up the view tree to return the closest * If the node is an embedded view, traverses up the view tree to return the closest
* ancestor view that is attached to a component. If it's already a component node, * ancestor view that is attached to a component. If it's already a component node,
@ -632,6 +648,9 @@ export class NodeInjector implements Injector {
if (token === viewEngine_ChangeDetectorRef) { if (token === viewEngine_ChangeDetectorRef) {
return getOrCreateChangeDetectorRef(this._lInjector, null); return getOrCreateChangeDetectorRef(this._lInjector, null);
} }
if (token === Renderer2) {
return getOrCreateRenderer2(this._lInjector);
}
return getOrCreateInjectable(this._lInjector, token); return getOrCreateInjectable(this._lInjector, token);
} }

View File

@ -14,7 +14,7 @@ import {PublicFeature} from './features/public_feature';
import {BaseDef, ComponentDef, ComponentDefInternal, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveDefInternal, DirectiveType, PipeDef} from './interfaces/definition'; import {BaseDef, ComponentDef, ComponentDefInternal, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveDefInternal, DirectiveType, PipeDef} from './interfaces/definition';
export {ComponentFactory, ComponentFactoryResolver, ComponentRef, WRAP_RENDERER_FACTORY2} from './component_ref'; export {ComponentFactory, ComponentFactoryResolver, ComponentRef, WRAP_RENDERER_FACTORY2} from './component_ref';
export {QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF, directiveInject, getFactoryOf, getInheritedFactory, injectAttribute, injectChangeDetectorRef, injectComponentFactoryResolver, injectElementRef, injectTemplateRef, injectViewContainerRef, templateRefExtractor} from './di'; export {QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF, directiveInject, getFactoryOf, getInheritedFactory, injectAttribute, injectChangeDetectorRef, injectComponentFactoryResolver, injectElementRef, injectRenderer2, injectTemplateRef, injectViewContainerRef, templateRefExtractor} from './di';
export {RenderFlags} from './interfaces/definition'; export {RenderFlags} from './interfaces/definition';
export {CssSelectorList} from './interfaces/projection'; export {CssSelectorList} from './interfaces/projection';

View File

@ -35,6 +35,7 @@ export const angularCoreEnv: {[name: string]: Function} = {
'ɵinjectTemplateRef': r3.injectTemplateRef, 'ɵinjectTemplateRef': r3.injectTemplateRef,
'ɵinjectViewContainerRef': r3.injectViewContainerRef, 'ɵinjectViewContainerRef': r3.injectViewContainerRef,
'ɵtemplateRefExtractor': r3.templateRefExtractor, 'ɵtemplateRefExtractor': r3.templateRefExtractor,
'ɵinjectRenderer2': r3.injectRenderer2,
'ɵNgOnChangesFeature': r3.NgOnChangesFeature, 'ɵNgOnChangesFeature': r3.NgOnChangesFeature,
'ɵPublicFeature': r3.PublicFeature, 'ɵPublicFeature': r3.PublicFeature,
'ɵInheritDefinitionFeature': r3.InheritDefinitionFeature, 'ɵInheritDefinitionFeature': r3.InheritDefinitionFeature,

View File

@ -137,6 +137,9 @@
{ {
"name": "RecordViewTuple" "name": "RecordViewTuple"
}, },
{
"name": "Renderer2"
},
{ {
"name": "RendererStyleFlags3" "name": "RendererStyleFlags3"
}, },
@ -590,6 +593,9 @@
{ {
"name": "getOrCreateNodeInjectorForNode" "name": "getOrCreateNodeInjectorForNode"
}, },
{
"name": "getOrCreateRenderer2"
},
{ {
"name": "getOrCreateTView" "name": "getOrCreateTView"
}, },

View File

@ -1679,6 +1679,9 @@
{ {
"name": "getOrCreateNodeInjectorForNode" "name": "getOrCreateNodeInjectorForNode"
}, },
{
"name": "getOrCreateRenderer2"
},
{ {
"name": "getOrCreateTView" "name": "getOrCreateTView"
}, },
@ -1805,6 +1808,9 @@
{ {
"name": "injectElementRef" "name": "injectElementRef"
}, },
{
"name": "injectRenderer2"
},
{ {
"name": "injectTemplateRef" "name": "injectTemplateRef"
}, },

View File

@ -6,18 +6,21 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {Attribute, ChangeDetectorRef, ElementRef, Host, InjectFlags, Optional, Self, SkipSelf, TemplateRef, ViewContainerRef, defineInjectable} from '@angular/core'; import {Attribute, ChangeDetectorRef, ElementRef, Host, InjectFlags, Optional, Renderer2, Self, SkipSelf, TemplateRef, ViewContainerRef, defineInjectable} from '@angular/core';
import {RenderFlags} from '@angular/core/src/render3/interfaces/definition'; import {RenderFlags} from '@angular/core/src/render3/interfaces/definition';
import {defineComponent} from '../../src/render3/definition'; import {defineComponent} from '../../src/render3/definition';
import {bloomAdd, bloomFindPossibleInjector, getOrCreateNodeInjector, injectAttribute} from '../../src/render3/di'; import {bloomAdd, bloomFindPossibleInjector, getOrCreateNodeInjector, injectAttribute} from '../../src/render3/di';
import {NgOnChangesFeature, PublicFeature, defineDirective, directiveInject, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index'; import {NgOnChangesFeature, PublicFeature, defineDirective, directiveInject, injectChangeDetectorRef, injectElementRef, injectRenderer2, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, createLNode, createLViewData, createTView, element, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, enterView, interpolation2, leaveView, projection, projectionDef, reference, template, text, textBinding, loadDirective, elementContainerStart, elementContainerEnd} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, createLNode, createLViewData, createTView, element, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, enterView, interpolation2, leaveView, projection, projectionDef, reference, template, text, textBinding, loadDirective, elementContainerStart, elementContainerEnd} from '../../src/render3/instructions';
import {LInjector} from '../../src/render3/interfaces/injector'; import {LInjector} from '../../src/render3/interfaces/injector';
import {isProceduralRenderer} from '../../src/render3/interfaces/renderer';
import {AttributeMarker, TNodeType} from '../../src/render3/interfaces/node'; import {AttributeMarker, TNodeType} from '../../src/render3/interfaces/node';
import {LViewFlags} from '../../src/render3/interfaces/view'; import {LViewFlags} from '../../src/render3/interfaces/view';
import {ViewRef} from '../../src/render3/view_ref'; import {ViewRef} from '../../src/render3/view_ref';
import {getRendererFactory2} from './imported_renderer2';
import {ComponentFixture, createComponent, createDirective, renderComponent, toHtml} from './render_util'; import {ComponentFixture, createComponent, createDirective, renderComponent, toHtml} from './render_util';
describe('di', () => { describe('di', () => {
@ -1205,6 +1208,36 @@ describe('di', () => {
}); });
}); });
describe('Renderer2', () => {
let comp: MyComp;
class MyComp {
constructor(public renderer: Renderer2) {}
static ngComponentDef = defineComponent({
type: MyComp,
selectors: [['my-comp']],
factory: () => comp = new MyComp(injectRenderer2()),
consts: 1,
vars: 0,
template: function(rf: RenderFlags, ctx: MyComp) {
if (rf & RenderFlags.Create) {
text(0, 'Foo');
}
}
});
}
it('should inject the Renderer2 used by the application', () => {
const rendererFactory = getRendererFactory2(document);
new ComponentFixture(MyComp, {rendererFactory: rendererFactory});
expect(isProceduralRenderer(comp.renderer)).toBeTruthy();
});
it('should throw when injecting Renderer2 but the application is using Renderer3',
() => { expect(() => new ComponentFixture(MyComp)).toThrow(); });
});
describe('@Attribute', () => { describe('@Attribute', () => {
class MyDirective { class MyDirective {

View File

@ -7,7 +7,7 @@
*/ */
import {CompileReflector, ExternalReference, Identifiers, getUrlScheme, syntaxError} from '@angular/compiler'; import {CompileReflector, ExternalReference, Identifiers, getUrlScheme, syntaxError} from '@angular/compiler';
import {ANALYZE_FOR_ENTRY_COMPONENTS, ChangeDetectionStrategy, ChangeDetectorRef, Component, ComponentFactory, ComponentFactoryResolver, ComponentRef, ElementRef, Injector, LOCALE_ID, NgModuleFactory, NgModuleRef, QueryList, Renderer, SecurityContext, TRANSLATIONS_FORMAT, TemplateRef, ViewContainerRef, ViewEncapsulation, ɵCodegenComponentFactoryResolver, ɵEMPTY_ARRAY, ɵEMPTY_MAP, ɵReflectionCapabilities as ReflectionCapabilities, ɵand, ɵccf, ɵcmf, ɵcrt, ɵdid, ɵeld, ɵinlineInterpolate, ɵinterpolate, ɵmod, ɵmpd, ɵncd, ɵnov, ɵpad, ɵpid, ɵpod, ɵppd, ɵprd, ɵqud, ɵregisterModuleFactory, ɵstringify as stringify, ɵted, ɵunv, ɵvid} from '@angular/core'; import {ANALYZE_FOR_ENTRY_COMPONENTS, ChangeDetectionStrategy, ChangeDetectorRef, Component, ComponentFactory, ComponentFactoryResolver, ComponentRef, ElementRef, Injector, LOCALE_ID, NgModuleFactory, NgModuleRef, QueryList, Renderer, Renderer2, SecurityContext, TRANSLATIONS_FORMAT, TemplateRef, ViewContainerRef, ViewEncapsulation, ɵCodegenComponentFactoryResolver, ɵEMPTY_ARRAY, ɵEMPTY_MAP, ɵReflectionCapabilities as ReflectionCapabilities, ɵand, ɵccf, ɵcmf, ɵcrt, ɵdid, ɵeld, ɵinlineInterpolate, ɵinterpolate, ɵmod, ɵmpd, ɵncd, ɵnov, ɵpad, ɵpid, ɵpod, ɵppd, ɵprd, ɵqud, ɵregisterModuleFactory, ɵstringify as stringify, ɵted, ɵunv, ɵvid} from '@angular/core';
export const MODULE_SUFFIX = ''; export const MODULE_SUFFIX = '';
const builtinExternalReferences = createBuiltinExternalReferencesMap(); const builtinExternalReferences = createBuiltinExternalReferencesMap();
@ -59,6 +59,7 @@ function createBuiltinExternalReferencesMap() {
map.set(Identifiers.NgModuleRef, NgModuleRef); map.set(Identifiers.NgModuleRef, NgModuleRef);
map.set(Identifiers.ViewContainerRef, ViewContainerRef); map.set(Identifiers.ViewContainerRef, ViewContainerRef);
map.set(Identifiers.ChangeDetectorRef, ChangeDetectorRef); map.set(Identifiers.ChangeDetectorRef, ChangeDetectorRef);
map.set(Identifiers.Renderer2, Renderer2);
map.set(Identifiers.QueryList, QueryList); map.set(Identifiers.QueryList, QueryList);
map.set(Identifiers.TemplateRef, TemplateRef); map.set(Identifiers.TemplateRef, TemplateRef);
map.set(Identifiers.CodegenComponentFactoryResolver, ɵCodegenComponentFactoryResolver); map.set(Identifiers.CodegenComponentFactoryResolver, ɵCodegenComponentFactoryResolver);