fix(ivy): objects like ElementRef should not use a special injection fn (#26064)

PR Close #26064
This commit is contained in:
Kara Erickson
2018-09-21 18:38:13 -07:00
parent 482e12c940
commit 6a62ed2245
56 changed files with 1367 additions and 1073 deletions

View File

@ -5,7 +5,9 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {ElementRef, TemplateRef} from '@angular/core';
import {RenderFlags} from '@angular/core/src/render3';
import {AnimationContext, PlayState, Player, PlayerHandler} from '../../../src/render3/animations/interfaces';
import {addPlayer, getOrCreateAnimationContext, getPlayers} from '../../../src/render3/animations/players';
import {QUERY_READ_FROM_NODE, defineComponent, getHostElement} from '../../../src/render3/index';
@ -13,6 +15,7 @@ import {element, elementEnd, elementStart, elementStyling, elementStylingApply,
import {RElement} from '../../../src/render3/interfaces/renderer';
import {QueryList, query, queryRefresh} from '../../../src/render3/query';
import {ComponentFixture} from '../render_util';
import {MockPlayer} from './mock_player';
describe('animation player access', () => {
@ -286,7 +289,7 @@ class SuperComp {
},
viewQuery: function(rf: RenderFlags, ctx: SuperComp) {
if (rf & RenderFlags.Create) {
query(0, ['child'], true, QUERY_READ_FROM_NODE);
query(0, ['child'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;

View File

@ -10,7 +10,8 @@ import {withBody} from '@angular/private/testing';
import {ChangeDetectionStrategy, ChangeDetectorRef, DoCheck, RendererType2} from '../../src/core';
import {getRenderedText, whenRendered} from '../../src/render3/component';
import {LifecycleHooksFeature, defineComponent, defineDirective, injectChangeDetectorRef} from '../../src/render3/index';
import {directiveInject} from '../../src/render3/di';
import {LifecycleHooksFeature, defineComponent, defineDirective} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, detectChanges, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation2, listener, markDirty, text, textBinding, tick} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {RElement, Renderer3, RendererFactory3} from '../../src/render3/interfaces/renderer';
@ -18,7 +19,6 @@ import {RElement, Renderer3, RendererFactory3} from '../../src/render3/interface
import {containerEl, createComponent, renderComponent, requestAnimationFrame} from './render_util';
describe('change detection', () => {
describe('markDirty, detectChanges, whenRendered, getRenderedText', () => {
class MyComponent implements DoCheck {
value: string = 'works';
@ -326,7 +326,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: MyComp,
selectors: [['my-comp']],
factory: () => myComp = new MyComp(injectChangeDetectorRef()),
factory: () => myComp = new MyComp(directiveInject(ChangeDetectorRef as any)),
consts: 1,
vars: 1,
/** {{ name }} */
@ -352,7 +352,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: ParentComp,
selectors: [['parent-comp']],
factory: () => new ParentComp(injectChangeDetectorRef()),
factory: () => new ParentComp(directiveInject(ChangeDetectorRef as any)),
consts: 2,
vars: 1,
/**
@ -378,7 +378,7 @@ describe('change detection', () => {
static ngDirectiveDef = defineDirective({
type: Dir,
selectors: [['', 'dir', '']],
factory: () => dir = new Dir(injectChangeDetectorRef())
factory: () => dir = new Dir(directiveInject(ChangeDetectorRef as any))
});
}
@ -487,7 +487,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()),
factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)),
consts: 2,
vars: 1,
/**
@ -542,7 +542,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: DetectChangesComp,
selectors: [['detect-changes-comp']],
factory: () => new DetectChangesComp(injectChangeDetectorRef()),
factory: () => new DetectChangesComp(directiveInject(ChangeDetectorRef as any)),
consts: 1,
vars: 1,
/** {{ value }} */
@ -575,7 +575,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: DetectChangesComp,
selectors: [['detect-changes-comp']],
factory: () => new DetectChangesComp(injectChangeDetectorRef()),
factory: () => new DetectChangesComp(directiveInject(ChangeDetectorRef as any)),
consts: 1,
vars: 1,
/** {{ doCheckCount }} */
@ -605,7 +605,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()),
factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)),
consts: 1,
vars: 0,
/** <detached-comp></detached-comp> */
@ -629,7 +629,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: DetachedComp,
selectors: [['detached-comp']],
factory: () => comp = new DetachedComp(injectChangeDetectorRef()),
factory: () => comp = new DetachedComp(directiveInject(ChangeDetectorRef as any)),
consts: 1,
vars: 1,
/** {{ value }} */
@ -730,7 +730,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: OnPushComp,
selectors: [['on-push-comp']],
factory: () => onPushComp = new OnPushComp(injectChangeDetectorRef()),
factory: () => onPushComp = new OnPushComp(directiveInject(ChangeDetectorRef as any)),
consts: 1,
vars: 1,
/** {{ value }} */
@ -791,7 +791,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: OnPushComp,
selectors: [['on-push-comp']],
factory: () => comp = new OnPushComp(injectChangeDetectorRef()),
factory: () => comp = new OnPushComp(directiveInject(ChangeDetectorRef as any)),
consts: 1,
vars: 1,
/** {{ value }} */
@ -960,7 +960,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: NoChangesComp,
selectors: [['no-changes-comp']],
factory: () => comp = new NoChangesComp(injectChangeDetectorRef()),
factory: () => comp = new NoChangesComp(directiveInject(ChangeDetectorRef as any)),
consts: 1,
vars: 1,
template: (rf: RenderFlags, ctx: NoChangesComp) => {
@ -982,7 +982,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: AppComp,
selectors: [['app-comp']],
factory: () => new AppComp(injectChangeDetectorRef()),
factory: () => new AppComp(directiveInject(ChangeDetectorRef as any)),
consts: 2,
vars: 1,
/**
@ -1045,7 +1045,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({
type: EmbeddedViewApp,
selectors: [['embedded-view-app']],
factory: () => new EmbeddedViewApp(injectChangeDetectorRef()),
factory: () => new EmbeddedViewApp(directiveInject(ChangeDetectorRef as any)),
consts: 1,
vars: 0,
/**

View File

@ -7,6 +7,7 @@
*/
import {NgForOfContext} from '@angular/common';
import {ElementRef, TemplateRef} from '@angular/core';
import {AttributeMarker, defineComponent, templateRefExtractor} from '../../src/render3/index';
import {bind, template, elementEnd, elementProperty, elementStart, getCurrentView, interpolation1, interpolation2, interpolation3, interpolationV, listener, load, nextContext, restoreView, text, textBinding, elementContainerStart, elementContainerEnd, reference} from '../../src/render3/instructions';
@ -896,11 +897,15 @@ describe('@angular/common integration', () => {
*/
template: (rf: RenderFlags, myApp: MyApp) => {
if (rf & RenderFlags.Create) {
template(0, (rf1: RenderFlags) => {
if (rf1 & RenderFlags.Create) {
text(0, 'from tpl');
}
}, 1, 0, undefined, undefined, ['tpl', ''], templateRefExtractor);
template(
0,
(rf1: RenderFlags) => {
if (rf1 & RenderFlags.Create) {
text(0, 'from tpl');
}
},
1, 0, undefined, undefined, ['tpl', ''],
templateRefExtractor(TemplateRef, ElementRef));
template(2, null, 0, 0, null, [AttributeMarker.SelectOnly, 'ngTemplateOutlet']);
}
if (rf & RenderFlags.Update) {
@ -939,11 +944,15 @@ describe('@angular/common integration', () => {
*/
template: (rf: RenderFlags, myApp: MyApp) => {
if (rf & RenderFlags.Create) {
template(0, (rf1: RenderFlags) => {
if (rf1 & RenderFlags.Create) {
text(0, 'from tpl');
}
}, 1, 0, undefined, undefined, ['tpl', ''], templateRefExtractor);
template(
0,
(rf1: RenderFlags) => {
if (rf1 & RenderFlags.Create) {
text(0, 'from tpl');
}
},
1, 0, undefined, undefined, ['tpl', ''],
templateRefExtractor(TemplateRef, ElementRef));
elementContainerStart(2, [AttributeMarker.SelectOnly, 'ngTemplateOutlet']);
elementContainerEnd();
}

View File

@ -7,9 +7,9 @@
*/
import {NgForOf as NgForOfDef, NgIf as NgIfDef, NgTemplateOutlet as NgTemplateOutletDef} from '@angular/common';
import {IterableDiffers} from '@angular/core';
import {IterableDiffers, TemplateRef, ViewContainerRef} from '@angular/core';
import {DirectiveType, NgOnChangesFeature, defineDirective, directiveInject, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index';
import {DirectiveType, NgOnChangesFeature, defineDirective, directiveInject} from '../../src/render3/index';
export const NgForOf: DirectiveType<NgForOfDef<any>> = NgForOfDef as any;
export const NgIf: DirectiveType<NgIfDef> = NgIfDef as any;
@ -19,7 +19,8 @@ NgForOf.ngDirectiveDef = defineDirective({
type: NgForOfDef,
selectors: [['', 'ngForOf', '']],
factory: () => new NgForOfDef(
injectViewContainerRef(), injectTemplateRef(), directiveInject(IterableDiffers)),
directiveInject(ViewContainerRef as any), directiveInject(TemplateRef as any),
directiveInject(IterableDiffers)),
inputs: {
ngForOf: 'ngForOf',
ngForTrackBy: 'ngForTrackBy',
@ -30,14 +31,15 @@ NgForOf.ngDirectiveDef = defineDirective({
(NgIf as any).ngDirectiveDef = defineDirective({
type: NgIfDef,
selectors: [['', 'ngIf', '']],
factory: () => new NgIfDef(injectViewContainerRef(), injectTemplateRef()),
factory: () => new NgIfDef(
directiveInject(ViewContainerRef as any), directiveInject(TemplateRef as any)),
inputs: {ngIf: 'ngIf', ngIfThen: 'ngIfThen', ngIfElse: 'ngIfElse'}
});
(NgTemplateOutlet as any).ngDirectiveDef = defineDirective({
type: NgTemplateOutletDef,
selectors: [['', 'ngTemplateOutlet', '']],
factory: () => new NgTemplateOutletDef(injectViewContainerRef()),
factory: () => new NgTemplateOutletDef(directiveInject(ViewContainerRef as any)),
features: [NgOnChangesFeature],
inputs:
{ngTemplateOutlet: 'ngTemplateOutlet', ngTemplateOutletContext: 'ngTemplateOutletContext'}

View File

@ -394,7 +394,7 @@ describe('components & directives', () => {
static ngDirectiveDef = $r3$.ɵdefineDirective({
type: IfDirective,
selectors: [['', 'if', '']],
factory: () => new IfDirective($r3$.ɵinjectTemplateRef()),
factory: () => new IfDirective($r3$.ɵdirectiveInject(TemplateRef as any)),
});
// /NORMATIVE
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Attribute, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, INJECTOR, Inject, InjectFlags, Injectable, Injector, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, SkipSelf, TemplateRef, ViewChild, ViewChildren, ViewContainerRef, defineInjectable, defineInjector, inject} from '../../../src/core';
import {Attribute, ChangeDetectorRef, Component, INJECTOR, Inject, InjectFlags, Injectable, Injector, SkipSelf, defineInjectable, inject} from '../../../src/core';
import * as $r3$ from '../../../src/core_render3_private_export';
import {renderComponent, toHtml} from '../render_util';
@ -32,7 +32,7 @@ describe('injection', () => {
type: MyComp,
selectors: [['my-comp']],
factory: function MyComp_Factory() {
return new MyComp($r3$.ɵinjectChangeDetectorRef());
return new MyComp($r3$.ɵdirectiveInject(ChangeDetectorRef as any));
},
consts: 1,
vars: 1,

View File

@ -6,10 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ElementRef, TemplateRef} from '@angular/core';
import {Component} from '../../../src/core';
import * as $r3$ from '../../../src/core_render3_private_export';
import {ComponentFixture} from '../render_util';
/// See: `normative.md`
describe('local references', () => {
type $RenderFlags$ = $r3$.ɵRenderFlags;
@ -69,7 +72,7 @@ describe('local references', () => {
if (rf & 1) {
$r3$.ɵtemplate(
0, MyComponent_Template_0, 0, 0, null, null, ['tpl', ''],
$r3$.ɵtemplateRefExtractor);
$r3$.ɵtemplateRefExtractor(TemplateRef, ElementRef));
$r3$.ɵtext(2);
}
if (rf & 2) {

View File

@ -6,12 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '../../../src/core';
import {Component, Directive, Input, OnDestroy, Pipe, PipeTransform, TemplateRef, ViewContainerRef} from '../../../src/core';
import * as $r3$ from '../../../src/core_render3_private_export';
import {ComponentDefInternal} from '../../../src/render3/interfaces/definition';
import {containerEl, renderComponent, toHtml} from '../render_util';
/// See: `normative.md`
describe('pipes', () => {
type $any$ = any;
@ -145,7 +146,9 @@ describe('pipes', () => {
static ngDirectiveDef = $r3$.ɵdefineDirective({
type: OneTimeIf,
selectors: [['', 'oneTimeIf', '']],
factory: () => new OneTimeIf($r3$.ɵinjectViewContainerRef(), $r3$.ɵinjectTemplateRef()),
factory: () => new OneTimeIf(
$r3$.ɵdirectiveInject(ViewContainerRef as any),
$r3$.ɵdirectiveInject(TemplateRef as any)),
inputs: {oneTimeIf: 'oneTimeIf'}
});
// /NORMATIVE

View File

@ -6,12 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '../../../src/core';
import {Component, Directive, Input, SimpleChanges, TemplateRef, ViewContainerRef, inject} from '../../../src/core';
import * as $r3$ from '../../../src/core_render3_private_export';
import {ComponentDefInternal} from '../../../src/render3/interfaces/definition';
import {renderComponent, toHtml} from '../render_util';
/// See: `normative.md`
describe('template variables', () => {
type $any$ = any;
@ -69,7 +70,9 @@ describe('template variables', () => {
type: ForOfDirective,
selectors: [['', 'forOf', '']],
factory: function ForOfDirective_Factory() {
return new ForOfDirective($r3$.ɵinjectViewContainerRef(), $r3$.ɵinjectTemplateRef());
return new ForOfDirective(
$r3$.ɵdirectiveInject(ViewContainerRef as any),
$r3$.ɵdirectiveInject(TemplateRef as any));
},
// TODO(chuckj): Enable when ngForOf enabling lands.
// features: [NgOnChangesFeature],

View File

@ -8,9 +8,6 @@
import {SelectorFlags} from '@angular/core/src/render3/interfaces/projection';
import {Input, TemplateRef, ViewContainerRef, ViewRef} from '../../src/core';
import {defineDirective} from '../../src/render3/definition';
import {injectTemplateRef, injectViewContainerRef} from '../../src/render3/di';
import {AttributeMarker, detectChanges} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, loadDirective, projection, projectionDef, template, text} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';

View File

@ -11,7 +11,8 @@ 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 {PublicFeature, defineDirective, directiveInject, injectChangeDetectorRef, injectElementRef, injectRenderer2, injectTemplateRef, injectViewContainerRef, load} from '../../src/render3/index';
import {PublicFeature, defineDirective, directiveInject, injectRenderer2, load} 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, loadDirective, elementContainerStart, elementContainerEnd} from '../../src/render3/instructions';
import {LInjector} from '../../src/render3/interfaces/injector';
import {isProceduralRenderer} from '../../src/render3/interfaces/renderer';
@ -786,445 +787,456 @@ describe('di', () => {
});
describe('ElementRef', () => {
it('should create directive with ElementRef dependencies', () => {
let dir !: Directive;
let dirSameInstance !: DirectiveSameInstance;
let divNode !: LElementNode;
describe('Special tokens', () => {
describe('ElementRef', () => {
it('should create directive with ElementRef dependencies', () => {
let dir !: Directive;
let dirSameInstance !: DirectiveSameInstance;
let divNode !: LElementNode;
class Directive {
value: string;
constructor(public elementRef: ElementRef) {
this.value = (elementRef.constructor as any).name;
}
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => dir = new Directive(directiveInject(ElementRef)),
features: [PublicFeature],
exportAs: 'dir'
});
}
class DirectiveSameInstance {
isSameInstance: boolean;
constructor(public elementRef: ElementRef, directive: Directive) {
this.isSameInstance = elementRef === directive.elementRef;
}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']],
factory: () => dirSameInstance = new DirectiveSameInstance(
directiveInject(ElementRef), directiveInject(Directive)),
exportAs: 'dirSame'
});
}
/** <div dir dirSame></div> */
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', '']);
elementEnd();
divNode = load(0);
}
}, 1, 0, [Directive, DirectiveSameInstance]);
const fixture = new ComponentFixture(App);
expect(dir.value).toContain('ElementRef');
expect(dir.elementRef.nativeElement).toEqual(divNode.native);
expect(dirSameInstance.elementRef.nativeElement).toEqual(divNode.native);
// Each ElementRef instance should be unique
expect(dirSameInstance.isSameInstance).toBe(false);
});
it('should create ElementRef with comment if requesting directive is on <ng-template> node',
() => {
let dir !: Directive;
let commentNode !: LContainerNode;
class Directive {
value: string;
constructor(public elementRef: ElementRef) {
this.value = (elementRef.constructor as any).name;
}
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => dir = new Directive(directiveInject(ElementRef)),
features: [PublicFeature],
exportAs: 'dir'
});
}
/** <ng-template dir></ng-template> */
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
template(0, () => {}, 0, 0, null, ['dir', '']);
commentNode = load(0);
}
}, 1, 0, [Directive]);
const fixture = new ComponentFixture(App);
expect(dir.value).toContain('ElementRef');
expect(dir.elementRef.nativeElement).toEqual(commentNode.native);
});
});
describe('TemplateRef', () => {
it('should create directive with TemplateRef dependencies', () => {
class Directive {
value: string;
constructor(public templateRef: TemplateRef<any>) {
this.value = (templateRef.constructor as any).name;
}
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => new Directive(directiveInject(TemplateRef as any)),
features: [PublicFeature],
exportAs: 'dir'
});
}
class DirectiveSameInstance {
isSameInstance: boolean;
constructor(templateRef: TemplateRef<any>, directive: Directive) {
this.isSameInstance = templateRef === directive.templateRef;
}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']],
factory: () => new DirectiveSameInstance(
directiveInject(TemplateRef as any), directiveInject(Directive)),
exportAs: 'dirSame'
});
}
/**
* <ng-template dir dirSame #dir="dir" #dirSame="dirSame">
* {{ dir.value }} - {{ dirSame.value }}
* </ng-template>
*/
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
template(0, function() {
}, 0, 0, undefined, ['dir', '', 'dirSame', ''], ['dir', 'dir', 'dirSame', 'dirSame']);
text(3);
}
if (rf & RenderFlags.Update) {
const tmp1 = reference(1) as any;
const tmp2 = reference(2) as any;
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.isSameInstance, ''));
}
}, 4, 2, [Directive, DirectiveSameInstance]);
const fixture = new ComponentFixture(App);
// Each TemplateRef instance should be unique
expect(fixture.html).toContain('TemplateRef');
expect(fixture.html).toContain('false');
});
});
describe('ViewContainerRef', () => {
it('should create directive with ViewContainerRef dependencies', () => {
class Directive {
value: string;
constructor(public viewContainerRef: ViewContainerRef) {
this.value = (viewContainerRef.constructor as any).name;
}
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => new Directive(directiveInject(ViewContainerRef as any)),
features: [PublicFeature],
exportAs: 'dir'
});
}
class DirectiveSameInstance {
isSameInstance: boolean;
constructor(viewContainerRef: ViewContainerRef, directive: Directive) {
this.isSameInstance = viewContainerRef === directive.viewContainerRef;
}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']],
factory: () => new DirectiveSameInstance(
directiveInject(ViewContainerRef as any), directiveInject(Directive)),
exportAs: 'dirSame'
});
}
/**
* <div dir dirSame #dir="dir" #dirSame="dirSame">
* {{ dir.value }} - {{ dirSame.value }}
* </div>
*/
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(
0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir', 'dirSame', 'dirSame']);
{ text(3); }
elementEnd();
}
if (rf & RenderFlags.Update) {
const tmp1 = reference(1) as any;
const tmp2 = reference(2) as any;
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.isSameInstance, ''));
}
}, 4, 2, [Directive, DirectiveSameInstance]);
const fixture = new ComponentFixture(App);
// Each ViewContainerRef instance should be unique
expect(fixture.html).toContain('ViewContainerRef');
expect(fixture.html).toContain('false');
});
});
describe('ChangeDetectorRef', () => {
let dir: Directive;
let dirSameInstance: DirectiveSameInstance;
let comp: MyComp;
class MyComp {
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyComp,
selectors: [['my-comp']],
factory: () => comp = new MyComp(directiveInject(ChangeDetectorRef as any)),
consts: 1,
vars: 0,
template: function(rf: RenderFlags, ctx: MyComp) {
if (rf & RenderFlags.Create) {
projectionDef();
projection(0);
}
}
});
}
class Directive {
value: string;
constructor(public elementRef: ElementRef) {
this.value = (elementRef.constructor as any).name;
}
constructor(public cdr: ChangeDetectorRef) { this.value = (cdr.constructor as any).name; }
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => dir = new Directive(injectElementRef()),
factory: () => dir = new Directive(directiveInject(ChangeDetectorRef as any)),
features: [PublicFeature],
exportAs: 'dir'
});
}
class DirectiveSameInstance {
isSameInstance: boolean;
constructor(public elementRef: ElementRef, directive: Directive) {
this.isSameInstance = elementRef === directive.elementRef;
}
constructor(public cdr: ChangeDetectorRef) {}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']],
factory: () => dirSameInstance =
new DirectiveSameInstance(injectElementRef(), directiveInject(Directive)),
exportAs: 'dirSame'
new DirectiveSameInstance(directiveInject(ChangeDetectorRef as any))
});
}
/** <div dir dirSame></div> */
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', '']);
elementEnd();
divNode = load(0);
}
}, 1, 0, [Directive, DirectiveSameInstance]);
const directives = [MyComp, Directive, DirectiveSameInstance, NgIf];
const fixture = new ComponentFixture(App);
expect(dir.value).toEqual('ElementRef');
expect(dir.elementRef.nativeElement).toEqual(divNode.native);
expect(dirSameInstance.elementRef.nativeElement).toEqual(divNode.native);
it('should inject current component ChangeDetectorRef into directives on the same node as components',
() => {
/** <my-comp dir dirSameInstance #dir="dir"></my-comp> {{ dir.value }} */
const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
element(0, 'my-comp', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
text(2);
}
if (rf & RenderFlags.Update) {
const tmp = reference(1) as any;
textBinding(2, bind(tmp.value));
}
}, 3, 1, directives);
// Each ElementRef instance should be unique
expect(dirSameInstance.isSameInstance).toBe(false);
});
const app = renderComponent(MyApp);
// ChangeDetectorRef is the token, ViewRef has historically been the constructor
expect(toHtml(app)).toEqual('<my-comp dir="" dirsame=""></my-comp>ViewRef');
expect((comp !.cdr as ViewRef<MyComp>).context).toBe(comp);
it('should create ElementRef with comment if requesting directive is on <ng-template> node',
() => {
let dir !: Directive;
let commentNode !: LContainerNode;
// Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(comp !.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
class Directive {
value: string;
constructor(public elementRef: ElementRef) {
this.value = (elementRef.constructor as any).name;
it('should inject host component ChangeDetectorRef into directives on normal elements',
() => {
class MyApp {
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
consts: 3,
vars: 1,
factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)),
/** <div dir dirSameInstance #dir="dir"> {{ dir.value }} </div> */
template: function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
}
if (rf & RenderFlags.Update) {
const tmp = reference(1) as any;
textBinding(2, bind(tmp.value));
}
},
directives: directives
});
}
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => dir = new Directive(injectElementRef()),
features: [PublicFeature],
exportAs: 'dir'
});
}
/** <ng-template dir></ng-template> */
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
template(0, () => {}, 0, 0, null, ['dir', '']);
commentNode = load(0);
const app = renderComponent(MyApp);
expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>');
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
// Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(app.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
it('should inject host component ChangeDetectorRef into directives in a component\'s ContentChildren',
() => {
class MyApp {
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
consts: 4,
vars: 1,
factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)),
/**
* <my-comp>
* <div dir dirSameInstance #dir="dir"></div>
* </my-comp>
* {{ dir.value }}
*/
template: function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'my-comp');
{ element(1, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']); }
elementEnd();
text(3);
}
if (rf & RenderFlags.Update) {
const tmp = reference(2) as any;
textBinding(3, bind(tmp.value));
}
},
directives: directives
});
}
}, 1, 0, [Directive]);
const fixture = new ComponentFixture(App);
expect(dir.value).toEqual('ElementRef');
expect(dir.elementRef.nativeElement).toEqual(commentNode.native);
});
});
const app = renderComponent(MyApp);
expect(toHtml(app)).toEqual('<my-comp><div dir="" dirsame=""></div></my-comp>ViewRef');
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
describe('TemplateRef', () => {
it('should create directive with TemplateRef dependencies', () => {
class Directive {
value: string;
constructor(public templateRef: TemplateRef<any>) {
this.value = (templateRef.constructor as any).name;
}
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => new Directive(injectTemplateRef()),
features: [PublicFeature],
exportAs: 'dir'
});
}
// Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(app !.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
class DirectiveSameInstance {
isSameInstance: boolean;
constructor(templateRef: TemplateRef<any>, directive: Directive) {
this.isSameInstance = templateRef === directive.templateRef;
}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']],
factory: () => new DirectiveSameInstance(injectTemplateRef(), directiveInject(Directive)),
exportAs: 'dirSame'
});
}
it('should inject host component ChangeDetectorRef into directives in embedded views', () => {
/**
* <ng-template dir dirSame #dir="dir" #dirSame="dirSame">
* {{ dir.value }} - {{ dirSame.value }}
* </ng-template>
*/
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
template(0, function() {
}, 0, 0, undefined, ['dir', '', 'dirSame', ''], ['dir', 'dir', 'dirSame', 'dirSame']);
text(3);
}
if (rf & RenderFlags.Update) {
const tmp1 = reference(1) as any;
const tmp2 = reference(2) as any;
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.isSameInstance, ''));
}
}, 4, 2, [Directive, DirectiveSameInstance]);
class MyApp {
showing = true;
const fixture = new ComponentFixture(App);
// Each TemplateRef instance should be unique
expect(fixture.html).toEqual('TemplateRef-false');
});
});
constructor(public cdr: ChangeDetectorRef) {}
describe('ViewContainerRef', () => {
it('should create directive with ViewContainerRef dependencies', () => {
class Directive {
value: string;
constructor(public viewContainerRef: ViewContainerRef) {
this.value = (viewContainerRef.constructor as any).name;
}
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => new Directive(injectViewContainerRef()),
features: [PublicFeature],
exportAs: 'dir'
});
}
class DirectiveSameInstance {
isSameInstance: boolean;
constructor(viewContainerRef: ViewContainerRef, directive: Directive) {
this.isSameInstance = viewContainerRef === directive.viewContainerRef;
}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']],
factory:
() => new DirectiveSameInstance(injectViewContainerRef(), directiveInject(Directive)),
exportAs: 'dirSame'
});
}
/**
* <div dir dirSame #dir="dir" #dirSame="dirSame">
* {{ dir.value }} - {{ dirSame.value }}
* </div>
*/
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir', 'dirSame', 'dirSame']);
{ text(3); }
elementEnd();
}
if (rf & RenderFlags.Update) {
const tmp1 = reference(1) as any;
const tmp2 = reference(2) as any;
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.isSameInstance, ''));
}
}, 4, 2, [Directive, DirectiveSameInstance]);
const fixture = new ComponentFixture(App);
// Each ViewContainerRef instance should be unique
expect(fixture.html).toEqual('<div dir="" dirsame="">ViewContainerRef-false</div>');
});
});
describe('ChangeDetectorRef', () => {
let dir: Directive;
let dirSameInstance: DirectiveSameInstance;
let comp: MyComp;
class MyComp {
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyComp,
selectors: [['my-comp']],
factory: () => comp = new MyComp(injectChangeDetectorRef()),
consts: 1,
vars: 0,
template: function(rf: RenderFlags, ctx: MyComp) {
if (rf & RenderFlags.Create) {
projectionDef();
projection(0);
}
}
});
}
class Directive {
value: string;
constructor(public cdr: ChangeDetectorRef) { this.value = (cdr.constructor as any).name; }
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => dir = new Directive(injectChangeDetectorRef()),
features: [PublicFeature],
exportAs: 'dir'
});
}
class DirectiveSameInstance {
constructor(public cdr: ChangeDetectorRef) {}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']],
factory: () => dirSameInstance = new DirectiveSameInstance(injectChangeDetectorRef())
});
}
const directives = [MyComp, Directive, DirectiveSameInstance, NgIf];
it('should inject current component ChangeDetectorRef into directives on the same node as components',
() => {
/** <my-comp dir dirSameInstance #dir="dir"></my-comp> {{ dir.value }} */
const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
element(0, 'my-comp', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
text(2);
}
if (rf & RenderFlags.Update) {
const tmp = reference(1) as any;
textBinding(2, bind(tmp.value));
}
}, 3, 1, directives);
const app = renderComponent(MyApp);
// ChangeDetectorRef is the token, ViewRef has historically been the constructor
expect(toHtml(app)).toEqual('<my-comp dir="" dirsame=""></my-comp>ViewRef');
expect((comp !.cdr as ViewRef<MyComp>).context).toBe(comp);
// Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(comp !.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
it('should inject host component ChangeDetectorRef into directives on normal elements', () => {
class MyApp {
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
consts: 3,
vars: 1,
factory: () => new MyApp(injectChangeDetectorRef()),
/** <div dir dirSameInstance #dir="dir"> {{ dir.value }} </div> */
template: function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
}
if (rf & RenderFlags.Update) {
const tmp = reference(1) as any;
textBinding(2, bind(tmp.value));
}
},
directives: directives
});
}
const app = renderComponent(MyApp);
expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>');
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
// Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(app.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
it('should inject host component ChangeDetectorRef into directives in a component\'s ContentChildren',
() => {
class MyApp {
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
consts: 4,
vars: 1,
factory: () => new MyApp(injectChangeDetectorRef()),
/**
* <my-comp>
* <div dir dirSameInstance #dir="dir"></div>
* </my-comp>
* {{ dir.value }}
*/
template: function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'my-comp');
{ element(1, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']); }
elementEnd();
text(3);
}
if (rf & RenderFlags.Update) {
const tmp = reference(2) as any;
textBinding(3, bind(tmp.value));
}
},
directives: directives
});
}
const app = renderComponent(MyApp);
expect(toHtml(app)).toEqual('<my-comp><div dir="" dirsame=""></div></my-comp>ViewRef');
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
// Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(app !.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
it('should inject host component ChangeDetectorRef into directives in embedded views', () => {
class MyApp {
showing = true;
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()),
consts: 1,
vars: 0,
/**
* % if (showing) {
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)),
consts: 1,
vars: 0,
/**
* % if (showing) {
* <div dir dirSameInstance #dir="dir"> {{ dir.value }} </div>
* % }
*/
template: function(rf: RenderFlags, ctx: MyApp) {
if (rf & RenderFlags.Create) {
container(0);
}
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.showing) {
let rf1 = embeddedViewStart(0, 3, 1);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
}
if (rf1 & RenderFlags.Update) {
const tmp = reference(1) as any;
textBinding(2, bind(tmp.value));
}
}
embeddedViewEnd();
*/
template: function(rf: RenderFlags, ctx: MyApp) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshEnd();
}
},
directives: directives
});
}
const app = renderComponent(MyApp);
expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>');
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
// Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(app.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
it('should inject host component ChangeDetectorRef into directives on containers', () => {
function C1(rf1: RenderFlags, ctx1: any) {
if (rf1 & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.showing) {
let rf1 = embeddedViewStart(0, 3, 1);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
}
if (rf1 & RenderFlags.Update) {
const tmp = reference(1) as any;
textBinding(2, bind(tmp.value));
}
}
embeddedViewEnd();
}
containerRefreshEnd();
}
},
directives: directives
});
}
if (rf1 & RenderFlags.Update) {
const tmp = reference(1) as any;
textBinding(2, bind(tmp.value));
const app = renderComponent(MyApp);
expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>');
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
// Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(app.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
it('should inject host component ChangeDetectorRef into directives on containers', () => {
function C1(rf1: RenderFlags, ctx1: any) {
if (rf1 & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
}
if (rf1 & RenderFlags.Update) {
const tmp = reference(1) as any;
textBinding(2, bind(tmp.value));
}
}
}
class MyApp {
showing = true;
class MyApp {
showing = true;
constructor(public cdr: ChangeDetectorRef) {}
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()),
consts: 1,
vars: 0,
/** <div *ngIf="showing" dir dirSameInstance #dir="dir"> {{ dir.value }} </div> */
template: function(rf: RenderFlags, ctx: MyApp) {
if (rf & RenderFlags.Create) {
template(0, C1, 3, 1, null, ['ngIf', 'showing']);
}
},
directives: directives
});
}
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)),
consts: 1,
vars: 0,
/** <div *ngIf="showing" dir dirSameInstance #dir="dir"> {{ dir.value }} </div> */
template: function(rf: RenderFlags, ctx: MyApp) {
if (rf & RenderFlags.Create) {
template(0, C1, 3, 1, null, ['ngIf', 'showing']);
}
},
directives: directives
});
}
const app = renderComponent(MyApp);
expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>');
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
const app = renderComponent(MyApp);
expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>');
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
// Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(app.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
// Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(app.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
});
});

