fix(ivy): Renderer2 should not use a special injection fn (#26369)

PR Close #26369
This commit is contained in:
Pawel Kozlowski 2018-10-10 15:53:14 +02:00 committed by Miško Hevery
parent 062fe5c2cf
commit 6a64ac4151
18 changed files with 44 additions and 61 deletions

View File

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

View File

@ -380,7 +380,7 @@ describe('ngtsc behavioral tests', () => {
const jsContents = env.getContents('test.js');
expect(jsContents)
.toContain(
`factory: function FooCmp_Factory(t) { return new (t || FooCmp)(i0.ɵinjectAttribute("test"), i0.ɵdirectiveInject(ChangeDetectorRef), i0.ɵdirectiveInject(ElementRef), i0.ɵdirectiveInject(i0.INJECTOR), i0.ɵinjectRenderer2(), i0.ɵdirectiveInject(TemplateRef), i0.ɵdirectiveInject(ViewContainerRef)); }`);
`factory: function FooCmp_Factory(t) { return new (t || FooCmp)(i0.ɵinjectAttribute("test"), i0.ɵdirectiveInject(ChangeDetectorRef), i0.ɵdirectiveInject(ElementRef), i0.ɵdirectiveInject(i0.INJECTOR), i0.ɵdirectiveInject(Renderer2), i0.ɵdirectiveInject(TemplateRef), i0.ɵdirectiveInject(ViewContainerRef)); }`);
});
it('should generate queries for components', () => {

View File

@ -15,7 +15,7 @@ import * as o from '../output/output_ast';
import {Identifiers as R3} from '../render3/r3_identifiers';
import {OutputContext} from '../util';
import {MEANING_SEPARATOR, unsupported} from './view/util';
import {unsupported} from './view/util';
/**
@ -100,11 +100,6 @@ export enum R3ResolvedDependencyType {
* The dependency is for the `Injector` type itself.
*/
Injector = 2,
/**
* The dependency is for `Renderer2`.
*/
Renderer2 = 3,
}
/**
@ -262,8 +257,6 @@ function compileInjectDependency(
case R3ResolvedDependencyType.Attribute:
// In the case of attributes, the attribute name in question is given as the token.
return o.importExpr(R3.injectAttribute).callFn([dep.token]);
case R3ResolvedDependencyType.Renderer2:
return o.importExpr(R3.injectRenderer2).callFn([]);
default:
return unsupported(
`Unknown R3ResolvedDependencyType: ${R3ResolvedDependencyType[dep.resolved]}`);
@ -280,11 +273,7 @@ export function dependenciesFromGlobalMetadata(
// Use the `CompileReflector` to look up references to some well-known Angular types. These will
// be compared with the token to statically determine whether the token has significance to
// Angular, and set the correct `R3ResolvedDependencyType` as a result.
const elementRef = reflector.resolveExternalReference(Identifiers.ElementRef);
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[] = [];
@ -294,8 +283,6 @@ export function dependenciesFromGlobalMetadata(
let resolved: R3ResolvedDependencyType = R3ResolvedDependencyType.Token;
if (tokenRef === injectorRef) {
resolved = R3ResolvedDependencyType.Injector;
} else if (tokenRef === renderer2) {
resolved = R3ResolvedDependencyType.Renderer2;
} else if (dependency.isAttribute) {
resolved = R3ResolvedDependencyType.Attribute;
}

View File

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

View File

@ -21,7 +21,6 @@ export {
DirectiveType as ɵDirectiveType,
RenderFlags as ɵRenderFlags,
directiveInject as ɵdirectiveInject,
injectRenderer2 as ɵinjectRenderer2,
injectAttribute as ɵinjectAttribute,
getFactoryOf as ɵgetFactoryOf,
getInheritedFactory as ɵgetInheritedFactory,
@ -195,6 +194,7 @@ export {
R3_TEMPLATE_REF_FACTORY__POST_NGCC__ as ɵR3_TEMPLATE_REF_FACTORY__POST_NGCC__,
R3_CHANGE_DETECTOR_REF_FACTORY__POST_NGCC__ as ɵR3_CHANGE_DETECTOR_REF_FACTORY__POST_NGCC__,
R3_VIEW_CONTAINER_REF_FACTORY__POST_NGCC__ as ɵR3_VIEW_CONTAINER_REF_FACTORY__POST_NGCC__,
R3_RENDERER2_FACTORY__POST_NGCC__ as ɵR3_RENDERER2_FACTORY__POST_NGCC__,
} from './ivy_switch/runtime/legacy';

View File

@ -6,9 +6,10 @@
* found in the LICENSE file at https://angular.io/license
*/
import {injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from '../../render3/view_engine_compatibility';
import {injectChangeDetectorRef, injectElementRef, injectRenderer2, injectTemplateRef, injectViewContainerRef} from '../../render3/view_engine_compatibility';
export const R3_ELEMENT_REF_FACTORY = injectElementRef;
export const R3_TEMPLATE_REF_FACTORY = injectTemplateRef;
export const R3_CHANGE_DETECTOR_REF_FACTORY = injectChangeDetectorRef;
export const R3_VIEW_CONTAINER_REF_FACTORY = injectViewContainerRef;
export const R3_RENDERER2_FACTORY = injectRenderer2;

View File

@ -18,14 +18,17 @@ export const R3_CHANGE_DETECTOR_REF_FACTORY__POST_NGCC__: FactoryFunction =
ivyOn.R3_CHANGE_DETECTOR_REF_FACTORY;
export const R3_VIEW_CONTAINER_REF_FACTORY__POST_NGCC__: FactoryFunction =
ivyOn.R3_VIEW_CONTAINER_REF_FACTORY;
export const R3_RENDERER2_FACTORY__POST_NGCC__: FactoryFunction = ivyOn.R3_RENDERER2_FACTORY;
export const R3_ELEMENT_REF_FACTORY__PRE_NGCC__ = noopFactory;
export const R3_TEMPLATE_REF_FACTORY__PRE_NGCC__ = noopFactory;
export const R3_CHANGE_DETECTOR_REF_FACTORY__PRE_NGCC__ = noopFactory;
export const R3_VIEW_CONTAINER_REF_FACTORY__PRE_NGCC__ = noopFactory;
export const R3_RENDERER2_FACTORY__PRE_NGCC__ = noopFactory;
export let R3_ELEMENT_REF_FACTORY = R3_ELEMENT_REF_FACTORY__PRE_NGCC__;
export let R3_TEMPLATE_REF_FACTORY = R3_TEMPLATE_REF_FACTORY__PRE_NGCC__;
export let R3_CHANGE_DETECTOR_REF_FACTORY = R3_CHANGE_DETECTOR_REF_FACTORY__PRE_NGCC__;
export let R3_VIEW_CONTAINER_REF_FACTORY = R3_VIEW_CONTAINER_REF_FACTORY__PRE_NGCC__;
export let R3_RENDERER2_FACTORY = R3_RENDERER2_FACTORY__PRE_NGCC__;

View File

@ -8,8 +8,10 @@
import {InjectionToken} from '../di/injection_token';
import {Injector} from '../di/injector';
import {R3_RENDERER2_FACTORY} from '../ivy_switch/runtime/index';
import {ViewEncapsulation} from '../metadata/view';
/**
* @deprecated Use `RendererType2` (and `Renderer2`) instead.
*/
@ -21,7 +23,7 @@ export class RenderComponentType {
}
/**
* @deprecated Debug info is handeled internally in the view engine now.
* @deprecated Debug info is handled internally in the view engine now.
*/
export abstract class RenderDebugInfo {
abstract get injector(): Injector;
@ -366,4 +368,7 @@ export abstract class Renderer2 {
abstract listen(
target: 'window'|'document'|'body'|any, eventName: string,
callback: (event: any) => boolean | void): () => void;
/** @internal */
static __NG_ELEMENT_ID__: () => Renderer2 = () => R3_RENDERER2_FACTORY();
}

View File

@ -22,7 +22,6 @@ import {_getViewData, assertPreviousIsParent, getPreviousOrParentTNode, resolveD
import {DirectiveDef} from './interfaces/definition';
import {InjectorLocationFlags, PARENT_INJECTOR, TNODE,} from './interfaces/injector';
import {AttributeMarker, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType} from './interfaces/node';
import {isProceduralRenderer} from './interfaces/renderer';
import {DECLARATION_VIEW, HOST_NODE, INJECTOR, LViewData, PARENT, RENDERER, TData, TVIEW, TView} from './interfaces/view';
import {assertNodeOfPossibleTypes} from './node_assert';
@ -246,9 +245,6 @@ export function directiveInject<T>(
return getOrCreateInjectable<T>(hostTNode, _getViewData(), token, flags);
}
export function injectRenderer2(): Renderer2 {
return getOrCreateRenderer2(_getViewData());
}
/**
* Inject static attribute value into directive constructor.
*
@ -298,14 +294,6 @@ export function injectAttribute(attrNameToInject: string): string|undefined {
return undefined;
}
function getOrCreateRenderer2(view: LViewData): Renderer2 {
const renderer = view[RENDERER];
if (isProceduralRenderer(renderer)) {
return renderer as Renderer2;
} else {
throw new Error('Cannot inject Renderer2 when the application uses Renderer3!');
}
}
/**
* Returns the value associated to the given token from the injectors.
@ -509,10 +497,6 @@ export class NodeInjector implements Injector {
}
get(token: any): any {
if (token === Renderer2) {
return getOrCreateRenderer2(this._hostView);
}
setEnvironment(this._tNode, this._hostView);
return getOrCreateInjectable(this._tNode, this._hostView, token);
}

View File

@ -14,7 +14,7 @@ import {PublicFeature} from './features/public_feature';
import {BaseDef, ComponentDef, ComponentDefWithMeta, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveDefWithMeta, DirectiveType, PipeDef, PipeDefWithMeta} from './interfaces/definition';
export {ComponentFactory, ComponentFactoryResolver, ComponentRef, WRAP_RENDERER_FACTORY2, injectComponentFactoryResolver} from './component_ref';
export {directiveInject, getFactoryOf, getInheritedFactory, injectAttribute, injectRenderer2} from './di';
export {directiveInject, getFactoryOf, getInheritedFactory, injectAttribute} from './di';
export {RenderFlags} from './interfaces/definition';
export {CssSelectorList} from './interfaces/projection';

View File

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

View File

@ -14,6 +14,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/api';
import {assertDefined, assertGreaterThan, assertLessThan} from './assert';
import {NodeInjector, getParentInjectorLocation, getParentInjectorView} from './di';
@ -23,7 +24,7 @@ import {RenderFlags} from './interfaces/definition';
import {InjectorLocationFlags} from './interfaces/injector';
import {LContainerNode, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TViewNode} from './interfaces/node';
import {LQueries} from './interfaces/query';
import {RComment, RElement, Renderer3} from './interfaces/renderer';
import {RComment, RElement, Renderer3, isProceduralRenderer} from './interfaces/renderer';
import {CONTEXT, HOST_NODE, LViewData, QUERIES, RENDERER, TVIEW, TView} from './interfaces/view';
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
import {addRemoveViewFromContainer, appendChild, detachView, findComponentView, getBeforeNodeForView, getRenderParent, insertView, removeView} from './node_manipulation';
@ -340,3 +341,17 @@ export function createViewRef(
}
return null !;
}
function getOrCreateRenderer2(view: LViewData): Renderer2 {
const renderer = view[RENDERER];
if (isProceduralRenderer(renderer)) {
return renderer as Renderer2;
} else {
throw new Error('Cannot inject Renderer2 when the application uses Renderer3!');
}
}
/** Returns a Renderer2 (or throws when application was bootstrapped with Renderer3) */
export function injectRenderer2(): Renderer2 {
return getOrCreateRenderer2(_getViewData());
}

View File

@ -167,9 +167,6 @@
{
"name": "RecordViewTuple"
},
{
"name": "Renderer2"
},
{
"name": "RendererStyleFlags3"
},
@ -617,9 +614,6 @@
{
"name": "getOrCreatePlayerContext"
},
{
"name": "getOrCreateRenderer2"
},
{
"name": "getOrCreateTView"
},

View File

@ -1253,6 +1253,9 @@
{
"name": "R3_ELEMENT_REF_FACTORY$1"
},
{
"name": "R3_RENDERER2_FACTORY$1"
},
{
"name": "R3_TEMPLATE_REF_FACTORY$1"
},

View File

@ -158,9 +158,6 @@
{
"name": "RecordViewTuple"
},
{
"name": "Renderer2"
},
{
"name": "RendererStyleFlags3"
},
@ -656,9 +653,6 @@
{
"name": "getOrCreateNodeInjectorForNode"
},
{
"name": "getOrCreateRenderer2"
},
{
"name": "getOrCreateTView"
},

View File

@ -671,6 +671,9 @@
{
"name": "R3_ELEMENT_REF_FACTORY"
},
{
"name": "R3_RENDERER2_FACTORY"
},
{
"name": "R3_TEMPLATE_REF_FACTORY"
},

View File

@ -11,7 +11,7 @@ import {RenderFlags} from '@angular/core/src/render3/interfaces/definition';
import {defineComponent} from '../../src/render3/definition';
import {bloomAdd, bloomHashBitOrFactory as bloomHash, getOrCreateNodeInjector, injectAttribute, injectorHasToken} from '../../src/render3/di';
import {PublicFeature, defineDirective, directiveInject, elementProperty, injectRenderer2, load, templateRefExtractor} from '../../src/render3/index';
import {PublicFeature, defineDirective, directiveInject, elementProperty, load, templateRefExtractor} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, createNodeAtIndex, createLViewData, createTView, element, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, enterView, interpolation2, leaveView, projection, projectionDef, reference, template, text, textBinding, elementContainerStart, elementContainerEnd} from '../../src/render3/instructions';
import {isProceduralRenderer} from '../../src/render3/interfaces/renderer';
@ -1535,15 +1535,13 @@ 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()),
factory: () => new MyComp(directiveInject(Renderer2 as any)),
consts: 1,
vars: 0,
template: function(rf: RenderFlags, ctx: MyComp) {
@ -1556,8 +1554,8 @@ describe('di', () => {
it('should inject the Renderer2 used by the application', () => {
const rendererFactory = getRendererFactory2(document);
new ComponentFixture(MyComp, {rendererFactory: rendererFactory});
expect(isProceduralRenderer(comp.renderer)).toBeTruthy();
const fixture = new ComponentFixture(MyComp, {rendererFactory: rendererFactory});
expect(isProceduralRenderer(fixture.component.renderer)).toBeTruthy();
});
it('should throw when injecting Renderer2 but the application is using Renderer3',

View File

@ -10,10 +10,11 @@ import {ChangeDetectorRef} from '@angular/core/src/change_detection/change_detec
import {ElementRef} from '@angular/core/src/linker/element_ref';
import {TemplateRef} from '@angular/core/src/linker/template_ref';
import {ViewContainerRef} from '@angular/core/src/linker/view_container_ref';
import {Renderer2} from '@angular/core/src/render/api';
import {stringifyElement} from '@angular/platform-browser/testing/src/browser_util';
import {Injector} from '../../src/di/injector';
import {R3_CHANGE_DETECTOR_REF_FACTORY, R3_ELEMENT_REF_FACTORY, R3_TEMPLATE_REF_FACTORY, R3_VIEW_CONTAINER_REF_FACTORY} from '../../src/ivy_switch/runtime/ivy_switch_on';
import {R3_CHANGE_DETECTOR_REF_FACTORY, R3_ELEMENT_REF_FACTORY, R3_RENDERER2_FACTORY, R3_TEMPLATE_REF_FACTORY, R3_VIEW_CONTAINER_REF_FACTORY} from '../../src/ivy_switch/runtime/ivy_switch_on';
import {CreateComponentOptions} from '../../src/render3/component';
import {discoverDirectives, getContext, isComponentInstance} from '../../src/render3/context_discovery';
import {extractDirectiveDef, extractPipeDef} from '../../src/render3/definition';
@ -318,4 +319,5 @@ export function enableIvyInjectableFactories() {
(ViewContainerRef as any)[NG_ELEMENT_ID] = () =>
R3_VIEW_CONTAINER_REF_FACTORY(ViewContainerRef, ElementRef);
(ChangeDetectorRef as any)[NG_ELEMENT_ID] = () => R3_CHANGE_DETECTOR_REF_FACTORY();
(Renderer2 as any)[NG_ELEMENT_ID] = () => R3_RENDERER2_FACTORY();
}