parent
ccb4a396f0
commit
00f13110be
|
@ -75,6 +75,9 @@ export function getConstructorDependencies(
|
|||
case 'ViewContainerRef':
|
||||
resolved = R3ResolvedDependencyType.ViewContainerRef;
|
||||
break;
|
||||
case 'Renderer2':
|
||||
resolved = R3ResolvedDependencyType.Renderer2;
|
||||
break;
|
||||
default:
|
||||
// Leave as a Token or Attribute.
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ export class ElementRef {}
|
|||
export class Injector {}
|
||||
export class TemplateRef<T = any> {}
|
||||
export class ViewContainerRef {}
|
||||
export class Renderer2 {}
|
||||
export class ɵNgModuleFactory<T> {
|
||||
constructor(public clazz: T) {}
|
||||
}
|
||||
|
|
|
@ -448,6 +448,7 @@ describe('ngtsc behavioral tests', () => {
|
|||
Component,
|
||||
ElementRef,
|
||||
Injector,
|
||||
Renderer2,
|
||||
TemplateRef,
|
||||
ViewContainerRef,
|
||||
} from '@angular/core';
|
||||
|
@ -462,6 +463,7 @@ describe('ngtsc behavioral tests', () => {
|
|||
cdr: ChangeDetectorRef,
|
||||
er: ElementRef,
|
||||
i: Injector,
|
||||
r2: Renderer2,
|
||||
tr: TemplateRef,
|
||||
vcr: ViewContainerRef,
|
||||
) {}
|
||||
|
@ -474,7 +476,7 @@ describe('ngtsc behavioral tests', () => {
|
|||
const jsContents = getContents('test.js');
|
||||
expect(jsContents)
|
||||
.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', () => {
|
||||
|
|
|
@ -28,6 +28,7 @@ export class Identifiers {
|
|||
};
|
||||
static QueryList: o.ExternalReference = {name: 'QueryList', moduleName: CORE};
|
||||
static TemplateRef: o.ExternalReference = {name: 'TemplateRef', moduleName: CORE};
|
||||
static Renderer2: o.ExternalReference = {name: 'Renderer2', moduleName: CORE};
|
||||
static CodegenComponentFactoryResolver: o.ExternalReference = {
|
||||
name: 'ɵCodegenComponentFactoryResolver',
|
||||
moduleName: CORE,
|
||||
|
|
|
@ -120,6 +120,11 @@ export enum R3ResolvedDependencyType {
|
|||
* The dependency is for `ChangeDetectorRef`.
|
||||
*/
|
||||
ChangeDetectorRef = 6,
|
||||
|
||||
/**
|
||||
* The dependency is for `Renderer2`.
|
||||
*/
|
||||
Renderer2 = 7,
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -285,6 +290,8 @@ function compileInjectDependency(
|
|||
return o.importExpr(R3.injectViewContainerRef).callFn([]);
|
||||
case R3ResolvedDependencyType.ChangeDetectorRef:
|
||||
return o.importExpr(R3.injectChangeDetectorRef).callFn([]);
|
||||
case R3ResolvedDependencyType.Renderer2:
|
||||
return o.importExpr(R3.injectRenderer2).callFn([]);
|
||||
default:
|
||||
return unsupported(
|
||||
`Unknown R3ResolvedDependencyType: ${R3ResolvedDependencyType[dep.resolved]}`);
|
||||
|
@ -305,6 +312,7 @@ export function dependenciesFromGlobalMetadata(
|
|||
const templateRef = reflector.resolveExternalReference(Identifiers.TemplateRef);
|
||||
const viewContainerRef = reflector.resolveExternalReference(Identifiers.ViewContainerRef);
|
||||
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.
|
||||
const deps: R3DependencyMetadata[] = [];
|
||||
|
@ -320,6 +328,8 @@ export function dependenciesFromGlobalMetadata(
|
|||
resolved = R3ResolvedDependencyType.ViewContainerRef;
|
||||
} else if (tokenRef === injectorRef) {
|
||||
resolved = R3ResolvedDependencyType.Injector;
|
||||
} else if (tokenRef === renderer2) {
|
||||
resolved = R3ResolvedDependencyType.Renderer2;
|
||||
} else if (dependency.isAttribute) {
|
||||
resolved = R3ResolvedDependencyType.Attribute;
|
||||
}
|
||||
|
|
|
@ -116,6 +116,8 @@ export class Identifiers {
|
|||
static injectChangeDetectorRef:
|
||||
o.ExternalReference = {name: 'ɵinjectChangeDetectorRef', moduleName: CORE};
|
||||
|
||||
static injectRenderer2: o.ExternalReference = {name: 'ɵinjectRenderer2', moduleName: CORE};
|
||||
|
||||
static directiveInject: o.ExternalReference = {name: 'ɵdirectiveInject', moduleName: CORE};
|
||||
|
||||
static templateRefExtractor:
|
||||
|
|
|
@ -25,6 +25,7 @@ export {
|
|||
injectTemplateRef as ɵinjectTemplateRef,
|
||||
injectViewContainerRef as ɵinjectViewContainerRef,
|
||||
injectChangeDetectorRef as ɵinjectChangeDetectorRef,
|
||||
injectRenderer2 as ɵinjectRenderer2,
|
||||
injectAttribute as ɵinjectAttribute,
|
||||
getFactoryOf as ɵgetFactoryOf,
|
||||
getInheritedFactory as ɵgetInheritedFactory,
|
||||
|
|
|
@ -216,6 +216,7 @@ The goal is for the `@Component` (and friends) to be the compiler of template. S
|
|||
| `injectElementRef()` | ✅ | ✅ | ✅ |
|
||||
| `injectViewContainerRef()` | ✅ | ✅ | ✅ |
|
||||
| `injectTemplateRef()` | ✅ | ✅ | ✅ |
|
||||
| `injectRenderer2()` | ✅ | ✅ | ✅ |
|
||||
| default `inject()` with no injector | ❌ | ❌ | ❌ |
|
||||
| sanitization with no injector | ✅ | ✅ | ❌ |
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import {NgModuleRef as viewEngine_NgModuleRef} from '../linker/ng_module_factory
|
|||
import {TemplateRef as viewEngine_TemplateRef} from '../linker/template_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 {Renderer2} from '../render';
|
||||
import {Type} from '../type';
|
||||
|
||||
import {assertDefined, assertGreaterThan, assertLessThan} from './assert';
|
||||
|
@ -29,7 +30,7 @@ import {DirectiveDefInternal, RenderFlags} from './interfaces/definition';
|
|||
import {LInjector} from './interfaces/injector';
|
||||
import {AttributeMarker, LContainerNode, LElementContainerNode, LElementNode, LNode, LNodeWithLocalRefs, LViewNode, TContainerNode, TElementNode, TNodeFlags, TNodeType} from './interfaces/node';
|
||||
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 {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
|
||||
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();
|
||||
|
||||
|
||||
export function injectRenderer2(): Renderer2 {
|
||||
return getOrCreateRenderer2(getOrCreateNodeInjector());
|
||||
}
|
||||
/**
|
||||
* Inject static attribute value into directive constructor.
|
||||
*
|
||||
|
@ -320,6 +325,17 @@ function getOrCreateHostChangeDetector(currentNode: LViewNode | LElementNode):
|
|||
.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
|
||||
* 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) {
|
||||
return getOrCreateChangeDetectorRef(this._lInjector, null);
|
||||
}
|
||||
if (token === Renderer2) {
|
||||
return getOrCreateRenderer2(this._lInjector);
|
||||
}
|
||||
|
||||
return getOrCreateInjectable(this._lInjector, token);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import {PublicFeature} from './features/public_feature';
|
|||
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 {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 {CssSelectorList} from './interfaces/projection';
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ export const angularCoreEnv: {[name: string]: Function} = {
|
|||
'ɵinjectTemplateRef': r3.injectTemplateRef,
|
||||
'ɵinjectViewContainerRef': r3.injectViewContainerRef,
|
||||
'ɵtemplateRefExtractor': r3.templateRefExtractor,
|
||||
'ɵinjectRenderer2': r3.injectRenderer2,
|
||||
'ɵNgOnChangesFeature': r3.NgOnChangesFeature,
|
||||
'ɵPublicFeature': r3.PublicFeature,
|
||||
'ɵInheritDefinitionFeature': r3.InheritDefinitionFeature,
|
||||
|
|
|
@ -137,6 +137,9 @@
|
|||
{
|
||||
"name": "RecordViewTuple"
|
||||
},
|
||||
{
|
||||
"name": "Renderer2"
|
||||
},
|
||||
{
|
||||
"name": "RendererStyleFlags3"
|
||||
},
|
||||
|
@ -590,6 +593,9 @@
|
|||
{
|
||||
"name": "getOrCreateNodeInjectorForNode"
|
||||
},
|
||||
{
|
||||
"name": "getOrCreateRenderer2"
|
||||
},
|
||||
{
|
||||
"name": "getOrCreateTView"
|
||||
},
|
||||
|
|
|
@ -1679,6 +1679,9 @@
|
|||
{
|
||||
"name": "getOrCreateNodeInjectorForNode"
|
||||
},
|
||||
{
|
||||
"name": "getOrCreateRenderer2"
|
||||
},
|
||||
{
|
||||
"name": "getOrCreateTView"
|
||||
},
|
||||
|
@ -1805,6 +1808,9 @@
|
|||
{
|
||||
"name": "injectElementRef"
|
||||
},
|
||||
{
|
||||
"name": "injectRenderer2"
|
||||
},
|
||||
{
|
||||
"name": "injectTemplateRef"
|
||||
},
|
||||
|
|
|
@ -6,18 +6,21 @@
|
|||
* 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 {defineComponent} from '../../src/render3/definition';
|
||||
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 {LInjector} from '../../src/render3/interfaces/injector';
|
||||
import {isProceduralRenderer} from '../../src/render3/interfaces/renderer';
|
||||
import {AttributeMarker, TNodeType} from '../../src/render3/interfaces/node';
|
||||
|
||||
import {LViewFlags} from '../../src/render3/interfaces/view';
|
||||
import {ViewRef} from '../../src/render3/view_ref';
|
||||
|
||||
import {getRendererFactory2} from './imported_renderer2';
|
||||
import {ComponentFixture, createComponent, createDirective, renderComponent, toHtml} from './render_util';
|
||||
|
||||
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', () => {
|
||||
|
||||
class MyDirective {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
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 = '';
|
||||
const builtinExternalReferences = createBuiltinExternalReferencesMap();
|
||||
|
@ -59,6 +59,7 @@ function createBuiltinExternalReferencesMap() {
|
|||
map.set(Identifiers.NgModuleRef, NgModuleRef);
|
||||
map.set(Identifiers.ViewContainerRef, ViewContainerRef);
|
||||
map.set(Identifiers.ChangeDetectorRef, ChangeDetectorRef);
|
||||
map.set(Identifiers.Renderer2, Renderer2);
|
||||
map.set(Identifiers.QueryList, QueryList);
|
||||
map.set(Identifiers.TemplateRef, TemplateRef);
|
||||
map.set(Identifiers.CodegenComponentFactoryResolver, ɵCodegenComponentFactoryResolver);
|
||||
|
|
Loading…
Reference in New Issue