View File

@ -10,8 +10,7 @@ import {ElementRef, TemplateRef, ViewContainerRef} from '@angular/core';
import {RenderFlags} from '@angular/core/src/render3';
import {RendererStyleFlags2, RendererType2} from '../../src/render/api';
import {createTemplateRef, getOrCreateNodeInjectorForNode} from '../../src/render3/di';
import {AttributeMarker, defineComponent, defineDirective, injectElementRef, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index';
import {AttributeMarker, defineComponent, defineDirective} from '../../src/render3/index';
import {NO_CHANGE, bind, container, containerRefreshEnd, containerRefreshStart, element, elementAttribute, elementClassProp, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, elementStyleProp, elementStyling, elementStylingApply, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV, listener, load, loadDirective, projection, projectionDef, text, textBinding, template} from '../../src/render3/instructions';
import {InitialStylingFlags} from '../../src/render3/interfaces/definition';
@ -21,9 +20,10 @@ import {sanitizeUrl} from '../../src/sanitization/sanitization';
import {Sanitizer, SecurityContext} from '../../src/sanitization/security';
import {NgIf} from './common_with_def';
import {ComponentFixture, TemplateFixture, containerEl, createComponent, renderToHtml} from './render_util';
import {ComponentFixture, TemplateFixture, createComponent, renderToHtml} from './render_util';
import {MONKEY_PATCH_KEY_NAME, getContext} from '../../src/render3/context_discovery';
import {StylingIndex} from '../../src/render3/styling';
import {directiveInject} from '../../src/render3/di';
describe('render3 integration test', () => {
@ -649,7 +649,9 @@ describe('render3 integration test', () => {
static ngDirectiveDef = defineDirective({
type: TestDirective,
selectors: [['', 'testDirective', '']],
factory: () => new TestDirective(injectTemplateRef(), injectViewContainerRef()),
factory:
() => new TestDirective(
directiveInject(TemplateRef as any), directiveInject(ViewContainerRef as any)),
});
}
@ -754,7 +756,9 @@ describe('render3 integration test', () => {
static ngDirectiveDef = defineDirective({
type: TestDirective,
selectors: [['', 'testDirective', '']],
factory: () => new TestDirective(injectTemplateRef(), injectViewContainerRef()),
factory:
() => new TestDirective(
directiveInject(TemplateRef as any), directiveInject(ViewContainerRef as any)),
});
}
@ -822,7 +826,7 @@ describe('render3 integration test', () => {
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => new Directive(injectElementRef()),
factory: () => new Directive(directiveInject(ElementRef)),
});
}

View File

@ -11,7 +11,7 @@ import 'reflect-metadata';
import {InjectorDef, defineInjectable} from '@angular/core/src/di/defs';
import {Injectable} from '@angular/core/src/di/injectable';
import {inject, setCurrentInjector} from '@angular/core/src/di/injector';
import {ivyEnabled} from '@angular/core/src/ivy_switch';
import {ivyEnabled} from '@angular/core/src/ivy_switch/compiler/index';
import {Component, HostBinding, HostListener, Input, Output, Pipe} from '@angular/core/src/metadata/directives';
import {NgModule, NgModuleDefInternal} from '@angular/core/src/metadata/ng_module';
import {ComponentDefInternal, PipeDefInternal} from '@angular/core/src/render3/interfaces/definition';

View File

@ -10,11 +10,14 @@ import {NgForOfContext} from '@angular/common';
import {ElementRef, TemplateRef, ViewContainerRef} from '@angular/core';
import {EventEmitter} from '../..';
import {QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF, templateRefExtractor} from '../../src/render3/di';
import {AttributeMarker, QueryList, defineComponent, defineDirective, detectChanges, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index';
import {directiveInject} from '../../src/render3/di';
import {AttributeMarker, QueryList, defineComponent, defineDirective, detectChanges} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, load, loadDirective, loadElement, loadQueryList, reference, registerContentQuery, template} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {query, queryRefresh} from '../../src/render3/query';
import {query, queryRefresh, QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF} from '../../src/render3/query';
import {templateRefExtractor} from '../../src/render3/view_engine_compatibility';
import {NgForOf, NgIf, NgTemplateOutlet} from './common_with_def';
import {ComponentFixture, TemplateFixture, createComponent, createDirective, renderComponent} from './render_util';
@ -118,7 +121,7 @@ describe('query', () => {
2, 0, [Child], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, Child, false, QUERY_READ_ELEMENT_REF);
query(0, Child, false, QUERY_READ_ELEMENT_REF(ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -226,7 +229,7 @@ describe('query', () => {
4, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_FROM_NODE);
query(0, ['foo'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -263,8 +266,8 @@ describe('query', () => {
6, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_FROM_NODE);
query(1, ['bar'], false, QUERY_READ_FROM_NODE);
query(0, ['foo'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
query(1, ['bar'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -312,7 +315,7 @@ describe('query', () => {
6, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE);
query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -349,7 +352,7 @@ describe('query', () => {
4, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF);
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF(ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -385,7 +388,7 @@ describe('query', () => {
3, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF);
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF(ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -421,7 +424,7 @@ describe('query', () => {
3, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -485,8 +488,8 @@ describe('query', () => {
5, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_ELEMENT_REF);
query(1, ['foo'], false, QUERY_READ_ELEMENT_REF);
query(0, ['foo'], true, QUERY_READ_ELEMENT_REF(ElementRef));
query(1, ['foo'], false, QUERY_READ_ELEMENT_REF(ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -520,7 +523,7 @@ describe('query', () => {
3, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_CONTAINER_REF);
query(0, ['foo'], false, QUERY_READ_CONTAINER_REF(ViewContainerRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -551,7 +554,7 @@ describe('query', () => {
3, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_CONTAINER_REF);
query(0, ['foo'], false, QUERY_READ_CONTAINER_REF(ViewContainerRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -584,7 +587,7 @@ describe('query', () => {
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF);
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF(ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -618,7 +621,7 @@ describe('query', () => {
3, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], undefined, QUERY_READ_FROM_NODE);
query(0, ['foo'], undefined, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -650,7 +653,7 @@ describe('query', () => {
3, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_TEMPLATE_REF);
query(0, ['foo'], false, QUERY_READ_TEMPLATE_REF(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -687,7 +690,7 @@ describe('query', () => {
3, 0, [Child], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -732,7 +735,7 @@ describe('query', () => {
3, 0, [Child], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -770,7 +773,7 @@ describe('query', () => {
3, 0, [Child], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -810,7 +813,7 @@ describe('query', () => {
4, 0, [Child1, Child2], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo', 'bar'], true, QUERY_READ_FROM_NODE);
query(0, ['foo', 'bar'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -849,8 +852,8 @@ describe('query', () => {
5, 0, [Child], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(1, ['bar'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
query(1, ['bar'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -893,7 +896,7 @@ describe('query', () => {
3, 0, [Child], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], undefined, QUERY_READ_ELEMENT_REF);
query(0, ['foo'], undefined, QUERY_READ_ELEMENT_REF(ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -931,7 +934,7 @@ describe('query', () => {
4, 0, [Child], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE);
query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -993,7 +996,7 @@ describe('query', () => {
selectors: [['', 'vc', '']],
factory: () => {
const directiveInstance =
new ViewContainerManipulatorDirective(injectViewContainerRef());
new ViewContainerManipulatorDirective(directiveInject(ViewContainerRef as any));
directiveInstances.push(directiveInstance);
return directiveInstance;
}
@ -1039,7 +1042,7 @@ describe('query', () => {
3, 1, [NgIf], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -1100,7 +1103,7 @@ describe('query', () => {
viewQuery: function(rf: RenderFlags, ctx: Cmpt) {
let tmp: any;
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
@ -1170,10 +1173,12 @@ describe('query', () => {
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
template(
1, Cmpt_Template_1, 2, 1, null, null, ['tpl1', ''], templateRefExtractor);
1, Cmpt_Template_1, 2, 1, null, null, ['tpl1', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(3, 'div', ['id', 'middle'], ['foo', '']);
template(
5, Cmpt_Template_5, 2, 1, null, null, ['tpl2', ''], templateRefExtractor);
5, Cmpt_Template_5, 2, 1, null, null, ['tpl2', ''],
templateRefExtractor(TemplateRef, ElementRef));
template(7, null, 0, 0, null, [AttributeMarker.SelectOnly, 'vc']);
}
@ -1186,7 +1191,7 @@ describe('query', () => {
9, 0, [ViewContainerManipulatorDirective], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -1268,7 +1273,9 @@ describe('query', () => {
template: function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (rf & RenderFlags.Create) {
template(1, Cmpt_Template_1, 2, 1, null, [], ['tpl', ''], templateRefExtractor);
template(
1, Cmpt_Template_1, 2, 1, null, [], ['tpl', ''],
templateRefExtractor(TemplateRef, ElementRef));
template(3, null, 0, 0, null, [AttributeMarker.SelectOnly, 'vc']);
template(4, null, 0, 0, null, [AttributeMarker.SelectOnly, 'vc']);
}
@ -1281,7 +1288,7 @@ describe('query', () => {
viewQuery: (rf: RenderFlags, cmpt: Cmpt) => {
let tmp: any;
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) &&
@ -1341,7 +1348,7 @@ describe('query', () => {
if (rf & RenderFlags.Create) {
template(
1, MyApp_Template_1, 2, 0, undefined, undefined, ['tpl', ''],
templateRefExtractor);
templateRefExtractor(TemplateRef, ElementRef));
template(3, null, 0, 0, null, [AttributeMarker.SelectOnly, 'ngTemplateOutlet']);
}
if (rf & RenderFlags.Update) {
@ -1353,7 +1360,7 @@ describe('query', () => {
viewQuery: (rf: RenderFlags, myApp: MyApp) => {
let tmp: any;
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) &&
@ -1418,7 +1425,7 @@ describe('query', () => {
2, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -1483,7 +1490,7 @@ describe('query', () => {
6, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -1560,7 +1567,7 @@ describe('query', () => {
2, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -1640,7 +1647,7 @@ describe('query', () => {
2, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -1709,8 +1716,8 @@ describe('query', () => {
5, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(1, ['foo'], false, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
query(1, ['foo'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -1790,7 +1797,7 @@ describe('query', () => {
2, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_FROM_NODE);
query(0, ['foo'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -1844,7 +1851,8 @@ describe('query', () => {
static ngDirectiveDef = defineDirective({
type: SomeDir,
selectors: [['', 'someDir', '']],
factory: () => new SomeDir(injectViewContainerRef(), injectTemplateRef())
factory: () => new SomeDir(
directiveInject(ViewContainerRef as any), directiveInject(TemplateRef as any))
});
}
@ -1870,7 +1878,7 @@ describe('query', () => {
4, 0, [SomeDir], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -1907,8 +1915,10 @@ describe('query', () => {
type: WithContentDirective,
selectors: [['', 'with-content', '']],
factory: () => new WithContentDirective(),
contentQueries:
() => { registerContentQuery(query(null, ['foo'], true, QUERY_READ_FROM_NODE)); },
contentQueries: () => {
registerContentQuery(
query(null, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef)));
},
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any;
withContentInstance = loadDirective<WithContentDirective>(dirIndex);
@ -1929,8 +1939,10 @@ describe('query', () => {
template: function(rf: RenderFlags, ctx: any) {},
consts: 0,
vars: 0,
contentQueries:
() => { registerContentQuery(query(null, ['foo'], false, QUERY_READ_FROM_NODE)); },
contentQueries: () => {
registerContentQuery(
query(null, ['foo'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef)));
},
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any;
shallowCompInstance = loadDirective<ShallowComp>(dirIndex);
@ -2046,7 +2058,7 @@ describe('query', () => {
6, 0, [WithContentDirective], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo', 'bar'], true, QUERY_READ_FROM_NODE);
query(0, ['foo', 'bar'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -2086,7 +2098,7 @@ describe('query', () => {
6, 0, [WithContentDirective], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['bar'], true, QUERY_READ_FROM_NODE);
query(0, ['bar'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
}
if (rf & RenderFlags.Update) {
let tmp: any;
@ -2110,7 +2122,8 @@ describe('query', () => {
contentQueries: () => {
// @ContentChildren('foo, bar, baz', {descendants: true}) fooBars:
// QueryList<ElementRef>;
registerContentQuery(query(null, ['foo', 'bar', 'baz'], true, QUERY_READ_FROM_NODE));
registerContentQuery(query(
null, ['foo', 'bar', 'baz'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef)));
},
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any;
@ -2174,7 +2187,8 @@ describe('query', () => {
contentQueries: () => {
// @ContentChildren('foo, bar, baz', {descendants: true}) fooBars:
// QueryList<ElementRef>;
registerContentQuery(query(null, ['foo'], false, QUERY_READ_FROM_NODE));
registerContentQuery(
query(null, ['foo'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef)));
},
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any;
@ -2227,7 +2241,8 @@ describe('query', () => {
factory: () => new ShallowQueryDirective(),
contentQueries: () => {
// @ContentChildren('foo', {descendants: false}) foos: QueryList<ElementRef>;
registerContentQuery(query(null, ['foo'], false, QUERY_READ_FROM_NODE));
registerContentQuery(
query(null, ['foo'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef)));
},
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any;
@ -2247,7 +2262,8 @@ describe('query', () => {
factory: () => new DeepQueryDirective(),
contentQueries: () => {
// @ContentChildren('foo', {descendants: false}) foos: QueryList<ElementRef>;
registerContentQuery(query(null, ['foo'], true, QUERY_READ_FROM_NODE));
registerContentQuery(
query(null, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef)));
},
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any;

View File

@ -6,13 +6,19 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ChangeDetectorRef} from '@angular/core/src/change_detection/change_detector_ref';
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 {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 {PlayerHandler} from '../../src/render3/animations/interfaces';
import {CreateComponentOptions} from '../../src/render3/component';
import {getContext, isComponentInstance} from '../../src/render3/context_discovery';
import {extractDirectiveDef, extractPipeDef} from '../../src/render3/definition';
import {NG_ELEMENT_ID} from '../../src/render3/fields';
import {ComponentTemplate, ComponentType, DirectiveDefInternal, DirectiveType, PublicFeature, RenderFlags, defineComponent, defineDirective, renderComponent as _renderComponent, tick} from '../../src/render3/index';
import {renderTemplate} from '../../src/render3/instructions';
import {DirectiveDefList, DirectiveTypesOrFactory, PipeDefInternal, PipeDefList, PipeTypesOrFactory} from '../../src/render3/interfaces/definition';
@ -208,6 +214,10 @@ function toDefs(
beforeEach(resetDOM);
// This is necessary so we can switch between the Render2 version and the Ivy version
// of special objects like ElementRef and TemplateRef.
beforeEach(enableIvyInjectableFactories);
/**
* @deprecated use `TemplateFixture` or `ComponentFixture`
*/
@ -285,3 +295,17 @@ export function createDirective(
export const renderer: Renderer3 = null as any as Document;
export const element: RElement = null as any as HTMLElement;
export const text: RText = null as any as Text;
/**
* Switches between Render2 version of special objects like ElementRef and the Ivy version
* of these objects. It's necessary to keep them separate so that we don't pull in fns
* like injectElementRef() prematurely.
*/
export function enableIvyInjectableFactories() {
(ElementRef as any)[NG_ELEMENT_ID] = () => R3_ELEMENT_REF_FACTORY(ElementRef);
(TemplateRef as any)[NG_ELEMENT_ID] = () => R3_TEMPLATE_REF_FACTORY(TemplateRef, ElementRef);
(ViewContainerRef as any)[NG_ELEMENT_ID] = () =>
R3_VIEW_CONTAINER_REF_FACTORY(ViewContainerRef, ElementRef);
(ChangeDetectorRef as any)[NG_ELEMENT_ID] = () => R3_CHANGE_DETECTOR_REF_FACTORY();
}

View File

@ -8,11 +8,12 @@
import {Component, ComponentFactoryResolver, ElementRef, EmbeddedViewRef, NgModuleRef, Pipe, PipeTransform, RendererFactory2, TemplateRef, ViewContainerRef, createInjector, defineInjector, ɵAPP_ROOT as APP_ROOT, ɵNgModuleDef as NgModuleDef} from '../../src/core';
import {ViewEncapsulation} from '../../src/metadata';
import {templateRefExtractor} from '../../src/render3/di';
import {AttributeMarker, NgOnChangesFeature, defineComponent, defineDirective, definePipe, injectComponentFactoryResolver, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index';
import {directiveInject} from '../../src/render3/di';
import {AttributeMarker, NgOnChangesFeature, defineComponent, defineDirective, definePipe, injectComponentFactoryResolver} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation3, loadDirective, nextContext, projection, projectionDef, reference, template, text, textBinding} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {templateRefExtractor} from '../../src/render3/view_engine_compatibility';
import {NgModuleFactory} from '../../src/render3/ng_module_ref';
import {pipe, pipeBind1} from '../../src/render3/pipe';
import {NgForOf} from '../../test/render3/common_with_def';
@ -23,7 +24,7 @@ import {ComponentFixture, TemplateFixture, createComponent} from './render_util'
describe('ViewContainerRef', () => {
let directiveInstance: DirectiveWithVCRef|null;
beforeEach(() => { directiveInstance = null; });
beforeEach(() => directiveInstance = null);
class DirectiveWithVCRef {
static ngDirectiveDef = defineDirective({
@ -31,7 +32,7 @@ describe('ViewContainerRef', () => {
selectors: [['', 'vcref', '']],
factory: () => directiveInstance = new DirectiveWithVCRef(
injectViewContainerRef(), injectComponentFactoryResolver()),
directiveInject(ViewContainerRef as any), injectComponentFactoryResolver()),
inputs: {tplRef: 'tplRef'}
});
@ -66,7 +67,9 @@ describe('ViewContainerRef', () => {
* <p vcref [tplRef]="tplRef"></p>
*/
function createTemplate() {
template(0, embeddedTemplate, 1, 1, null, null, ['tplRef', ''], templateRefExtractor);
template(
0, embeddedTemplate, 1, 1, null, null, ['tplRef', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'p', ['vcref', '']);
}
@ -83,7 +86,9 @@ describe('ViewContainerRef', () => {
* <footer></footer>
*/
function createTemplate() {
template(0, embeddedTemplate, 1, 1, null, null, ['tplRef', ''], templateRefExtractor);
template(
0, embeddedTemplate, 1, 1, null, null, ['tplRef', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'header', ['vcref', '']);
element(3, 'footer');
}
@ -119,7 +124,9 @@ describe('ViewContainerRef', () => {
* <footer></footer>
*/
function createTemplate() {
template(0, embeddedTemplate, 1, 1, null, [], ['tplRef', ''], templateRefExtractor);
template(
0, embeddedTemplate, 1, 1, null, [], ['tplRef', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'header-cmp', ['vcref', '']);
element(3, 'footer');
}
@ -155,7 +162,9 @@ describe('ViewContainerRef', () => {
* <div vcref [tplRef]="tplRef"></div>
*/
function createTemplate() {
template(0, embeddedTemplate, 1, 1, null, null, ['tplRef', ''], templateRefExtractor);
template(
0, embeddedTemplate, 1, 1, null, null, ['tplRef', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'div', ['vcref', '']);
element(3, 'div', ['vcref', '']);
@ -186,7 +195,8 @@ describe('ViewContainerRef', () => {
*/
function createTemplate() {
template(
0, embeddedTemplate, 1, 1, null, ['vcref', ''], ['tplRef', ''], templateRefExtractor);
0, embeddedTemplate, 1, 1, null, ['vcref', ''], ['tplRef', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'footer');
}
@ -225,7 +235,8 @@ describe('ViewContainerRef', () => {
type: TestDirective,
selectors: [['', 'testdir', '']],
factory: () => {
const instance = new TestDirective(injectViewContainerRef(), injectTemplateRef());
const instance = new TestDirective(
directiveInject(ViewContainerRef as any), directiveInject(TemplateRef as any));
directiveInstances.push(instance);
@ -299,8 +310,9 @@ describe('ViewContainerRef', () => {
static ngDirectiveDef = defineDirective({
type: TestDirective,
selectors: [['', 'testdir', '']],
factory: () => directiveInstance =
new TestDirective(injectViewContainerRef(), injectTemplateRef())
factory: () => directiveInstance = new TestDirective(
directiveInject(ViewContainerRef as any),
directiveInject(TemplateRef as any))
});
constructor(private _vcRef: ViewContainerRef, private _tplRef: TemplateRef<{}>) {}
@ -455,7 +467,8 @@ describe('ViewContainerRef', () => {
template: (rf: RenderFlags, cmp: SomeComponent) => {
if (rf & RenderFlags.Create) {
template(
0, SomeComponent_Template_0, 2, 3, null, [], ['foo', ''], templateRefExtractor);
0, SomeComponent_Template_0, 2, 3, null, [], ['foo', ''],
templateRefExtractor(TemplateRef, ElementRef));
pipe(2, 'starPipe');
element(3, 'child', ['vcref', '']);
pipe(4, 'starPipe');
@ -495,7 +508,7 @@ describe('ViewContainerRef', () => {
static ngDirectiveDef = defineDirective({
type: InsertionDir,
selectors: [['', 'tplDir', '']],
factory: () => new InsertionDir(injectViewContainerRef()),
factory: () => new InsertionDir(directiveInject(ViewContainerRef as any)),
inputs: {tplDir: 'tplDir'}
});
}
@ -546,7 +559,9 @@ describe('ViewContainerRef', () => {
*/
const Parent = createComponent('parent', function(rf: RenderFlags, parent: any) {
if (rf & RenderFlags.Create) {
template(0, fooTemplate, 2, 1, null, null, ['foo', ''], templateRefExtractor);
template(
0, fooTemplate, 2, 1, null, null, ['foo', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'child');
}
@ -637,7 +652,9 @@ describe('ViewContainerRef', () => {
*/
const Parent = createComponent('parent', function(rf: RenderFlags, parent: any) {
if (rf & RenderFlags.Create) {
template(0, rowTemplate, 3, 2, null, null, ['rowTemplate', ''], templateRefExtractor);
template(
0, rowTemplate, 3, 2, null, null, ['rowTemplate', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'loop-comp');
}
@ -651,7 +668,9 @@ describe('ViewContainerRef', () => {
function rowTemplate(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
template(0, cellTemplate, 2, 3, null, null, ['cellTemplate', ''], templateRefExtractor);
template(
0, cellTemplate, 2, 3, null, null, ['cellTemplate', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'loop-comp');
}
@ -1196,7 +1215,9 @@ describe('ViewContainerRef', () => {
vars: 2,
template: (rf: RenderFlags, cmp: Parent) => {
if (rf & RenderFlags.Create) {
template(0, embeddedTemplate, 2, 1, null, null, ['foo', ''], templateRefExtractor);
template(
0, embeddedTemplate, 2, 1, null, null, ['foo', ''],
templateRefExtractor(TemplateRef, ElementRef));
elementStart(2, 'child');
{
elementStart(3, 'header', ['vcref', '']);
@ -1291,7 +1312,8 @@ describe('ViewContainerRef', () => {
template: (rf: RenderFlags, cmp: Parent) => {
if (rf & RenderFlags.Create) {
template(
0, embeddedTemplate, 2, 1, null, undefined, ['foo', ''], templateRefExtractor);
0, embeddedTemplate, 2, 1, null, undefined, ['foo', ''],
templateRefExtractor(TemplateRef, ElementRef));
elementStart(2, 'child-with-view');
text(3, 'Before projected');
elementStart(4, 'header', ['vcref', '']);
@ -1375,7 +1397,8 @@ describe('ViewContainerRef', () => {
let tplRef: any;
if (rf & RenderFlags.Create) {
template(
0, embeddedTemplate, 2, 1, null, null, ['foo', ''], templateRefExtractor);
0, embeddedTemplate, 2, 1, null, null, ['foo', ''],
templateRefExtractor(TemplateRef, ElementRef));
elementStart(2, 'child-with-selector');
elementStart(3, 'header', ['vcref', '']);
text(4, 'blah');
@ -1428,7 +1451,8 @@ describe('ViewContainerRef', () => {
let tplRef: any;
if (rf & RenderFlags.Create) {
template(
0, embeddedTemplate, 2, 1, null, null, ['foo', ''], templateRefExtractor);
0, embeddedTemplate, 2, 1, null, null, ['foo', ''],
templateRefExtractor(TemplateRef, ElementRef));
elementStart(2, 'child-with-selector');
elementStart(3, 'footer', ['vcref', '']);
text(4, 'blah');
@ -1533,7 +1557,8 @@ describe('ViewContainerRef', () => {
template: (rf: RenderFlags, cmp: SomeComponent) => {
if (rf & RenderFlags.Create) {
template(
0, SomeComponent_Template_0, 1, 1, null, [], ['foo', ''], templateRefExtractor);
0, SomeComponent_Template_0, 1, 1, null, [], ['foo', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'hooks', ['vcref', '']);
element(3, 'hooks');
}