fix(ivy): support separate creation mode and update mode execution in runtime (#23292)

PR Close #23292
This commit is contained in:
Kara Erickson
2018-04-10 20:57:09 -07:00
committed by Victor Berchet
parent 764760ba63
commit de3ca56769
40 changed files with 3121 additions and 2353 deletions

View File

@ -15,6 +15,7 @@ export {
renderComponent as ɵrenderComponent,
ComponentType as ɵComponentType,
DirectiveType as ɵDirectiveType,
RenderFlags as ɵRenderFlags,
directiveInject as ɵdirectiveInject,
injectTemplateRef as ɵinjectTemplateRef,
injectViewContainerRef as ɵinjectViewContainerRef,

View File

@ -12,6 +12,7 @@ import {InjectFlags} from './di';
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveType, PipeDef} from './interfaces/definition';
export {InjectFlags, QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF, directiveInject, injectAttribute, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from './di';
export {RenderFlags} from './interfaces/definition';
export {CssSelectorList} from './interfaces/projection';

View File

@ -17,9 +17,9 @@ import {CurrentMatchesList, LView, LViewFlags, LifecycleStage, RootContext, TDat
import {LContainerNode, LElementNode, LNode, LNodeType, TNodeFlags, LProjectionNode, LTextNode, LViewNode, TNode, TContainerNode, InitialInputData, InitialInputs, PropertyAliases, PropertyAliasValue,} from './interfaces/node';
import {assertNodeType} from './node_assert';
import {appendChild, insertChild, insertView, appendProjectedNode, removeView, canInsertNativeNode} from './node_manipulation';
import {appendChild, insertChild, insertView, appendProjectedNode, removeView, canInsertNativeNode, createTextNode} from './node_manipulation';
import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector_matcher';
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefList, DirectiveDefListOrFactory, DirectiveType, PipeDef, PipeDefListOrFactory} from './interfaces/definition';
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefList, DirectiveDefListOrFactory, DirectiveType, PipeDef, PipeDefListOrFactory, RenderFlags} from './interfaces/definition';
import {RElement, RText, Renderer3, RendererFactory3, ProceduralRenderer3, ObjectOrientedRenderer3, RendererStyleFlags3, isProceduralRenderer} from './interfaces/renderer';
import {isDifferent, stringify} from './util';
import {executeHooks, queueLifecycleHooks, queueInitHooks, executeInitHooks} from './hooks';
@ -458,7 +458,7 @@ export function renderEmbeddedTemplate<T>(
try {
isParent = true;
previousOrParentNode = null !;
let cm: boolean = false;
let rf: RenderFlags = RenderFlags.Update;
if (viewNode == null) {
// TODO: revisit setting currentView when re-writing view containers
const directives = currentView && currentView.tView.directiveRegistry;
@ -468,11 +468,11 @@ export function renderEmbeddedTemplate<T>(
const lView = createLView(-1, renderer, tView, template, context, LViewFlags.CheckAlways);
viewNode = createLNode(null, LNodeType.View, null, lView);
cm = true;
rf = RenderFlags.Create;
}
oldView = enterView(viewNode.data, viewNode);
template(context, cm);
template(rf, context);
refreshDirectives();
refreshDynamicChildren();
@ -492,7 +492,8 @@ export function renderComponentOrTemplate<T>(
rendererFactory.begin();
}
if (template) {
template(componentOrContext !, creationMode);
template(getRenderFlags(hostView), componentOrContext !);
refreshDynamicChildren();
refreshDirectives();
} else {
executeInitAndContentHooks();
@ -510,6 +511,20 @@ export function renderComponentOrTemplate<T>(
}
}
/**
* This function returns the default configuration of rendering flags depending on when the
* template is in creation mode or update mode. By default, the update block is run with the
* creation block when the view is in creation mode. Otherwise, the update block is run
* alone.
*
* Dynamically created views do NOT use this configuration (update block and create block are
* always run separately).
*/
function getRenderFlags(view: LView): RenderFlags {
return view.flags & LViewFlags.CreationMode ? RenderFlags.Create | RenderFlags.Update :
RenderFlags.Update;
}
//////////////////////////
//// Element
//////////////////////////
@ -1146,10 +1161,7 @@ export function elementStyle<T>(
export function text(index: number, value?: any): void {
ngDevMode &&
assertNull(currentView.bindingStartIndex, 'text nodes should be created before bindings');
const textNode = value != null ?
(isProceduralRenderer(renderer) ? renderer.createText(stringify(value)) :
renderer.createTextNode(stringify(value))) :
null;
const textNode = value != null ? createTextNode(value, renderer) : null;
const node = createLNode(index, LNodeType.Element, textNode);
// Text nodes are self closing.
isParent = false;
@ -1174,14 +1186,11 @@ export function textBinding<T>(index: number, value: T | NO_CHANGE): void {
existingNode.native.textContent = stringify(value));
} else {
// Node was created but DOM node creation was delayed. Create and append now.
existingNode.native = isProceduralRenderer(renderer) ?
renderer.createText(stringify(value)) :
renderer.createTextNode(stringify(value));
existingNode.native = createTextNode(value, renderer);
insertChild(existingNode, currentView);
}
}
//////////////////////////
//// Directive
//////////////////////////
@ -1491,18 +1500,18 @@ function scanForView(
* @param viewBlockId The ID of this view
* @return boolean Whether or not this view is in creation mode
*/
export function embeddedViewStart(viewBlockId: number): boolean {
export function embeddedViewStart(viewBlockId: number): RenderFlags {
const container =
(isParent ? previousOrParentNode : previousOrParentNode.parent !) as LContainerNode;
ngDevMode && assertNodeType(container, LNodeType.Container);
const lContainer = container.data;
const existingViewNode = scanForView(container, lContainer.nextIndex, viewBlockId);
let viewNode: LViewNode|null = scanForView(container, lContainer.nextIndex, viewBlockId);
if (existingViewNode) {
previousOrParentNode = existingViewNode;
if (viewNode) {
previousOrParentNode = viewNode;
ngDevMode && assertNodeType(previousOrParentNode, LNodeType.View);
isParent = true;
enterView((existingViewNode as LViewNode).data, existingViewNode as LViewNode);
enterView(viewNode.data, viewNode);
} else {
// When we create a new LView, we always reset the state of the instructions.
const newView = createLView(
@ -1512,9 +1521,9 @@ export function embeddedViewStart(viewBlockId: number): boolean {
newView.queries = lContainer.queries.enterView(lContainer.nextIndex);
}
enterView(newView, createLNode(null, LNodeType.View, null, newView));
enterView(newView, viewNode = createLNode(null, LNodeType.View, null, newView));
}
return !existingViewNode;
return getRenderFlags(viewNode.data);
}
/**
@ -1919,7 +1928,7 @@ export function detectChangesInternal<T>(
const template = def.template;
try {
template(component, creationMode);
template(getRenderFlags(hostView), component);
refreshDirectives();
refreshDynamicChildren();
} finally {
@ -1967,13 +1976,7 @@ export const NO_CHANGE = {} as NO_CHANGE;
* (ie `bind()`, `interpolationX()`, `pureFunctionX()`)
*/
function initBindings() {
// `bindingIndex` is initialized when the view is first entered when not in creation mode
ngDevMode &&
assertEqual(
creationMode, true, 'should only be called in creationMode for performance reasons');
if (currentView.bindingStartIndex == null) {
bindingIndex = currentView.bindingStartIndex = data.length;
}
bindingIndex = currentView.bindingStartIndex = data.length;
}
/**
@ -1982,7 +1985,7 @@ function initBindings() {
* @param value Value to diff
*/
export function bind<T>(value: T | NO_CHANGE): T|NO_CHANGE {
if (creationMode) {
if (currentView.bindingStartIndex == null) {
initBindings();
return data[bindingIndex++] = value;
}
@ -2166,7 +2169,7 @@ export function consumeBinding(): any {
export function bindingUpdated(value: any): boolean {
ngDevMode && assertNotEqual(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
if (creationMode) {
if (currentView.bindingStartIndex == null) {
initBindings();
} else if (isDifferent(data[bindingIndex], value)) {
throwErrorIfNoChangesMode(creationMode, checkNoChangesMode, data[bindingIndex], value);

View File

@ -6,22 +6,34 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ChangeDetectionStrategy} from '../../change_detection/constants';
import {PipeTransform} from '../../change_detection/pipe_transform';
import {Provider} from '../../core';
import {RendererType2} from '../../render/api';
import {Type} from '../../type';
import {resolveRendererType2} from '../../view/util';
import {CssSelectorList} from './projection';
/**
* Definition of what a template rendering function should look like.
*/
export type ComponentTemplate<T> = {
(ctx: T, creationMode: boolean): void; ngPrivateData?: never;
(rf: RenderFlags, ctx: T): void; ngPrivateData?: never;
};
/**
* Flags passed into template functions to determine which blocks (i.e. creation, update)
* should be executed.
*
* Typically, a template runs both the creation block and the update block on initialization and
* subsequent runs only execute the update block. However, dynamically created views require that
* the creation block be executed separately from the update block (for backwards compat).
*/
export const enum RenderFlags {
/* Whether to run the creation block (e.g. create elements and directives) */
Create = 0b01,
/* Whether to run the update block (e.g. refresh bindings) */
Update = 0b10
}
/**
* A subclass of `Type` which has a static `ngComponentDef`:`ComponentDef` field making it
* consumable for rendering.

View File

@ -11,9 +11,10 @@ import {callHooks} from './hooks';
import {LContainer, unusedValueExportToPlacateAjd as unused1} from './interfaces/container';
import {LContainerNode, LElementNode, LNode, LNodeType, LProjectionNode, LTextNode, LViewNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node';
import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection';
import {ProceduralRenderer3, RElement, RNode, RText, isProceduralRenderer, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
import {ProceduralRenderer3, RElement, RNode, RText, Renderer3, isProceduralRenderer, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
import {HookData, LView, LViewOrLContainer, TView, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
import {assertNodeType} from './node_assert';
import {stringify} from './util';
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5;
@ -143,6 +144,11 @@ function findFirstRNode(rootNode: LNode): RElement|RText|null {
return null;
}
export function createTextNode(value: any, renderer: Renderer3): RText {
return isProceduralRenderer(renderer) ? renderer.createText(stringify(value)) :
renderer.createTextNode(stringify(value));
}
/**
* Adds or removes all DOM elements associated with a view.
*
@ -174,6 +180,12 @@ export function addRemoveViewFromContainer(
const renderer = container.view.renderer;
if (node.type === LNodeType.Element) {
if (insertMode) {
if (!node.native) {
// If the native element doesn't exist, this is a bound text node that hasn't yet been
// created because update mode has not run (occurs when a bound text node is a root
// node of a dynamically created view). See textBinding() in instructions for ctx.
(node as LTextNode).native = createTextNode('', renderer);
}
isProceduralRenderer(renderer) ?
renderer.insertBefore(parent, node.native !, beforeNode as RNode | null) :
parent.insertBefore(node.native !, beforeNode as RNode | null, true);

View File

@ -62,6 +62,9 @@
{
"name": "createTView"
},
{
"name": "createTextNode"
},
{
"name": "currentView"
},
@ -104,6 +107,9 @@
{
"name": "getOrCreateTView"
},
{
"name": "getRenderFlags"
},
{
"name": "hostElement"
},

View File

@ -269,6 +269,9 @@
{
"name": "createTView"
},
{
"name": "createTextNode"
},
{
"name": "currentView"
},
@ -398,6 +401,9 @@
{
"name": "getPreviousOrParentNode"
},
{
"name": "getRenderFlags"
},
{
"name": "getRenderer"
},

View File

@ -8,7 +8,7 @@
import {defineComponent} from '../../src/render3/index';
import {container, containerRefreshEnd, containerRefreshStart, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, text} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {document, renderComponent} from './render_util';
describe('iv perf test', () => {
@ -35,25 +35,27 @@ describe('iv perf test', () => {
static ngComponentDef = defineComponent({
type: Component,
selectors: [['div']],
template: function Template(ctx: any, cm: any) {
if (cm) {
template: function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
for (let i = 0; i < count; i++) {
let cm0 = embeddedViewStart(0);
{
if (cm0) {
elementStart(0, 'div');
text(1, '-');
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
for (let i = 0; i < count; i++) {
let rf0 = embeddedViewStart(0);
{
if (rf0 & RenderFlags.Create) {
elementStart(0, 'div');
text(1, '-');
elementEnd();
}
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
},
factory: () => new Component
});

View File

@ -12,7 +12,7 @@ import {ChangeDetectionStrategy, ChangeDetectorRef, DoCheck} from '../../src/cor
import {getRenderedText, whenRendered} from '../../src/render3/component';
import {LifecycleHooksFeature, defineComponent, defineDirective, injectChangeDetectorRef} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, detectChanges, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation2, listener, markDirty, text, textBinding, tick} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {containerEl, createComponent, renderComponent, requestAnimationFrame} from './render_util';
describe('change detection', () => {
@ -27,13 +27,15 @@ describe('change detection', () => {
type: MyComponent,
selectors: [['my-comp']],
factory: () => new MyComponent(),
template: (ctx: MyComponent, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: MyComponent) => {
if (rf & RenderFlags.Create) {
elementStart(0, 'span');
text(1);
elementEnd();
}
textBinding(1, bind(ctx.value));
if (rf & RenderFlags.Update) {
textBinding(1, bind(ctx.value));
}
}
});
}
@ -102,8 +104,8 @@ describe('change detection', () => {
* {{ doCheckCount }} - {{ name }}
* <button (click)="onClick()"></button>
*/
template: (ctx: MyComponent, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: MyComponent) => {
if (rf & RenderFlags.Create) {
text(0);
elementStart(1, 'button');
{
@ -126,12 +128,14 @@ describe('change detection', () => {
selectors: [['my-app']],
factory: () => new MyApp(),
/** <my-comp [name]="name"></my-comp> */
template: (ctx: MyApp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: MyApp) => {
if (rf & RenderFlags.Create) {
elementStart(0, 'my-comp');
elementEnd();
}
elementProperty(0, 'name', bind(ctx.name));
if (rf & RenderFlags.Update) {
elementProperty(0, 'name', bind(ctx.name));
}
},
directives: () => [MyComponent]
});
@ -195,8 +199,8 @@ describe('change detection', () => {
it('should not check OnPush components in update mode when parent events occur', () => {
function noop() {}
const ButtonParent = createComponent('button-parent', function(ctx: any, cm: boolean) {
if (cm) {
const ButtonParent = createComponent('button-parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'my-comp');
elementEnd();
elementStart(1, 'button', ['id', 'parent']);
@ -226,21 +230,23 @@ describe('change detection', () => {
selectors: [['button-parent']],
factory: () => parent = new ButtonParent(),
/** {{ doCheckCount }} - <my-comp></my-comp> */
template: (ctx: ButtonParent, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: ButtonParent) => {
if (rf & RenderFlags.Create) {
text(0);
elementStart(1, 'my-comp');
elementEnd();
}
textBinding(0, interpolation1('', ctx.doCheckCount, ' - '));
if (rf & RenderFlags.Update) {
textBinding(0, interpolation1('', ctx.doCheckCount, ' - '));
}
},
directives: () => [MyComponent],
changeDetection: ChangeDetectionStrategy.OnPush
});
}
const MyButtonApp = createComponent('my-button-app', function(ctx: any, cm: boolean) {
if (cm) {
const MyButtonApp = createComponent('my-button-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button-parent');
elementEnd();
}
@ -285,11 +291,13 @@ describe('change detection', () => {
selectors: [['my-comp']],
factory: () => myComp = new MyComp(injectChangeDetectorRef()),
/** {{ name }} */
template: (ctx: MyComp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: MyComp) => {
if (rf & RenderFlags.Create) {
text(0);
}
textBinding(0, bind(ctx.name));
if (rf & RenderFlags.Update) {
textBinding(0, bind(ctx.name));
}
},
changeDetection: ChangeDetectionStrategy.OnPush
});
@ -310,13 +318,15 @@ describe('change detection', () => {
* {{ doCheckCount}} -
* <my-comp></my-comp>
*/
template: (ctx: ParentComp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: ParentComp) => {
if (rf & RenderFlags.Create) {
text(0);
elementStart(1, 'my-comp');
elementEnd();
}
textBinding(0, interpolation1('', ctx.doCheckCount, ' - '));
if (rf & RenderFlags.Update) {
textBinding(0, interpolation1('', ctx.doCheckCount, ' - '));
}
},
directives: () => [MyComp]
});
@ -388,8 +398,8 @@ describe('change detection', () => {
it('should check component view when called by directive on component node', () => {
/** <my-comp dir></my-comp> */
const MyApp = createComponent('my-app', function(ctx: any, cm: boolean) {
if (cm) {
const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'my-comp', ['dir', '']);
elementEnd();
}
@ -408,13 +418,15 @@ describe('change detection', () => {
* {{ name }}
* <div dir></div>
*/
const MyApp = createComponent('my-app', function(ctx: any, cm: boolean) {
if (cm) {
const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
text(0);
elementStart(1, 'div', ['dir', '']);
elementEnd();
}
textBinding(1, bind(ctx.value));
if (rf & RenderFlags.Update) {
textBinding(1, bind(ctx.value));
}
}, [Dir]);
const app = renderComponent(MyApp);
@ -444,23 +456,26 @@ describe('change detection', () => {
* <div dir></div>
* % }
*/
template: function(ctx: MyApp, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: MyApp) {
if (rf & RenderFlags.Create) {
text(0);
container(1);
}
textBinding(0, bind(ctx.name));
containerRefreshStart(1);
{
if (ctx.showing) {
if (embeddedViewStart(0)) {
elementStart(0, 'div', ['dir', '']);
elementEnd();
if (rf & RenderFlags.Update) {
textBinding(0, bind(ctx.name));
containerRefreshStart(1);
{
if (ctx.showing) {
let rf0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '']);
elementEnd();
}
}
embeddedViewEnd();
}
embeddedViewEnd();
containerRefreshEnd();
}
containerRefreshEnd();
},
directives: [Dir]
});
@ -490,11 +505,13 @@ describe('change detection', () => {
selectors: [['detect-changes-comp']],
factory: () => new DetectChangesComp(injectChangeDetectorRef()),
/** {{ value }} */
template: (ctx: DetectChangesComp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: DetectChangesComp) => {
if (rf & RenderFlags.Create) {
text(0);
}
textBinding(0, bind(ctx.value));
if (rf & RenderFlags.Update) {
textBinding(0, bind(ctx.value));
}
}
});
}
@ -519,11 +536,13 @@ describe('change detection', () => {
selectors: [['detect-changes-comp']],
factory: () => new DetectChangesComp(injectChangeDetectorRef()),
/** {{ doCheckCount }} */
template: (ctx: DetectChangesComp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: DetectChangesComp) => {
if (rf & RenderFlags.Create) {
text(0);
}
textBinding(0, bind(ctx.doCheckCount));
if (rf & RenderFlags.Update) {
textBinding(0, bind(ctx.doCheckCount));
}
}
});
}
@ -545,8 +564,8 @@ describe('change detection', () => {
selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()),
/** <detached-comp></detached-comp> */
template: (ctx: MyApp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: MyApp) => {
if (rf & RenderFlags.Create) {
elementStart(0, 'detached-comp');
elementEnd();
}
@ -568,11 +587,13 @@ describe('change detection', () => {
selectors: [['detached-comp']],
factory: () => comp = new DetachedComp(injectChangeDetectorRef()),
/** {{ value }} */
template: (ctx: DetachedComp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: DetachedComp) => {
if (rf & RenderFlags.Create) {
text(0);
}
textBinding(0, bind(ctx.value));
if (rf & RenderFlags.Update) {
textBinding(0, bind(ctx.value));
}
}
});
}
@ -664,11 +685,13 @@ describe('change detection', () => {
selectors: [['on-push-comp']],
factory: () => onPushComp = new OnPushComp(injectChangeDetectorRef()),
/** {{ value }} */
template: (ctx: OnPushComp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: any) => {
if (rf & RenderFlags.Create) {
text(0);
}
textBinding(0, bind(ctx.value));
if (rf & RenderFlags.Update) {
textBinding(0, bind(ctx.value));
}
},
changeDetection: ChangeDetectionStrategy.OnPush,
inputs: {value: 'value'}
@ -676,12 +699,14 @@ describe('change detection', () => {
}
/** <on-push-comp [value]="value"></on-push-comp> */
const OnPushApp = createComponent('on-push-app', function(ctx: any, cm: boolean) {
if (cm) {
const OnPushApp = createComponent('on-push-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'on-push-comp');
elementEnd();
}
elementProperty(0, 'value', bind(ctx.value));
if (rf & RenderFlags.Update) {
elementProperty(0, 'value', bind(ctx.value));
}
}, [OnPushComp]);
const app = renderComponent(OnPushApp);
@ -720,11 +745,13 @@ describe('change detection', () => {
selectors: [['on-push-comp']],
factory: () => comp = new OnPushComp(injectChangeDetectorRef()),
/** {{ value }} */
template: (ctx: OnPushComp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: OnPushComp) => {
if (rf & RenderFlags.Create) {
text(0);
}
textBinding(0, bind(ctx.value));
if (rf & RenderFlags.Update) {
textBinding(0, bind(ctx.value));
}
},
changeDetection: ChangeDetectionStrategy.OnPush
});
@ -741,13 +768,15 @@ describe('change detection', () => {
* {{ value }} -
* <on-push-comp></on-push-comp>
*/
template: (ctx: OnPushParent, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: OnPushParent) => {
if (rf & RenderFlags.Create) {
text(0);
elementStart(1, 'on-push-comp');
elementEnd();
}
textBinding(0, interpolation1('', ctx.value, ' - '));
if (rf & RenderFlags.Update) {
textBinding(0, interpolation1('', ctx.value, ' - '));
}
},
directives: () => [OnPushComp],
changeDetection: ChangeDetectionStrategy.OnPush
@ -810,23 +839,26 @@ describe('change detection', () => {
* <on-push-comp></on-push-comp>
* % }
*/
template: (ctx: EmbeddedViewParent, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: any) => {
if (rf & RenderFlags.Create) {
text(0);
container(1);
}
textBinding(0, interpolation1('', ctx.value, ' - '));
containerRefreshStart(1);
{
if (ctx.showing) {
if (embeddedViewStart(0)) {
elementStart(0, 'on-push-comp');
elementEnd();
if (rf & RenderFlags.Update) {
textBinding(0, interpolation1('', ctx.value, ' - '));
containerRefreshStart(1);
{
if (ctx.showing) {
let rf0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
elementStart(0, 'on-push-comp');
elementEnd();
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
},
directives: () => [OnPushComp],
changeDetection: ChangeDetectionStrategy.OnPush
@ -877,11 +909,13 @@ describe('change detection', () => {
type: NoChangesComp,
selectors: [['no-changes-comp']],
factory: () => comp = new NoChangesComp(injectChangeDetectorRef()),
template: (ctx: NoChangesComp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: NoChangesComp) => {
if (rf & RenderFlags.Create) {
text(0);
}
textBinding(0, bind(ctx.value));
if (rf & RenderFlags.Update) {
textBinding(0, bind(ctx.value));
}
}
});
}
@ -899,13 +933,15 @@ describe('change detection', () => {
* {{ value }} -
* <no-changes-comp></no-changes-comp>
*/
template: (ctx: AppComp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: AppComp) => {
if (rf & RenderFlags.Create) {
text(0);
elementStart(1, 'no-changes-comp');
elementEnd();
}
textBinding(0, interpolation1('', ctx.value, ' - '));
if (rf & RenderFlags.Update) {
textBinding(0, interpolation1('', ctx.value, ' - '));
}
},
directives: () => [NoChangesComp]
});
@ -960,21 +996,26 @@ describe('change detection', () => {
* {{ value }}
* %}
*/
template: (ctx: EmbeddedViewApp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: EmbeddedViewApp) => {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
if (ctx.showing) {
if (embeddedViewStart(0)) {
text(0);
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.showing) {
let rf0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
text(0);
}
if (rf0 & RenderFlags.Update) {
textBinding(0, bind(ctx.value));
}
embeddedViewEnd();
}
textBinding(0, bind(ctx.value));
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
});
}

View File

@ -10,7 +10,7 @@ import {NgForOfContext} from '@angular/common';
import {defineComponent} from '../../src/render3/index';
import {bind, container, elementEnd, elementProperty, elementStart, interpolation3, text, textBinding, tick} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {NgForOf} from './common_with_def';
import {ComponentFixture} from './render_util';
@ -28,21 +28,25 @@ describe('@angular/common integration', () => {
// <ul>
// <li *ngFor="let item of items">{{item}}</li>
// </ul>
template: (myApp: MyApp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, myApp: MyApp) => {
if (rf & RenderFlags.Create) {
elementStart(0, 'ul');
{ container(1, liTemplate, undefined, ['ngForOf', '']); }
elementEnd();
}
elementProperty(1, 'ngForOf', bind(myApp.items));
if (rf & RenderFlags.Update) {
elementProperty(1, 'ngForOf', bind(myApp.items));
}
function liTemplate(row: NgForOfContext<string>, cm: boolean) {
if (cm) {
function liTemplate(rf1: RenderFlags, row: NgForOfContext<string>) {
if (rf1 & RenderFlags.Create) {
elementStart(0, 'li');
{ text(1); }
elementEnd();
}
textBinding(1, bind(row.$implicit));
if (rf1 & RenderFlags.Update) {
textBinding(1, bind(row.$implicit));
}
}
},
directives: () => [NgForOf]
@ -84,22 +88,26 @@ describe('@angular/common integration', () => {
// <ul>
// <li *ngFor="let item of items">{{index}} of {{count}}: {{item}}</li>
// </ul>
template: (myApp: MyApp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, myApp: MyApp) => {
if (rf & RenderFlags.Create) {
elementStart(0, 'ul');
{ container(1, liTemplate, undefined, ['ngForOf', '']); }
elementEnd();
}
elementProperty(1, 'ngForOf', bind(myApp.items));
if (rf & RenderFlags.Update) {
elementProperty(1, 'ngForOf', bind(myApp.items));
}
function liTemplate(row: NgForOfContext<string>, cm: boolean) {
if (cm) {
function liTemplate(rf1: RenderFlags, row: NgForOfContext<string>) {
if (rf1 & RenderFlags.Create) {
elementStart(0, 'li');
{ text(1); }
elementEnd();
}
textBinding(
1, interpolation3('', row.index, ' of ', row.count, ': ', row.$implicit, ''));
if (rf1 & RenderFlags.Update) {
textBinding(
1, interpolation3('', row.index, ' of ', row.count, ': ', row.$implicit, ''));
}
}
},
directives: () => [NgForOf]

View File

@ -12,11 +12,10 @@ import {renderComponent, toHtml} from '../render_util';
/// See: `normative.md`
describe('components & directives', () => {
type $boolean$ = boolean;
type $RenderFlags$ = $r3$.ɵRenderFlags;
type $any$ = any;
type $number$ = number;
it('should instantiate directives', () => {
type $ChildComponent$ = ChildComponent;
type $MyComponent$ = MyComponent;
@ -29,9 +28,9 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({
type: ChildComponent,
selectors: [['child']],
factory: () => new ChildComponent(),
template: function(ctx: $ChildComponent$, cm: $boolean$) {
if (cm) {
factory: function ChildComponent_Factory() { return new ChildComponent(); },
template: function ChildComponent_Template(rf: $RenderFlags$, ctx: $ChildComponent$) {
if (rf & 1) {
$r3$.ɵT(0, 'child-view');
}
}
@ -65,8 +64,8 @@ describe('components & directives', () => {
type: MyComponent,
selectors: [['my-component']],
factory: () => new MyComponent(),
template: function(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
template: function(rf: $RenderFlags$, ctx: $MyComponent$) {
if (rf & 1) {
$r3$.ɵE(0, 'child', $e0_attrs$);
$r3$.ɵe();
$r3$.ɵT(1, '!');
@ -117,8 +116,8 @@ describe('components & directives', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'div', $e0_attrs$);
$r3$.ɵe();
}
@ -167,8 +166,8 @@ describe('components & directives', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'button', $e0_attrs$);
$r3$.ɵT(1, 'Click');
$r3$.ɵe();
@ -213,8 +212,8 @@ describe('components & directives', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'div', $e0_attrs$);
$r3$.ɵe();
}
@ -261,8 +260,8 @@ describe('components & directives', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'div', $e0_attrs$);
$r3$.ɵe();
}
@ -296,8 +295,8 @@ describe('components & directives', () => {
type: MyComp,
selectors: [['my-comp']],
factory: function MyComp_Factory() { return new MyComp(); },
template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) {
if (cm) {
template: function MyComp_Template(rf: $RenderFlags$, ctx: $MyComp$) {
if (rf & 1) {
$r3$.ɵT(0);
}
$r3$.ɵt(0, $r3$.ɵb(ctx.name));
@ -321,12 +320,14 @@ describe('components & directives', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'my-comp');
$r3$.ɵe();
}
$r3$.ɵp(0, 'name', $r3$.ɵb(ctx.name));
if (rf & 2) {
$r3$.ɵp(0, 'name', $r3$.ɵb(ctx.name));
}
}
});
}
@ -370,23 +371,27 @@ describe('components & directives', () => {
type: MyComponent,
selectors: [['my-component']],
factory: () => new MyComponent(),
template: function(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
template: function(rf: $RenderFlags$, ctx: $MyComponent$) {
if (rf & 1) {
$r3$.ɵE(0, 'ul', null, $e0_locals$);
$r3$.ɵC(2, C1, '', ['if', '']);
$r3$.ɵe();
}
let $foo$ = $r3$.ɵld<any>(1);
$r3$.ɵcR(2);
$r3$.ɵcr();
if (rf & 2) {
$r3$.ɵcR(2);
$r3$.ɵcr();
}
function C1(ctx1: $any$, cm: $boolean$) {
if (cm) {
function C1(rf1: $RenderFlags$, ctx1: $any$) {
if (rf1 & 1) {
$r3$.ɵE(0, 'li');
$r3$.ɵT(1);
$r3$.ɵe();
}
$r3$.ɵt(1, $r3$.ɵi2('', ctx.salutation, ' ', $foo$, ''));
if (rf1 & 2) {
$r3$.ɵt(1, $r3$.ɵi2('', ctx.salutation, ' ', $foo$, ''));
}
}
}
});
@ -413,11 +418,13 @@ describe('components & directives', () => {
type: MyArrayComp,
selectors: [['my-array-comp']],
factory: function MyArrayComp_Factory() { return new MyArrayComp(); },
template: function MyArrayComp_Template(ctx: $MyArrayComp$, cm: $boolean$) {
if (cm) {
template: function MyArrayComp_Template(rf: $RenderFlags$, ctx: $MyArrayComp$) {
if (rf & 1) {
$r3$.ɵT(0);
}
$r3$.ɵt(0, $r3$.ɵi2('', ctx.names[0], ' ', ctx.names[1], ''));
if (rf & 2) {
$r3$.ɵt(0, $r3$.ɵi2('', ctx.names[0], ' ', ctx.names[1], ''));
}
},
inputs: {names: 'names'}
});
@ -442,12 +449,14 @@ describe('components & directives', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'my-array-comp');
$r3$.ɵe();
}
$r3$.ɵp(0, 'names', cm ? $e0_arr$ : $r3$.ɵNC);
if (rf & 2) {
$r3$.ɵp(0, 'names', rf & 1 ? $e0_arr$ : $r3$.ɵNC);
}
}
});
// /NORMATIVE
@ -484,12 +493,14 @@ describe('components & directives', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'my-array-comp');
$r3$.ɵe();
}
$r3$.ɵp(0, 'names', $r3$.ɵb(ctx.someFn($r3$.ɵf0($e0_ff$))));
if (rf & 2) {
$r3$.ɵp(0, 'names', $r3$.ɵb(ctx.someFn($r3$.ɵf0($e0_ff$))));
}
}
});
// /NORMATIVE
@ -514,11 +525,13 @@ describe('components & directives', () => {
type: MyComp,
selectors: [['my-comp']],
factory: function MyComp_Factory() { return new MyComp(); },
template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) {
if (cm) {
template: function MyComp_Template(rf: $RenderFlags$, ctx: $MyComp$) {
if (rf & 1) {
$r3$.ɵT(0);
}
$r3$.ɵt(0, $r3$.ɵb(ctx.num));
if (rf & 2) {
$r3$.ɵt(0, $r3$.ɵb(ctx.num));
}
},
inputs: {num: 'num'}
});
@ -540,12 +553,14 @@ describe('components & directives', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'my-comp');
$r3$.ɵe();
}
$r3$.ɵp(0, 'num', $r3$.ɵb($r3$.ɵf0($e0_ff$).length + 1));
if (rf & 2) {
$r3$.ɵp(0, 'num', $r3$.ɵb($r3$.ɵf0($e0_ff$).length + 1));
}
}
});
// /NORMATIVE
@ -580,12 +595,14 @@ describe('components & directives', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'my-array-comp');
$r3$.ɵe();
}
$r3$.ɵp(0, 'names', $r3$.ɵb($r3$.ɵf1($e0_ff$, ctx.customName)));
if (rf & 2) {
$r3$.ɵp(0, 'names', $r3$.ɵb($r3$.ɵf1($e0_ff$, ctx.customName)));
}
}
});
// /NORMATIVE
@ -624,8 +641,8 @@ describe('components & directives', () => {
type: MyComp,
selectors: [['my-comp']],
factory: function MyComp_Factory() { return new MyComp(); },
template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) {
if (cm) {
template: function MyComp_Template(rf: $RenderFlags$, ctx: $MyComp$) {
if (rf & 1) {
$r3$.ɵT(0);
$r3$.ɵT(1);
$r3$.ɵT(2);
@ -639,18 +656,20 @@ describe('components & directives', () => {
$r3$.ɵT(10);
$r3$.ɵT(11);
}
$r3$.ɵt(0, $r3$.ɵb(ctx.names[0]));
$r3$.ɵt(1, $r3$.ɵb(ctx.names[1]));
$r3$.ɵt(2, $r3$.ɵb(ctx.names[2]));
$r3$.ɵt(3, $r3$.ɵb(ctx.names[3]));
$r3$.ɵt(4, $r3$.ɵb(ctx.names[4]));
$r3$.ɵt(5, $r3$.ɵb(ctx.names[5]));
$r3$.ɵt(6, $r3$.ɵb(ctx.names[6]));
$r3$.ɵt(7, $r3$.ɵb(ctx.names[7]));
$r3$.ɵt(8, $r3$.ɵb(ctx.names[8]));
$r3$.ɵt(9, $r3$.ɵb(ctx.names[9]));
$r3$.ɵt(10, $r3$.ɵb(ctx.names[10]));
$r3$.ɵt(11, $r3$.ɵb(ctx.names[11]));
if (rf & 2) {
$r3$.ɵt(0, $r3$.ɵb(ctx.names[0]));
$r3$.ɵt(1, $r3$.ɵb(ctx.names[1]));
$r3$.ɵt(2, $r3$.ɵb(ctx.names[2]));
$r3$.ɵt(3, $r3$.ɵb(ctx.names[3]));
$r3$.ɵt(4, $r3$.ɵb(ctx.names[4]));
$r3$.ɵt(5, $r3$.ɵb(ctx.names[5]));
$r3$.ɵt(6, $r3$.ɵb(ctx.names[6]));
$r3$.ɵt(7, $r3$.ɵb(ctx.names[7]));
$r3$.ɵt(8, $r3$.ɵb(ctx.names[8]));
$r3$.ɵt(9, $r3$.ɵb(ctx.names[9]));
$r3$.ɵt(10, $r3$.ɵb(ctx.names[10]));
$r3$.ɵt(11, $r3$.ɵb(ctx.names[11]));
}
},
inputs: {names: 'names'}
});
@ -685,14 +704,17 @@ describe('components & directives', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(c: MyApp, cm: boolean) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, c: $any$) {
if (rf & 1) {
$r3$.ɵE(0, 'my-comp');
$r3$.ɵe();
}
$r3$.ɵp(
0, 'names',
$r3$.ɵb($r3$.ɵfV($e0_ff$, [c.n0, c.n1, c.n2, c.n3, c.n4, c.n5, c.n6, c.n7, c.n8])));
if (rf & 2) {
$r3$.ɵp(
0, 'names',
$r3$.ɵb(
$r3$.ɵfV($e0_ff$, [c.n0, c.n1, c.n2, c.n3, c.n4, c.n5, c.n6, c.n7, c.n8])));
}
}
});
// /NORMATIVE
@ -723,8 +745,8 @@ describe('components & directives', () => {
type: ObjectComp,
selectors: [['object-comp']],
factory: function ObjectComp_Factory() { return new ObjectComp(); },
template: function ObjectComp_Template(ctx: $ObjectComp$, cm: $boolean$) {
if (cm) {
template: function ObjectComp_Template(rf: $RenderFlags$, ctx: $ObjectComp$) {
if (rf & 1) {
$r3$.ɵE(0, 'p');
$r3$.ɵT(1);
$r3$.ɵe();
@ -732,8 +754,10 @@ describe('components & directives', () => {
$r3$.ɵT(3);
$r3$.ɵe();
}
$r3$.ɵt(1, $r3$.ɵb(ctx.config['duration']));
$r3$.ɵt(3, $r3$.ɵb(ctx.config.animation));
if (rf & 2) {
$r3$.ɵt(1, $r3$.ɵb(ctx.config['duration']));
$r3$.ɵt(3, $r3$.ɵb(ctx.config.animation));
}
},
inputs: {config: 'config'}
});
@ -757,12 +781,14 @@ describe('components & directives', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'object-comp');
$r3$.ɵe();
}
$r3$.ɵp(0, 'config', $r3$.ɵb($r3$.ɵf1($e0_ff$, ctx.name)));
if (rf & 2) {
$r3$.ɵp(0, 'config', $r3$.ɵb($r3$.ɵf1($e0_ff$, ctx.name)));
}
}
});
// /NORMATIVE
@ -794,8 +820,8 @@ describe('components & directives', () => {
type: NestedComp,
selectors: [['nested-comp']],
factory: function NestedComp_Factory() { return new NestedComp(); },
template: function NestedComp_Template(ctx: $NestedComp$, cm: $boolean$) {
if (cm) {
template: function NestedComp_Template(rf: $RenderFlags$, ctx: $NestedComp$) {
if (rf & 1) {
$r3$.ɵE(0, 'p');
$r3$.ɵT(1);
$r3$.ɵe();
@ -806,9 +832,11 @@ describe('components & directives', () => {
$r3$.ɵT(5);
$r3$.ɵe();
}
$r3$.ɵt(1, $r3$.ɵb(ctx.config.animation));
$r3$.ɵt(3, $r3$.ɵb(ctx.config.actions[0].opacity));
$r3$.ɵt(5, $r3$.ɵb(ctx.config.actions[1].duration));
if (rf & 2) {
$r3$.ɵt(1, $r3$.ɵb(ctx.config.animation));
$r3$.ɵt(3, $r3$.ɵb(ctx.config.actions[0].opacity));
$r3$.ɵt(5, $r3$.ɵb(ctx.config.actions[1].duration));
}
},
inputs: {config: 'config'}
});
@ -837,15 +865,17 @@ describe('components & directives', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'nested-comp');
$r3$.ɵe();
}
$r3$.ɵp(
0, 'config', $r3$.ɵf2(
$e0_ff_2$, ctx.name,
$r3$.ɵb($r3$.ɵf1($e0_ff_1$, $r3$.ɵf1($e0_ff$, ctx.duration)))));
if (rf & 2) {
$r3$.ɵp(
0, 'config', $r3$.ɵf2(
$e0_ff_2$, ctx.name,
$r3$.ɵb($r3$.ɵf1($e0_ff_1$, $r3$.ɵf1($e0_ff$, ctx.duration)))));
}
}
});
// /NORMATIVE

View File

@ -8,11 +8,10 @@
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 * as $r3$ from '../../../src/core_render3_private_export';
import {renderComponent, toHtml} from '../render_util';
/// See: `normative.md`
describe('content projection', () => {
type $boolean$ = boolean;
type $RenderFlags$ = $r3$.ɵRenderFlags;
it('should support content projection', () => {
type $SimpleComponent$ = SimpleComponent;
@ -26,8 +25,8 @@ describe('content projection', () => {
type: SimpleComponent,
selectors: [['simple']],
factory: () => new SimpleComponent(),
template: function(ctx: $SimpleComponent$, cm: $boolean$) {
if (cm) {
template: function(rf: $RenderFlags$, ctx: $SimpleComponent$) {
if (rf & 1) {
$r3$.ɵpD(0);
$r3$.ɵE(1, 'div');
$r3$.ɵP(2, 0);
@ -56,8 +55,8 @@ describe('content projection', () => {
type: ComplexComponent,
selectors: [['complex']],
factory: () => new ComplexComponent(),
template: function(ctx: $ComplexComponent$, cm: $boolean$) {
if (cm) {
template: function(rf: $RenderFlags$, ctx: $ComplexComponent$) {
if (rf & 1) {
$r3$.ɵpD(0, $pD_0P$, $pD_0R$);
$r3$.ɵE(1, 'div', ['id', 'first']);
$r3$.ɵP(2, 0, 1);
@ -81,8 +80,8 @@ describe('content projection', () => {
type: MyApp,
selectors: [['my-app']],
factory: () => new MyApp(),
template: function(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'simple');
$r3$.ɵT(1, 'content');
$r3$.ɵe();

View File

@ -13,10 +13,9 @@ import {ComponentFixture, renderComponent, toHtml} from '../render_util';
/// See: `normative.md`
describe('elements', () => {
// Saving type as $boolean$, etc to simplify testing for compiler, as types aren't saved
type $boolean$ = boolean;
// Saving type as $any$, etc to simplify testing for compiler, as types aren't saved
type $any$ = any;
type $number$ = number;
type $RenderFlags$ = $r3$.ɵRenderFlags;
it('should translate DOM structure', () => {
type $MyComponent$ = MyComponent;
@ -34,8 +33,8 @@ describe('elements', () => {
type: MyComponent,
selectors: [['my-component']],
factory: () => new MyComponent(),
template: function(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
template: function(rf: $RenderFlags$, ctx: $MyComponent$) {
if (rf & 1) {
$r3$.ɵE(0, 'div', $e0_attrs$);
$r3$.ɵT(1, 'Hello ');
$r3$.ɵE(2, 'b');
@ -85,15 +84,19 @@ describe('elements', () => {
type: LocalRefComp,
selectors: [['local-ref-comp']],
factory: function LocalRefComp_Factory() { return new LocalRefComp(); },
template: function LocalRefComp_Template(ctx: $LocalRefComp$, cm: $boolean$) {
if (cm) {
template: function LocalRefComp_Template(rf: $RenderFlags$, ctx: $LocalRefComp$) {
let $tmp$: any;
let $tmp_2$: any;
if (rf & 1) {
$r3$.ɵE(0, 'div', $e0_attrs$, $e0_locals$);
$r3$.ɵe();
$r3$.ɵT(3);
}
const $tmp$ = $r3$.ɵld(1) as any;
const $tmp_2$ = $r3$.ɵld(2) as any;
$r3$.ɵt(3, $r3$.ɵi2(' ', $tmp$.value, ' - ', $tmp_2$.tagName, ''));
if (rf & 2) {
$tmp$ = $r3$.ɵld(1);
$tmp_2$ = $r3$.ɵld(2);
$r3$.ɵt(3, $r3$.ɵi2(' ', $tmp$.value, ' - ', $tmp_2$.tagName, ''));
}
}
});
// /NORMATIVE
@ -125,8 +128,8 @@ describe('elements', () => {
type: ListenerComp,
selectors: [['listener-comp']],
factory: function ListenerComp_Factory() { return new ListenerComp(); },
template: function ListenerComp_Template(ctx: $ListenerComp$, cm: $boolean$) {
if (cm) {
template: function ListenerComp_Template(rf: $RenderFlags$, ctx: $ListenerComp$) {
if (rf & 1) {
$r3$.ɵE(0, 'button');
$r3$.ɵL('click', function ListenerComp_click_Handler() { return ctx.onClick(); });
$r3$.ɵL('keypress', function ListenerComp_keypress_Handler($event: $any$) {
@ -157,12 +160,14 @@ describe('elements', () => {
type: MyComponent,
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵe();
}
$r3$.ɵp(0, 'id', $r3$.ɵb(ctx.someProperty));
if (rf & 2) {
$r3$.ɵp(0, 'id', $r3$.ɵb(ctx.someProperty));
}
}
});
// /NORMATIVE
@ -187,12 +192,14 @@ describe('elements', () => {
type: MyComponent,
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵe();
}
$r3$.ɵa(0, 'title', $r3$.ɵb(ctx.someAttribute));
if (rf & 2) {
$r3$.ɵa(0, 'title', $r3$.ɵb(ctx.someAttribute));
}
}
});
// /NORMATIVE
@ -217,12 +224,14 @@ describe('elements', () => {
type: MyComponent,
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵe();
}
$r3$.ɵkn(0, 'foo', $r3$.ɵb(ctx.someFlag));
if (rf & 2) {
$r3$.ɵkn(0, 'foo', $r3$.ɵb(ctx.someFlag));
}
}
});
// /NORMATIVE
@ -251,13 +260,15 @@ describe('elements', () => {
type: MyComponent,
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵe();
}
$r3$.ɵsn(0, 'color', $r3$.ɵb(ctx.someColor));
$r3$.ɵsn(0, 'width', $r3$.ɵb(ctx.someWidth), 'px');
if (rf & 2) {
$r3$.ɵsn(0, 'color', $r3$.ɵb(ctx.someColor));
$r3$.ɵsn(0, 'width', $r3$.ɵb(ctx.someWidth), 'px');
}
}
});
// /NORMATIVE
@ -299,13 +310,15 @@ describe('elements', () => {
type: MyComponent,
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
if (rf & 1) {
$r3$.ɵE(0, 'div', $e0_attrs$);
$r3$.ɵe();
}
$r3$.ɵp(0, 'id', $r3$.ɵb(ctx.someString + 1));
$r3$.ɵkn(0, 'foo', $r3$.ɵb(ctx.someString == 'initial'));
if (rf & 2) {
$r3$.ɵp(0, 'id', $r3$.ɵb(ctx.someString + 1));
$r3$.ɵkn(0, 'foo', $r3$.ɵb(ctx.someString == 'initial'));
}
}
});
// /NORMATIVE
@ -333,13 +346,15 @@ describe('elements', () => {
type: StyleComponent,
selectors: [['style-comp']],
factory: function StyleComponent_Factory() { return new StyleComponent(); },
template: function StyleComponent_Template(ctx: $StyleComponent$, cm: $boolean$) {
if (cm) {
template: function StyleComponent_Template(rf: $RenderFlags$, ctx: $StyleComponent$) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵe();
}
$r3$.ɵk(0, $r3$.ɵb(ctx.classExp));
$r3$.ɵs(0, $r3$.ɵb(ctx.styleExp));
if (rf & 2) {
$r3$.ɵk(0, $r3$.ɵb(ctx.classExp));
$r3$.ɵs(0, $r3$.ɵb(ctx.styleExp));
}
}
});
// /NORMATIVE

View File

@ -14,7 +14,7 @@ import {renderComponent, toHtml} from '../render_util';
/// See: `normative.md`
describe('injection', () => {
type $boolean$ = boolean;
type $RenderFlags$ = $r3$.ɵRenderFlags;
describe('directives', () => {
// Directives (and Components) should use `directiveInject`
@ -34,11 +34,13 @@ describe('injection', () => {
factory: function MyComp_Factory() {
return new MyComp($r3$.ɵinjectChangeDetectorRef());
},
template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) {
if (cm) {
template: function MyComp_Template(rf: $RenderFlags$, ctx: $MyComp$) {
if (rf & 1) {
$r3$.ɵT(0);
}
$r3$.ɵt(0, $r3$.ɵb(ctx.value));
if (rf & 2) {
$r3$.ɵt(0, $r3$.ɵb(ctx.value));
}
}
});
// /NORMATIVE
@ -50,8 +52,8 @@ describe('injection', () => {
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
/** <my-comp></my-comp> */
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'my-comp');
$r3$.ɵe();
}
@ -79,11 +81,13 @@ describe('injection', () => {
type: MyComp,
selectors: [['my-comp']],
factory: function MyComp_Factory() { return new MyComp($r3$.ɵinjectAttribute('title')); },
template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) {
if (cm) {
template: function MyComp_Template(rf: $RenderFlags$, ctx: $MyComp$) {
if (rf & 1) {
$r3$.ɵT(0);
}
$r3$.ɵt(0, $r3$.ɵb(ctx.title));
if (rf & 2) {
$r3$.ɵt(0, $r3$.ɵb(ctx.title));
}
}
});
// /NORMATIVE
@ -95,8 +99,8 @@ describe('injection', () => {
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
/** <my-comp></my-comp> */
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'my-comp', e0_attrs);
$r3$.ɵe();
}
@ -148,7 +152,7 @@ describe('injection', () => {
$r3$.ɵdirectiveInject(ServiceA), $r3$.ɵdirectiveInject(ServiceB), inject(INJECTOR));
},
/** */
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {},
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {},
providers: [ServiceA],
viewProviders: [ServiceB],
});

View File

@ -15,7 +15,7 @@ describe('lifecycle hooks', () => {
let events: string[] = [];
let simpleLayout: SimpleLayout;
type $boolean$ = boolean;
type $RenderFlags$ = $r3$.ɵRenderFlags;
type $LifecycleComp$ = LifecycleComp;
type $SimpleLayout$ = SimpleLayout;
@ -43,7 +43,7 @@ describe('lifecycle hooks', () => {
type: LifecycleComp,
selectors: [['lifecycle-comp']],
factory: function LifecycleComp_Factory() { return new LifecycleComp(); },
template: function LifecycleComp_Template(ctx: $LifecycleComp$, cm: $boolean$) {},
template: function LifecycleComp_Template(rf: $RenderFlags$, ctx: $LifecycleComp$) {},
inputs: {nameMin: 'name'},
features: [$r3$.ɵNgOnChangesFeature({nameMin: 'nameMin'})]
});
@ -66,15 +66,17 @@ describe('lifecycle hooks', () => {
type: SimpleLayout,
selectors: [['simple-layout']],
factory: function SimpleLayout_Factory() { return simpleLayout = new SimpleLayout(); },
template: function SimpleLayout_Template(ctx: $SimpleLayout$, cm: $boolean$) {
if (cm) {
template: function SimpleLayout_Template(rf: $RenderFlags$, ctx: $SimpleLayout$) {
if (rf & 1) {
$r3$.ɵE(0, 'lifecycle-comp');
$r3$.ɵe();
$r3$.ɵE(1, 'lifecycle-comp');
$r3$.ɵe();
}
$r3$.ɵp(0, 'name', $r3$.ɵb(ctx.name1));
$r3$.ɵp(1, 'name', $r3$.ɵb(ctx.name2));
if (rf & 2) {
$r3$.ɵp(0, 'name', $r3$.ɵb(ctx.name1));
$r3$.ɵp(1, 'name', $r3$.ɵb(ctx.name2));
}
}
});
// /NORMATIVE

View File

@ -12,7 +12,7 @@ import {renderComponent, toHtml} from '../render_util';
/// See: `normative.md`
describe('local references', () => {
type $boolean$ = boolean;
type $RenderFlags$ = $r3$.ɵRenderFlags;
// TODO(misko): currently disabled until local refs are working
xit('should translate DOM structure', () => {
@ -25,14 +25,17 @@ describe('local references', () => {
type: MyComponent,
selectors: [['my-component']],
factory: () => new MyComponent,
template: function(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
template: function(rf: $RenderFlags$, ctx: $MyComponent$) {
let l1_user: any;
if (rf & 1) {
$r3$.ɵE(0, 'input', null, ['user', '']);
$r3$.ɵe();
$r3$.ɵT(2);
}
const l1_user = $r3$.ɵld<any>(1);
$r3$.ɵt(2, $r3$.ɵi1('Hello ', l1_user.value, '!'));
if (rf & 2) {
l1_user = $r3$.ɵld<any>(1);
$r3$.ɵt(2, $r3$.ɵi1('Hello ', l1_user.value, '!'));
}
}
});
// NORMATIVE

View File

@ -13,7 +13,7 @@ import {containerEl, renderComponent, toHtml} from '../render_util';
/// See: `normative.md`
describe('pipes', () => {
type $any$ = any;
type $boolean$ = boolean;
type $RenderFlags$ = $r3$.ɵRenderFlags;
let myPipeTransformCalls = 0;
let myPurePipeTransformCalls = 0;
@ -81,13 +81,15 @@ describe('pipes', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵT(0);
$r3$.ɵPp(1, 'myPipe');
$r3$.ɵPp(2, 'myPurePipe');
}
$r3$.ɵt(0, $r3$.ɵi1('', $r3$.ɵpb2(1, $r3$.ɵpb2(2, ctx.name, ctx.size), ctx.size), ''));
if (rf & 2) {
$r3$.ɵt(0, $r3$.ɵi1('', $r3$.ɵpb2(1, $r3$.ɵpb2(2, ctx.name, ctx.size), ctx.size), ''));
}
}
});
// /NORMATIVE
@ -154,28 +156,32 @@ describe('pipes', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵT(0);
$r3$.ɵPp(1, 'myPurePipe');
$r3$.ɵT(2);
$r3$.ɵPp(3, 'myPurePipe');
$r3$.ɵC(4, C4, '', ['oneTimeIf', '']);
}
$r3$.ɵt(0, $r3$.ɵi1('', $r3$.ɵpb2(1, ctx.name, ctx.size), ''));
$r3$.ɵt(2, $r3$.ɵi1('', $r3$.ɵpb2(3, ctx.name, ctx.size), ''));
$r3$.ɵp(4, 'oneTimeIf', $r3$.ɵb(ctx.more));
$r3$.ɵcR(4);
$r3$.ɵcr();
if (rf & 2) {
$r3$.ɵt(0, $r3$.ɵi1('', $r3$.ɵpb2(1, ctx.name, ctx.size), ''));
$r3$.ɵt(2, $r3$.ɵi1('', $r3$.ɵpb2(3, ctx.name, ctx.size), ''));
$r3$.ɵp(4, 'oneTimeIf', $r3$.ɵb(ctx.more));
$r3$.ɵcR(4);
$r3$.ɵcr();
}
function C4(ctx1: $any$, cm: $boolean$) {
if (cm) {
function C4(rf: $RenderFlags$, ctx1: $any$) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵT(1);
$r3$.ɵPp(2, 'myPurePipe');
$r3$.ɵe();
}
$r3$.ɵt(1, $r3$.ɵi1('', $r3$.ɵpb2(2, ctx.name, ctx.size), ''));
if (rf & 2) {
$r3$.ɵt(1, $r3$.ɵi1('', $r3$.ɵpb2(2, ctx.name, ctx.size), ''));
}
}
}
});

View File

@ -12,7 +12,7 @@ import {renderComponent, toHtml} from '../render_util';
/// See: `normative.md`
describe('queries', () => {
type $boolean$ = boolean;
type $RenderFlags$ = $r3$.ɵRenderFlags;
type $number$ = number;
let someDir: SomeDirective;
@ -50,18 +50,20 @@ describe('queries', () => {
type: ViewQueryComponent,
selectors: [['view-query-component']],
factory: function ViewQueryComponent_Factory() { return new ViewQueryComponent(); },
template: function ViewQueryComponent_Template(ctx: $ViewQueryComponent$, cm: $boolean$) {
template: function ViewQueryComponent_Template(
rf: $RenderFlags$, ctx: $ViewQueryComponent$) {
let $tmp$: any;
if (cm) {
if (rf & 1) {
$r3$.ɵQ(0, SomeDirective, false);
$r3$.ɵQ(1, SomeDirective, false);
$r3$.ɵE(2, 'div', $e1_attrs$);
$r3$.ɵe();
}
$r3$.ɵqR($tmp$ = $r3$.ɵld<QueryList<any>>(0)) && (ctx.someDir = $tmp$.first);
$r3$.ɵqR($tmp$ = $r3$.ɵld<QueryList<any>>(1)) &&
(ctx.someDirList = $tmp$ as QueryList<any>);
if (rf & 2) {
$r3$.ɵqR($tmp$ = $r3$.ɵld<QueryList<any>>(0)) && (ctx.someDir = $tmp$.first);
$r3$.ɵqR($tmp$ = $r3$.ɵld<QueryList<any>>(1)) &&
(ctx.someDirList = $tmp$ as QueryList<any>);
}
}
});
// /NORMATIVE
@ -110,8 +112,8 @@ describe('queries', () => {
$r3$.ɵqR($tmp$ = $r3$.ɵd<any[]>(dirIndex)[2]) && ($instance$.someDirList = $tmp$);
},
template: function ContentQueryComponent_Template(
ctx: $ContentQueryComponent$, cm: $boolean$) {
if (cm) {
rf: $number$, ctx: $ContentQueryComponent$) {
if (rf & 1) {
$r3$.ɵpD(0);
$r3$.ɵE(1, 'div');
$r3$.ɵP(2, 0);
@ -138,8 +140,8 @@ describe('queries', () => {
type: MyApp,
selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) {
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'content-query-component');
contentQueryComp = $r3$.ɵd<any[]>(0)[0];
$r3$.ɵE(1, 'div', $e2_attrs$);

View File

@ -19,7 +19,8 @@ import {renderComponent, toHtml} from '../render_util';
*/
describe('compiler sanitization', () => {
type $boolean$ = boolean;
type $RenderFlags$ = $r3$.ɵRenderFlags;
it('should translate DOM structure', () => {
type $MyComponent$ = MyComponent;
@ -40,18 +41,20 @@ describe('compiler sanitization', () => {
type: MyComponent,
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵe();
$r3$.ɵE(1, 'img');
$r3$.ɵe();
}
$r3$.ɵp(0, 'innerHTML', $r3$.ɵb(ctx.innerHTML), $r3$.ɵsanitizeHtml);
$r3$.ɵp(0, 'hidden', $r3$.ɵb(ctx.hidden));
$r3$.ɵsn(1, 'background-image', $r3$.ɵb(ctx.style), $r3$.ɵsanitizeStyle);
$r3$.ɵp(1, 'src', $r3$.ɵb(ctx.url), $r3$.ɵsanitizeUrl);
$r3$.ɵa(1, 'srcset', $r3$.ɵb(ctx.url), $r3$.ɵsanitizeUrl);
if (rf & 2) {
$r3$.ɵp(0, 'innerHTML', $r3$.ɵb(ctx.innerHTML), $r3$.ɵsanitizeHtml);
$r3$.ɵp(0, 'hidden', $r3$.ɵb(ctx.hidden));
$r3$.ɵsn(1, 'background-image', $r3$.ɵb(ctx.style), $r3$.ɵsanitizeStyle);
$r3$.ɵp(1, 'src', $r3$.ɵb(ctx.url), $r3$.ɵsanitizeUrl);
$r3$.ɵa(1, 'srcset', $r3$.ɵb(ctx.url), $r3$.ɵsanitizeUrl);
}
}
});
// /NORMATIVE

View File

@ -21,6 +21,8 @@ interface ToDo {
done: boolean;
}
type $RenderFlags$ = r3.RenderFlags;
@Injectable()
class AppState {
todos: ToDo[] = [
@ -62,16 +64,18 @@ class ToDoAppComponent {
factory: function ToDoAppComponent_Factory() {
return new ToDoAppComponent(r3.directiveInject(AppState));
},
template: function ToDoAppComponent_Template(ctx: ToDoAppComponent, cm: boolean) {
if (cm) {
template: function ToDoAppComponent_Template(rf: $RenderFlags$, ctx: ToDoAppComponent) {
if (rf & 1) {
const ToDoAppComponent_NgForOf_Template = function ToDoAppComponent_NgForOf_Template(
ctx1: NgForOfContext<ToDo>, cm: boolean) {
if (cm) {
rf: $RenderFlags$, ctx1: NgForOfContext<ToDo>) {
if (rf & 1) {
r3.E(0, 'todo');
r3.L('archive', ctx.onArchive.bind(ctx));
r3.e();
}
r3.p(0, 'todo', r3.b(ctx1.$implicit));
if (rf & 2) {
r3.p(0, 'todo', r3.b(ctx1.$implicit));
}
};
r3.E(0, 'h1');
r3.T(1, 'ToDo Application');
@ -83,7 +87,9 @@ class ToDoAppComponent {
r3.T(5);
r3.e();
}
r3.t(5, r3.i1('count: ', ctx.appState.todos.length, ''));
if (rf & 2) {
r3.t(5, r3.i1('count: ', ctx.appState.todos.length, ''));
}
}
});
// /NORMATIVE
@ -125,8 +131,8 @@ class ToDoItemComponent {
type: ToDoItemComponent,
selectors: [['todo']],
factory: function ToDoItemComponent_Factory() { return new ToDoItemComponent(); },
template: function ToDoItemComponent_Template(ctx: ToDoItemComponent, cm: boolean) {
if (cm) {
template: function ToDoItemComponent_Template(rf: $RenderFlags$, ctx: ToDoItemComponent) {
if (rf & 1) {
r3.E(0, 'div');
r3.E(1, 'input', e1_attrs);
r3.L('click', ctx.onCheckboxClick.bind(ctx));
@ -140,8 +146,10 @@ class ToDoItemComponent {
r3.e();
r3.e();
}
r3.p(1, 'value', r3.b(ctx.todo.done));
r3.t(3, r3.b(ctx.todo.text));
if (rf & 2) {
r3.p(1, 'value', r3.b(ctx.todo.done));
r3.t(3, r3.b(ctx.todo.text));
}
},
inputs: {todo: 'todo'},
});

View File

@ -12,9 +12,9 @@ import {renderComponent, toHtml} from '../render_util';
/// See: `normative.md`
describe('template variables', () => {
type $boolean$ = boolean;
type $any$ = any;
type $number$ = number;
type $RenderFlags$ = $r3$.ɵRenderFlags;
interface ForOfContext {
$implicit: any;
@ -93,24 +93,29 @@ describe('template variables', () => {
type: MyComponent,
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
if (rf & 1) {
$r3$.ɵE(0, 'ul');
$r3$.ɵC(1, MyComponent_ForOfDirective_Template_1, '', ['forOf', '']);
$r3$.ɵe();
}
$r3$.ɵp(1, 'forOf', $r3$.ɵb(ctx.items));
$r3$.ɵcR(1);
$r3$.ɵcr();
if (rf & 2) {
$r3$.ɵp(1, 'forOf', $r3$.ɵb(ctx.items));
$r3$.ɵcR(1);
$r3$.ɵcr();
}
function MyComponent_ForOfDirective_Template_1(ctx1: $any$, cm: $boolean$) {
if (cm) {
function MyComponent_ForOfDirective_Template_1(rf: $RenderFlags$, ctx1: $any$) {
if (rf & 1) {
$r3$.ɵE(0, 'li');
$r3$.ɵT(1);
$r3$.ɵe();
}
const $l0_item$ = ctx1.$implicit;
$r3$.ɵt(1, $r3$.ɵi1('', $l0_item$.name, ''));
let $l0_item$: any;
if (rf & 2) {
$l0_item$ = ctx1.$implicit;
$r3$.ɵt(1, $r3$.ɵi1('', $l0_item$.name, ''));
}
}
}
});
@ -161,18 +166,20 @@ describe('template variables', () => {
type: MyComponent,
selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
if (cm) {
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
if (rf & 1) {
$r3$.ɵE(0, 'ul');
$r3$.ɵC(1, MyComponent_ForOfDirective_Template_1, '', ['forOf', '']);
$r3$.ɵe();
}
$r3$.ɵp(1, 'forOf', $r3$.ɵb(ctx.items));
$r3$.ɵcR(1);
$r3$.ɵcr();
if (rf & 2) {
$r3$.ɵp(1, 'forOf', $r3$.ɵb(ctx.items));
$r3$.ɵcR(1);
$r3$.ɵcr();
}
function MyComponent_ForOfDirective_Template_1(ctx1: $any$, cm: $boolean$) {
if (cm) {
function MyComponent_ForOfDirective_Template_1(rf1: $RenderFlags$, ctx1: $any$) {
if (rf & 1) {
$r3$.ɵE(0, 'li');
$r3$.ɵE(1, 'div');
$r3$.ɵT(2);
@ -182,21 +189,27 @@ describe('template variables', () => {
$r3$.ɵe();
$r3$.ɵe();
}
const $l0_item$ = ctx1.$implicit;
$r3$.ɵp(4, 'forOf', $r3$.ɵb($l0_item$.infos));
$r3$.ɵt(2, $r3$.ɵi1('', $l0_item$.name, ''));
$r3$.ɵcR(4);
$r3$.ɵcr();
let $l0_item$: any;
if (rf & 2) {
$l0_item$ = ctx1.$implicit;
$r3$.ɵp(4, 'forOf', $r3$.ɵb($l0_item$.infos));
$r3$.ɵt(2, $r3$.ɵi1('', $l0_item$.name, ''));
$r3$.ɵcR(4);
$r3$.ɵcr();
}
function MyComponent_ForOfDirective_ForOfDirective_Template_3(
ctx2: $any$, cm: $boolean$) {
if (cm) {
rf2: $number$, ctx2: $any$) {
if (rf & 1) {
$r3$.ɵE(0, 'li');
$r3$.ɵT(1);
$r3$.ɵe();
}
const $l0_info$ = ctx2.$implicit;
$r3$.ɵt(1, $r3$.ɵi2(' ', $l0_item$.name, ': ', $l0_info$.description, ' '));
let $l0_info$: any;
if (rf & 2) {
$l0_info$ = ctx2.$implicit;
$r3$.ɵt(1, $r3$.ɵi2(' ', $l0_item$.name, ': ', $l0_info$.description, ' '));
}
}
}
}

View File

@ -11,6 +11,7 @@ import {DoCheck, ViewEncapsulation} from '../../src/core';
import {getRenderedText} from '../../src/render3/component';
import {LifecycleHooksFeature, defineComponent, markDirty} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, text, textBinding, tick} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {createRendererType2} from '../../src/view/index';
import {getRendererFactory2} from './imported_renderer2';
@ -25,11 +26,13 @@ describe('component', () => {
static ngComponentDef = defineComponent({
type: CounterComponent,
selectors: [['counter']],
template: function(ctx: CounterComponent, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: CounterComponent) {
if (rf & RenderFlags.Create) {
text(0);
}
textBinding(0, bind(ctx.count));
if (rf & RenderFlags.Update) {
textBinding(0, bind(ctx.count));
}
},
factory: () => new CounterComponent,
inputs: {count: 'count'},
@ -63,24 +66,28 @@ describe('component', () => {
describe('component with a container', () => {
function showItems(ctx: {items: string[]}, cm: boolean) {
if (cm) {
function showItems(rf: RenderFlags, ctx: {items: string[]}) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
for (const item of ctx.items) {
const cm0 = embeddedViewStart(0);
{
if (cm0) {
text(0);
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
for (const item of ctx.items) {
const rf0 = embeddedViewStart(0);
{
if (rf0 & RenderFlags.Create) {
text(0);
}
if (rf0 & RenderFlags.Update) {
textBinding(0, bind(item));
}
}
textBinding(0, bind(item));
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
class WrapperComponent {
@ -88,29 +95,33 @@ describe('component with a container', () => {
static ngComponentDef = defineComponent({
type: WrapperComponent,
selectors: [['wrapper']],
template: function ChildComponentTemplate(ctx: {items: string[]}, cm: boolean) {
if (cm) {
template: function ChildComponentTemplate(rf: RenderFlags, ctx: {items: string[]}) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
const cm0 = embeddedViewStart(0);
{ showItems({items: ctx.items}, cm0); }
embeddedViewEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
const rf0 = embeddedViewStart(0);
{ showItems(rf0, {items: ctx.items}); }
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
},
factory: () => new WrapperComponent,
inputs: {items: 'items'}
});
}
function template(ctx: {items: string[]}, cm: boolean) {
if (cm) {
function template(rf: RenderFlags, ctx: {items: string[]}) {
if (rf & RenderFlags.Create) {
elementStart(0, 'wrapper');
elementEnd();
}
elementProperty(0, 'items', bind(ctx.items));
if (rf & RenderFlags.Update) {
elementProperty(0, 'items', bind(ctx.items));
}
}
const defs = [WrapperComponent];
@ -132,8 +143,8 @@ describe('encapsulation', () => {
static ngComponentDef = defineComponent({
type: WrapperComponent,
selectors: [['wrapper']],
template: function(ctx: WrapperComponent, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: WrapperComponent) {
if (rf & RenderFlags.Create) {
elementStart(0, 'encapsulated');
elementEnd();
}
@ -147,8 +158,8 @@ describe('encapsulation', () => {
static ngComponentDef = defineComponent({
type: EncapsulatedComponent,
selectors: [['encapsulated']],
template: function(ctx: EncapsulatedComponent, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: EncapsulatedComponent) {
if (rf & RenderFlags.Create) {
text(0, 'foo');
elementStart(1, 'leaf');
elementEnd();
@ -165,8 +176,8 @@ describe('encapsulation', () => {
static ngComponentDef = defineComponent({
type: LeafComponent,
selectors: [['leaf']],
template: function(ctx: LeafComponent, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: LeafComponent) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span');
{ text(1, 'bar'); }
elementEnd();
@ -195,8 +206,8 @@ describe('encapsulation', () => {
static ngComponentDef = defineComponent({
type: WrapperComponentWith,
selectors: [['wrapper']],
template: function(ctx: WrapperComponentWith, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: WrapperComponentWith) {
if (rf & RenderFlags.Create) {
elementStart(0, 'leaf');
elementEnd();
}
@ -212,8 +223,8 @@ describe('encapsulation', () => {
static ngComponentDef = defineComponent({
type: LeafComponentwith,
selectors: [['leaf']],
template: function(ctx: LeafComponentwith, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: LeafComponentwith) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span');
{ text(1, 'bar'); }
elementEnd();
@ -252,37 +263,45 @@ describe('recursive components', () => {
type: TreeComponent,
selectors: [['tree-comp']],
factory: () => new TreeComponent(),
template: (ctx: TreeComponent, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: TreeComponent) => {
if (rf & RenderFlags.Create) {
text(0);
container(1);
container(2);
}
textBinding(0, bind(ctx.data.value));
containerRefreshStart(1);
{
if (ctx.data.left != null) {
if (embeddedViewStart(0)) {
elementStart(0, 'tree-comp');
elementEnd();
if (rf & RenderFlags.Update) {
textBinding(0, bind(ctx.data.value));
containerRefreshStart(1);
{
if (ctx.data.left != null) {
let rf0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
elementStart(0, 'tree-comp');
elementEnd();
}
if (rf0 & RenderFlags.Update) {
elementProperty(0, 'data', bind(ctx.data.left));
}
embeddedViewEnd();
}
elementProperty(0, 'data', bind(ctx.data.left));
embeddedViewEnd();
}
}
containerRefreshEnd();
containerRefreshStart(2);
{
if (ctx.data.right != null) {
if (embeddedViewStart(0)) {
elementStart(0, 'tree-comp');
elementEnd();
containerRefreshEnd();
containerRefreshStart(2);
{
if (ctx.data.right != null) {
let rf0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
elementStart(0, 'tree-comp');
elementEnd();
}
if (rf0 & RenderFlags.Update) {
elementProperty(0, 'data', bind(ctx.data.right));
}
embeddedViewEnd();
}
elementProperty(0, 'data', bind(ctx.data.right));
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
},
inputs: {data: 'data'}
});

View File

@ -10,7 +10,7 @@ import {SelectorFlags} from '@angular/core/src/render3/interfaces/projection';
import {detectChanges} from '../../src/render3/index';
import {container, containerRefreshEnd, containerRefreshStart, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, load, loadDirective, projection, projectionDef, text} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {createComponent, renderComponent, toHtml} from './render_util';
describe('content projection', () => {
@ -19,8 +19,8 @@ describe('content projection', () => {
/**
* <div><ng-content></ng-content></div>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
elementStart(1, 'div');
{ projection(2, 0); }
@ -31,8 +31,8 @@ describe('content projection', () => {
/**
* <child>content</child>
*/
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{ text(1, 'content'); }
elementEnd();
@ -44,14 +44,14 @@ describe('content projection', () => {
});
it('should project content when root.', () => {
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
projection(1, 0);
}
});
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{ text(1, 'content'); }
elementEnd();
@ -63,24 +63,24 @@ describe('content projection', () => {
});
it('should re-project content when root.', () => {
const GrandChild = createComponent('grand-child', function(ctx: any, cm: boolean) {
if (cm) {
const GrandChild = createComponent('grand-child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
elementStart(1, 'div');
{ projection(2, 0); }
elementEnd();
}
});
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
elementStart(1, 'grand-child');
{ projection(2, 0); }
elementEnd();
}
}, [GrandChild]);
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
elementStart(1, 'b');
@ -100,8 +100,8 @@ describe('content projection', () => {
it('should project components', () => {
/** <div><ng-content></ng-content></div> */
const Child = createComponent('child', (ctx: any, cm: boolean) => {
if (cm) {
const Child = createComponent('child', (rf: RenderFlags, ctx: any) => {
if (rf & RenderFlags.Create) {
projectionDef(0);
elementStart(1, 'div');
{ projection(2, 0); }
@ -109,8 +109,8 @@ describe('content projection', () => {
}
});
const ProjectedComp = createComponent('projected-comp', (ctx: any, cm: boolean) => {
if (cm) {
const ProjectedComp = createComponent('projected-comp', (rf: RenderFlags, ctx: any) => {
if (rf & RenderFlags.Create) {
text(0, 'content');
}
});
@ -120,8 +120,8 @@ describe('content projection', () => {
* <projected-comp></projected-comp>
* </child>
*/
const Parent = createComponent('parent', (ctx: any, cm: boolean) => {
if (cm) {
const Parent = createComponent('parent', (rf: RenderFlags, ctx: any) => {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
elementStart(1, 'projected-comp');
@ -137,16 +137,16 @@ describe('content projection', () => {
});
it('should project content with container.', () => {
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
elementStart(1, 'div');
{ projection(2, 0); }
elementEnd();
}
});
const Parent = createComponent('parent', function(ctx: {value: any}, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: {value: any}) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
text(1, '(');
@ -155,16 +155,19 @@ describe('content projection', () => {
}
elementEnd();
}
containerRefreshStart(2);
{
if (ctx.value) {
if (embeddedViewStart(0)) {
text(0, 'content');
if (rf & RenderFlags.Update) {
containerRefreshStart(2);
{
if (ctx.value) {
let rf0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
text(0, 'content');
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}, [Child]);
const parent = renderComponent(Parent);
@ -178,28 +181,31 @@ describe('content projection', () => {
});
it('should project content with container into root', () => {
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
projection(1, 0);
}
});
const Parent = createComponent('parent', function(ctx: {value: any}, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: {value: any}) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{ container(1); }
elementEnd();
}
containerRefreshStart(1);
{
if (ctx.value) {
if (embeddedViewStart(0)) {
text(0, 'content');
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
if (ctx.value) {
let rf0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
text(0, 'content');
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}, [Child]);
const parent = renderComponent(Parent);
@ -215,16 +221,16 @@ describe('content projection', () => {
});
it('should project content with container and if-else.', () => {
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
elementStart(1, 'div');
{ projection(2, 0); }
elementEnd();
}
});
const Parent = createComponent('parent', function(ctx: {value: any}, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: {value: any}) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
text(1, '(');
@ -233,21 +239,24 @@ describe('content projection', () => {
}
elementEnd();
}
containerRefreshStart(2);
{
if (ctx.value) {
if (embeddedViewStart(0)) {
text(0, 'content');
if (rf & RenderFlags.Update) {
containerRefreshStart(2);
{
if (ctx.value) {
let rf0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
text(0, 'content');
}
embeddedViewEnd();
} else {
if (embeddedViewStart(1)) {
text(0, 'else');
}
embeddedViewEnd();
}
embeddedViewEnd();
} else {
if (embeddedViewStart(1)) {
text(0, 'else');
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}, [Child]);
const parent = renderComponent(Parent);
@ -272,32 +281,35 @@ describe('content projection', () => {
* % }
* </div>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
elementStart(1, 'div');
{ container(2); }
elementEnd();
}
containerRefreshStart(2);
{
if (!ctx.skipContent) {
if (embeddedViewStart(0)) {
elementStart(0, 'span');
projection(1, 0);
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(2);
{
if (!ctx.skipContent) {
let rf0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
elementStart(0, 'span');
projection(1, 0);
elementEnd();
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
});
/**
* <child>content</child>
*/
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
childCmptInstance = loadDirective(0);
@ -326,30 +338,33 @@ describe('content projection', () => {
* % }
* </div>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
elementStart(1, 'div');
{ container(2); }
elementEnd();
}
containerRefreshStart(2);
{
if (!ctx.skipContent) {
if (embeddedViewStart(0)) {
projection(0, 0);
if (rf & RenderFlags.Update) {
containerRefreshStart(2);
{
if (!ctx.skipContent) {
let rf0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
projection(0, 0);
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
});
/**
* <child>content</child>
*/
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
childCmptInstance = loadDirective(0);
@ -378,32 +393,35 @@ describe('content projection', () => {
* % }
* </div>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
elementStart(1, 'div');
{ container(2); }
elementEnd();
}
containerRefreshStart(2);
{
if (!ctx.skipContent) {
if (embeddedViewStart(0)) {
text(0, 'before-');
projection(1, 0);
text(2, '-after');
if (rf & RenderFlags.Update) {
containerRefreshStart(2);
{
if (!ctx.skipContent) {
let rf0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
text(0, 'before-');
projection(1, 0);
text(2, '-after');
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
});
/**
* <child>content</child>
*/
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
childCmptInstance = loadDirective(0);
@ -426,8 +444,8 @@ describe('content projection', () => {
* <div><ng-content></ng-content></div>
* <span><ng-content></ng-content></span>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
elementStart(1, 'div');
{ projection(2, 0); }
@ -441,8 +459,8 @@ describe('content projection', () => {
/**
* <child>content</child>
*/
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{ text(1, 'content'); }
elementEnd();
@ -472,31 +490,34 @@ describe('content projection', () => {
* % }
* </div>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
projection(1, 0);
elementStart(2, 'div');
{ container(3); }
elementEnd();
}
containerRefreshStart(3);
{
if (ctx.show) {
if (embeddedViewStart(0)) {
projection(0, 0);
if (rf & RenderFlags.Update) {
containerRefreshStart(3);
{
if (ctx.show) {
let rf0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
projection(0, 0);
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
});
/**
* <child>content</child>
*/
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
childCmptInstance = loadDirective(0);
@ -521,8 +542,8 @@ describe('content projection', () => {
* <div id="first"><ng-content select="span[title=toFirst]"></ng-content></div>
* <div id="second"><ng-content select="span[title=toSecond]"></ng-content></div>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(
0, [[['span', 'title', 'toFirst']], [['span', 'title', 'toSecond']]],
['span[title=toFirst]', 'span[title=toSecond]']);
@ -541,8 +562,8 @@ describe('content projection', () => {
* <span title="toSecond">2</span>
* </child>
*/
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
elementStart(1, 'span', ['title', 'toFirst']);
@ -567,8 +588,8 @@ describe('content projection', () => {
* <div id="first"><ng-content select="span.toFirst"></ng-content></div>
* <div id="second"><ng-content select="span.toSecond"></ng-content></div>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(
0,
[
@ -591,8 +612,8 @@ describe('content projection', () => {
* <span class="toSecond">2</span>
* </child>
*/
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
elementStart(1, 'span', ['class', 'toFirst']);
@ -617,8 +638,8 @@ describe('content projection', () => {
* <div id="first"><ng-content select="span.toFirst"></ng-content></div>
* <div id="second"><ng-content select="span.toSecond"></ng-content></div>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(
0,
[
@ -641,8 +662,8 @@ describe('content projection', () => {
* <span class="toSecond noise">2</span>
* </child>
*/
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
elementStart(1, 'span', ['class', 'other toFirst']);
@ -667,8 +688,8 @@ describe('content projection', () => {
* <div id="first"><ng-content select="span"></ng-content></div>
* <div id="second"><ng-content select="span.toSecond"></ng-content></div>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(
0, [[['span']], [['span', SelectorFlags.CLASS, 'toSecond']]],
['span', 'span.toSecond']);
@ -687,8 +708,8 @@ describe('content projection', () => {
* <span class="toSecond">2</span>
* </child>
*/
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
elementStart(1, 'span', ['class', 'toFirst']);
@ -713,8 +734,8 @@ describe('content projection', () => {
* <div id="first"><ng-content select="span.toFirst"></ng-content></div>
* <div id="second"><ng-content></ng-content></div>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0, [[['span', SelectorFlags.CLASS, 'toFirst']]], ['span.toFirst']);
elementStart(1, 'div', ['id', 'first']);
{ projection(2, 0, 1); }
@ -731,8 +752,8 @@ describe('content projection', () => {
* <span class="toSecond noise">2</span>
* </child>
*/
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
elementStart(1, 'span', ['class', 'toFirst']);
@ -758,8 +779,8 @@ describe('content projection', () => {
* <div id="first"><ng-content></ng-content></div>
* <div id="second"><ng-content select="span.toSecond"></ng-content></div>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0, [[['span', SelectorFlags.CLASS, 'toSecond']]], ['span.toSecond']);
elementStart(1, 'div', ['id', 'first']);
{ projection(2, 0); }
@ -777,8 +798,8 @@ describe('content projection', () => {
* remaining
* </child>
*/
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
elementStart(1, 'span');
@ -810,8 +831,8 @@ describe('content projection', () => {
* <hr>
* <ng-content></ng-content>
*/
const GrandChild = createComponent('grand-child', function(ctx: any, cm: boolean) {
if (cm) {
const GrandChild = createComponent('grand-child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0, [[['span']]], ['span']);
projection(1, 0, 1);
elementStart(2, 'hr');
@ -826,8 +847,8 @@ describe('content projection', () => {
* <span>in child template</span>
* </grand-child>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
elementStart(1, 'grand-child');
{
@ -847,8 +868,8 @@ describe('content projection', () => {
* </div>
* </child>
*/
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
elementStart(1, 'span');
@ -872,8 +893,8 @@ describe('content projection', () => {
* <hr>
* <ng-content select="[card-content]"></ng-content>
*/
const Card = createComponent('card', function(ctx: any, cm: boolean) {
if (cm) {
const Card = createComponent('card', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(
0, [[['', 'card-title', '']], [['', 'card-content', '']]],
['[card-title]', '[card-content]']);
@ -890,8 +911,8 @@ describe('content projection', () => {
* <ng-content card-content></ng-content>
* </card>
*/
const CardWithTitle = createComponent('card-with-title', function(ctx: any, cm: boolean) {
if (cm) {
const CardWithTitle = createComponent('card-with-title', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
elementStart(1, 'card');
{
@ -909,8 +930,8 @@ describe('content projection', () => {
* content
* </card-with-title>
*/
const App = createComponent('app', function(ctx: any, cm: boolean) {
if (cm) {
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'card-with-title');
{ text(1, 'content'); }
elementEnd();
@ -931,8 +952,8 @@ describe('content projection', () => {
* <hr>
* <ng-content select="[card-content]"></ng-content>
*/
const Card = createComponent('card', function(ctx: any, cm: boolean) {
if (cm) {
const Card = createComponent('card', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(
0, [[['', 'card-title', '']], [['', 'card-content', '']]],
['[card-title]', '[card-content]']);
@ -949,8 +970,8 @@ describe('content projection', () => {
* <ng-content ngProjectAs="[card-content]"></ng-content>
* </card>
*/
const CardWithTitle = createComponent('card-with-title', function(ctx: any, cm: boolean) {
if (cm) {
const CardWithTitle = createComponent('card-with-title', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0);
elementStart(1, 'card');
{
@ -968,8 +989,8 @@ describe('content projection', () => {
* content
* </card-with-title>
*/
const App = createComponent('app', function(ctx: any, cm: boolean) {
if (cm) {
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'card-with-title');
{ text(1, 'content'); }
elementEnd();
@ -987,8 +1008,8 @@ describe('content projection', () => {
/**
* <ng-content select="div"></ng-content>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0, [[['div']]], ['div']);
projection(1, 0, 1);
}
@ -1000,8 +1021,8 @@ describe('content projection', () => {
* <div>should project</div>
* </child>
*/
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{
elementStart(1, 'div', ['ngProjectAs', 'span']);
@ -1026,8 +1047,8 @@ describe('content projection', () => {
* <ng-content select="div"></ng-content>
* </span>
*/
const Child = createComponent('child', function(ctx: any, cm: boolean) {
if (cm) {
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
projectionDef(0, [[['div']]], ['div']);
elementStart(1, 'span');
{ projection(2, 0, 1); }
@ -1040,24 +1061,27 @@ describe('content projection', () => {
* <div *ngIf="true">content</div>
* </child>
*/
const Parent = createComponent('parent', function(ctx: {value: any}, cm: boolean) {
if (cm) {
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: {value: any}) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{ container(1, undefined, 'div'); }
elementEnd();
}
containerRefreshStart(1);
{
if (true) {
if (embeddedViewStart(0)) {
elementStart(0, 'div');
{ text(1, 'content'); }
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
if (true) {
let rf0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
elementStart(0, 'div');
{ text(1, 'content'); }
elementEnd();
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}, [Child]);
const parent = renderComponent(Parent);
expect(toHtml(parent)).toEqual('<child><span><div>content</div></span></child>');

View File

@ -8,32 +8,36 @@
import {defineComponent} from '../../src/render3/definition';
import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, text, textBinding} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {ComponentFixture, createComponent, renderToHtml} from './render_util';
describe('JS control flow', () => {
it('should work with if block', () => {
const ctx: {message: string | null, condition: boolean} = {message: 'Hello', condition: true};
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
{ container(1); }
elementEnd();
}
containerRefreshStart(1);
{
if (ctx.condition) {
let cm1 = embeddedViewStart(1);
{
if (cm1) {
elementStart(0, 'span');
{ text(1); }
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
if (ctx.condition) {
let rf1 = embeddedViewStart(1);
{
if (rf1 & RenderFlags.Create) {
elementStart(0, 'span');
{ text(1); }
elementEnd();
}
if (rf1 & RenderFlags.Update) {
textBinding(1, bind(ctx.message));
}
}
textBinding(1, bind(ctx.message));
embeddedViewEnd();
}
embeddedViewEnd();
}
}
containerRefreshEnd();
@ -63,40 +67,44 @@ describe('JS control flow', () => {
* % }
* </div>
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
{ container(1); }
elementEnd();
}
containerRefreshStart(1);
{
if (ctx.condition) {
let cm1 = embeddedViewStart(1);
{
if (cm1) {
elementStart(0, 'span');
{ container(1); }
elementEnd();
}
containerRefreshStart(1);
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
if (ctx.condition) {
let rf1 = embeddedViewStart(1);
{
if (ctx.condition2) {
let cm2 = embeddedViewStart(2);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'span');
{ container(1); }
elementEnd();
}
if (rf1 & RenderFlags.Update) {
containerRefreshStart(1);
{
if (cm2) {
text(0, 'Hello');
if (ctx.condition2) {
let rf2 = embeddedViewStart(2);
{
if (rf2 & RenderFlags.Create) {
text(0, 'Hello');
}
}
embeddedViewEnd();
}
}
embeddedViewEnd();
containerRefreshEnd();
}
}
containerRefreshEnd();
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
expect(renderToHtml(Template, ctx)).toEqual('<div><span>Hello</span></div>');
@ -139,33 +147,35 @@ describe('JS control flow', () => {
* 3
* % }
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
if (ctx.condition1) {
const cm1 = embeddedViewStart(1);
if (cm1) {
text(0, '1');
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
if (ctx.condition1) {
const rf1 = embeddedViewStart(1);
if (rf1 & RenderFlags.Create) {
text(0, '1');
}
embeddedViewEnd();
} // can't have ; here due linting rules
if (ctx.condition2) {
const rf2 = embeddedViewStart(2);
if (rf2 & RenderFlags.Create) {
text(0, '2');
}
embeddedViewEnd();
} // can't have ; here due linting rules
if (ctx.condition3) {
const rf3 = embeddedViewStart(3);
if (rf3 & RenderFlags.Create) {
text(0, '3');
}
embeddedViewEnd();
}
embeddedViewEnd();
} // can't have ; here due linting rules
if (ctx.condition2) {
const cm2 = embeddedViewStart(2);
if (cm2) {
text(0, '2');
}
embeddedViewEnd();
} // can't have ; here due linting rules
if (ctx.condition3) {
const cm3 = embeddedViewStart(3);
if (cm3) {
text(0, '3');
}
embeddedViewEnd();
containerRefreshEnd();
}
containerRefreshEnd();
}
expect(renderToHtml(Template, ctx)).toEqual('123');
@ -175,39 +185,43 @@ describe('JS control flow', () => {
});
it('should work with containers with views as parents', () => {
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
{ text(1, 'hello'); }
elementEnd();
container(2);
}
containerRefreshStart(2);
{
if (ctx.condition1) {
let cm0 = embeddedViewStart(0);
{
if (cm0) {
container(0);
}
containerRefreshStart(0);
if (rf & RenderFlags.Update) {
containerRefreshStart(2);
{
if (ctx.condition1) {
let rf0 = embeddedViewStart(0);
{
if (ctx.condition2) {
let cm0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
container(0);
}
if (rf0 & RenderFlags.Update) {
containerRefreshStart(0);
{
if (cm0) {
text(0, 'world');
if (ctx.condition2) {
let rf0 = embeddedViewStart(0);
{
if (rf0 & RenderFlags.Create) {
text(0, 'world');
}
}
embeddedViewEnd();
}
}
embeddedViewEnd();
containerRefreshEnd();
}
}
containerRefreshEnd();
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
expect(renderToHtml(Template, {condition1: true, condition2: true}))
@ -220,28 +234,32 @@ describe('JS control flow', () => {
it('should work with loop block', () => {
const ctx: {data: string[] | null} = {data: ['a', 'b', 'c']};
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'ul');
{ container(1); }
elementEnd();
}
containerRefreshStart(1);
{
for (let i = 0; i < ctx.data.length; i++) {
let cm1 = embeddedViewStart(1);
{
if (cm1) {
elementStart(0, 'li');
{ text(1); }
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
for (let i = 0; i < ctx.data.length; i++) {
let rf1 = embeddedViewStart(1);
{
if (rf1 & RenderFlags.Create) {
elementStart(0, 'li');
{ text(1); }
elementEnd();
}
if (rf1 & RenderFlags.Update) {
textBinding(1, bind(ctx.data[i]));
}
}
textBinding(1, bind(ctx.data[i]));
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
expect(renderToHtml(Template, ctx)).toEqual('<ul><li>a</li><li>b</li><li>c</li></ul>');
@ -266,38 +284,45 @@ describe('JS control flow', () => {
it('should work with nested loop blocks', () => {
const ctx: {data: string[][] | null} = {data: [['a', 'b', 'c'], ['m', 'n']]};
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'ul');
{ container(1); }
elementEnd();
}
containerRefreshStart(1);
{
for (let i = 0; i < ctx.data[0].length; i++) {
let cm1 = embeddedViewStart(1);
{
if (cm1) {
elementStart(0, 'li');
{ container(1); }
elementEnd();
}
containerRefreshStart(1);
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
for (let i = 0; i < ctx.data[0].length; i++) {
let rf1 = embeddedViewStart(1);
{
ctx.data[1].forEach((value: string, ind: number) => {
if (embeddedViewStart(2)) {
text(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'li');
{ container(1); }
elementEnd();
}
if (rf1 & RenderFlags.Update) {
containerRefreshStart(1);
{
ctx.data[1].forEach((value: string, ind: number) => {
let rf2 = embeddedViewStart(2);
if (rf2 & RenderFlags.Create) {
text(0);
}
if (rf2 & RenderFlags.Update) {
textBinding(0, bind(ctx.data[0][i] + value));
}
embeddedViewEnd();
});
}
textBinding(0, bind(ctx.data[0][i] + value));
embeddedViewEnd();
});
containerRefreshEnd();
}
}
containerRefreshEnd();
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
expect(renderToHtml(Template, ctx)).toEqual('<ul><li>aman</li><li>bmbn</li><li>cmcn</li></ul>');
@ -321,8 +346,8 @@ describe('JS control flow', () => {
* After
* <div>
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
{
text(1, 'Before');
@ -331,35 +356,42 @@ describe('JS control flow', () => {
}
elementEnd();
}
containerRefreshStart(2);
{
for (let i = 0; i < ctx.cafes.length; i++) {
let cm1 = embeddedViewStart(1);
{
if (cm1) {
elementStart(0, 'h2');
{ text(1); }
elementEnd();
container(2);
text(3, '-');
}
textBinding(1, bind(ctx.cafes[i].name));
containerRefreshStart(2);
if (rf & RenderFlags.Update) {
containerRefreshStart(2);
{
for (let i = 0; i < ctx.cafes.length; i++) {
let rf1 = embeddedViewStart(1);
{
for (let j = 0; j < ctx.cafes[i].entrees.length; j++) {
if (embeddedViewStart(1)) {
text(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'h2');
{ text(1); }
elementEnd();
container(2);
text(3, '-');
}
if (rf1 & RenderFlags.Update) {
textBinding(1, bind(ctx.cafes[i].name));
containerRefreshStart(2);
{
for (let j = 0; j < ctx.cafes[i].entrees.length; j++) {
let rf2 = embeddedViewStart(2);
if (rf2 & RenderFlags.Create) {
text(0);
}
if (rf2 & RenderFlags.Update) {
textBinding(0, bind(ctx.cafes[i].entrees[j]));
}
embeddedViewEnd();
}
}
textBinding(0, bind(ctx.cafes[i].entrees[j]));
embeddedViewEnd();
containerRefreshEnd();
}
}
containerRefreshEnd();
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
const ctx = {
@ -401,8 +433,8 @@ describe('JS control flow', () => {
* After
* <div>
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
{
text(1, 'Before');
@ -411,52 +443,61 @@ describe('JS control flow', () => {
}
elementEnd();
}
containerRefreshStart(2);
{
for (let i = 0; i < ctx.cafes.length; i++) {
let cm1 = embeddedViewStart(1);
{
if (cm1) {
elementStart(0, 'h2');
{ text(1); }
elementEnd();
container(2);
text(3, '-');
}
textBinding(1, bind(ctx.cafes[i].name));
containerRefreshStart(2);
if (rf & RenderFlags.Update) {
containerRefreshStart(2);
{
for (let i = 0; i < ctx.cafes.length; i++) {
let rf1 = embeddedViewStart(1);
{
for (let j = 0; j < ctx.cafes[i].entrees.length; j++) {
let cm1 = embeddedViewStart(1);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'h2');
{ text(1); }
elementEnd();
container(2);
text(3, '-');
}
if (rf1 & RenderFlags.Update) {
textBinding(1, bind(ctx.cafes[i].name));
containerRefreshStart(2);
{
if (cm1) {
elementStart(0, 'h3');
{ text(1); }
elementEnd();
container(2);
}
textBinding(1, bind(ctx.cafes[i].entrees[j].name));
containerRefreshStart(2);
{
for (let k = 0; k < ctx.cafes[i].entrees[j].foods.length; k++) {
if (embeddedViewStart(1)) {
text(0);
for (let j = 0; j < ctx.cafes[i].entrees.length; j++) {
let rf1 = embeddedViewStart(1);
{
if (rf1 & RenderFlags.Create) {
elementStart(0, 'h3');
{ text(1); }
elementEnd();
container(2);
}
if (rf1 & RenderFlags.Update) {
textBinding(1, bind(ctx.cafes[i].entrees[j].name));
containerRefreshStart(2);
{
for (let k = 0; k < ctx.cafes[i].entrees[j].foods.length; k++) {
let rf2 = embeddedViewStart(1);
if (rf2 & RenderFlags.Create) {
text(0);
}
if (rf2 & RenderFlags.Update) {
textBinding(0, bind(ctx.cafes[i].entrees[j].foods[k]));
}
embeddedViewEnd();
}
}
containerRefreshEnd();
}
textBinding(0, bind(ctx.cafes[i].entrees[j].foods[k]));
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
embeddedViewEnd();
containerRefreshEnd();
}
}
containerRefreshEnd();
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
const ctx = {
@ -491,37 +532,39 @@ describe('JS control flow', () => {
it('should work with if/else blocks', () => {
const ctx: {message: string | null, condition: boolean} = {message: 'Hello', condition: true};
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
{ container(1); }
elementEnd();
}
containerRefreshStart(1);
{
if (ctx.condition) {
let cm1 = embeddedViewStart(1);
{
if (cm1) {
elementStart(0, 'span');
{ text(1, 'Hello'); }
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
if (ctx.condition) {
let rf1 = embeddedViewStart(1);
{
if (rf1 & RenderFlags.Create) {
elementStart(0, 'span');
{ text(1, 'Hello'); }
elementEnd();
}
}
}
embeddedViewEnd();
} else {
let cm2 = embeddedViewStart(2);
{
if (cm2) {
elementStart(0, 'div');
{ text(1, 'Goodbye'); }
elementEnd();
embeddedViewEnd();
} else {
let rf2 = embeddedViewStart(2);
{
if (rf2) {
elementStart(0, 'div');
{ text(1, 'Goodbye'); }
elementEnd();
}
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
expect(renderToHtml(Template, ctx)).toEqual('<div><span>Hello</span></div>');
@ -546,7 +589,7 @@ describe('JS control flow', () => {
log.push('comp!');
return new Comp();
},
template: function(ctx: Comp, cm: boolean) {}
template: function(rf: RenderFlags, ctx: Comp) {}
});
}
@ -558,35 +601,39 @@ describe('JS control flow', () => {
type: App,
selectors: [['app']],
factory: () => new App(),
template: function(ctx: any, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
elementEnd();
container(1);
container(2);
}
containerRefreshStart(1);
{
if (ctx.condition) {
if (embeddedViewStart(0)) {
elementStart(0, 'comp');
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
if (ctx.condition) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'comp');
elementEnd();
}
embeddedViewEnd();
}
embeddedViewEnd();
}
}
containerRefreshEnd();
containerRefreshStart(2);
{
if (ctx.condition2) {
if (embeddedViewStart(0)) {
elementStart(0, 'comp');
elementEnd();
containerRefreshEnd();
containerRefreshStart(2);
{
if (ctx.condition2) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'comp');
elementEnd();
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
},
directives: () => [Comp]
});
@ -609,7 +656,7 @@ describe('JS control flow', () => {
log.push('comp!');
return new Comp();
},
template: function(ctx: Comp, cm: boolean) {}
template: function(rf: RenderFlags, ctx: Comp) {}
});
}
@ -621,35 +668,39 @@ describe('JS control flow', () => {
type: App,
selectors: [['app']],
factory: () => new App(),
template: function(ctx: any, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
elementEnd();
container(1);
container(2);
}
containerRefreshStart(1);
{
if (ctx.condition) {
if (embeddedViewStart(0)) {
elementStart(0, 'comp');
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
if (ctx.condition) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'comp');
elementEnd();
}
embeddedViewEnd();
}
embeddedViewEnd();
}
}
containerRefreshEnd();
containerRefreshStart(2);
{
if (ctx.condition2) {
if (embeddedViewStart(0)) {
elementStart(0, 'comp');
elementEnd();
containerRefreshEnd();
containerRefreshStart(2);
{
if (ctx.condition2) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'comp');
elementEnd();
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
},
directives: () => [Comp]
});
@ -678,30 +729,38 @@ describe('JS for loop', () => {
* % }
* </div>
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
{ container(1); }
elementEnd();
}
containerRefreshStart(1);
{
for (let i = 0; i < ctx.data1.length; i++) {
if (embeddedViewStart(1)) {
text(0);
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
for (let i = 0; i < ctx.data1.length; i++) {
let rf2 = embeddedViewStart(1);
if (rf2 & RenderFlags.Create) {
text(0);
}
if (rf2 & RenderFlags.Update) {
textBinding(0, bind(ctx.data1[i]));
}
embeddedViewEnd();
}
textBinding(0, bind(ctx.data1[i]));
embeddedViewEnd();
}
for (let j = 0; j < ctx.data2.length; j++) {
if (embeddedViewStart(2)) {
text(0);
for (let j = 0; j < ctx.data2.length; j++) {
let rf2 = embeddedViewStart(1);
if (rf2 & RenderFlags.Create) {
text(0);
}
if (rf2 & RenderFlags.Update) {
textBinding(0, bind(ctx.data2[j]));
}
embeddedViewEnd();
}
textBinding(0, bind(ctx.data2[j]));
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
expect(renderToHtml(Template, ctx)).toEqual('<div>abc12</div>');
@ -721,18 +780,20 @@ describe('function calls', () => {
it('should work', () => {
const ctx: {data: string[]} = {data: ['foo', 'bar']};
function spanify(ctx: {message: string | null}, cm: boolean) {
function spanify(rf: RenderFlags, ctx: {message: string | null}) {
const message = ctx.message;
if (cm) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span');
{ text(1); }
elementEnd();
}
textBinding(1, bind(message));
if (rf & RenderFlags.Update) {
textBinding(1, bind(message));
}
}
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
{
text(1, 'Before');
@ -742,20 +803,22 @@ describe('function calls', () => {
}
elementEnd();
}
containerRefreshStart(2);
{
let cm0 = embeddedViewStart(0);
{ spanify({message: ctx.data[0]}, cm0); }
embeddedViewEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(2);
{
let rf0 = embeddedViewStart(0);
{ spanify(rf0, {message: ctx.data[0]}); }
embeddedViewEnd();
}
containerRefreshEnd();
containerRefreshStart(3);
{
let rf0 = embeddedViewStart(0);
{ spanify(rf0, {message: ctx.data[1]}); }
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
containerRefreshStart(3);
{
let cm0 = embeddedViewStart(0);
{ spanify({message: ctx.data[1]}, cm0); }
embeddedViewEnd();
}
containerRefreshEnd();
}
expect(renderToHtml(Template, ctx))

View File

@ -7,6 +7,7 @@
*/
import {ChangeDetectorRef, ElementRef, TemplateRef, ViewContainerRef} from '@angular/core';
import {RenderFlags} from '@angular/core/src/render3/interfaces/definition';
import {defineComponent} from '../../src/render3/definition';
import {InjectFlags, bloomAdd, bloomFindPossibleInjector, getOrCreateNodeInjector, injectAttribute} from '../../src/render3/di';
@ -33,14 +34,17 @@ describe('di', () => {
}
/** <div dir #dir="dir"> {{ dir.value }} </div> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
}
const tmp = load(1) as any;
textBinding(2, bind(tmp.value));
let tmp: any;
if (rf & RenderFlags.Update) {
tmp = load(1);
textBinding(2, bind(tmp.value));
}
}
expect(renderToHtml(Template, {}, [Directive])).toEqual('<div dir="">Created</div>');
@ -91,8 +95,8 @@ describe('di', () => {
* <span dirB dirC #dir="dirC"> {{ dir.value }} </span>
* </div>
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dirA', '']);
{
elementStart(1, 'span', ['dirB', '', 'dirC', ''], ['dir', 'dirC']);
@ -101,8 +105,11 @@ describe('di', () => {
}
elementEnd();
}
const tmp = load(2) as any;
textBinding(3, bind(tmp.value));
let tmp: any;
if (rf & RenderFlags.Update) {
tmp = load(2);
textBinding(3, bind(tmp.value));
}
}
const defs = [DirA, DirB, DirC];
@ -326,8 +333,8 @@ describe('di', () => {
type: App,
factory: () => new App(),
/** <div dirA dirB dirC></div> */
template: (ctx: any, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: any) => {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dirA', '', 'dirB', '', 'dirC', 'dirC']);
elementEnd();
}
@ -516,16 +523,20 @@ describe('di', () => {
* {{ dir.value }} - {{ dirSame.value }}
* </div>
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dirSame', 'dirSame', 'dir', 'dir']);
{ text(3); }
elementEnd();
}
const tmp1 = load(1) as any;
const tmp2 = load(2) as any;
textBinding(3, interpolation2('', tmp2.value, '-', tmp1.value, ''));
let tmp1: any;
let tmp2: any;
if (rf & RenderFlags.Update) {
tmp1 = load(1);
tmp2 = load(2);
textBinding(3, interpolation2('', tmp2.value, '-', tmp1.value, ''));
}
}
const defs = [Directive, DirectiveSameInstance];
@ -568,15 +579,19 @@ describe('di', () => {
* {{ dir.value }} - {{ dirSame.value }}
* </ng-template>
*/
function Template(ctx: any, cm: any) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0, function() {
}, undefined, ['dir', '', 'dirSame', ''], ['dir', 'dir', 'dirSame', 'dirSame']);
text(3);
}
const tmp1 = load(1) as any;
const tmp2 = load(2) as any;
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, ''));
let tmp1: any;
let tmp2: any;
if (rf & RenderFlags.Update) {
tmp1 = load(1);
tmp2 = load(2);
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, ''));
}
}
const defs = [Directive, DirectiveSameInstance];
@ -619,16 +634,19 @@ describe('di', () => {
* {{ dir.value }} - {{ dirSame.value }}
* </div>
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir', 'dirSame', 'dirSame']);
{ text(3); }
elementEnd();
}
const tmp1 = load(1) as any;
const tmp2 = load(2) as any;
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, ''));
let tmp1: any;
let tmp2: any;
if (rf & RenderFlags.Update) {
tmp1 = load(1);
tmp2 = load(2);
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, ''));
}
}
const defs = [Directive, DirectiveSameInstance];
@ -649,8 +667,8 @@ describe('di', () => {
type: MyComp,
selectors: [['my-comp']],
factory: () => comp = new MyComp(injectChangeDetectorRef()),
template: function(ctx: MyComp, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: MyComp) {
if (rf & RenderFlags.Create) {
projectionDef(0);
projection(1, 0);
}
@ -708,14 +726,17 @@ describe('di', () => {
it('should inject current component ChangeDetectorRef into directives on components', () => {
/** <my-comp dir dirSameInstance #dir="dir"></my-comp> {{ dir.value }} */
const MyApp = createComponent('my-app', function(ctx: any, cm: boolean) {
if (cm) {
const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'my-comp', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
elementEnd();
text(2);
}
const tmp = load(1) as any;
textBinding(2, bind(tmp.value));
let tmp: any;
if (rf & RenderFlags.Update) {
tmp = load(1);
textBinding(2, bind(tmp.value));
}
}, directives);
const app = renderComponent(MyApp);
@ -737,14 +758,17 @@ describe('di', () => {
selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()),
/** <div dir dirSameInstance #dir="dir"> {{ dir.value }} </div> */
template: function(ctx: any, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
}
const tmp = load(1) as any;
textBinding(2, bind(tmp.value));
let tmp: any;
if (rf & RenderFlags.Update) {
tmp = load(1);
textBinding(2, bind(tmp.value));
}
},
directives: directives
});
@ -772,8 +796,8 @@ describe('di', () => {
* </my-comp>
* {{ dir.value }}
*/
template: function(ctx: any, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'my-comp');
{
elementStart(1, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
@ -783,7 +807,9 @@ describe('di', () => {
text(3);
}
const tmp = load(2) as any;
textBinding(3, bind(tmp.value));
if (rf & RenderFlags.Update) {
textBinding(3, bind(tmp.value));
}
},
directives: directives
});
@ -813,24 +839,30 @@ describe('di', () => {
* <div dir dirSameInstance #dir="dir"> {{ dir.value }} </div>
* % }
*/
template: function(ctx: MyApp, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: MyApp) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
if (ctx.showing) {
if (embeddedViewStart(0)) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.showing) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
}
let tmp: any;
if (rf1 & RenderFlags.Update) {
tmp = load(1);
textBinding(2, bind(tmp.value));
}
}
const tmp = load(1) as any;
textBinding(2, bind(tmp.value));
embeddedViewEnd();
}
embeddedViewEnd();
containerRefreshEnd();
}
containerRefreshEnd();
},
directives: directives
});
@ -855,21 +887,26 @@ describe('di', () => {
selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()),
/** <div *myIf="showing" dir dirSameInstance #dir="dir"> {{ dir.value }} </div> */
template: function(ctx: MyApp, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: MyApp) {
if (rf & RenderFlags.Create) {
container(0, C1, undefined, ['myIf', 'showing']);
}
containerRefreshStart(0);
containerRefreshEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
containerRefreshEnd();
}
function C1(ctx1: any, cm1: boolean) {
if (cm1) {
function C1(rf1: RenderFlags, ctx1: any) {
if (rf1 & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
}
const tmp = load(1) as any;
textBinding(2, bind(tmp.value));
let tmp: any;
if (rf1 & RenderFlags.Update) {
tmp = load(1);
textBinding(2, bind(tmp.value));
}
}
},
directives: directives
@ -889,8 +926,8 @@ describe('di', () => {
let exist: string|undefined = 'wrong';
let nonExist: string|undefined = 'wrong';
const MyApp = createComponent('my-app', function(ctx: any, cm: boolean) {
if (cm) {
const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['exist', 'existValue', 'other', 'ignore']);
exist = injectAttribute('exist');
nonExist = injectAttribute('nonExist');
@ -1025,27 +1062,34 @@ describe('di', () => {
* </span>
* </div>
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['parentDir', '']);
{ container(1); }
elementEnd();
}
containerRefreshStart(1);
{
if (embeddedViewStart(0)) {
elementStart(
0, 'span', ['childDir', '', 'child2Dir', ''],
['child1', 'childDir', 'child2', 'child2Dir']);
{ text(3); }
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(
0, 'span', ['childDir', '', 'child2Dir', ''],
['child1', 'childDir', 'child2', 'child2Dir']);
{ text(3); }
elementEnd();
}
let tmp1: any;
let tmp2: any;
if (rf & RenderFlags.Update) {
tmp1 = load(1);
tmp2 = load(2);
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, ''));
}
embeddedViewEnd();
}
const tmp1 = load(1) as any;
const tmp2 = load(2) as any;
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, ''));
embeddedViewEnd();
containerRefreshEnd();
}
containerRefreshEnd();
}
const defs = [ChildDirective, Child2Directive, ParentDirective];

View File

@ -8,7 +8,7 @@
import {defineDirective} from '../../src/render3/index';
import {bind, elementEnd, elementProperty, elementStart, loadDirective} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {renderToHtml} from './render_util';
describe('directive', () => {
@ -31,8 +31,8 @@ describe('directive', () => {
});
}
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span', ['dir', '']);
elementEnd();
}

View File

@ -8,21 +8,24 @@
import {defineComponent, defineDirective} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, elementAttribute, elementClassNamed, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, load, text, textBinding} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {ComponentFixture, createComponent, renderToHtml} from './render_util';
describe('exports', () => {
it('should support export of DOM element', () => {
/** <input value="one" #myInput> {{ myInput.value }} */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'input', ['value', 'one'], ['myInput', '']);
elementEnd();
text(2);
}
const tmp = load(1) as any;
textBinding(2, tmp.value);
let tmp: any;
if (rf & RenderFlags.Update) {
tmp = load(1);
textBinding(2, tmp.value);
}
}
expect(renderToHtml(Template, {})).toEqual('<input value="one">one');
@ -31,14 +34,17 @@ describe('exports', () => {
it('should support basic export of component', () => {
/** <comp #myComp></comp> {{ myComp.name }} */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'comp', null, ['myComp', '']);
elementEnd();
text(2);
}
const tmp = load(1) as any;
textBinding(2, tmp.name);
let tmp: any;
if (rf & RenderFlags.Update) {
tmp = load(1);
textBinding(2, tmp.name);
}
}
class MyComponent {
@ -83,15 +89,18 @@ describe('exports', () => {
const defs = [MyComponent, MyDir];
/** <comp #myComp></comp> <div [myDir]="myComp"></div> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'comp', null, ['myComp', '']);
elementEnd();
elementStart(2, 'div', ['myDir', '']);
elementEnd();
}
const tmp = load(1) as any;
elementProperty(2, 'myDir', bind(tmp));
let tmp: any;
if (rf & RenderFlags.Update) {
tmp = load(1);
elementProperty(2, 'myDir', bind(tmp));
}
}
renderToHtml(Template, {}, defs);
@ -101,14 +110,17 @@ describe('exports', () => {
it('should work with directives with exportAs set', () => {
/** <div someDir #myDir="someDir"></div> {{ myDir.name }} */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['someDir', ''], ['myDir', 'someDir']);
elementEnd();
text(2);
}
const tmp = load(1) as any;
textBinding(2, tmp.name);
let tmp: any;
if (rf & RenderFlags.Update) {
tmp = load(1);
textBinding(2, tmp.name);
}
}
class SomeDir {
@ -127,8 +139,8 @@ describe('exports', () => {
it('should throw if export name is not found', () => {
/** <div #myDir="someDir"></div> */
const App = createComponent('app', function(ctx: any, cm: boolean) {
if (cm) {
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', null, ['myDir', 'someDir']);
elementEnd();
}
@ -142,14 +154,16 @@ describe('exports', () => {
describe('forward refs', () => {
it('should work with basic text bindings', () => {
/** {{ myInput.value}} <input value="one" #myInput> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
text(0);
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
elementEnd();
}
const tmp = load(2) as any;
textBinding(0, bind(tmp.value));
if (rf & RenderFlags.Update) {
textBinding(0, bind(tmp.value));
}
}
expect(renderToHtml(Template, {})).toEqual('one<input value="one">');
@ -158,15 +172,17 @@ describe('exports', () => {
it('should work with element properties', () => {
/** <div [title]="myInput.value"</div> <input value="one" #myInput> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
elementEnd();
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
elementEnd();
}
const tmp = load(2) as any;
elementProperty(0, 'title', bind(tmp.value));
if (rf & RenderFlags.Update) {
elementProperty(0, 'title', bind(tmp.value));
}
}
expect(renderToHtml(Template, {})).toEqual('<div title="one"></div><input value="one">');
@ -174,15 +190,17 @@ describe('exports', () => {
it('should work with element attrs', () => {
/** <div [attr.aria-label]="myInput.value"</div> <input value="one" #myInput> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
elementEnd();
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
elementEnd();
}
const tmp = load(2) as any;
elementAttribute(0, 'aria-label', bind(tmp.value));
if (rf & RenderFlags.Update) {
elementAttribute(0, 'aria-label', bind(tmp.value));
}
}
expect(renderToHtml(Template, {})).toEqual('<div aria-label="one"></div><input value="one">');
@ -190,15 +208,17 @@ describe('exports', () => {
it('should work with element classes', () => {
/** <div [class.red]="myInput.checked"</div> <input type="checkbox" checked #myInput> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
elementEnd();
elementStart(1, 'input', ['type', 'checkbox', 'checked', 'true'], ['myInput', '']);
elementEnd();
}
const tmp = load(2) as any;
elementClassNamed(0, 'red', bind(tmp.checked));
if (rf & RenderFlags.Update) {
elementClassNamed(0, 'red', bind(tmp.checked));
}
}
expect(renderToHtml(Template, {}))
@ -216,7 +236,7 @@ describe('exports', () => {
static ngComponentDef = defineComponent({
type: MyComponent,
selectors: [['comp']],
template: function(ctx: MyComponent, cm: boolean) {},
template: function(rf: RenderFlags, ctx: MyComponent) {},
factory: () => new MyComponent
});
}
@ -235,15 +255,18 @@ describe('exports', () => {
}
/** <div [myDir]="myComp"></div><comp #myComp></comp> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['myDir', '']);
elementEnd();
elementStart(1, 'comp', null, ['myComp', '']);
elementEnd();
}
const tmp = load(2) as any;
elementProperty(0, 'myDir', bind(tmp));
let tmp: any;
if (rf & RenderFlags.Update) {
tmp = load(2) as any;
elementProperty(0, 'myDir', bind(tmp));
}
}
renderToHtml(Template, {}, [MyComponent, MyDir]);
@ -253,8 +276,8 @@ describe('exports', () => {
it('should work with multiple forward refs', () => {
/** {{ myInput.value }} {{ myComp.name }} <comp #myComp></comp> <input value="one" #myInput>
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
text(0);
text(1);
elementStart(2, 'comp', null, ['myComp', '']);
@ -262,10 +285,14 @@ describe('exports', () => {
elementStart(4, 'input', ['value', 'one'], ['myInput', '']);
elementEnd();
}
const tmp1 = load(3) as any;
const tmp2 = load(5) as any;
textBinding(0, bind(tmp2.value));
textBinding(1, bind(tmp1.name));
let tmp1: any;
let tmp2: any;
if (rf & RenderFlags.Update) {
tmp1 = load(3) as any;
tmp2 = load(5) as any;
textBinding(0, bind(tmp2.value));
textBinding(1, bind(tmp1.name));
}
}
let myComponent: MyComponent;
@ -287,29 +314,34 @@ describe('exports', () => {
});
it('should work inside a view container', () => {
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
{ container(1); }
elementEnd();
}
containerRefreshStart(1);
{
if (ctx.condition) {
let cm1 = embeddedViewStart(1);
{
if (cm1) {
text(0);
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
if (ctx.condition) {
let rf1 = embeddedViewStart(1);
{
let tmp: any;
if (rf1 & RenderFlags.Create) {
text(0);
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
elementEnd();
}
if (rf1 & RenderFlags.Update) {
tmp = load(2);
textBinding(0, bind(tmp.value));
}
}
const tmp = load(2) as any;
textBinding(0, bind(tmp.value));
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
expect(renderToHtml(Template, {

View File

@ -6,8 +6,11 @@
* found in the LICENSE file at https://angular.io/license
*/
import {RenderFlags} from '@angular/core/src/render3';
import {defineComponent, defineDirective} from '../../src/render3/index';
import {NO_CHANGE, bind, container, containerRefreshEnd, containerRefreshStart, elementAttribute, elementClassNamed, elementEnd, elementProperty, elementStart, elementStyleNamed, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV, load, loadDirective, projection, projectionDef, text, textBinding} from '../../src/render3/instructions';
import {LViewFlags} from '../../src/render3/interfaces/view';
import {ComponentFixture, containerEl, renderToHtml} from './render_util';
@ -18,8 +21,8 @@ describe('render3 integration test', () => {
it('should render basic template', () => {
expect(renderToHtml(Template, {})).toEqual('<span title="Hello">Greetings</span>');
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span', ['title', 'Hello']);
{ text(1, 'Greetings'); }
elementEnd();
@ -31,24 +34,28 @@ describe('render3 integration test', () => {
expect(renderToHtml(Template, 'World')).toEqual('<h1>Hello, World!</h1>');
expect(renderToHtml(Template, 'New World')).toEqual('<h1>Hello, New World!</h1>');
function Template(name: string, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'h1');
{ text(1); }
elementEnd();
}
textBinding(1, interpolation1('Hello, ', name, '!'));
if (rf & RenderFlags.Update) {
textBinding(1, interpolation1('Hello, ', ctx, '!'));
}
}
});
});
describe('text bindings', () => {
it('should render "undefined" as "" when used with `bind()`', () => {
function Template(name: string, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, name: string) {
if (rf & RenderFlags.Create) {
text(0);
}
textBinding(0, bind(name));
if (rf & RenderFlags.Update) {
textBinding(0, bind(name));
}
}
expect(renderToHtml(Template, 'benoit')).toEqual('benoit');
@ -56,11 +63,13 @@ describe('render3 integration test', () => {
});
it('should render "null" as "" when used with `bind()`', () => {
function Template(name: string, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, name: string) {
if (rf & RenderFlags.Create) {
text(0);
}
textBinding(0, bind(name));
if (rf & RenderFlags.Update) {
textBinding(0, bind(name));
}
}
expect(renderToHtml(Template, 'benoit')).toEqual('benoit');
@ -68,11 +77,13 @@ describe('render3 integration test', () => {
});
it('should support creation-time values in text nodes', () => {
function Template(value: string, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, value: string) {
if (rf & RenderFlags.Create) {
text(0);
}
textBinding(0, cm ? value : NO_CHANGE);
if (rf & RenderFlags.Update) {
textBinding(0, rf & RenderFlags.Create ? value : NO_CHANGE);
}
}
expect(renderToHtml(Template, 'once')).toEqual('once');
expect(renderToHtml(Template, 'twice')).toEqual('once');
@ -82,21 +93,23 @@ describe('render3 integration test', () => {
describe('Siblings update', () => {
it('should handle a flat list of static/bound text nodes', () => {
function Template(name: string, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, name: string) {
if (rf & RenderFlags.Create) {
text(0, 'Hello ');
text(1);
text(2, '!');
}
textBinding(1, bind(name));
if (rf & RenderFlags.Update) {
textBinding(1, bind(name));
}
}
expect(renderToHtml(Template, 'world')).toEqual('Hello world!');
expect(renderToHtml(Template, 'monde')).toEqual('Hello monde!');
});
it('should handle a list of static/bound text nodes as element children', () => {
function Template(name: string, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, name: string) {
if (rf & RenderFlags.Create) {
elementStart(0, 'b');
{
text(1, 'Hello ');
@ -105,15 +118,17 @@ describe('render3 integration test', () => {
}
elementEnd();
}
textBinding(2, bind(name));
if (rf & RenderFlags.Update) {
textBinding(2, bind(name));
}
}
expect(renderToHtml(Template, 'world')).toEqual('<b>Hello world!</b>');
expect(renderToHtml(Template, 'mundo')).toEqual('<b>Hello mundo!</b>');
});
it('should render/update text node as a child of a deep list of elements', () => {
function Template(name: string, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, name: string) {
if (rf & RenderFlags.Create) {
elementStart(0, 'b');
{
elementStart(1, 'b');
@ -130,15 +145,17 @@ describe('render3 integration test', () => {
}
elementEnd();
}
textBinding(4, interpolation1('Hello ', name, '!'));
if (rf & RenderFlags.Update) {
textBinding(4, interpolation1('Hello ', name, '!'));
}
}
expect(renderToHtml(Template, 'world')).toEqual('<b><b><b><b>Hello world!</b></b></b></b>');
expect(renderToHtml(Template, 'mundo')).toEqual('<b><b><b><b>Hello mundo!</b></b></b></b>');
});
it('should update 2 sibling elements', () => {
function Template(id: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, id: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'b');
{
elementStart(1, 'span');
@ -149,7 +166,9 @@ describe('render3 integration test', () => {
}
elementEnd();
}
elementAttribute(2, 'id', bind(id));
if (rf & RenderFlags.Update) {
elementAttribute(2, 'id', bind(id));
}
}
expect(renderToHtml(Template, 'foo'))
.toEqual('<b><span></span><span class="foo" id="foo"></span></b>');
@ -158,8 +177,8 @@ describe('render3 integration test', () => {
});
it('should handle sibling text node after element with child text node', () => {
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'p');
{ text(1, 'hello'); }
elementEnd();
@ -179,8 +198,8 @@ describe('render3 integration test', () => {
static ngComponentDef = defineComponent({
type: TodoComponent,
selectors: [['todo']],
template: function TodoTemplate(ctx: any, cm: boolean) {
if (cm) {
template: function TodoTemplate(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'p');
{
text(1, 'Todo');
@ -188,7 +207,9 @@ describe('render3 integration test', () => {
}
elementEnd();
}
textBinding(2, bind(ctx.value));
if (rf & RenderFlags.Update) {
textBinding(2, bind(ctx.value));
}
},
factory: () => new TodoComponent
});
@ -197,8 +218,8 @@ describe('render3 integration test', () => {
const defs = [TodoComponent];
it('should support a basic component template', () => {
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'todo');
elementEnd();
}
@ -208,8 +229,8 @@ describe('render3 integration test', () => {
});
it('should support a component template with sibling', () => {
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'todo');
elementEnd();
text(1, 'two');
@ -223,8 +244,8 @@ describe('render3 integration test', () => {
* <todo></todo>
* <todo></todo>
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'todo');
elementEnd();
elementStart(1, 'todo');
@ -244,11 +265,13 @@ describe('render3 integration test', () => {
type: TodoComponentHostBinding,
selectors: [['todo']],
template: function TodoComponentHostBindingTemplate(
ctx: TodoComponentHostBinding, cm: boolean) {
if (cm) {
rf: RenderFlags, ctx: TodoComponentHostBinding) {
if (rf & RenderFlags.Create) {
text(0);
}
textBinding(0, bind(ctx.title));
if (rf & RenderFlags.Update) {
textBinding(0, bind(ctx.title));
}
},
factory: () => cmptInstance = new TodoComponentHostBinding,
hostBindings: function(directiveIndex: number, elementIndex: number): void {
@ -260,8 +283,8 @@ describe('render3 integration test', () => {
});
}
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'todo');
elementEnd();
}
@ -279,7 +302,7 @@ describe('render3 integration test', () => {
type: HostAttributeComp,
selectors: [['host-attr-comp']],
factory: () => new HostAttributeComp(),
template: (ctx: HostAttributeComp, cm: boolean) => {},
template: (rf: RenderFlags, ctx: HostAttributeComp) => {},
attributes: ['role', 'button']
});
}
@ -295,20 +318,22 @@ describe('render3 integration test', () => {
static ngComponentDef = defineComponent({
type: MyComp,
selectors: [['comp']],
template: function MyCompTemplate(ctx: any, cm: boolean) {
if (cm) {
template: function MyCompTemplate(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'p');
{ text(1); }
elementEnd();
}
textBinding(1, bind(ctx.name));
if (rf & RenderFlags.Update) {
textBinding(1, bind(ctx.name));
}
},
factory: () => new MyComp
});
}
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'comp');
elementEnd();
}
@ -328,22 +353,25 @@ describe('render3 integration test', () => {
static ngComponentDef = defineComponent({
type: MyComp,
selectors: [['comp']],
template: function MyCompTemplate(ctx: any, cm: boolean) {
if (cm) {
template: function MyCompTemplate(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
if (ctx.condition) {
if (embeddedViewStart(0)) {
elementStart(0, 'div');
{ text(1, 'text'); }
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.condition) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'div');
{ text(1, 'text'); }
elementEnd();
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
},
factory: () => new MyComp,
inputs: {condition: 'condition'}
@ -351,12 +379,14 @@ describe('render3 integration test', () => {
}
/** <comp [condition]="condition"></comp> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'comp');
elementEnd();
}
elementProperty(0, 'condition', bind(ctx.condition));
if (rf & RenderFlags.Update) {
elementProperty(0, 'condition', bind(ctx.condition));
}
}
const defs = [MyComp];
@ -381,49 +411,54 @@ describe('render3 integration test', () => {
afterTree: Tree;
}
function showLabel(ctx: {label: string | undefined}, cm: boolean) {
if (cm) {
function showLabel(rf: RenderFlags, ctx: {label: string | undefined}) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
if (ctx.label != null) {
if (embeddedViewStart(0)) {
text(0);
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.label != null) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
text(0);
}
if (rf1 & RenderFlags.Update) {
textBinding(0, bind(ctx.label));
}
embeddedViewEnd();
}
textBinding(0, bind(ctx.label));
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
function showTree(ctx: {tree: Tree}, cm: boolean) {
if (cm) {
function showTree(rf: RenderFlags, ctx: {tree: Tree}) {
if (rf & RenderFlags.Create) {
container(0);
container(1);
container(2);
}
containerRefreshStart(0);
{
const cm0 = embeddedViewStart(0);
{ showLabel({label: ctx.tree.beforeLabel}, cm0); }
const rf0 = embeddedViewStart(0);
{ showLabel(rf0, {label: ctx.tree.beforeLabel}); }
embeddedViewEnd();
}
containerRefreshEnd();
containerRefreshStart(1);
{
for (let subTree of ctx.tree.subTrees || []) {
const cm0 = embeddedViewStart(0);
{ showTree({tree: subTree}, cm0); }
const rf0 = embeddedViewStart(0);
{ showTree(rf0, {tree: subTree}); }
embeddedViewEnd();
}
}
containerRefreshEnd();
containerRefreshStart(2);
{
const cm0 = embeddedViewStart(0);
{ showLabel({label: ctx.tree.afterLabel}, cm0); }
const rf0 = embeddedViewStart(0);
{ showLabel(rf0, {label: ctx.tree.afterLabel}); }
embeddedViewEnd();
}
containerRefreshEnd();
@ -436,8 +471,8 @@ describe('render3 integration test', () => {
selectors: [['child']],
type: ChildComponent,
template: function ChildComponentTemplate(
ctx: {beforeTree: Tree, afterTree: Tree}, cm: boolean) {
if (cm) {
rf: RenderFlags, ctx: {beforeTree: Tree, afterTree: Tree}) {
if (rf & RenderFlags.Create) {
projectionDef(0);
container(1);
projection(2, 0);
@ -445,15 +480,15 @@ describe('render3 integration test', () => {
}
containerRefreshStart(1);
{
const cm0 = embeddedViewStart(0);
{ showTree({tree: ctx.beforeTree}, cm0); }
const rf0 = embeddedViewStart(0);
{ showTree(rf0, {tree: ctx.beforeTree}); }
embeddedViewEnd();
}
containerRefreshEnd();
containerRefreshStart(3);
{
const cm0 = embeddedViewStart(0);
{ showTree({tree: ctx.afterTree}, cm0); }
const rf0 = embeddedViewStart(0);
{ showTree(rf0, {tree: ctx.afterTree}); }
embeddedViewEnd();
}
containerRefreshEnd();
@ -463,21 +498,23 @@ describe('render3 integration test', () => {
});
}
function parentTemplate(ctx: ParentCtx, cm: boolean) {
if (cm) {
function parentTemplate(rf: RenderFlags, ctx: ParentCtx) {
if (rf & RenderFlags.Create) {
elementStart(0, 'child');
{ container(1); }
elementEnd();
}
elementProperty(0, 'beforeTree', bind(ctx.beforeTree));
elementProperty(0, 'afterTree', bind(ctx.afterTree));
containerRefreshStart(1);
{
const cm0 = embeddedViewStart(0);
{ showTree({tree: ctx.projectedTree}, cm0); }
embeddedViewEnd();
if (rf & RenderFlags.Update) {
elementProperty(0, 'beforeTree', bind(ctx.beforeTree));
elementProperty(0, 'afterTree', bind(ctx.afterTree));
containerRefreshStart(1);
{
const rf0 = embeddedViewStart(0);
{ showTree(rf0, {tree: ctx.projectedTree}); }
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
it('should work with a tree', () => {
@ -509,12 +546,14 @@ describe('render3 integration test', () => {
it('should support attribute bindings', () => {
const ctx: {title: string | null} = {title: 'Hello'};
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span');
elementEnd();
}
elementAttribute(0, 'title', bind(ctx.title));
if (rf & RenderFlags.Update) {
elementAttribute(0, 'title', bind(ctx.title));
}
}
// initial binding
@ -532,12 +571,14 @@ describe('render3 integration test', () => {
it('should stringify values used attribute bindings', () => {
const ctx: {title: any} = {title: NaN};
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span');
elementEnd();
}
elementAttribute(0, 'title', bind(ctx.title));
if (rf & RenderFlags.Update) {
elementAttribute(0, 'title', bind(ctx.title));
}
}
expect(renderToHtml(Template, ctx)).toEqual('<span title="NaN"></span>');
@ -547,33 +588,35 @@ describe('render3 integration test', () => {
});
it('should update bindings', () => {
function Template(c: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, c: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'b');
elementEnd();
}
elementAttribute(0, 'a', interpolationV(c));
elementAttribute(0, 'a0', bind(c[1]));
elementAttribute(0, 'a1', interpolation1(c[0], c[1], c[16]));
elementAttribute(0, 'a2', interpolation2(c[0], c[1], c[2], c[3], c[16]));
elementAttribute(0, 'a3', interpolation3(c[0], c[1], c[2], c[3], c[4], c[5], c[16]));
elementAttribute(
0, 'a4', interpolation4(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[16]));
elementAttribute(
0, 'a5',
interpolation5(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[16]));
elementAttribute(
0, 'a6',
interpolation6(
c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10], c[11], c[16]));
elementAttribute(
0, 'a7', interpolation7(
c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10], c[11],
c[12], c[13], c[16]));
elementAttribute(
0, 'a8', interpolation8(
c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10], c[11],
c[12], c[13], c[14], c[15], c[16]));
if (rf & RenderFlags.Update) {
elementAttribute(0, 'a', interpolationV(c));
elementAttribute(0, 'a0', bind(c[1]));
elementAttribute(0, 'a1', interpolation1(c[0], c[1], c[16]));
elementAttribute(0, 'a2', interpolation2(c[0], c[1], c[2], c[3], c[16]));
elementAttribute(0, 'a3', interpolation3(c[0], c[1], c[2], c[3], c[4], c[5], c[16]));
elementAttribute(
0, 'a4', interpolation4(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[16]));
elementAttribute(
0, 'a5',
interpolation5(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[16]));
elementAttribute(
0, 'a6', interpolation6(
c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10],
c[11], c[16]));
elementAttribute(
0, 'a7', interpolation7(
c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10],
c[11], c[12], c[13], c[16]));
elementAttribute(
0, 'a8', interpolation8(
c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10],
c[11], c[12], c[13], c[14], c[15], c[16]));
}
}
let args = ['(', 0, 'a', 1, 'b', 2, 'c', 3, 'd', 4, 'e', 5, 'f', 6, 'g', 7, ')'];
expect(renderToHtml(Template, args))
@ -592,29 +635,31 @@ describe('render3 integration test', () => {
it('should not update DOM if context has not changed', () => {
const ctx: {title: string | null} = {title: 'Hello'};
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span');
container(1);
elementEnd();
}
elementAttribute(0, 'title', bind(ctx.title));
containerRefreshStart(1);
{
if (true) {
let cm1 = embeddedViewStart(1);
{
if (cm1) {
elementStart(0, 'b');
{}
elementEnd();
if (rf & RenderFlags.Update) {
elementAttribute(0, 'title', bind(ctx.title));
containerRefreshStart(1);
{
if (true) {
let rf1 = embeddedViewStart(1);
{
if (rf1 & RenderFlags.Create) {
elementStart(0, 'b');
{}
elementEnd();
}
elementAttribute(0, 'title', bind(ctx.title));
}
elementAttribute(0, 'title', bind(ctx.title));
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
// initial binding
@ -650,8 +695,8 @@ describe('render3 integration test', () => {
});
}
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['hostBindingDir', '']);
elementEnd();
}
@ -670,12 +715,14 @@ describe('render3 integration test', () => {
describe('elementStyle', () => {
it('should support binding to styles', () => {
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span');
elementEnd();
}
elementStyleNamed(0, 'border-color', bind(ctx));
if (rf & RenderFlags.Update) {
elementStyleNamed(0, 'border-color', bind(ctx));
}
}
expect(renderToHtml(Template, 'red')).toEqual('<span style="border-color: red;"></span>');
@ -685,12 +732,14 @@ describe('render3 integration test', () => {
});
it('should support binding to styles with suffix', () => {
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span');
elementEnd();
}
elementStyleNamed(0, 'font-size', bind(ctx), 'px');
if (rf & RenderFlags.Update) {
elementStyleNamed(0, 'font-size', bind(ctx), 'px');
}
}
expect(renderToHtml(Template, '100')).toEqual('<span style="font-size: 100px;"></span>');
@ -702,12 +751,14 @@ describe('render3 integration test', () => {
describe('elementClass', () => {
it('should support CSS class toggle', () => {
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span');
elementEnd();
}
elementClassNamed(0, 'active', bind(ctx));
if (rf & RenderFlags.Update) {
elementClassNamed(0, 'active', bind(ctx));
}
}
expect(renderToHtml(Template, true)).toEqual('<span class="active"></span>');
@ -723,12 +774,14 @@ describe('render3 integration test', () => {
});
it('should work correctly with existing static classes', () => {
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span', ['class', 'existing']);
elementEnd();
}
elementClassNamed(0, 'active', bind(ctx));
if (rf & RenderFlags.Update) {
elementClassNamed(0, 'active', bind(ctx));
}
}
expect(renderToHtml(Template, true)).toEqual('<span class="existing active"></span>');
@ -745,22 +798,24 @@ describe('render3 integration test', () => {
* <div></div>
* % }
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
if (ctx.condition) {
if (embeddedViewStart(0)) {
elementStart(0, 'div');
{}
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.condition) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'div');
elementEnd();
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
expect((Template as any).ngPrivateData).toBeUndefined();

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
import {defineComponent, defineDirective} from '../../src/render3/index';
import {container, containerRefreshEnd, containerRefreshStart, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, listener, text} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {getRendererFactory2} from './imported_renderer2';
import {containerEl, renderComponent, renderToHtml} from './render_util';
@ -26,8 +26,8 @@ describe('event listeners', () => {
type: MyComp,
selectors: [['comp']],
/** <button (click)="onClick()"> Click me </button> */
template: function CompTemplate(ctx: any, cm: boolean) {
if (cm) {
template: function CompTemplate(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button');
{
listener('click', function() { return ctx.onClick(); });
@ -64,8 +64,8 @@ describe('event listeners', () => {
selectors: [['prevent-default-comp']],
factory: () => new PreventDefaultComp(),
/** <button (click)="onClick($event)">Click</button> */
template: (ctx: PreventDefaultComp, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, ctx: PreventDefaultComp) => {
if (rf & RenderFlags.Create) {
elementStart(0, 'button');
{
listener('click', function($event: any) { return ctx.onClick($event); });
@ -124,8 +124,8 @@ describe('event listeners', () => {
it('should call function chain on event emit', () => {
/** <button (click)="onClick(); onClick2(); "> Click me </button> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button');
{
listener('click', function() {
@ -159,8 +159,8 @@ describe('event listeners', () => {
it('should evaluate expression on event emit', () => {
/** <button (click)="showing=!showing"> Click me </button> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button');
{
listener('click', function() { return ctx.showing = !ctx.showing; });
@ -188,25 +188,27 @@ describe('event listeners', () => {
* <button (click)="onClick()"> Click me </button>
* % }
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
if (ctx.showing) {
if (embeddedViewStart(1)) {
elementStart(0, 'button');
{
listener('click', function() { return ctx.onClick(); });
text(1, 'Click me');
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.showing) {
if (embeddedViewStart(1)) {
elementStart(0, 'button');
{
listener('click', function() { return ctx.onClick(); });
text(1, 'Click me');
}
elementEnd();
}
elementEnd();
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
let comp = new MyComp();
@ -244,8 +246,8 @@ describe('event listeners', () => {
});
}
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button', ['hostListenerDir', '']);
text(1, 'Click');
elementEnd();
@ -271,36 +273,42 @@ describe('event listeners', () => {
* % }
* % }
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
if (ctx.showing) {
if (embeddedViewStart(0)) {
text(0, 'Hello');
container(1);
}
containerRefreshStart(1);
{
if (ctx.button) {
if (embeddedViewStart(0)) {
elementStart(0, 'button');
{
listener('click', function() { return ctx.onClick(); });
text(1, 'Click');
}
elementEnd();
}
embeddedViewEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.showing) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
text(0, 'Hello');
container(1);
}
if (rf1 & RenderFlags.Update) {
containerRefreshStart(1);
{
if (ctx.button) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'button');
{
listener('click', function() { return ctx.onClick(); });
text(1, 'Click');
}
elementEnd();
}
embeddedViewEnd();
}
}
containerRefreshEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
const comp = {showing: true, counter: 0, button: true, onClick: function() { this.counter++; }};
@ -329,24 +337,27 @@ describe('event listeners', () => {
* comp:
* <button (click)="onClick()"> Click </button>
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
if (ctx.showing) {
if (embeddedViewStart(0)) {
text(0, 'Hello');
elementStart(1, 'comp');
elementEnd();
elementStart(2, 'comp');
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.showing) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
text(0, 'Hello');
elementStart(1, 'comp');
elementEnd();
elementStart(2, 'comp');
elementEnd();
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
const ctx = {showing: true};
@ -381,52 +392,59 @@ describe('event listeners', () => {
* % }
* % }
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
if (ctx.condition) {
if (embeddedViewStart(0)) {
text(0, 'Hello');
container(1);
container(2);
}
containerRefreshStart(1);
{
if (ctx.sub1) {
if (embeddedViewStart(0)) {
elementStart(0, 'button');
{
listener('click', function() { return ctx.counter1++; });
text(1, 'Click');
}
elementEnd();
}
embeddedViewEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.condition) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
text(0, 'Hello');
container(1);
container(2);
}
}
containerRefreshEnd();
containerRefreshStart(2);
{
if (ctx.sub2) {
if (embeddedViewStart(0)) {
elementStart(0, 'button');
{
listener('click', function() { return ctx.counter2++; });
text(1, 'Click');
if (rf1 & RenderFlags.Update) {
containerRefreshStart(1);
{
if (ctx.sub1) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'button');
{
listener('click', function() { return ctx.counter1++; });
text(1, 'Click');
}
elementEnd();
}
embeddedViewEnd();
}
elementEnd();
}
embeddedViewEnd();
containerRefreshEnd();
containerRefreshStart(2);
{
if (ctx.sub2) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'button');
{
listener('click', function() { return ctx.counter2++; });
text(1, 'Click');
}
elementEnd();
}
embeddedViewEnd();
}
}
containerRefreshEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
const ctx = {condition: true, counter1: 0, counter2: 0, sub1: true, sub2: true};

View File

@ -10,7 +10,7 @@ import {EventEmitter} from '@angular/core';
import {defineComponent, defineDirective} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, listener, text} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {containerEl, renderToHtml} from './render_util';
describe('outputs', () => {
@ -25,7 +25,7 @@ describe('outputs', () => {
static ngComponentDef = defineComponent({
type: ButtonToggle,
selectors: [['button-toggle']],
template: function(ctx: any, cm: boolean) {},
template: function(rf: RenderFlags, ctx: any) {},
factory: () => buttonToggle = new ButtonToggle(),
outputs: {change: 'change', resetStream: 'reset'}
});
@ -51,7 +51,7 @@ describe('outputs', () => {
static ngComponentDef = defineComponent({
type: DestroyComp,
selectors: [['destroy-comp']],
template: function(ctx: any, cm: boolean) {},
template: function(rf: RenderFlags, ctx: any) {},
factory: () => destroyComp = new DestroyComp()
});
}
@ -73,8 +73,8 @@ describe('outputs', () => {
it('should call component output function when event is emitted', () => {
/** <button-toggle (change)="onChange()"></button-toggle> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button-toggle');
{
listener('change', function() { return ctx.onChange(); });
@ -96,8 +96,8 @@ describe('outputs', () => {
it('should support more than 1 output function on the same node', () => {
/** <button-toggle (change)="onChange()" (reset)="onReset()"></button-toggle> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button-toggle');
{
listener('change', function() { return ctx.onChange(); });
@ -121,8 +121,8 @@ describe('outputs', () => {
it('should eval component output expression when event is emitted', () => {
/** <button-toggle (change)="counter++"></button-toggle> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button-toggle');
{
listener('change', function() { return ctx.counter++; });
@ -149,24 +149,27 @@ describe('outputs', () => {
* % }
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
if (ctx.condition) {
if (embeddedViewStart(0)) {
elementStart(0, 'button-toggle');
{
listener('change', function() { return ctx.onChange(); });
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.condition) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'button-toggle');
{
listener('change', function() { return ctx.onChange(); });
}
elementEnd();
}
elementEnd();
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
let counter = 0;
@ -193,34 +196,38 @@ describe('outputs', () => {
* % }
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
if (ctx.condition) {
if (embeddedViewStart(0)) {
container(0);
}
containerRefreshStart(0);
{
if (ctx.condition2) {
if (embeddedViewStart(0)) {
elementStart(0, 'button-toggle');
{
listener('change', function() { return ctx.onChange(); });
}
elementEnd();
}
embeddedViewEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.condition) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
if (ctx.condition2) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'button-toggle');
{
listener('change', function() { return ctx.onChange(); });
}
elementEnd();
}
embeddedViewEnd();
}
}
containerRefreshEnd();
embeddedViewEnd();
}
containerRefreshEnd();
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
let counter = 0;
@ -245,32 +252,35 @@ describe('outputs', () => {
* <destroy-comp></destroy-comp>
* % }
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
if (ctx.condition) {
if (embeddedViewStart(0)) {
elementStart(0, 'button');
{
listener('click', function() { return ctx.onClick(); });
text(1, 'Click me');
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.condition) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'button');
{
listener('click', function() { return ctx.onClick(); });
text(1, 'Click me');
}
elementEnd();
elementStart(2, 'button-toggle');
{
listener('change', function() { return ctx.onChange(); });
}
elementEnd();
elementStart(3, 'destroy-comp');
elementEnd();
}
elementEnd();
elementStart(2, 'button-toggle');
{
listener('change', function() { return ctx.onChange(); });
}
elementEnd();
elementStart(3, 'destroy-comp');
elementEnd();
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
let clickCounter = 0;
@ -299,8 +309,8 @@ describe('outputs', () => {
});
it('should fire event listeners along with outputs if they match', () => {
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button', ['myButton', '']);
{
listener('click', function() { return ctx.onClick(); });
@ -324,8 +334,8 @@ describe('outputs', () => {
it('should work with two outputs of the same name', () => {
/** <button-toggle (change)="onChange()" otherDir></button-toggle> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button-toggle', ['otherDir', '']);
{
listener('change', function() { return ctx.onChange(); });
@ -359,15 +369,17 @@ describe('outputs', () => {
}
/** <button-toggle (change)="onChange()" otherChangeDir [change]="change"></button-toggle> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button-toggle', ['otherChangeDir', '']);
{
listener('change', function() { return ctx.onChange(); });
}
elementEnd();
}
elementProperty(0, 'change', bind(ctx.change));
if (rf & RenderFlags.Update) {
elementProperty(0, 'change', bind(ctx.change));
}
}
let counter = 0;
@ -392,8 +404,8 @@ describe('outputs', () => {
* 'changeStream']}
* % }
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button');
{
listener('click', function() { return ctx.onClick(); });
@ -402,29 +414,32 @@ describe('outputs', () => {
elementEnd();
container(2);
}
containerRefreshStart(2);
{
if (ctx.condition) {
if (embeddedViewStart(0)) {
elementStart(0, 'button-toggle');
{
listener('change', function() { return ctx.onChange(); });
if (rf & RenderFlags.Update) {
containerRefreshStart(2);
{
if (ctx.condition) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'button-toggle');
{
listener('change', function() { return ctx.onChange(); });
}
elementEnd();
}
elementEnd();
}
embeddedViewEnd();
} else {
if (embeddedViewStart(1)) {
elementStart(0, 'div', ['otherDir', '']);
{
listener('change', function() { return ctx.onChange(); });
embeddedViewEnd();
} else {
if (embeddedViewStart(1)) {
elementStart(0, 'div', ['otherDir', '']);
{
listener('change', function() { return ctx.onChange(); });
}
elementEnd();
}
elementEnd();
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
let counter = 0;

View File

@ -11,6 +11,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
import {defineDirective, definePipe} from '../../src/render3/definition';
import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, load, loadDirective, text, textBinding} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {pipe, pipeBind1, pipeBind3, pipeBind4, pipeBindV} from '../../src/render3/pipe';
import {RenderLog, getRendererFactory2, patchLoggingRenderer2} from './imported_renderer2';
@ -33,12 +34,14 @@ describe('pipe', () => {
const pipes = () => [CountingPipe, MultiArgPipe, CountingImpurePipe];
it('should support interpolation', () => {
function Template(person: Person, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, person: Person) {
if (rf & RenderFlags.Create) {
text(0);
pipe(1, 'countingPipe');
}
textBinding(0, interpolation1('', pipeBind1(1, person.name), ''));
if (rf & RenderFlags.Update) {
textBinding(0, interpolation1('', pipeBind1(1, person.name), ''));
}
}
person.init('bob', null);
@ -46,12 +49,14 @@ describe('pipe', () => {
});
it('should throw if pipe is not found', () => {
const App = createComponent('app', function(ctx: any, cm: boolean) {
if (cm) {
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
text(0);
pipe(1, 'randomPipeName');
}
textBinding(0, interpolation1('', pipeBind1(1, ctx.value), ''));
if (rf & RenderFlags.Update) {
textBinding(0, interpolation1('', pipeBind1(1, ctx.value), ''));
}
}, [], pipes);
expect(() => {
@ -87,27 +92,31 @@ describe('pipe', () => {
});
}
function Template(ctx: string, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: string) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['myDir', '']);
pipe(1, 'double');
elementEnd();
}
elementProperty(0, 'elprop', bind(pipeBind1(1, ctx)));
directive = loadDirective(0);
if (rf & RenderFlags.Update) {
elementProperty(0, 'elprop', bind(pipeBind1(1, ctx)));
directive = loadDirective(0);
}
}
renderToHtml(Template, 'a', [MyDir], [DoublePipe]);
expect(directive !.dirProp).toEqual('aa');
});
it('should support arguments in pipes', () => {
function Template(person: Person, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, person: Person) {
if (rf & RenderFlags.Create) {
text(0);
pipe(1, 'multiArgPipe');
}
textBinding(
0, interpolation1('', pipeBind3(1, person.name, 'one', person.address !.city), ''));
if (rf & RenderFlags.Update) {
textBinding(
0, interpolation1('', pipeBind3(1, person.name, 'one', person.address !.city), ''));
}
}
person.init('value', new Address('two'));
@ -115,14 +124,17 @@ describe('pipe', () => {
});
it('should support calling pipes with different number of arguments', () => {
function Template(person: Person, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, person: Person) {
if (rf & RenderFlags.Create) {
text(0);
pipe(1, 'multiArgPipe');
pipe(2, 'multiArgPipe');
}
textBinding(
0, interpolation1('', pipeBind4(2, pipeBindV(1, [person.name, 'a', 'b']), 0, 1, 2), ''));
if (rf & RenderFlags.Update) {
textBinding(
0,
interpolation1('', pipeBind4(2, pipeBindV(1, [person.name, 'a', 'b']), 0, 1, 2), ''));
}
}
person.init('value', null);
@ -141,13 +153,15 @@ describe('pipe', () => {
});
}
function Template(person: Person, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, person: Person) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
pipe(1, 'identityPipe');
elementEnd();
}
elementProperty(0, 'someProp', bind(pipeBind1(1, 'Megatron')));
if (rf & RenderFlags.Update) {
elementProperty(0, 'someProp', bind(pipeBind1(1, 'Megatron')));
}
}
renderToHtml(Template, person, null, [IdentityPipe], rendererFactory2);
@ -160,12 +174,14 @@ describe('pipe', () => {
describe('pure', () => {
it('should call pure pipes only if the arguments change', () => {
function Template(person: Person, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, person: Person) {
if (rf & RenderFlags.Create) {
text(0);
pipe(1, 'countingPipe');
}
textBinding(0, interpolation1('', pipeBind1(1, person.name), ''));
if (rf & RenderFlags.Update) {
textBinding(0, interpolation1('', pipeBind1(1, person.name), ''));
}
}
// change from undefined -> null
@ -187,12 +203,14 @@ describe('pipe', () => {
describe('impure', () => {
it('should call impure pipes on each change detection run', () => {
function Template(person: Person, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, person: Person) {
if (rf & RenderFlags.Create) {
text(0);
pipe(1, 'countingImpurePipe');
}
textBinding(0, interpolation1('', pipeBind1(1, person.name), ''));
if (rf & RenderFlags.Update) {
textBinding(0, interpolation1('', pipeBind1(1, person.name), ''));
}
}
person.name = 'bob';
@ -201,8 +219,8 @@ describe('pipe', () => {
});
it('should not cache impure pipes', () => {
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
pipe(1, 'countingImpurePipe');
elementEnd();
@ -211,26 +229,30 @@ describe('pipe', () => {
elementEnd();
container(4);
}
elementProperty(0, 'someProp', bind(pipeBind1(1, true)));
elementProperty(2, 'someProp', bind(pipeBind1(3, true)));
pipeInstances.push(load<CountingImpurePipe>(1), load(3));
containerRefreshStart(4);
{
for (let i of [1, 2]) {
let cm1 = embeddedViewStart(1);
{
if (cm1) {
elementStart(0, 'div');
pipe(1, 'countingImpurePipe');
elementEnd();
if (rf & RenderFlags.Update) {
elementProperty(0, 'someProp', bind(pipeBind1(1, true)));
elementProperty(2, 'someProp', bind(pipeBind1(3, true)));
pipeInstances.push(load<CountingImpurePipe>(1), load(3));
containerRefreshStart(4);
{
for (let i of [1, 2]) {
let rf1 = embeddedViewStart(1);
{
if (rf1 & RenderFlags.Create) {
elementStart(0, 'div');
pipe(1, 'countingImpurePipe');
elementEnd();
}
if (rf1 & RenderFlags.Update) {
elementProperty(0, 'someProp', bind(pipeBind1(1, true)));
pipeInstances.push(load<CountingImpurePipe>(1));
}
}
elementProperty(0, 'someProp', bind(pipeBind1(1, true)));
pipeInstances.push(load<CountingImpurePipe>(1));
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
const pipeInstances: CountingImpurePipe[] = [];
@ -261,25 +283,29 @@ describe('pipe', () => {
}
it('should call ngOnDestroy on pipes', () => {
function Template(person: Person, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, person: Person) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
if (person.age > 20) {
let cm1 = embeddedViewStart(1);
{
if (cm1) {
text(0);
pipe(1, 'pipeWithOnDestroy');
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (person.age > 20) {
let rf1 = embeddedViewStart(1);
{
if (rf1 & RenderFlags.Create) {
text(0);
pipe(1, 'pipeWithOnDestroy');
}
if (rf & RenderFlags.Update) {
textBinding(0, interpolation1('', pipeBind1(1, person.age), ''));
}
}
textBinding(0, interpolation1('', pipeBind1(1, person.age), ''));
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
const pipes = [PipeWithOnDestroy];

View File

@ -10,18 +10,20 @@ import {EventEmitter} from '@angular/core';
import {defineComponent, defineDirective, tick} from '../../src/render3/index';
import {NO_CHANGE, bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, listener, load, loadDirective, text, textBinding} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {ComponentFixture, renderToHtml} from './render_util';
describe('elementProperty', () => {
it('should support bindings to properties', () => {
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span');
elementEnd();
}
elementProperty(0, 'id', bind(ctx));
if (rf & RenderFlags.Update) {
elementProperty(0, 'id', bind(ctx));
}
}
expect(renderToHtml(Template, 'testId')).toEqual('<span id="testId"></span>');
@ -37,12 +39,14 @@ describe('elementProperty', () => {
}
}
function Template(ctx: string, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: string) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span');
elementEnd();
}
elementProperty(0, 'id', cm ? expensive(ctx) : NO_CHANGE);
if (rf & RenderFlags.Update) {
elementProperty(0, 'id', rf & RenderFlags.Create ? expensive(ctx) : NO_CHANGE);
}
}
expect(renderToHtml(Template, 'cheapId')).toEqual('<span id="cheapId"></span>');
@ -50,12 +54,14 @@ describe('elementProperty', () => {
});
it('should support interpolation for properties', () => {
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span');
elementEnd();
}
elementProperty(0, 'id', interpolation1('_', ctx, '_'));
if (rf & RenderFlags.Update) {
elementProperty(0, 'id', interpolation1('_', ctx, '_'));
}
}
expect(renderToHtml(Template, 'testId')).toEqual('<span id="_testId_"></span>');
@ -74,7 +80,7 @@ describe('elementProperty', () => {
const instance = loadDirective(dirIndex) as HostBindingComp;
elementProperty(elIndex, 'id', bind(instance.id));
},
template: (ctx: HostBindingComp, cm: boolean) => {}
template: (rf: RenderFlags, ctx: HostBindingComp) => {}
});
}
@ -144,15 +150,16 @@ describe('elementProperty', () => {
it('should check input properties before setting (directives)', () => {
/** <button myButton otherDir [id]="id" [disabled]="isDisabled">Click me</button> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button', ['otherDir', '', 'myButton', '']);
{ text(1, 'Click me'); }
elementEnd();
}
elementProperty(0, 'disabled', bind(ctx.isDisabled));
elementProperty(0, 'id', bind(ctx.id));
if (rf & RenderFlags.Update) {
elementProperty(0, 'disabled', bind(ctx.isDisabled));
elementProperty(0, 'id', bind(ctx.id));
}
}
const ctx: any = {isDisabled: true, id: 0};
@ -172,15 +179,16 @@ describe('elementProperty', () => {
it('should support mixed element properties and input properties', () => {
/** <button myButton [id]="id" [disabled]="isDisabled">Click me</button> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button', ['myButton', '']);
{ text(1, 'Click me'); }
elementEnd();
}
elementProperty(0, 'disabled', bind(ctx.isDisabled));
elementProperty(0, 'id', bind(ctx.id));
if (rf & RenderFlags.Update) {
elementProperty(0, 'disabled', bind(ctx.isDisabled));
elementProperty(0, 'id', bind(ctx.id));
}
}
const ctx: any = {isDisabled: true, id: 0};
@ -205,19 +213,21 @@ describe('elementProperty', () => {
static ngComponentDef = defineComponent({
type: Comp,
selectors: [['comp']],
template: function(ctx: any, cm: boolean) {},
template: function(rf: RenderFlags, ctx: any) {},
factory: () => comp = new Comp(),
inputs: {id: 'id'}
});
}
/** <comp [id]="id"></comp> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'comp');
elementEnd();
}
elementProperty(0, 'id', bind(ctx.id));
if (rf & RenderFlags.Update) {
elementProperty(0, 'id', bind(ctx.id));
}
}
const deps = [Comp];
@ -231,13 +241,15 @@ describe('elementProperty', () => {
it('should support two input properties with the same name', () => {
/** <button myButton otherDisabledDir [disabled]="isDisabled">Click me</button> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button', ['myButton', '', 'otherDisabledDir', '']);
{ text(1, 'Click me'); }
elementEnd();
}
elementProperty(0, 'disabled', bind(ctx.isDisabled));
if (rf & RenderFlags.Update) {
elementProperty(0, 'disabled', bind(ctx.isDisabled));
}
}
const ctx: any = {isDisabled: true};
@ -255,8 +267,8 @@ describe('elementProperty', () => {
it('should set input property if there is an output first', () => {
/** <button otherDir [id]="id" (click)="onClick()">Click me</button> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button', ['otherDir', '']);
{
listener('click', ctx.onClick.bind(ctx));
@ -264,7 +276,9 @@ describe('elementProperty', () => {
}
elementEnd();
}
elementProperty(0, 'id', bind(ctx.id));
if (rf & RenderFlags.Update) {
elementProperty(0, 'id', bind(ctx.id));
}
}
let counter = 0;
@ -289,35 +303,43 @@ describe('elementProperty', () => {
* <button otherDir [id]="id3">Click me too</button> // inputs: {'id': [0, 'id']}
* % }
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'button', ['idDir', '']);
{ text(1, 'Click me'); }
elementEnd();
container(2);
}
elementProperty(0, 'id', bind(ctx.id1));
containerRefreshStart(2);
{
if (ctx.condition) {
if (embeddedViewStart(0)) {
elementStart(0, 'button');
{ text(1, 'Click me too'); }
elementEnd();
if (rf & RenderFlags.Update) {
elementProperty(0, 'id', bind(ctx.id1));
containerRefreshStart(2);
{
if (ctx.condition) {
let rf0 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
elementStart(0, 'button');
{ text(1, 'Click me too'); }
elementEnd();
}
if (rf0 & RenderFlags.Update) {
elementProperty(0, 'id', bind(ctx.id2));
}
embeddedViewEnd();
} else {
let rf1 = embeddedViewStart(1);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'button', ['otherDir', '']);
{ text(1, 'Click me too'); }
elementEnd();
}
if (rf1 & RenderFlags.Update) {
elementProperty(0, 'id', bind(ctx.id3));
}
embeddedViewEnd();
}
elementProperty(0, 'id', bind(ctx.id2));
embeddedViewEnd();
} else {
if (embeddedViewStart(1)) {
elementStart(0, 'button', ['otherDir', '']);
{ text(1, 'Click me too'); }
elementEnd();
}
elementProperty(0, 'id', bind(ctx.id3));
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
expect(renderToHtml(Template, {condition: true, id1: 'one', id2: 'two', id3: 'three'}, deps))
@ -367,8 +389,8 @@ describe('elementProperty', () => {
it('should set input property based on attribute if existing', () => {
/** <div role="button" myDir></div> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['role', 'button', 'myDir', '']);
elementEnd();
}
@ -381,12 +403,14 @@ describe('elementProperty', () => {
it('should set input property and attribute if both defined', () => {
/** <div role="button" [role]="role" myDir></div> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['role', 'button', 'myDir', '']);
elementEnd();
}
elementProperty(0, 'role', bind(ctx.role));
if (rf & RenderFlags.Update) {
elementProperty(0, 'role', bind(ctx.role));
}
}
expect(renderToHtml(Template, {role: 'listbox'}, deps))
@ -400,8 +424,8 @@ describe('elementProperty', () => {
it('should set two directive input properties based on same attribute', () => {
/** <div role="button" myDir myDirB></div> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['role', 'button', 'myDir', '', 'myDirB', '']);
elementEnd();
}
@ -416,8 +440,8 @@ describe('elementProperty', () => {
it('should process two attributes on same directive', () => {
/** <div role="button" dir="rtl" myDir></div> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['role', 'button', 'dir', 'rtl', 'myDir', '']);
elementEnd();
}
@ -432,8 +456,8 @@ describe('elementProperty', () => {
it('should process attributes and outputs properly together', () => {
/** <div role="button" (change)="onChange()" myDir></div> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['role', 'button', 'myDir', '']);
{ listener('change', ctx.onChange.bind(ctx)); }
elementEnd();
@ -455,8 +479,8 @@ describe('elementProperty', () => {
* <div role="button" dir="rtl" myDir></div>
* <div role="listbox" myDirB></div>
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['role', 'button', 'dir', 'rtl', 'myDir', '']);
elementEnd();
elementStart(1, 'div', ['role', 'listbox', 'myDirB', '']);
@ -482,30 +506,33 @@ describe('elementProperty', () => {
* <div role="menu"></div> // initialInputs: [null]
* % }
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['role', 'listbox', 'myDir', '']);
elementEnd();
container(1);
}
containerRefreshStart(1);
{
if (ctx.condition) {
if (embeddedViewStart(0)) {
elementStart(0, 'div', ['role', 'button', 'myDirB', '']);
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
if (ctx.condition) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'div', ['role', 'button', 'myDirB', '']);
elementEnd();
}
embeddedViewEnd();
} else {
let rf2 = embeddedViewStart(1);
if (rf2 & RenderFlags.Create) {
elementStart(0, 'div', ['role', 'menu']);
elementEnd();
}
embeddedViewEnd();
}
embeddedViewEnd();
} else {
if (embeddedViewStart(1)) {
elementStart(0, 'div', ['role', 'menu']);
{}
elementEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
expect(renderToHtml(Template, {condition: true}, deps))
@ -526,14 +553,16 @@ describe('elementProperty', () => {
type: Comp,
selectors: [['comp']],
/** <div role="button" dir #dir="myDir"></div> {{ dir.role }} */
template: function(ctx: any, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['role', 'button', 'myDir', ''], ['dir', 'myDir']);
elementEnd();
text(2);
}
const tmp = load(1) as any;
textBinding(2, bind(tmp.role));
if (rf & RenderFlags.Update) {
const tmp = load(1) as any;
textBinding(2, bind(tmp.role));
}
},
factory: () => new Comp(),
directives: () => [MyDir]
@ -545,21 +574,24 @@ describe('elementProperty', () => {
* <comp></comp>
* % }
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
for (let i = 0; i < 2; i++) {
if (embeddedViewStart(0)) {
elementStart(0, 'comp');
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
for (let i = 0; i < 2; i++) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'comp');
elementEnd();
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
expect(renderToHtml(Template, {}, [Comp]))

View File

@ -7,6 +7,7 @@
*/
import {defineComponent} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, load, loadDirective} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {pureFunction1, pureFunction2, pureFunction3, pureFunction4, pureFunction5, pureFunction6, pureFunction7, pureFunction8, pureFunctionV} from '../../src/render3/pure_function';
import {renderToHtml} from '../../test/render3/render_util';
@ -20,7 +21,7 @@ describe('array literals', () => {
type: MyComp,
selectors: [['my-comp']],
factory: function MyComp_Factory() { return myComp = new MyComp(); },
template: function MyComp_Template(ctx: MyComp, cm: boolean) {},
template: function MyComp_Template(rf: RenderFlags, ctx: MyComp) {},
inputs: {names: 'names'}
});
}
@ -31,12 +32,14 @@ describe('array literals', () => {
const e0_ff = (v: any) => ['Nancy', v, 'Bess'];
/** <my-comp [names]="['Nancy', customName, 'Bess']"></my-comp> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'my-comp');
elementEnd();
}
elementProperty(0, 'names', bind(pureFunction1(e0_ff, ctx.customName)));
if (rf & RenderFlags.Update) {
elementProperty(0, 'names', bind(pureFunction1(e0_ff, ctx.customName)));
}
}
renderToHtml(Template, {customName: 'Carson'}, directives);
@ -71,7 +74,7 @@ describe('array literals', () => {
type: ManyPropComp,
selectors: [['many-prop-comp']],
factory: function ManyPropComp_Factory() { return manyPropComp = new ManyPropComp(); },
template: function ManyPropComp_Template(ctx: ManyPropComp, cm: boolean) {},
template: function ManyPropComp_Template(rf: RenderFlags, ctx: ManyPropComp) {},
inputs: {names1: 'names1', names2: 'names2'}
});
}
@ -83,13 +86,15 @@ describe('array literals', () => {
* <many-prop-comp [names1]="['Nancy', customName]" [names2]="[customName2]">
* </many-prop-comp>
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'many-prop-comp');
elementEnd();
}
elementProperty(0, 'names1', bind(pureFunction1(e0_ff, ctx.customName)));
elementProperty(0, 'names2', bind(pureFunction1(e0_ff_1, ctx.customName2)));
if (rf & RenderFlags.Update) {
elementProperty(0, 'names1', bind(pureFunction1(e0_ff, ctx.customName)));
elementProperty(0, 'names2', bind(pureFunction1(e0_ff_1, ctx.customName2)));
}
}
const defs = [ManyPropComp];
@ -120,20 +125,22 @@ describe('array literals', () => {
type: ParentComp,
selectors: [['parent-comp']],
factory: () => new ParentComp(),
template: function(ctx: any, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'my-comp');
myComps.push(loadDirective(0));
elementEnd();
}
elementProperty(0, 'names', bind(ctx.someFn(pureFunction1(e0_ff, ctx.customName))));
if (rf & RenderFlags.Update) {
elementProperty(0, 'names', bind(ctx.someFn(pureFunction1(e0_ff, ctx.customName))));
}
},
directives: directives
});
}
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'parent-comp');
elementEnd();
elementStart(1, 'parent-comp');
@ -159,12 +166,14 @@ describe('array literals', () => {
const e0_ff = (v1: any, v2: any) => ['Nancy', v1, 'Bess', v2];
/** <my-comp [names]="['Nancy', customName, 'Bess', customName2]"></my-comp> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'my-comp');
elementEnd();
}
elementProperty(0, 'names', bind(pureFunction2(e0_ff, ctx.customName, ctx.customName2)));
if (rf & RenderFlags.Update) {
elementProperty(0, 'names', bind(pureFunction2(e0_ff, ctx.customName, ctx.customName2)));
}
}
renderToHtml(Template, {customName: 'Carson', customName2: 'Hannah'}, directives);
@ -212,8 +221,8 @@ describe('array literals', () => {
(v1: any, v2: any, v3: any, v4: any, v5: any, v6: any, v7: any,
v8: any) => [v1, v2, v3, v4, v5, v6, v7, v8];
function Template(c: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, c: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'my-comp');
f3Comp = loadDirective(0);
elementEnd();
@ -233,14 +242,17 @@ describe('array literals', () => {
f8Comp = loadDirective(5);
elementEnd();
}
elementProperty(0, 'names', bind(pureFunction3(e0_ff, c[5], c[6], c[7])));
elementProperty(1, 'names', bind(pureFunction4(e2_ff, c[4], c[5], c[6], c[7])));
elementProperty(2, 'names', bind(pureFunction5(e4_ff, c[3], c[4], c[5], c[6], c[7])));
elementProperty(3, 'names', bind(pureFunction6(e6_ff, c[2], c[3], c[4], c[5], c[6], c[7])));
elementProperty(
4, 'names', bind(pureFunction7(e8_ff, c[1], c[2], c[3], c[4], c[5], c[6], c[7])));
elementProperty(
5, 'names', bind(pureFunction8(e10_ff, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7])));
if (rf & RenderFlags.Update) {
elementProperty(0, 'names', bind(pureFunction3(e0_ff, c[5], c[6], c[7])));
elementProperty(1, 'names', bind(pureFunction4(e2_ff, c[4], c[5], c[6], c[7])));
elementProperty(2, 'names', bind(pureFunction5(e4_ff, c[3], c[4], c[5], c[6], c[7])));
elementProperty(3, 'names', bind(pureFunction6(e6_ff, c[2], c[3], c[4], c[5], c[6], c[7])));
elementProperty(
4, 'names', bind(pureFunction7(e8_ff, c[1], c[2], c[3], c[4], c[5], c[6], c[7])));
elementProperty(
5, 'names',
bind(pureFunction8(e10_ff, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7])));
}
}
renderToHtml(Template, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], directives);
@ -279,14 +291,17 @@ describe('array literals', () => {
* <my-comp [names]="['start', v0, v1, v2, v3, {name: v4}, v5, v6, v7, v8, 'end']">
* </my-comp>
*/
function Template(c: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, c: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'my-comp');
elementEnd();
}
elementProperty(0, 'names', bind(pureFunctionV(e0_ff, [
c[0], c[1], c[2], c[3], pureFunction1(e0_ff_1, c[4]), c[5], c[6], c[7], c[8]
])));
if (rf & RenderFlags.Update) {
elementProperty(
0, 'names', bind(pureFunctionV(e0_ff, [
c[0], c[1], c[2], c[3], pureFunction1(e0_ff_1, c[4]), c[5], c[6], c[7], c[8]
])));
}
}
expect(myComp !.names).toEqual([
@ -315,7 +330,7 @@ describe('object literals', () => {
type: ObjectComp,
selectors: [['object-comp']],
factory: function ObjectComp_Factory() { return objectComp = new ObjectComp(); },
template: function ObjectComp_Template(ctx: ObjectComp, cm: boolean) {},
template: function ObjectComp_Template(rf: RenderFlags, ctx: ObjectComp) {},
inputs: {config: 'config'}
});
}
@ -326,12 +341,14 @@ describe('object literals', () => {
const e0_ff = (v: any) => { return {duration: 500, animation: v}; };
/** <object-comp [config]="{duration: 500, animation: name}"></object-comp> */
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'object-comp');
elementEnd();
}
elementProperty(0, 'config', bind(pureFunction1(e0_ff, ctx.name)));
if (rf & RenderFlags.Update) {
elementProperty(0, 'config', bind(pureFunction1(e0_ff, ctx.name)));
}
}
renderToHtml(Template, {name: 'slide'}, defs);
@ -359,15 +376,17 @@ describe('object literals', () => {
* duration: duration }]}">
* </object-comp>
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'object-comp');
elementEnd();
}
elementProperty(
0, 'config',
bind(pureFunction2(
e0_ff, ctx.name, pureFunction1(e0_ff_1, pureFunction1(e0_ff_2, ctx.duration)))));
if (rf & RenderFlags.Update) {
elementProperty(
0, 'config',
bind(pureFunction2(
e0_ff, ctx.name, pureFunction1(e0_ff_1, pureFunction1(e0_ff_2, ctx.duration)))));
}
}
renderToHtml(Template, {name: 'slide', duration: 100}, defs);
@ -419,25 +438,30 @@ describe('object literals', () => {
* </object-comp>
* % }
*/
function Template(ctx: any, cm: boolean) {
if (cm) {
function Template(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0);
}
containerRefreshStart(0);
{
for (let i = 0; i < 2; i++) {
if (embeddedViewStart(0)) {
elementStart(0, 'object-comp');
objectComps.push(loadDirective(0));
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
for (let i = 0; i < 2; i++) {
let rf1 = embeddedViewStart(0);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'object-comp');
objectComps.push(loadDirective(0));
elementEnd();
}
if (rf1 & RenderFlags.Update) {
elementProperty(
0, 'config',
bind(pureFunction2(e0_ff, ctx.configs[i].opacity, ctx.configs[i].duration)));
}
embeddedViewEnd();
}
elementProperty(
0, 'config',
bind(pureFunction2(e0_ff, ctx.configs[i].opacity, ctx.configs[i].duration)));
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
}
const e0_ff = (v1: any, v2: any) => { return {opacity: v1, duration: v2}; };

View File

@ -8,6 +8,7 @@
import {QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF} from '../../src/render3/di';
import {QueryList, defineComponent, detectChanges} from '../../src/render3/index';
import {container, containerRefreshEnd, containerRefreshStart, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, load, loadDirective} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {query, queryRefresh} from '../../src/render3/query';
import {createComponent, createDirective, renderComponent} from './render_util';
@ -43,11 +44,11 @@ function isViewContainerRef(candidate: any): boolean {
describe('query', () => {
it('should project query children', () => {
const Child = createComponent('child', function(ctx: any, cm: boolean) {});
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {});
let child1 = null;
let child2 = null;
const Cmp = createComponent('cmp', function(ctx: any, cm: boolean) {
const Cmp = createComponent('cmp', function(rf: RenderFlags, ctx: any) {
/**
* <child>
* <child>
@ -59,7 +60,7 @@ describe('query', () => {
* }
*/
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, Child, false);
query(1, Child, true);
elementStart(2, 'child');
@ -71,8 +72,10 @@ describe('query', () => {
}
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query0 = tmp as QueryList<any>);
queryRefresh(tmp = load<QueryList<any>>(1)) && (ctx.query1 = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query0 = tmp as QueryList<any>);
queryRefresh(tmp = load<QueryList<any>>(1)) && (ctx.query1 = tmp as QueryList<any>);
}
}, [Child]);
const parent = renderComponent(Cmp);
@ -91,14 +94,16 @@ describe('query', () => {
* @ViewChildren(Child, {read: ElementRef}) query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, Child, false, QUERY_READ_ELEMENT_REF);
elToQuery = elementStart(1, 'div', ['child', '']);
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
@ -119,15 +124,17 @@ describe('query', () => {
* @ViewChildren(Child, {read: OtherChild}) query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, Child, false, OtherChild);
elementStart(1, 'div', ['child', '', 'otherChild', '']);
{ otherChildInstance = loadDirective(1); }
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
}, [Child, OtherChild]);
const cmptInstance = renderComponent(Cmpt);
@ -145,14 +152,16 @@ describe('query', () => {
* @ViewChildren(Child, {read: OtherChild}) query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, Child, false, OtherChild);
elementStart(1, 'div', ['child', '']);
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
}, [Child, OtherChild]);
const cmptInstance = renderComponent(Cmpt);
@ -173,16 +182,18 @@ describe('query', () => {
* @ViewChildren('foo') query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_FROM_NODE);
elToQuery = elementStart(1, 'div', null, ['foo', '']);
elementEnd();
elementStart(3, 'div');
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
});
const cmptInstance = renderComponent(Cmpt);
@ -202,9 +213,9 @@ describe('query', () => {
* @ViewChildren('bar') barQuery;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_FROM_NODE);
query(1, ['bar'], false, QUERY_READ_FROM_NODE);
elToQuery = elementStart(2, 'div', null, ['foo', '', 'bar', '']);
@ -212,8 +223,10 @@ describe('query', () => {
elementStart(5, 'div');
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.fooQuery = tmp as QueryList<any>);
queryRefresh(tmp = load<QueryList<any>>(1)) && (ctx.barQuery = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.fooQuery = tmp as QueryList<any>);
queryRefresh(tmp = load<QueryList<any>>(1)) && (ctx.barQuery = tmp as QueryList<any>);
}
});
const cmptInstance = renderComponent(Cmpt);
@ -239,9 +252,9 @@ describe('query', () => {
* @ViewChildren('foo,bar') query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE);
el1ToQuery = elementStart(1, 'div', null, ['foo', '']);
elementEnd();
@ -250,7 +263,9 @@ describe('query', () => {
el2ToQuery = elementStart(4, 'div', null, ['bar', '']);
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
});
const cmptInstance = renderComponent(Cmpt);
@ -270,16 +285,18 @@ describe('query', () => {
* @ViewChildren('foo', {read: ElementRef}) query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF);
elToQuery = elementStart(1, 'div', null, ['foo', '']);
elementEnd();
elementStart(3, 'div');
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
});
const cmptInstance = renderComponent(Cmpt);
@ -296,14 +313,16 @@ describe('query', () => {
* @ViewChildren('foo', {read: ViewContainerRef}) query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_CONTAINER_REF);
elementStart(1, 'div', null, ['foo', '']);
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
});
const cmptInstance = renderComponent(Cmpt);
@ -319,13 +338,15 @@ describe('query', () => {
* @ViewChildren('foo', {read: ViewContainerRef}) query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_CONTAINER_REF);
container(1, undefined, undefined, undefined, ['foo', '']);
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
});
const cmptInstance = renderComponent(Cmpt);
@ -342,13 +363,15 @@ describe('query', () => {
* @ViewChildren('foo', {read: ElementRef}) query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF);
container(1, undefined, undefined, undefined, ['foo', '']);
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
});
const cmptInstance = renderComponent(Cmpt);
@ -365,13 +388,15 @@ describe('query', () => {
* @ViewChildren('foo') query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], undefined, QUERY_READ_FROM_NODE);
container(1, undefined, undefined, undefined, ['foo', '']);
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
});
const cmptInstance = renderComponent(Cmpt);
@ -388,13 +413,15 @@ describe('query', () => {
* @ViewChildren('foo', {read: TemplateRef}) query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_TEMPLATE_REF);
container(1, undefined, undefined, undefined, ['foo', '']);
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
});
const cmptInstance = renderComponent(Cmpt);
@ -404,7 +431,7 @@ describe('query', () => {
});
it('should read component instance if element queried for is a component host', () => {
const Child = createComponent('child', function(ctx: any, cm: boolean) {});
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {});
let childInstance;
/**
@ -413,15 +440,17 @@ describe('query', () => {
* @ViewChildren('foo') query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
elementStart(1, 'child', null, ['foo', '']);
{ childInstance = loadDirective(0); }
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
@ -438,7 +467,7 @@ describe('query', () => {
type: Child,
selectors: [['child']],
factory: () => childInstance = new Child(),
template: (ctx: Child, cm: boolean) => {},
template: (rf: RenderFlags, ctx: Child) => {},
exportAs: 'child'
});
}
@ -449,14 +478,16 @@ describe('query', () => {
* @ViewChildren('foo') query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
elementStart(1, 'child', null, ['foo', 'child']);
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
@ -476,15 +507,17 @@ describe('query', () => {
* @ViewChildren('foo') query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
elementStart(1, 'div', ['child', ''], ['foo', 'child']);
childInstance = loadDirective(0);
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
@ -504,9 +537,9 @@ describe('query', () => {
* @ViewChildren('foo, bar') query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo', 'bar'], true, QUERY_READ_FROM_NODE);
elementStart(1, 'div', ['child1', '', 'child2', ''], ['foo', 'child1', 'bar', 'child2']);
{
@ -515,7 +548,9 @@ describe('query', () => {
}
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
}, [Child1, Child2]);
const cmptInstance = renderComponent(Cmpt);
@ -536,17 +571,19 @@ describe('query', () => {
* @ViewChildren('bar') barQuery;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(1, ['bar'], true, QUERY_READ_FROM_NODE);
elementStart(2, 'div', ['child', ''], ['foo', 'child', 'bar', 'child']);
{ childInstance = loadDirective(0); }
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.fooQuery = tmp as QueryList<any>);
queryRefresh(tmp = load<QueryList<any>>(1)) && (ctx.barQuery = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.fooQuery = tmp as QueryList<any>);
queryRefresh(tmp = load<QueryList<any>>(1)) && (ctx.barQuery = tmp as QueryList<any>);
}
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
@ -570,14 +607,16 @@ describe('query', () => {
* @ViewChildren('foo', {read: ElementRef}) query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], undefined, QUERY_READ_ELEMENT_REF);
div = elementStart(1, 'div', ['child', ''], ['foo', 'child']);
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
@ -596,15 +635,17 @@ describe('query', () => {
* @ViewChildren('foo, bar') query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE);
div = elementStart(1, 'div', ['child', ''], ['foo', '', 'bar', 'child']);
{ childInstance = loadDirective(0); }
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
@ -623,14 +664,16 @@ describe('query', () => {
* @ViewChildren('foo', {read: Child}) query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], false, Child);
elementStart(1, 'div', ['foo', '']);
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
@ -652,27 +695,29 @@ describe('query', () => {
* @ViewChildren('foo') query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
container(1);
}
containerRefreshStart(1);
{
if (ctx.exp) {
let cm1 = embeddedViewStart(1);
{
if (cm1) {
firstEl = elementStart(0, 'div', null, ['foo', '']);
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
if (ctx.exp) {
let rf1 = embeddedViewStart(1);
{
if (rf1 & RenderFlags.Create) {
firstEl = elementStart(0, 'div', null, ['foo', '']);
elementEnd();
}
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
containerRefreshEnd();
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
});
const cmptInstance = renderComponent(Cmpt);
@ -702,9 +747,9 @@ describe('query', () => {
* @ViewChildren('foo') query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
firstEl = elementStart(1, 'span', null, ['foo', '']);
elementEnd();
@ -712,21 +757,23 @@ describe('query', () => {
lastEl = elementStart(4, 'span', null, ['foo', '']);
elementEnd();
}
containerRefreshStart(3);
{
if (ctx.exp) {
let cm1 = embeddedViewStart(1);
{
if (cm1) {
viewEl = elementStart(0, 'div', null, ['foo', '']);
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(3);
{
if (ctx.exp) {
let rf1 = embeddedViewStart(1);
{
if (rf1 & RenderFlags.Create) {
viewEl = elementStart(0, 'div', null, ['foo', '']);
elementEnd();
}
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
containerRefreshEnd();
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
});
const cmptInstance = renderComponent(Cmpt);
@ -762,37 +809,39 @@ describe('query', () => {
* @ViewChildren('foo') query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
container(1);
}
containerRefreshStart(1);
{
if (ctx.exp1) {
let cm1 = embeddedViewStart(0);
{
if (cm1) {
firstEl = elementStart(0, 'div', null, ['foo', '']);
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
if (ctx.exp1) {
let rf0 = embeddedViewStart(0);
{
if (rf0 & RenderFlags.Create) {
firstEl = elementStart(0, 'div', null, ['foo', '']);
elementEnd();
}
}
embeddedViewEnd();
}
embeddedViewEnd();
}
if (ctx.exp2) {
let cm1 = embeddedViewStart(1);
{
if (cm1) {
lastEl = elementStart(0, 'span', null, ['foo', '']);
elementEnd();
if (ctx.exp2) {
let rf1 = embeddedViewStart(1);
{
if (rf1 & RenderFlags.Create) {
lastEl = elementStart(0, 'span', null, ['foo', '']);
elementEnd();
}
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
containerRefreshEnd();
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
});
const cmptInstance = renderComponent(Cmpt);
@ -824,42 +873,46 @@ describe('query', () => {
* @ViewChildren('foo') query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
container(1);
}
containerRefreshStart(1);
{
if (ctx.exp1) {
let cm1 = embeddedViewStart(0);
{
if (cm1) {
firstEl = elementStart(0, 'div', null, ['foo', '']);
elementEnd();
container(2);
}
containerRefreshStart(2);
if (rf & RenderFlags.Update) {
containerRefreshStart(1);
{
if (ctx.exp1) {
let rf0 = embeddedViewStart(0);
{
if (ctx.exp2) {
let cm2 = embeddedViewStart(0);
if (rf0 & RenderFlags.Create) {
firstEl = elementStart(0, 'div', null, ['foo', '']);
elementEnd();
container(2);
}
if (rf0 & RenderFlags.Update) {
containerRefreshStart(2);
{
if (cm2) {
lastEl = elementStart(0, 'span', null, ['foo', '']);
elementEnd();
if (ctx.exp2) {
let rf2 = embeddedViewStart(0);
{
if (rf2) {
lastEl = elementStart(0, 'span', null, ['foo', '']);
elementEnd();
}
}
embeddedViewEnd();
}
}
embeddedViewEnd();
containerRefreshEnd();
}
}
containerRefreshEnd();
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
containerRefreshEnd();
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
});
const cmptInstance = renderComponent(Cmpt);
@ -888,31 +941,33 @@ describe('query', () => {
* @ViewChildren('foo') query;
* }
*/
const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) {
const Cmpt = createComponent('cmpt', function(rf: RenderFlags, ctx: any) {
let tmp: any;
if (cm) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(1, ['foo'], false, QUERY_READ_FROM_NODE);
container(2);
elementStart(3, 'span', null, ['foo', '']);
elementEnd();
}
containerRefreshStart(2);
{
if (ctx.exp) {
let cm1 = embeddedViewStart(0);
{
if (cm1) {
elementStart(0, 'div', null, ['foo', '']);
elementEnd();
if (rf & RenderFlags.Update) {
containerRefreshStart(2);
{
if (ctx.exp) {
let rf0 = embeddedViewStart(0);
{
if (rf0 & RenderFlags.Create) {
elementStart(0, 'div', null, ['foo', '']);
elementEnd();
}
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.deep = tmp as QueryList<any>);
queryRefresh(tmp = load<QueryList<any>>(1)) && (ctx.shallow = tmp as QueryList<any>);
}
containerRefreshEnd();
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.deep = tmp as QueryList<any>);
queryRefresh(tmp = load<QueryList<any>>(1)) && (ctx.shallow = tmp as QueryList<any>);
});
const cmptInstance = renderComponent(Cmpt);

View File

@ -10,7 +10,7 @@ import {stringifyElement} from '@angular/platform-browser/testing/src/browser_ut
import {CreateComponentOptions} from '../../src/render3/component';
import {extractDirectiveDef, extractPipeDef} from '../../src/render3/definition';
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveType, PublicFeature, defineComponent, defineDirective, renderComponent as _renderComponent, tick} from '../../src/render3/index';
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveType, PublicFeature, RenderFlags, defineComponent, defineDirective, renderComponent as _renderComponent, tick} from '../../src/render3/index';
import {NG_HOST_SYMBOL, renderTemplate} from '../../src/render3/instructions';
import {DirectiveDefList, DirectiveDefListOrFactory, DirectiveTypesOrFactory, PipeDef, PipeDefList, PipeDefListOrFactory, PipeTypesOrFactory} from '../../src/render3/interfaces/definition';
import {LElementNode} from '../../src/render3/interfaces/node';
@ -63,11 +63,13 @@ export class TemplateFixture extends BaseFixture {
super();
this._directiveDefs = toDefs(directives, extractDirectiveDef);
this._pipeDefs = toDefs(pipes, extractPipeDef);
this.hostNode = renderTemplate(this.hostElement, (ctx: any, cm: boolean) => {
if (cm) {
this.hostNode = renderTemplate(this.hostElement, (rf: RenderFlags, ctx: any) => {
if (rf & RenderFlags.Create) {
this.createBlock();
}
this.updateBlock();
if (rf & RenderFlags.Update) {
this.updateBlock();
}
}, null !, domRendererFactory3, null, this._directiveDefs, this._pipeDefs);
}

View File

@ -12,6 +12,7 @@ import {MockAnimationDriver, MockAnimationPlayer} from '@angular/animations/brow
import {RendererType2, ViewEncapsulation} from '../../src/core';
import {defineComponent, detectChanges} from '../../src/render3/index';
import {bind, elementEnd, elementProperty, elementStart, listener, text, tick} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {createRendererType2} from '../../src/view/index';
import {getAnimationRendererFactory2, getRendererFactory2} from './imported_renderer2';
@ -32,9 +33,9 @@ describe('renderer factory lifecycle', () => {
static ngComponentDef = defineComponent({
type: SomeComponent,
selectors: [['some-component']],
template: function(ctx: SomeComponent, cm: boolean) {
template: function(rf: RenderFlags, ctx: SomeComponent) {
logs.push('component');
if (cm) {
if (rf & RenderFlags.Create) {
text(0, 'foo');
}
},
@ -46,25 +47,25 @@ describe('renderer factory lifecycle', () => {
static ngComponentDef = defineComponent({
type: SomeComponentWhichThrows,
selectors: [['some-component-with-Error']],
template: function(ctx: SomeComponentWhichThrows, cm: boolean) {
template: function(rf: RenderFlags, ctx: SomeComponentWhichThrows) {
throw(new Error('SomeComponentWhichThrows threw'));
},
factory: () => new SomeComponentWhichThrows
});
}
function Template(ctx: any, cm: boolean) {
function Template(rf: RenderFlags, ctx: any) {
logs.push('function');
if (cm) {
if (rf & RenderFlags.Create) {
text(0, 'bar');
}
}
const directives = [SomeComponent, SomeComponentWhichThrows];
function TemplateWithComponent(ctx: any, cm: boolean) {
function TemplateWithComponent(rf: RenderFlags, ctx: any) {
logs.push('function_with_component');
if (cm) {
if (rf & RenderFlags.Create) {
text(0, 'bar');
elementStart(1, 'some-component');
elementEnd();
@ -125,8 +126,8 @@ describe('animation renderer factory', () => {
static ngComponentDef = defineComponent({
type: SomeComponent,
selectors: [['some-component']],
template: function(ctx: SomeComponent, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: SomeComponent) {
if (rf & RenderFlags.Create) {
text(0, 'foo');
}
},
@ -142,8 +143,8 @@ describe('animation renderer factory', () => {
static ngComponentDef = defineComponent({
type: SomeComponentWithAnimation,
selectors: [['some-component']],
template: function(ctx: SomeComponentWithAnimation, cm: boolean) {
if (cm) {
template: function(rf: RenderFlags, ctx: SomeComponentWithAnimation) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div');
{
listener('@myAnimation.start', ctx.callback.bind(ctx));
@ -152,7 +153,9 @@ describe('animation renderer factory', () => {
}
elementEnd();
}
elementProperty(0, '@myAnimation', bind(ctx.exp));
if (rf & RenderFlags.Update) {
elementProperty(0, '@myAnimation', bind(ctx.exp));
}
},
factory: () => new SomeComponentWithAnimation,
rendererType: createRendererType2({

View File

@ -10,6 +10,7 @@ import {Component, Directive, TemplateRef, ViewContainerRef} from '../../src/cor
import {getOrCreateNodeInjectorForNode, getOrCreateTemplateRef} from '../../src/render3/di';
import {defineComponent, defineDirective, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, load, loadDirective, projection, projectionDef, text, textBinding} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {ComponentFixture, TemplateFixture} from './render_util';
@ -34,11 +35,13 @@ describe('ViewContainerRef', () => {
}
describe('API', () => {
function embeddedTemplate(ctx: any, cm: boolean) {
if (cm) {
function embeddedTemplate(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
text(0);
}
textBinding(0, ctx.name);
if (rf & RenderFlags.Update) {
textBinding(0, bind(ctx.name));
}
}
function createView(s: string, index?: number) {
@ -99,7 +102,7 @@ describe('ViewContainerRef', () => {
type: HeaderComponent,
selectors: [['header-cmp']],
factory: () => new HeaderComponent(),
template: (cmp: HeaderComponent, cm: boolean) => {}
template: (rf: RenderFlags, cmp: HeaderComponent) => {}
});
}
@ -143,7 +146,8 @@ describe('ViewContainerRef', () => {
const tplRef = getOrCreateTemplateRef(getOrCreateNodeInjectorForNode(load(0)));
elementProperty(0, 'tplRef', bind(tplRef));
containerRefreshStart(0);
if (embeddedViewStart(1)) {
let rf1 = embeddedViewStart(1);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'header');
elementEnd();
}
@ -195,14 +199,14 @@ describe('ViewContainerRef', () => {
remove(index?: number) { this._vcRef.remove(index); }
}
function EmbeddedTemplateA(ctx: any, cm: boolean) {
if (cm) {
function EmbeddedTemplateA(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
text(0, 'A');
}
}
function EmbeddedTemplateB(ctx: any, cm: boolean) {
if (cm) {
function EmbeddedTemplateB(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
text(0, 'B');
}
}
@ -219,8 +223,8 @@ describe('ViewContainerRef', () => {
type: TestComponent,
selectors: [['test-cmp']],
factory: () => new TestComponent(),
template: (cmp: TestComponent, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, cmp: TestComponent) => {
if (rf & RenderFlags.Create) {
text(0, 'before|');
container(1, EmbeddedTemplateA, undefined, ['testdir', '']);
container(2, EmbeddedTemplateB, undefined, ['testdir', '']);
@ -261,8 +265,8 @@ describe('ViewContainerRef', () => {
remove(index?: number) { this._vcRef.remove(index); }
}
function EmbeddedTemplateA(ctx: any, cm: boolean) {
if (cm) {
function EmbeddedTemplateA(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
text(0, 'A');
}
}
@ -282,26 +286,28 @@ describe('ViewContainerRef', () => {
type: TestComponent,
selectors: [['test-cmp']],
factory: () => new TestComponent(),
template: (cmp: TestComponent, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, cmp: TestComponent) => {
if (rf & RenderFlags.Create) {
text(0, 'before|');
container(1, EmbeddedTemplateA, undefined, ['testdir', '']);
container(2);
text(3, '|after');
}
containerRefreshStart(2);
{
if (cmp.condition) {
let cm1 = embeddedViewStart(0);
{
if (cm1) {
text(0, 'B');
if (rf & RenderFlags.Update) {
containerRefreshStart(2);
{
if (cmp.condition) {
let rf1 = embeddedViewStart(0);
{
if (rf1 & RenderFlags.Create) {
text(0, 'B');
}
}
embeddedViewEnd();
}
embeddedViewEnd();
}
containerRefreshEnd();
}
containerRefreshEnd();
},
directives: [TestDirective]
});
@ -456,8 +462,8 @@ describe('ViewContainerRef', () => {
});
describe('projection', () => {
function embeddedTemplate(ctx: any, cm: boolean) {
if (cm) {
function embeddedTemplate(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'span');
text(1);
elementEnd();
@ -472,8 +478,8 @@ describe('ViewContainerRef', () => {
type: Child,
selectors: [['child']],
factory: () => new Child(),
template: (cmp: Child, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, cmp: Child) => {
if (rf & RenderFlags.Create) {
projectionDef(0);
elementStart(1, 'div');
{ projection(2, 0); }
@ -497,8 +503,8 @@ describe('ViewContainerRef', () => {
type: Parent,
selectors: [['parent']],
factory: () => new Parent(),
template: (cmp: Parent, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, cmp: Parent) => {
if (rf & RenderFlags.Create) {
container(0, embeddedTemplate);
elementStart(1, 'child');
elementStart(2, 'header', ['vcref', '']);
@ -506,9 +512,12 @@ describe('ViewContainerRef', () => {
elementEnd();
elementEnd();
}
const tplRef = getOrCreateTemplateRef(getOrCreateNodeInjectorForNode(load(0)));
elementProperty(2, 'tplRef', bind(tplRef));
elementProperty(2, 'name', bind(cmp.name));
let tplRef: any;
if (rf & RenderFlags.Update) {
tplRef = getOrCreateTemplateRef(getOrCreateNodeInjectorForNode(load(0)));
elementProperty(2, 'tplRef', bind(tplRef));
elementProperty(2, 'name', bind(cmp.name));
}
},
directives: [Child, DirectiveWithVCRef]
});
@ -535,8 +544,8 @@ describe('ViewContainerRef', () => {
type: ChildWithSelector,
selectors: [['child-with-selector']],
factory: () => new ChildWithSelector(),
template: (cmp: ChildWithSelector, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, cmp: ChildWithSelector) => {
if (rf & RenderFlags.Create) {
projectionDef(0, [[['header']]], ['header']);
elementStart(1, 'first');
{ projection(2, 0, 1); }
@ -545,7 +554,8 @@ describe('ViewContainerRef', () => {
{ projection(4, 0); }
elementEnd();
}
}
},
directives: [ChildWithSelector, DirectiveWithVCRef]
});
}
@ -565,8 +575,9 @@ describe('ViewContainerRef', () => {
type: Parent,
selectors: [['parent']],
factory: () => new Parent(),
template: (cmp: Parent, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, cmp: Parent) => {
let tplRef: any;
if (rf & RenderFlags.Create) {
container(0, embeddedTemplate);
elementStart(1, 'child-with-selector');
elementStart(2, 'header', ['vcref', '']);
@ -574,9 +585,11 @@ describe('ViewContainerRef', () => {
elementEnd();
elementEnd();
}
const tplRef = getOrCreateTemplateRef(getOrCreateNodeInjectorForNode(load(0)));
elementProperty(2, 'tplRef', bind(tplRef));
elementProperty(2, 'name', bind(cmp.name));
if (rf & RenderFlags.Update) {
tplRef = getOrCreateTemplateRef(getOrCreateNodeInjectorForNode(load(0)));
elementProperty(2, 'tplRef', bind(tplRef));
elementProperty(2, 'name', bind(cmp.name));
}
},
directives: [ChildWithSelector, DirectiveWithVCRef]
});
@ -611,8 +624,9 @@ describe('ViewContainerRef', () => {
type: Parent,
selectors: [['parent']],
factory: () => new Parent(),
template: (cmp: Parent, cm: boolean) => {
if (cm) {
template: (rf: RenderFlags, cmp: Parent) => {
let tplRef: any;
if (rf & RenderFlags.Create) {
container(0, embeddedTemplate);
elementStart(1, 'child-with-selector');
elementStart(2, 'footer', ['vcref', '']);
@ -620,9 +634,11 @@ describe('ViewContainerRef', () => {
elementEnd();
elementEnd();
}
const tplRef = getOrCreateTemplateRef(getOrCreateNodeInjectorForNode(load(0)));
elementProperty(2, 'tplRef', bind(tplRef));
elementProperty(2, 'name', bind(cmp.name));
if (rf & RenderFlags.Update) {
tplRef = getOrCreateTemplateRef(getOrCreateNodeInjectorForNode(load(0)));
elementProperty(2, 'tplRef', bind(tplRef));
elementProperty(2, 'name', bind(cmp.name));
}
},
directives: [ChildWithSelector, DirectiveWithVCRef]
});