refactor(ivy): move directives into separate array (#22918)

PR Close #22918
This commit is contained in:
Kara Erickson 2018-03-21 15:10:34 -07:00 committed by Matias Niemelä
parent 34981063ec
commit 49396ca2ae
28 changed files with 544 additions and 441 deletions

View File

@ -30,6 +30,7 @@ export {
T as ɵT, T as ɵT,
V as ɵV, V as ɵV,
Q as ɵQ, Q as ɵQ,
d as ɵd,
P as ɵP, P as ɵP,
b as ɵb, b as ɵb,
i1 as ɵi1, i1 as ɵi1,

View File

@ -140,9 +140,9 @@ export function renderComponent<T>(
try { try {
// Create element node at index 0 in data array // Create element node at index 0 in data array
elementNode = hostElement(hostNode, componentDef); elementNode = hostElement(hostNode, componentDef);
// Create directive instance with factory() and store at index 1 in data array (el is 0) // Create directive instance with factory() and store at index 0 in directives array
component = rootContext.component = component = rootContext.component =
baseDirectiveCreate(1, componentDef.factory(), componentDef) as T; baseDirectiveCreate(0, componentDef.factory(), componentDef) as T;
initChangeDetectorIfExisting(elementNode.nodeInjector, component); initChangeDetectorIfExisting(elementNode.nodeInjector, component);
} finally { } finally {
// We must not use leaveView here because it will set creationMode to false too early, // We must not use leaveView here because it will set creationMode to false too early,
@ -172,8 +172,8 @@ export function renderComponent<T>(
export function LifecycleHooksFeature(component: any, def: ComponentDef<any>): void { export function LifecycleHooksFeature(component: any, def: ComponentDef<any>): void {
const elementNode = _getComponentHostLElementNode(component); const elementNode = _getComponentHostLElementNode(component);
// Root component is always created at dir index 1, after host element at 0 // Root component is always created at dir index 0
queueInitHooks(1, def.onInit, def.doCheck, elementNode.view.tView); queueInitHooks(0, def.onInit, def.doCheck, elementNode.view.tView);
queueLifecycleHooks(elementNode.tNode !.flags, elementNode.view); queueLifecycleHooks(elementNode.tNode !.flags, elementNode.view);
} }

View File

@ -316,10 +316,11 @@ function getOrCreateHostChangeDetector(currentNode: LViewNode | LElementNode):
const hostInjector = hostNode.nodeInjector; const hostInjector = hostNode.nodeInjector;
const existingRef = hostInjector && hostInjector.changeDetectorRef; const existingRef = hostInjector && hostInjector.changeDetectorRef;
return existingRef ? existingRef : return existingRef ?
existingRef :
createViewRef( createViewRef(
hostNode.data as LView, hostNode.data as LView,
hostNode.view.data[hostNode.tNode !.flags >> TNodeFlags.INDX_SHIFT]); hostNode.view.directives ![hostNode.tNode !.flags >> TNodeFlags.INDX_SHIFT]);
} }
/** /**
@ -394,13 +395,13 @@ export function getOrCreateInjectable<T>(
// nothing to the "left" of it so it doesn't need a mask. // nothing to the "left" of it so it doesn't need a mask.
const start = flags >> TNodeFlags.INDX_SHIFT; const start = flags >> TNodeFlags.INDX_SHIFT;
const tData = node.view.tView.data; const defs = node.view.tView.directives !;
for (let i = start, ii = start + size; i < ii; i++) { for (let i = start, ii = start + size; i < ii; i++) {
// Get the definition for the directive at this index and, if it is injectable (diPublic), // Get the definition for the directive at this index and, if it is injectable (diPublic),
// and matches the given token, return the directive instance. // and matches the given token, return the directive instance.
const directiveDef = tData[i] as DirectiveDef<any>; const directiveDef = defs[i] as DirectiveDef<any>;
if (directiveDef.diPublic && directiveDef.type == token) { if (directiveDef.diPublic && directiveDef.type == token) {
return getDirectiveInstance(node.view.data[i]); return getDirectiveInstance(node.view.directives ![i]);
} }
} }
} }
@ -530,7 +531,7 @@ export const QUERY_READ_FROM_NODE =
(new ReadFromInjectorFn<any>((injector: LInjector, node: LNode, directiveIdx: number) => { (new ReadFromInjectorFn<any>((injector: LInjector, node: LNode, directiveIdx: number) => {
ngDevMode && assertNodeOfPossibleTypes(node, LNodeType.Container, LNodeType.Element); ngDevMode && assertNodeOfPossibleTypes(node, LNodeType.Container, LNodeType.Element);
if (directiveIdx > -1) { if (directiveIdx > -1) {
return node.view.data[directiveIdx]; return node.view.directives ![directiveIdx];
} else if (node.type === LNodeType.Element) { } else if (node.type === LNodeType.Element) {
return getOrCreateElementRef(injector); return getOrCreateElementRef(injector);
} else if (node.type === LNodeType.Container) { } else if (node.type === LNodeType.Container) {

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {assertEqual} from './assert';
import {DirectiveDef} from './interfaces/definition'; import {DirectiveDef} from './interfaces/definition';
import {TNodeFlags} from './interfaces/node'; import {TNodeFlags} from './interfaces/node';
import {HookData, LView, LifecycleStage, TView} from './interfaces/view'; import {HookData, LView, LifecycleStage, TView} from './interfaces/view';
@ -24,17 +25,17 @@ import {HookData, LView, LifecycleStage, TView} from './interfaces/view';
*/ */
export function queueInitHooks( export function queueInitHooks(
index: number, onInit: (() => void) | null, doCheck: (() => void) | null, tView: TView): void { index: number, onInit: (() => void) | null, doCheck: (() => void) | null, tView: TView): void {
if (tView.firstTemplatePass === true) { ngDevMode &&
if (onInit != null) { assertEqual(tView.firstTemplatePass, true, 'Should only be called on first template pass');
if (onInit) {
(tView.initHooks || (tView.initHooks = [])).push(index, onInit); (tView.initHooks || (tView.initHooks = [])).push(index, onInit);
} }
if (doCheck != null) { if (doCheck) {
(tView.initHooks || (tView.initHooks = [])).push(index, doCheck); (tView.initHooks || (tView.initHooks = [])).push(index, doCheck);
(tView.checkHooks || (tView.checkHooks = [])).push(index, doCheck); (tView.checkHooks || (tView.checkHooks = [])).push(index, doCheck);
} }
} }
}
/** /**
* Loops through the directives on a node and queues all their hooks except ngOnInit * Loops through the directives on a node and queues all their hooks except ngOnInit
@ -50,7 +51,7 @@ export function queueLifecycleHooks(flags: number, currentView: LView): void {
// directiveCreate) so we can preserve the current hook order. Content, view, and destroy // directiveCreate) so we can preserve the current hook order. Content, view, and destroy
// hooks for projected components and directives must be called *before* their hosts. // hooks for projected components and directives must be called *before* their hosts.
for (let i = start; i < end; i++) { for (let i = start; i < end; i++) {
const def = (tView.data[i] as DirectiveDef<any>); const def = (tView.directives ![i] as DirectiveDef<any>);
queueContentHooks(def, tView, i); queueContentHooks(def, tView, i);
queueViewHooks(def, tView, i); queueViewHooks(def, tView, i);
queueDestroyHooks(def, tView, i); queueDestroyHooks(def, tView, i);
@ -60,11 +61,11 @@ export function queueLifecycleHooks(flags: number, currentView: LView): void {
/** Queues afterContentInit and afterContentChecked hooks on TView */ /** Queues afterContentInit and afterContentChecked hooks on TView */
function queueContentHooks(def: DirectiveDef<any>, tView: TView, i: number): void { function queueContentHooks(def: DirectiveDef<any>, tView: TView, i: number): void {
if (def.afterContentInit != null) { if (def.afterContentInit) {
(tView.contentHooks || (tView.contentHooks = [])).push(i, def.afterContentInit); (tView.contentHooks || (tView.contentHooks = [])).push(i, def.afterContentInit);
} }
if (def.afterContentChecked != null) { if (def.afterContentChecked) {
(tView.contentHooks || (tView.contentHooks = [])).push(i, def.afterContentChecked); (tView.contentHooks || (tView.contentHooks = [])).push(i, def.afterContentChecked);
(tView.contentCheckHooks || (tView.contentCheckHooks = [])).push(i, def.afterContentChecked); (tView.contentCheckHooks || (tView.contentCheckHooks = [])).push(i, def.afterContentChecked);
} }
@ -72,11 +73,11 @@ function queueContentHooks(def: DirectiveDef<any>, tView: TView, i: number): voi
/** Queues afterViewInit and afterViewChecked hooks on TView */ /** Queues afterViewInit and afterViewChecked hooks on TView */
function queueViewHooks(def: DirectiveDef<any>, tView: TView, i: number): void { function queueViewHooks(def: DirectiveDef<any>, tView: TView, i: number): void {
if (def.afterViewInit != null) { if (def.afterViewInit) {
(tView.viewHooks || (tView.viewHooks = [])).push(i, def.afterViewInit); (tView.viewHooks || (tView.viewHooks = [])).push(i, def.afterViewInit);
} }
if (def.afterViewChecked != null) { if (def.afterViewChecked) {
(tView.viewHooks || (tView.viewHooks = [])).push(i, def.afterViewChecked); (tView.viewHooks || (tView.viewHooks = [])).push(i, def.afterViewChecked);
(tView.viewCheckHooks || (tView.viewCheckHooks = [])).push(i, def.afterViewChecked); (tView.viewCheckHooks || (tView.viewCheckHooks = [])).push(i, def.afterViewChecked);
} }
@ -96,7 +97,7 @@ function queueDestroyHooks(def: DirectiveDef<any>, tView: TView, i: number): voi
*/ */
export function executeInitHooks(currentView: LView, tView: TView, creationMode: boolean): void { export function executeInitHooks(currentView: LView, tView: TView, creationMode: boolean): void {
if (currentView.lifecycleStage === LifecycleStage.INIT) { if (currentView.lifecycleStage === LifecycleStage.INIT) {
executeHooks(currentView.data, tView.initHooks, tView.checkHooks, creationMode); executeHooks(currentView.directives !, tView.initHooks, tView.checkHooks, creationMode);
currentView.lifecycleStage = LifecycleStage.AFTER_INIT; currentView.lifecycleStage = LifecycleStage.AFTER_INIT;
} }
} }
@ -110,7 +111,7 @@ export function executeHooks(
data: any[], allHooks: HookData | null, checkHooks: HookData | null, data: any[], allHooks: HookData | null, checkHooks: HookData | null,
creationMode: boolean): void { creationMode: boolean): void {
const hooksToCall = creationMode ? allHooks : checkHooks; const hooksToCall = creationMode ? allHooks : checkHooks;
if (hooksToCall != null) { if (hooksToCall) {
callHooks(data, hooksToCall); callHooks(data, hooksToCall);
} }
} }

View File

@ -56,6 +56,7 @@ export {
listener as L, listener as L,
store as st, store as st,
load as ld, load as ld,
loadDirective as d,
projection as P, projection as P,
projectionDef as pD, projectionDef as pD,

View File

@ -48,7 +48,7 @@ export type Sanitizer = (value: any) => string;
* *
* Saved here to avoid re-instantiating an array on every change detection run. * Saved here to avoid re-instantiating an array on every change detection run.
*/ */
const rootDirectiveIndices = [1, 0]; const rootDirectiveIndices = [0, 0];
/** /**
@ -95,9 +95,8 @@ let isParent: boolean;
* Static data that corresponds to the instance-specific data array on an LView. * Static data that corresponds to the instance-specific data array on an LView.
* *
* Each node's static data is stored in tData at the same index that it's stored * Each node's static data is stored in tData at the same index that it's stored
* in the data array. Each directive's definition is stored here at the same index * in the data array. Any nodes that do not have static data store a null value in
* as its directive instance in the data array. Any nodes that do not have static * tData to avoid a sparse array.
* data store a null value in tData to avoid a sparse array.
*/ */
let tData: TData; let tData: TData;
@ -134,6 +133,14 @@ export function getCreationMode(): boolean {
*/ */
let data: any[]; let data: any[];
/**
* An array of directive instances in the current view.
*
* These must be stored separately from LNodes because their presence is
* unknown at compile-time and thus space cannot be reserved in data[].
*/
let directives: any[]|null;
/** /**
* Points to the next binding index to read or write to. * Points to the next binding index to read or write to.
*/ */
@ -188,6 +195,7 @@ const enum BindingDirection {
export function enterView(newView: LView, host: LElementNode | LViewNode | null): LView { export function enterView(newView: LView, host: LElementNode | LViewNode | null): LView {
const oldView = currentView; const oldView = currentView;
data = newView && newView.data; data = newView && newView.data;
directives = newView && newView.directives;
bindingIndex = newView && newView.bindingStartIndex || 0; bindingIndex = newView && newView.bindingStartIndex || 0;
tData = newView && newView.tView.data; tData = newView && newView.tView.data;
creationMode = newView && (newView.flags & LViewFlags.CreationMode) === LViewFlags.CreationMode; creationMode = newView && (newView.flags & LViewFlags.CreationMode) === LViewFlags.CreationMode;
@ -214,8 +222,7 @@ export function enterView(newView: LView, host: LElementNode | LViewNode | null)
export function leaveView(newView: LView): void { export function leaveView(newView: LView): void {
if (!checkNoChangesMode) { if (!checkNoChangesMode) {
executeHooks( executeHooks(
currentView.data, currentView.tView.viewHooks, currentView.tView.viewCheckHooks, directives !, currentView.tView.viewHooks, currentView.tView.viewCheckHooks, creationMode);
creationMode);
} }
// Views should be clean and in update mode after being checked, so these bits are cleared // Views should be clean and in update mode after being checked, so these bits are cleared
currentView.flags &= ~(LViewFlags.CreationMode | LViewFlags.Dirty); currentView.flags &= ~(LViewFlags.CreationMode | LViewFlags.Dirty);
@ -229,7 +236,6 @@ function refreshDirectives() {
const tView = currentView.tView; const tView = currentView.tView;
// This needs to be set before children are processed to support recursive components // This needs to be set before children are processed to support recursive components
// so to refresh the component, refresh() needs to be called with (1, 0)
tView.firstTemplatePass = firstTemplatePass = false; tView.firstTemplatePass = firstTemplatePass = false;
setHostBindings(tView.hostBindings); setHostBindings(tView.hostBindings);
@ -239,11 +245,11 @@ function refreshDirectives() {
/** Sets the host bindings for the current view. */ /** Sets the host bindings for the current view. */
function setHostBindings(bindings: number[] | null): void { function setHostBindings(bindings: number[] | null): void {
if (bindings != null) { if (bindings != null) {
const defs = currentView.tView.directives !;
for (let i = 0; i < bindings.length; i += 2) { for (let i = 0; i < bindings.length; i += 2) {
const dirIndex = bindings[i]; const dirIndex = bindings[i];
const elementIndex = bindings[i | 1]; const def = defs[dirIndex] as DirectiveDef<any>;
const def = tData[dirIndex] as DirectiveDef<any>; def.hostBindings && def.hostBindings(dirIndex, bindings[i | 1]);
def.hostBindings && def.hostBindings(dirIndex, elementIndex);
} }
} }
} }
@ -251,8 +257,8 @@ function setHostBindings(bindings: number[] | null): void {
/** Refreshes child components in the current view. */ /** Refreshes child components in the current view. */
function refreshChildComponents(components: number[] | null): void { function refreshChildComponents(components: number[] | null): void {
if (components != null) { if (components != null) {
for (let i = 0; i < components.length; i++) { for (let i = 0; i < components.length; i += 2) {
componentRefresh(components[i] + 1, components[i]); componentRefresh(components[i], components[i | 1]);
} }
} }
} }
@ -261,7 +267,7 @@ function executeInitAndContentHooks(): void {
if (!checkNoChangesMode) { if (!checkNoChangesMode) {
const tView = currentView.tView; const tView = currentView.tView;
executeInitHooks(currentView, tView, creationMode); executeInitHooks(currentView, tView, creationMode);
executeHooks(currentView.data, tView.contentHooks, tView.contentCheckHooks, creationMode); executeHooks(directives !, tView.contentHooks, tView.contentCheckHooks, creationMode);
} }
} }
@ -274,6 +280,7 @@ export function createLView(
flags: flags | LViewFlags.CreationMode | LViewFlags.Attached, flags: flags | LViewFlags.CreationMode | LViewFlags.Attached,
node: null !, // until we initialize it in createNode. node: null !, // until we initialize it in createNode.
data: [], data: [],
directives: null,
tView: tView, tView: tView,
cleanup: null, cleanup: null,
renderer: renderer, renderer: renderer,
@ -451,9 +458,10 @@ export function renderComponentOrTemplate<T>(
} else { } else {
executeInitAndContentHooks(); executeInitAndContentHooks();
// Element was stored at 0 and directive was stored at 1 in renderComponent // Element was stored at 0 in data and directive was stored at 0 in directives
// in renderComponent()
setHostBindings(rootDirectiveIndices); setHostBindings(rootDirectiveIndices);
componentRefresh(1, 0); componentRefresh(0, 0);
} }
} finally { } finally {
if (rendererFactory.end) { if (rendererFactory.end) {
@ -497,10 +505,14 @@ export function elementStart(
let hostComponentDef: ComponentDef<any>|null = null; let hostComponentDef: ComponentDef<any>|null = null;
let name = nameOrComponentType as string; let name = nameOrComponentType as string;
let directiveIndex = getNextDirectiveIndex(index);
if (isHostElement) { if (isHostElement) {
hostComponentDef = firstTemplatePass ? hostComponentDef = firstTemplatePass ?
(nameOrComponentType as ComponentType<any>).ngComponentDef : (nameOrComponentType as ComponentType<any>).ngComponentDef :
tData[index + 1] as ComponentDef<any>; currentView.tView.directives ![directiveIndex] as ComponentDef<any>;
name = hostComponentDef !.tag; name = hostComponentDef !.tag;
} }
@ -524,8 +536,8 @@ export function elementStart(
node = createLNode(index, LNodeType.Element, native, componentView); node = createLNode(index, LNodeType.Element, native, componentView);
if (node.tNode == null) { if (node.tNode == null) {
const localNames: (string | number)[]|null = const localNames: (string | number)[]|null = findMatchingLocalNames(
findMatchingLocalNames(hostComponentDef, localRefs, isHostElement ? index + 1 : -1, ''); hostComponentDef, localRefs, isHostElement ? directiveIndex : -1, '');
ngDevMode && assertDataInRange(index - 1); ngDevMode && assertDataInRange(index - 1);
node.tNode = tData[index] = createTNode(name, attrs || null, null, localNames); node.tNode = tData[index] = createTNode(name, attrs || null, null, localNames);
} }
@ -533,37 +545,34 @@ export function elementStart(
if (attrs) setUpAttributes(native, attrs); if (attrs) setUpAttributes(native, attrs);
appendChild(node.parent !, native, currentView); appendChild(node.parent !, native, currentView);
const elementIndex = index;
if (hostComponentDef) { if (hostComponentDef) {
// TODO(mhevery): This assumes that the directives come in correct order, which // TODO(mhevery): This assumes that the directives come in correct order, which
// is not guaranteed. Must be refactored to take it into account. // is not guaranteed. Must be refactored to take it into account.
const instance = hostComponentDef.factory(); const instance = hostComponentDef.factory();
directiveCreate(++index, instance, hostComponentDef, null); directiveCreate(directiveIndex, index, instance, hostComponentDef, null);
initChangeDetectorIfExisting(node.nodeInjector, instance); initChangeDetectorIfExisting(node.nodeInjector, instance);
queueComponentIndexForCheck(elementIndex); queueComponentIndexForCheck(directiveIndex, index);
if (hostComponentDef.hostBindings) queueHostBindingForCheck(index, elementIndex); directiveIndex++;
} }
hack_declareDirectives(index, elementIndex, directiveTypes, localRefs); hack_declareDirectives(directiveIndex, index, directiveTypes, localRefs);
} }
} }
return native; return native;
} }
/** Stores index of component's host element so it will be queued for view refresh during CD. */ /** Stores index of component's host element so it will be queued for view refresh during CD. */
function queueComponentIndexForCheck(elIndex: number): void { function queueComponentIndexForCheck(dirIndex: number, elIndex: number): void {
if (firstTemplatePass) { if (firstTemplatePass) {
(currentView.tView.components || (currentView.tView.components = [])).push(elIndex); (currentView.tView.components || (currentView.tView.components = [])).push(dirIndex, elIndex);
} }
} }
/** Stores index of directive and host element so it will be queued for binding refresh during CD. /** Stores index of directive and host element so it will be queued for binding refresh during CD.
*/ */
function queueHostBindingForCheck(dirIndex: number, elIndex: number): void { function queueHostBindingForCheck(dirIndex: number, elIndex: number): void {
if (firstTemplatePass) { ngDevMode &&
(currentView.tView.hostBindings || (currentView.tView.hostBindings = [ assertEqual(firstTemplatePass, true, 'Should only be called in first template pass.');
])).push(dirIndex, elIndex); (currentView.tView.hostBindings || (currentView.tView.hostBindings = [])).push(dirIndex, elIndex);
}
} }
/** Sets the context for a ChangeDetectorRef to the given instance. */ /** Sets the context for a ChangeDetectorRef to the given instance. */
@ -578,20 +587,19 @@ export function initChangeDetectorIfExisting(injector: LInjector | null, instanc
* come in the correct order for DI. * come in the correct order for DI.
*/ */
function hack_declareDirectives( function hack_declareDirectives(
index: number, elIndex: number, directiveTypes: DirectiveType<any>[] | null | undefined, index: number, elementIndex: number, directiveTypes: DirectiveType<any>[] | null | undefined,
localRefs: string[] | null | undefined, ) { localRefs: string[] | null | undefined, ) {
if (directiveTypes) { if (directiveTypes) {
const defs = currentView.tView.directives !;
// TODO(mhevery): This assumes that the directives come in correct order, which // TODO(mhevery): This assumes that the directives come in correct order, which
// is not guaranteed. Must be refactored to take it into account. // is not guaranteed. Must be refactored to take it into account.
for (let i = 0; i < directiveTypes.length; i++) { for (let i = 0; i < directiveTypes.length; i++) {
index++;
const directiveType = directiveTypes[i]; const directiveType = directiveTypes[i];
const directiveDef = const directiveDef =
firstTemplatePass ? directiveType.ngDirectiveDef : tData[index] as DirectiveDef<any>; firstTemplatePass ? directiveType.ngDirectiveDef : defs[index] as DirectiveDef<any>;
const localNames = directiveCreate(index, elementIndex, directiveDef.factory(), directiveDef, localRefs);
firstTemplatePass ? findMatchingLocalNames(directiveDef, localRefs, index) : null; index++;
directiveCreate(index, directiveDef.factory(), directiveDef, localNames);
if (directiveDef.hostBindings) queueHostBindingForCheck(index, elIndex);
} }
} }
} }
@ -633,6 +641,7 @@ function getOrCreateTView(template: ComponentTemplate<any>): TView {
export function createTView(): TView { export function createTView(): TView {
return { return {
data: [], data: [],
directives: null,
firstTemplatePass: true, firstTemplatePass: true,
initHooks: null, initHooks: null,
checkHooks: null, checkHooks: null,
@ -641,6 +650,7 @@ export function createTView(): TView {
viewHooks: null, viewHooks: null,
viewCheckHooks: null, viewCheckHooks: null,
destroyHooks: null, destroyHooks: null,
pipeDestroyHooks: null,
hostBindings: null, hostBindings: null,
components: null components: null
}; };
@ -758,8 +768,8 @@ export function listener(
*/ */
function createOutput(outputs: PropertyAliasValue, listener: Function): void { function createOutput(outputs: PropertyAliasValue, listener: Function): void {
for (let i = 0; i < outputs.length; i += 2) { for (let i = 0; i < outputs.length; i += 2) {
ngDevMode && assertDataInRange(outputs[i] as number); ngDevMode && assertDataInRange(outputs[i] as number, directives !);
const subscription = data[outputs[i] as number][outputs[i | 1]].subscribe(listener); const subscription = directives ![outputs[i] as number][outputs[i | 1]].subscribe(listener);
cleanup !.push(subscription.unsubscribe, subscription); cleanup !.push(subscription.unsubscribe, subscription);
} }
} }
@ -874,8 +884,8 @@ function createTNode(
*/ */
function setInputsForProperty(inputs: PropertyAliasValue, value: any): void { function setInputsForProperty(inputs: PropertyAliasValue, value: any): void {
for (let i = 0; i < inputs.length; i += 2) { for (let i = 0; i < inputs.length; i += 2) {
ngDevMode && assertDataInRange(inputs[i] as number); ngDevMode && assertDataInRange(inputs[i] as number, directives !);
data[inputs[i] as number][inputs[i | 1]] = value; directives ![inputs[i] as number][inputs[i | 1]] = value;
} }
} }
@ -894,9 +904,10 @@ function generatePropertyAliases(
if (size > 0) { if (size > 0) {
const start = tNodeFlags >> TNodeFlags.INDX_SHIFT; const start = tNodeFlags >> TNodeFlags.INDX_SHIFT;
const isInput = direction === BindingDirection.Input; const isInput = direction === BindingDirection.Input;
const defs = currentView.tView.directives !;
for (let i = start, ii = start + size; i < ii; i++) { for (let i = start, ii = start + size; i < ii; i++) {
const directiveDef = tData ![i] as DirectiveDef<any>; const directiveDef = defs[i] as DirectiveDef<any>;
const propertyAliasMap: {[publicName: string]: string} = const propertyAliasMap: {[publicName: string]: string} =
isInput ? directiveDef.inputs : directiveDef.outputs; isInput ? directiveDef.inputs : directiveDef.outputs;
for (let publicName in propertyAliasMap) { for (let publicName in propertyAliasMap) {
@ -1090,32 +1101,38 @@ export function textBinding<T>(index: number, value: T | NO_CHANGE): void {
* NOTE: directives can be created in order other than the index order. They can also * NOTE: directives can be created in order other than the index order. They can also
* be retrieved before they are created in which case the value will be null. * be retrieved before they are created in which case the value will be null.
* *
* @param index Each directive in a `View` will have a unique index. Directives can * @param index Index to save the directive in the directives array
* be created or retrieved out of order. * @param elementIndex Index of the host element in the data array
* @param directive The directive instance. * @param directive The directive instance.
* @param directiveDef DirectiveDef object which contains information about the template. * @param directiveDef DirectiveDef object which contains information about the template.
* @param localNames Names under which a query can retrieve the directive instance * @param localRefs Names under which a query can retrieve the directive instance
*/ */
export function directiveCreate<T>( export function directiveCreate<T>(
index: number, directive: T, directiveDef: DirectiveDef<T>, index: number, elementIndex: number, directive: T, directiveDef: DirectiveDef<T>,
localNames?: (string | number)[] | null): T { localRefs?: string[] | null): T {
const instance = baseDirectiveCreate(index, directive, directiveDef); const instance = baseDirectiveCreate(index, directive, directiveDef);
ngDevMode && assertNotNull(previousOrParentNode.tNode, 'previousOrParentNode.tNode'); ngDevMode && assertNotNull(previousOrParentNode.tNode, 'previousOrParentNode.tNode');
const tNode: TNode|null = previousOrParentNode.tNode !; const tNode: TNode|null = previousOrParentNode.tNode !;
if (firstTemplatePass && localNames) { if (firstTemplatePass) {
tNode.localNames = tNode.localNames ? tNode.localNames.concat(localNames) : localNames;
}
if (tNode && tNode.attrs) {
setInputsFromAttrs<T>(instance, directiveDef !.inputs, tNode);
}
// Init hooks are queued now so ngOnInit is called in host components before // Init hooks are queued now so ngOnInit is called in host components before
// any projected components. // any projected components.
queueInitHooks(index, directiveDef.onInit, directiveDef.doCheck, currentView.tView); queueInitHooks(index, directiveDef.onInit, directiveDef.doCheck, currentView.tView);
if (directiveDef.hostBindings) queueHostBindingForCheck(index, elementIndex);
if (localRefs) {
const localNames = findMatchingLocalNames(directiveDef, localRefs, index);
tNode.localNames =
localNames && tNode.localNames ? tNode.localNames.concat(localNames) : localNames;
}
}
if (tNode && tNode.attrs) {
setInputsFromAttrs<T>(index, instance, directiveDef.inputs, tNode);
}
return instance; return instance;
} }
@ -1127,25 +1144,27 @@ export function directiveCreate<T>(
*/ */
export function baseDirectiveCreate<T>( export function baseDirectiveCreate<T>(
index: number, directive: T, directiveDef: DirectiveDef<T>): T { index: number, directive: T, directiveDef: DirectiveDef<T>): T {
let instance;
ngDevMode && ngDevMode &&
assertNull(currentView.bindingStartIndex, 'directives should be created before any bindings'); assertNull(currentView.bindingStartIndex, 'directives should be created before any bindings');
ngDevMode && assertPreviousIsParent(); ngDevMode && assertPreviousIsParent();
if (firstTemplatePass) {
const flags = previousOrParentNode.tNode !.flags;
previousOrParentNode.tNode !.flags =
(flags & TNodeFlags.SIZE_MASK) === 0 ? (index << TNodeFlags.INDX_SHIFT) | 1 : flags + 1;
}
ngDevMode && assertDataInRange(index - 1);
Object.defineProperty( Object.defineProperty(
directive, NG_HOST_SYMBOL, {enumerable: false, value: previousOrParentNode}); directive, NG_HOST_SYMBOL, {enumerable: false, value: previousOrParentNode});
data[index] = instance = directive; if (directives == null) currentView.directives = directives = [];
if (index >= tData.length) { ngDevMode && assertDataNext(index, directives);
tData[index] = directiveDef !; directives[index] = directive;
if (firstTemplatePass) {
const defs = currentView.tView.directives || (currentView.tView.directives = []);
ngDevMode && assertDataNext(index, defs);
defs[index] = (directiveDef);
const flags = previousOrParentNode.tNode !.flags;
previousOrParentNode.tNode !.flags =
(flags & TNodeFlags.SIZE_MASK) === 0 ? (index << TNodeFlags.INDX_SHIFT) | 1 : flags + 1;
} }
const diPublic = directiveDef !.diPublic; const diPublic = directiveDef !.diPublic;
@ -1158,19 +1177,19 @@ export function baseDirectiveCreate<T>(
(previousOrParentNode as LElementNode).native, directiveDef !.attributes as string[]); (previousOrParentNode as LElementNode).native, directiveDef !.attributes as string[]);
} }
return instance; return directive;
} }
/** /**
* Sets initial input properties on directive instances from attribute data * Sets initial input properties on directive instances from attribute data
* *
* @param directiveIndex Index of the directive in directives array
* @param instance Instance of the directive on which to set the initial inputs * @param instance Instance of the directive on which to set the initial inputs
* @param inputs The list of inputs from the directive def * @param inputs The list of inputs from the directive def
* @param tNode The static data for this node * @param tNode The static data for this node
*/ */
function setInputsFromAttrs<T>(instance: T, inputs: {[key: string]: string}, tNode: TNode): void { function setInputsFromAttrs<T>(
const directiveIndex = (previousOrParentNode.tNode !.flags & TNodeFlags.SIZE_MASK) - 1; directiveIndex: number, instance: T, inputs: {[key: string]: string}, tNode: TNode): void {
let initialInputData = tNode.initialInputs as InitialInputData | undefined; let initialInputData = tNode.initialInputs as InitialInputData | undefined;
if (initialInputData === undefined || directiveIndex >= initialInputData.length) { if (initialInputData === undefined || directiveIndex >= initialInputData.length) {
initialInputData = generateInitialInputs(directiveIndex, inputs, tNode); initialInputData = generateInitialInputs(directiveIndex, inputs, tNode);
@ -1266,7 +1285,7 @@ export function container(
// Containers are added to the current view tree instead of their embedded views // Containers are added to the current view tree instead of their embedded views
// because views can be removed and re-inserted. // because views can be removed and re-inserted.
addToViewTree(node.data); addToViewTree(node.data);
hack_declareDirectives(index, index, directiveTypes, localRefs); hack_declareDirectives(getNextDirectiveIndex(index), index, directiveTypes, localRefs);
isParent = false; isParent = false;
ngDevMode && assertNodeType(previousOrParentNode, LNodeType.Container); ngDevMode && assertNodeType(previousOrParentNode, LNodeType.Container);
@ -1279,6 +1298,12 @@ export function container(
} }
} }
/** Retrieves the next directive index to write */
function getNextDirectiveIndex(index: number): number {
return firstTemplatePass ? (directives ? directives.length : 0) :
(tData[index] as TNode).flags >> TNodeFlags.INDX_SHIFT;
}
/** /**
* Sets a container up to receive views. * Sets a container up to receive views.
* *
@ -1461,10 +1486,10 @@ export function componentRefresh<T>(directiveIndex: number, elementIndex: number
// Only attached CheckAlways components or attached, dirty OnPush components should be checked // Only attached CheckAlways components or attached, dirty OnPush components should be checked
if (viewAttached(hostView) && hostView.flags & (LViewFlags.CheckAlways | LViewFlags.Dirty)) { if (viewAttached(hostView) && hostView.flags & (LViewFlags.CheckAlways | LViewFlags.Dirty)) {
ngDevMode && assertDataInRange(directiveIndex); ngDevMode && assertDataInRange(directiveIndex, directives !);
const template = (tData[directiveIndex] as ComponentDef<any>).template; const template = (currentView.tView.directives ![directiveIndex] as ComponentDef<any>).template;
detectChangesInternal( detectChangesInternal(
hostView, element, template, getDirectiveInstance<T>(data[directiveIndex])); hostView, element, template, getDirectiveInstance<T>(directives ![directiveIndex]));
} }
} }
@ -1770,7 +1795,7 @@ export function detectChanges<T>(component: T): void {
const hostNode = _getComponentHostLElementNode(component); const hostNode = _getComponentHostLElementNode(component);
ngDevMode && assertNotNull(hostNode.data, 'Component host node should be attached to an LView'); ngDevMode && assertNotNull(hostNode.data, 'Component host node should be attached to an LView');
const componentIndex = hostNode.tNode !.flags >> TNodeFlags.INDX_SHIFT; const componentIndex = hostNode.tNode !.flags >> TNodeFlags.INDX_SHIFT;
const template = (hostNode.view.tView.data[componentIndex] as ComponentDef<T>).template; const template = (hostNode.view.tView.directives ![componentIndex] as ComponentDef<T>).template;
detectChangesInternal(hostNode.data as LView, hostNode, template, component); detectChangesInternal(hostNode.data as LView, hostNode, template, component);
} }
@ -2035,10 +2060,17 @@ export function store<T>(index: number, value: T): void {
/** Retrieves a value from the `data`. */ /** Retrieves a value from the `data`. */
export function load<T>(index: number): T { export function load<T>(index: number): T {
ngDevMode && assertDataInRange(index, data); ngDevMode && assertDataInRange(index);
return data[index]; return data[index];
} }
/** Retrieves a value from the `directives` array. */
export function loadDirective<T>(index: number): T {
ngDevMode && assertNotNull(directives, 'Directives array should be defined if reading a dir.');
ngDevMode && assertDataInRange(index, directives !);
return directives ![index];
}
/** Gets the current binding value and increments the binding index. */ /** Gets the current binding value and increments the binding index. */
export function consumeBinding(): any { export function consumeBinding(): any {
ngDevMode && assertDataInRange(bindingIndex); ngDevMode && assertDataInRange(bindingIndex);
@ -2087,7 +2119,7 @@ export function getTView(): TView {
} }
export function getDirectiveInstance<T>(instanceOrArray: T | [T]): T { export function getDirectiveInstance<T>(instanceOrArray: T | [T]): T {
// Directives with content queries store an array in data[directiveIndex] // Directives with content queries store an array in directives[directiveIndex]
// with the instance as the first index // with the instance as the first index
return Array.isArray(instanceOrArray) ? instanceOrArray[0] : instanceOrArray; return Array.isArray(instanceOrArray) ? instanceOrArray[0] : instanceOrArray;
} }
@ -2105,8 +2137,9 @@ function assertDataInRange(index: number, arr?: any[]) {
assertLessThan(index, arr ? arr.length : 0, 'index expected to be a valid data index'); assertLessThan(index, arr ? arr.length : 0, 'index expected to be a valid data index');
} }
function assertDataNext(index: number) { function assertDataNext(index: number, arr?: any[]) {
assertEqual(data.length, index, 'index expected to be at the end of data'); if (arr == null) arr = data;
assertEqual(arr.length, index, 'index expected to be at the end of arr');
} }
export function _getComponentHostLElementNode<T>(component: T): LElementNode { export function _getComponentHostLElementNode<T>(component: T): LElementNode {

View File

@ -7,12 +7,13 @@
*/ */
import {LContainer} from './container'; import {LContainer} from './container';
import {ComponentTemplate, DirectiveDef, PipeDef} from './definition'; import {ComponentDef, ComponentTemplate, DirectiveDef, PipeDef} from './definition';
import {LElementNode, LViewNode, TNode} from './node'; import {LElementNode, LViewNode, TNode} from './node';
import {LQueries} from './query'; import {LQueries} from './query';
import {Renderer3} from './renderer'; import {Renderer3} from './renderer';
/** /**
* `LView` stores all of the information needed to process the instructions as * `LView` stores all of the information needed to process the instructions as
* they are invoked from the template. Each embedded view and component view has its * they are invoked from the template. Each embedded view and component view has its
@ -131,7 +132,7 @@ export interface LView {
* This array stores all element/text/container nodes created inside this view * This array stores all element/text/container nodes created inside this view
* and their bindings. Stored as an array rather than a linked list so we can * and their bindings. Stored as an array rather than a linked list so we can
* look up nodes directly in the case of forward declaration or bindings * look up nodes directly in the case of forward declaration or bindings
* (e.g. E(1)).. * (e.g. E(1)).
* *
* All bindings for a given view are stored in the order in which they * All bindings for a given view are stored in the order in which they
* appear in the template, starting with `bindingStartIndex`. * appear in the template, starting with `bindingStartIndex`.
@ -140,6 +141,14 @@ export interface LView {
*/ */
readonly data: any[]; readonly data: any[];
/**
* An array of directive instances in the current view.
*
* These must be stored separately from LNodes because their presence is
* unknown at compile-time and thus space cannot be reserved in data[].
*/
directives: any[]|null;
/** /**
* The static data for this view. We need a reference to this so we can easily walk up the * The static data for this view. We need a reference to this so we can easily walk up the
* node tree in DI and get the TView.data array associated with a node (where the * node tree in DI and get the TView.data array associated with a node (where the
@ -210,9 +219,17 @@ export interface LViewOrLContainer {
* Stored on the template function as ngPrivateData. * Stored on the template function as ngPrivateData.
*/ */
export interface TView { export interface TView {
/** Static data equivalent of LView.data[]. Contains TNodes and directive defs. */ /** Static data equivalent of LView.data[]. Contains TNodes. */
data: TData; data: TData;
/**
* Directive and component defs for this view
*
* Defs are stored at the same index in TView.directives[] as their instances
* are stored in LView.directives[]. This simplifies lookup in DI.
*/
directives: (ComponentDef<any>|DirectiveDef<any>)[]|null;
/** Whether or not this template has been processed. */ /** Whether or not this template has been processed. */
firstTemplatePass: boolean; firstTemplatePass: boolean;
@ -278,8 +295,22 @@ export interface TView {
destroyHooks: HookData|null; destroyHooks: HookData|null;
/** /**
* A list of element indices for child components that will need to be refreshed when the * Array of pipe ngOnDestroy hooks that should be executed when this view is destroyed.
* current view has finished its check. *
* Even indices: Index of pipe in data
* Odd indices: Hook function
*
* These must be stored separately from directive destroy hooks because their contexts
* are stored in data.
*/
pipeDestroyHooks: HookData|null;
/**
* A list of directive and element indices for child components that will need to be
* refreshed when the current view has finished its check.
*
* Even indices: Directive indices
* Odd indices: Element indices
*/ */
components: number[]|null; components: number[]|null;
@ -340,11 +371,11 @@ export const enum LifecycleStage {
* Static data that corresponds to the instance-specific data array on an LView. * Static data that corresponds to the instance-specific data array on an LView.
* *
* Each node's static data is stored in tData at the same index that it's stored * Each node's static data is stored in tData at the same index that it's stored
* in the data array. Each directive/pipe's definition is stored here at the same index * in the data array. Each pipe's definition is stored here at the same index
* as its directive/pipe instance in the data array. Any nodes that do not have static * as its pipe instance in the data array. Any nodes that do not have static
* data store a null value in tData to avoid a sparse array. * data store a null value in tData to avoid a sparse array.
*/ */
export type TData = (TNode | DirectiveDef<any>| PipeDef<any>| null)[]; export type TData = (TNode | PipeDef<any>| null)[];
// Note: This hack is necessary so we don't erroneously get a circular dependency // Note: This hack is necessary so we don't erroneously get a circular dependency
// failure based on types. // failure based on types.

View File

@ -361,6 +361,7 @@ export function getParentState(state: LViewOrLContainer, rootView: LView): LView
function cleanUpView(view: LView): void { function cleanUpView(view: LView): void {
removeListeners(view); removeListeners(view);
executeOnDestroys(view); executeOnDestroys(view);
executePipeOnDestroys(view);
} }
/** Removes listeners and unsubscribes from output subscriptions */ /** Removes listeners and unsubscribes from output subscriptions */
@ -384,7 +385,15 @@ function executeOnDestroys(view: LView): void {
const tView = view.tView; const tView = view.tView;
let destroyHooks: HookData|null; let destroyHooks: HookData|null;
if (tView != null && (destroyHooks = tView.destroyHooks) != null) { if (tView != null && (destroyHooks = tView.destroyHooks) != null) {
callHooks(view.data, destroyHooks); callHooks(view.directives !, destroyHooks);
}
}
/** Calls pipe destroy hooks for this view */
function executePipeOnDestroys(view: LView): void {
const pipeDestroyHooks = view.tView && view.tView.pipeDestroyHooks;
if (pipeDestroyHooks) {
callHooks(view.data !, pipeDestroyHooks);
} }
} }

View File

@ -25,8 +25,8 @@ export function pipe<T>(index: number, pipeDef: PipeDef<T>, firstInstance?: T):
const tView = getTView(); const tView = getTView();
if (tView.firstTemplatePass) { if (tView.firstTemplatePass) {
tView.data[index] = pipeDef; tView.data[index] = pipeDef;
if (pipeDef.onDestroy != null) { if (pipeDef.onDestroy) {
(tView.destroyHooks || (tView.destroyHooks = [])).push(index, pipeDef.onDestroy); (tView.pipeDestroyHooks || (tView.pipeDestroyHooks = [])).push(index, pipeDef.onDestroy);
} }
} }
const pipeInstance = pipeDef.pure && firstInstance ? firstInstance : pipeDef.n(); const pipeInstance = pipeDef.pure && firstInstance ? firstInstance : pipeDef.n();

View File

@ -194,11 +194,11 @@ function getIdxOfMatchingSelector(tNode: TNode, selector: string): number|null {
* @returns Index of a found directive or null when none found. * @returns Index of a found directive or null when none found.
*/ */
function geIdxOfMatchingDirective(node: LNode, type: Type<any>): number|null { function geIdxOfMatchingDirective(node: LNode, type: Type<any>): number|null {
const tData = node.view.tView.data; const defs = node.view.tView.directives !;
const flags = node.tNode !.flags; const flags = node.tNode !.flags;
for (let i = flags >> TNodeFlags.INDX_SHIFT, ii = i + (flags & TNodeFlags.SIZE_MASK); i < ii; for (let i = flags >> TNodeFlags.INDX_SHIFT, ii = i + (flags & TNodeFlags.SIZE_MASK); i < ii;
i++) { i++) {
const def = tData[i] as DirectiveDef<any>; const def = defs[i] as DirectiveDef<any>;
if (def.diPublic && def.type === type) { if (def.diPublic && def.type === type) {
return i; return i;
} }
@ -214,7 +214,7 @@ function readFromNodeInjector(
} else { } else {
const matchingIdx = geIdxOfMatchingDirective(node, read as Type<any>); const matchingIdx = geIdxOfMatchingDirective(node, read as Type<any>);
if (matchingIdx !== null) { if (matchingIdx !== null) {
return node.view.data[matchingIdx]; return node.view.directives ![matchingIdx];
} }
} }
return null; return null;

View File

@ -207,7 +207,7 @@ describe('change detection', () => {
if (cm) { if (cm) {
elementStart(0, MyComponent); elementStart(0, MyComponent);
elementEnd(); elementEnd();
elementStart(2, 'button', ['id', 'parent']); elementStart(1, 'button', ['id', 'parent']);
{ listener('click', () => ctx.noop()); } { listener('click', () => ctx.noop()); }
elementEnd(); elementEnd();
} }

View File

@ -69,7 +69,7 @@ describe('components & directives', () => {
if (cm) { if (cm) {
$r3$.ɵE(0, ChildComponent, $e0_attrs$, $e0_dirs$); $r3$.ɵE(0, ChildComponent, $e0_attrs$, $e0_dirs$);
$r3$.ɵe(); $r3$.ɵe();
$r3$.ɵT(3, '!'); $r3$.ɵT(1, '!');
} }
} }
}); });
@ -92,7 +92,7 @@ describe('components & directives', () => {
type: HostBindingDir, type: HostBindingDir,
factory: function HostBindingDir_Factory() { return new HostBindingDir(); }, factory: function HostBindingDir_Factory() { return new HostBindingDir(); },
hostBindings: function HostBindingDir_HostBindings(dirIndex: $number$, elIndex: $number$) { hostBindings: function HostBindingDir_HostBindings(dirIndex: $number$, elIndex: $number$) {
$r3$.ɵp(elIndex, 'id', $r3$.ɵb($r3$.ɵld<HostBindingDir>(dirIndex).dirId)); $r3$.ɵp(elIndex, 'id', $r3$.ɵb($r3$.ɵd<HostBindingDir>(dirIndex).dirId));
} }
}); });
// /NORMATIVE // /NORMATIVE
@ -161,7 +161,7 @@ describe('components & directives', () => {
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) { template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) { if (cm) {
$r3$.ɵE(0, 'button', $e0_attrs$, $e0_dirs$); $r3$.ɵE(0, 'button', $e0_attrs$, $e0_dirs$);
$r3$.ɵT(2, 'Click'); $r3$.ɵT(1, 'Click');
$r3$.ɵe(); $r3$.ɵe();
} }
} }
@ -224,7 +224,7 @@ describe('components & directives', () => {
type: HostBindingDir, type: HostBindingDir,
factory: function HostBindingDir_Factory() { return new HostBindingDir(); }, factory: function HostBindingDir_Factory() { return new HostBindingDir(); },
hostBindings: function HostBindingDir_HostBindings(dirIndex: $number$, elIndex: $number$) { hostBindings: function HostBindingDir_HostBindings(dirIndex: $number$, elIndex: $number$) {
$r3$.ɵa(elIndex, 'aria-label', $r3$.ɵb($r3$.ɵld<HostBindingDir>(dirIndex).label)); $r3$.ɵa(elIndex, 'aria-label', $r3$.ɵb($r3$.ɵd<HostBindingDir>(dirIndex).label));
} }
}); });
// /NORMATIVE // /NORMATIVE

View File

@ -84,7 +84,7 @@ describe('content projection', () => {
template: function(ctx: $MyApp$, cm: $boolean$) { template: function(ctx: $MyApp$, cm: $boolean$) {
if (cm) { if (cm) {
$r3$.ɵE(0, SimpleComponent); $r3$.ɵE(0, SimpleComponent);
$r3$.ɵT(2, 'content'); $r3$.ɵT(1, 'content');
$r3$.ɵe(); $r3$.ɵe();
} }
} }

View File

@ -70,11 +70,11 @@ describe('lifecycle hooks', () => {
if (cm) { if (cm) {
$r3$.ɵE(0, LifecycleComp); $r3$.ɵE(0, LifecycleComp);
$r3$.ɵe(); $r3$.ɵe();
$r3$.ɵE(2, LifecycleComp); $r3$.ɵE(1, LifecycleComp);
$r3$.ɵe(); $r3$.ɵe();
} }
$r3$.ɵp(0, 'name', $r3$.ɵb(ctx.name1)); $r3$.ɵp(0, 'name', $r3$.ɵb(ctx.name1));
$r3$.ɵp(2, 'name', $r3$.ɵb(ctx.name2)); $r3$.ɵp(1, 'name', $r3$.ɵb(ctx.name2));
} }
}); });
// /NORMATIVE // /NORMATIVE

View File

@ -102,9 +102,9 @@ describe('queries', () => {
hostBindings: function ContentQueryComponent_HostBindings( hostBindings: function ContentQueryComponent_HostBindings(
dirIndex: $number$, elIndex: $number$) { dirIndex: $number$, elIndex: $number$) {
let $tmp$: any; let $tmp$: any;
const $instance$ = $r3$.ɵld<any[]>(dirIndex)[0]; const $instance$ = $r3$.ɵd<any[]>(dirIndex)[0];
$r3$.ɵqR($tmp$ = $r3$.ɵld<any[]>(dirIndex)[1]) && ($instance$.someDir = $tmp$.first); $r3$.ɵqR($tmp$ = $r3$.ɵd<any[]>(dirIndex)[1]) && ($instance$.someDir = $tmp$.first);
$r3$.ɵqR($tmp$ = $r3$.ɵld<any[]>(dirIndex)[2]) && ($instance$.someDirList = $tmp$); $r3$.ɵqR($tmp$ = $r3$.ɵd<any[]>(dirIndex)[2]) && ($instance$.someDirList = $tmp$);
}, },
template: function ContentQueryComponent_Template( template: function ContentQueryComponent_Template(
ctx: $ContentQueryComponent$, cm: $boolean$) { ctx: $ContentQueryComponent$, cm: $boolean$) {
@ -139,8 +139,8 @@ describe('queries', () => {
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) { template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) { if (cm) {
$r3$.ɵE(0, ContentQueryComponent); $r3$.ɵE(0, ContentQueryComponent);
contentQueryComp = $r3$.ɵld<any[]>(1)[0]; contentQueryComp = $r3$.ɵd<any[]>(0)[0];
$r3$.ɵE(2, 'div', $e2_attrs$, $e2_dirs$); $r3$.ɵE(1, 'div', $e2_attrs$, $e2_dirs$);
$r3$.ɵe(); $r3$.ɵe();
$r3$.ɵe(); $r3$.ɵe();
} }

View File

@ -7,7 +7,7 @@
*/ */
import {detectChanges} from '../../src/render3/index'; import {detectChanges} from '../../src/render3/index';
import {container, containerRefreshEnd, containerRefreshStart, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, load, projection, projectionDef, text} from '../../src/render3/instructions'; import {container, containerRefreshEnd, containerRefreshStart, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, load, loadDirective, projection, projectionDef, text} from '../../src/render3/instructions';
import {createComponent, renderComponent, toHtml} from './render_util'; import {createComponent, renderComponent, toHtml} from './render_util';
@ -32,7 +32,7 @@ describe('content projection', () => {
const Parent = createComponent('parent', function(ctx: any, cm: boolean) { const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ text(2, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
}); });
@ -50,7 +50,7 @@ describe('content projection', () => {
const Parent = createComponent('parent', function(ctx: any, cm: boolean) { const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ text(2, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
}); });
@ -71,7 +71,7 @@ describe('content projection', () => {
if (cm) { if (cm) {
projectionDef(0); projectionDef(0);
elementStart(1, GrandChild); elementStart(1, GrandChild);
{ projection(3, 0); } { projection(2, 0); }
elementEnd(); elementEnd();
} }
}); });
@ -79,10 +79,10 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
elementStart(2, 'b'); elementStart(1, 'b');
text(3, 'Hello'); text(2, 'Hello');
elementEnd(); elementEnd();
text(4, 'World!'); text(3, 'World!');
} }
elementEnd(); elementEnd();
} }
@ -119,7 +119,7 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
elementStart(2, ProjectedComp); elementStart(1, ProjectedComp);
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
@ -143,13 +143,13 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
text(2, '('); text(1, '(');
container(3); container(2);
text(4, ')'); text(3, ')');
} }
elementEnd(); elementEnd();
} }
containerRefreshStart(3); containerRefreshStart(2);
{ {
if (ctx.value) { if (ctx.value) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
@ -180,10 +180,10 @@ describe('content projection', () => {
const Parent = createComponent('parent', function(ctx: {value: any}, cm: boolean) { const Parent = createComponent('parent', function(ctx: {value: any}, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ container(2); } { container(1); }
elementEnd(); elementEnd();
} }
containerRefreshStart(2); containerRefreshStart(1);
{ {
if (ctx.value) { if (ctx.value) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
@ -219,13 +219,13 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
text(2, '('); text(1, '(');
container(3); container(2);
text(4, ')'); text(3, ')');
} }
elementEnd(); elementEnd();
} }
containerRefreshStart(3); containerRefreshStart(2);
{ {
if (ctx.value) { if (ctx.value) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
@ -291,8 +291,8 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
childCmptInstance = load(1); childCmptInstance = loadDirective(0);
text(2, 'content'); text(1, 'content');
} }
elementEnd(); elementEnd();
} }
@ -342,8 +342,8 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
childCmptInstance = load(1); childCmptInstance = loadDirective(0);
text(2, 'content'); text(1, 'content');
} }
elementEnd(); elementEnd();
} }
@ -395,8 +395,8 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
childCmptInstance = load(1); childCmptInstance = loadDirective(0);
text(2, 'content'); text(1, 'content');
} }
elementEnd(); elementEnd();
} }
@ -432,7 +432,7 @@ describe('content projection', () => {
const Parent = createComponent('parent', function(ctx: any, cm: boolean) { const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ text(2, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
}); });
@ -486,8 +486,8 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
childCmptInstance = load(1); childCmptInstance = loadDirective(0);
text(2, 'content'); text(1, 'content');
} }
elementEnd(); elementEnd();
} }
@ -531,11 +531,11 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
elementStart(2, 'span', ['title', 'toFirst']); elementStart(1, 'span', ['title', 'toFirst']);
{ text(3, '1'); } { text(2, '1'); }
elementEnd(); elementEnd();
elementStart(4, 'span', ['title', 'toSecond']); elementStart(3, 'span', ['title', 'toSecond']);
{ text(5, '2'); } { text(4, '2'); }
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
@ -577,11 +577,11 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
elementStart(2, 'span', ['class', 'toFirst']); elementStart(1, 'span', ['class', 'toFirst']);
{ text(3, '1'); } { text(2, '1'); }
elementEnd(); elementEnd();
elementStart(4, 'span', ['class', 'toSecond']); elementStart(3, 'span', ['class', 'toSecond']);
{ text(5, '2'); } { text(4, '2'); }
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
@ -623,11 +623,11 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
elementStart(2, 'span', ['class', 'other toFirst']); elementStart(1, 'span', ['class', 'other toFirst']);
{ text(3, '1'); } { text(2, '1'); }
elementEnd(); elementEnd();
elementStart(4, 'span', ['class', 'toSecond noise']); elementStart(3, 'span', ['class', 'toSecond noise']);
{ text(5, '2'); } { text(4, '2'); }
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
@ -669,11 +669,11 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
elementStart(2, 'span', ['class', 'toFirst']); elementStart(1, 'span', ['class', 'toFirst']);
{ text(3, '1'); } { text(2, '1'); }
elementEnd(); elementEnd();
elementStart(4, 'span', ['class', 'toSecond']); elementStart(3, 'span', ['class', 'toSecond']);
{ text(5, '2'); } { text(4, '2'); }
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
@ -713,13 +713,13 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
elementStart(2, 'span', ['class', 'toFirst']); elementStart(1, 'span', ['class', 'toFirst']);
{ text(3, '1'); } { text(2, '1'); }
elementEnd(); elementEnd();
elementStart(4, 'span'); elementStart(3, 'span');
{ text(5, 'remaining'); } { text(4, 'remaining'); }
elementEnd(); elementEnd();
text(6, 'more remaining'); text(5, 'more remaining');
} }
elementEnd(); elementEnd();
} }
@ -759,13 +759,13 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
elementStart(2, 'span'); elementStart(1, 'span');
{ text(3, '1'); } { text(2, '1'); }
elementEnd(); elementEnd();
elementStart(4, 'span', ['class', 'toSecond']); elementStart(3, 'span', ['class', 'toSecond']);
{ text(5, '2'); } { text(4, '2'); }
elementEnd(); elementEnd();
text(6, 'remaining'); text(5, 'remaining');
} }
elementEnd(); elementEnd();
} }
@ -809,9 +809,9 @@ describe('content projection', () => {
projectionDef(0); projectionDef(0);
elementStart(1, GrandChild); elementStart(1, GrandChild);
{ {
projection(3, 0); projection(2, 0);
elementStart(4, 'span'); elementStart(3, 'span');
{ text(5, 'in child template'); } { text(4, 'in child template'); }
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
@ -829,8 +829,8 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
elementStart(2, 'span'); elementStart(1, 'span');
{ text(3, 'parent content'); } { text(2, 'parent content'); }
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
@ -873,10 +873,10 @@ describe('content projection', () => {
projectionDef(0); projectionDef(0);
elementStart(1, Card); elementStart(1, Card);
{ {
elementStart(3, 'h1', ['card-title', '']); elementStart(2, 'h1', ['card-title', '']);
{ text(4, 'Title'); } { text(3, 'Title'); }
elementEnd(); elementEnd();
projection(5, 0, 0, ['card-content', '']); projection(4, 0, 0, ['card-content', '']);
} }
elementEnd(); elementEnd();
} }
@ -890,7 +890,7 @@ describe('content projection', () => {
const App = createComponent('app', function(ctx: any, cm: boolean) { const App = createComponent('app', function(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, CardWithTitle); elementStart(0, CardWithTitle);
{ text(2, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
}); });
@ -932,10 +932,10 @@ describe('content projection', () => {
projectionDef(0); projectionDef(0);
elementStart(1, Card); elementStart(1, Card);
{ {
elementStart(3, 'h1', ['ngProjectAs', '[card-title]']); elementStart(2, 'h1', ['ngProjectAs', '[card-title]']);
{ text(4, 'Title'); } { text(3, 'Title'); }
elementEnd(); elementEnd();
projection(5, 0, 0, ['ngProjectAs', '[card-content]']); projection(4, 0, 0, ['ngProjectAs', '[card-content]']);
} }
elementEnd(); elementEnd();
} }
@ -949,7 +949,7 @@ describe('content projection', () => {
const App = createComponent('app', function(ctx: any, cm: boolean) { const App = createComponent('app', function(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, CardWithTitle); elementStart(0, CardWithTitle);
{ text(2, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
}); });
@ -982,11 +982,11 @@ describe('content projection', () => {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ {
elementStart(2, 'div', ['ngProjectAs', 'span']); elementStart(1, 'div', ['ngProjectAs', 'span']);
{ text(3, 'should not project'); } { text(2, 'should not project'); }
elementEnd(); elementEnd();
elementStart(4, 'div'); elementStart(3, 'div');
{ text(5, 'should project'); } { text(4, 'should project'); }
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
@ -1021,10 +1021,10 @@ describe('content projection', () => {
const Parent = createComponent('parent', function(ctx: {value: any}, cm: boolean) { const Parent = createComponent('parent', function(ctx: {value: any}, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Child); elementStart(0, Child);
{ container(2, undefined, undefined, 'div'); } { container(1, undefined, undefined, 'div'); }
elementEnd(); elementEnd();
} }
containerRefreshStart(2); containerRefreshStart(1);
{ {
if (true) { if (true) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {

View File

@ -11,7 +11,7 @@ import {ChangeDetectorRef, ElementRef, TemplateRef, ViewContainerRef} from '@ang
import {defineComponent} from '../../src/render3/definition'; import {defineComponent} from '../../src/render3/definition';
import {InjectFlags, bloomAdd, bloomFindPossibleInjector, getOrCreateNodeInjector, injectAttribute} from '../../src/render3/di'; import {InjectFlags, bloomAdd, bloomFindPossibleInjector, getOrCreateNodeInjector, injectAttribute} from '../../src/render3/di';
import {NgOnChangesFeature, PublicFeature, defineDirective, directiveInject, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index'; import {NgOnChangesFeature, PublicFeature, defineDirective, directiveInject, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, createLNode, createLView, createTView, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, enterView, interpolation2, leaveView, load, projection, projectionDef, text, textBinding} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, createLNode, createLView, createTView, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, enterView, interpolation2, leaveView, load, loadDirective, projection, projectionDef, text, textBinding} from '../../src/render3/instructions';
import {LInjector} from '../../src/render3/interfaces/injector'; import {LInjector} from '../../src/render3/interfaces/injector';
import {LNodeType} from '../../src/render3/interfaces/node'; import {LNodeType} from '../../src/render3/interfaces/node';
import {LViewFlags} from '../../src/render3/interfaces/view'; import {LViewFlags} from '../../src/render3/interfaces/view';
@ -30,10 +30,11 @@ describe('di', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, 'div', null, [Directive]); elementStart(0, 'div', null, [Directive]);
{ text(2); } { text(1); }
elementEnd(); elementEnd();
} }
textBinding(2, bind(load<Directive>(1).value)); // TODO: remove loadDirective when removing directive references
textBinding(1, bind(loadDirective<Directive>(0).value));
} }
expect(renderToHtml(Template, {})).toEqual('<div>Created</div>'); expect(renderToHtml(Template, {})).toEqual('<div>Created</div>');
@ -67,13 +68,14 @@ describe('di', () => {
if (cm) { if (cm) {
elementStart(0, 'div', null, [DirectiveA]); elementStart(0, 'div', null, [DirectiveA]);
{ {
elementStart(2, 'span', null, [DirectiveB, DirectiveC]); elementStart(1, 'span', null, [DirectiveB, DirectiveC]);
{ text(5); } { text(2); }
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
} }
textBinding(5, bind(load<DirectiveC>(4).value)); // TODO: remove loadDirective when removing directive references
textBinding(2, bind(loadDirective<DirectiveC>(2).value));
} }
expect(renderToHtml(Template, {})).toEqual('<div><span>AB</span></div>'); expect(renderToHtml(Template, {})).toEqual('<div><span>AB</span></div>');
@ -108,12 +110,14 @@ describe('di', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, 'div', null, [Directive, DirectiveSameInstance]); elementStart(0, 'div', null, [Directive, DirectiveSameInstance]);
{ text(3); } { text(1); }
elementEnd(); elementEnd();
} }
// TODO: remove loadDirective when removing directive references
textBinding( textBinding(
3, interpolation2( 1, interpolation2(
'', load<Directive>(1).value, '-', load<DirectiveSameInstance>(2).value, '')); '', loadDirective<Directive>(0).value, '-',
loadDirective<DirectiveSameInstance>(1).value, ''));
} }
expect(renderToHtml(Template, {})).toEqual('<div>ElementRef-true</div>'); expect(renderToHtml(Template, {})).toEqual('<div>ElementRef-true</div>');
@ -149,11 +153,13 @@ describe('di', () => {
function Template(ctx: any, cm: any) { function Template(ctx: any, cm: any) {
if (cm) { if (cm) {
container(0, [Directive, DirectiveSameInstance], function() {}); container(0, [Directive, DirectiveSameInstance], function() {});
text(3); text(1);
} }
// TODO: remove loadDirective when removing directive references
textBinding( textBinding(
3, interpolation2( 1, interpolation2(
'', load<Directive>(1).value, '-', load<DirectiveSameInstance>(2).value, '')); '', loadDirective<Directive>(0).value, '-',
loadDirective<DirectiveSameInstance>(1).value, ''));
} }
expect(renderToHtml(Template, {})).toEqual('TemplateRef-true'); expect(renderToHtml(Template, {})).toEqual('TemplateRef-true');
@ -189,12 +195,14 @@ describe('di', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, 'div', null, [Directive, DirectiveSameInstance]); elementStart(0, 'div', null, [Directive, DirectiveSameInstance]);
{ text(3); } { text(1); }
elementEnd(); elementEnd();
} }
// TODO: remove loadDirective when removing directive references
textBinding( textBinding(
3, interpolation2( 1, interpolation2(
'', load<Directive>(1).value, '-', load<DirectiveSameInstance>(2).value, '')); '', loadDirective<Directive>(0).value, '-',
loadDirective<DirectiveSameInstance>(1).value, ''));
} }
expect(renderToHtml(Template, {})).toEqual('<div>ViewContainerRef-true</div>'); expect(renderToHtml(Template, {})).toEqual('<div>ViewContainerRef-true</div>');
@ -255,9 +263,10 @@ describe('di', () => {
if (cm) { if (cm) {
elementStart(0, MyComp, $e0_attrs$, [Directive, DirectiveSameInstance]); elementStart(0, MyComp, $e0_attrs$, [Directive, DirectiveSameInstance]);
elementEnd(); elementEnd();
text(4); text(1);
} }
textBinding(4, bind(load<Directive>(2).value)); // TODO: remove loadDirective when removing directive references
textBinding(1, bind(loadDirective<Directive>(1).value));
} }
}); });
} }
@ -284,10 +293,11 @@ describe('di', () => {
template: function(ctx: any, cm: boolean) { template: function(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, 'div', $e0_attrs$, [Directive, DirectiveSameInstance]); elementStart(0, 'div', $e0_attrs$, [Directive, DirectiveSameInstance]);
{ text(3); } { text(1); }
elementEnd(); elementEnd();
} }
textBinding(3, bind(load<Directive>(1).value)); // TODO: remove loadDirective when removing directive references
textBinding(1, bind(loadDirective<Directive>(0).value));
} }
}); });
} }
@ -318,13 +328,14 @@ describe('di', () => {
if (cm) { if (cm) {
elementStart(0, MyComp); elementStart(0, MyComp);
{ {
elementStart(2, 'div', $e0_attrs$, [Directive, DirectiveSameInstance]); elementStart(1, 'div', $e0_attrs$, [Directive, DirectiveSameInstance]);
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
text(5); text(2);
} }
textBinding(5, bind(load<Directive>(3).value)); // TODO: remove loadDirective when removing directive references
textBinding(2, bind(loadDirective<Directive>(1).value));
} }
}); });
} }
@ -363,10 +374,11 @@ describe('di', () => {
if (ctx.showing) { if (ctx.showing) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
elementStart(0, 'div', $e0_attrs$, [Directive, DirectiveSameInstance]); elementStart(0, 'div', $e0_attrs$, [Directive, DirectiveSameInstance]);
{ text(3); } { text(1); }
elementEnd(); elementEnd();
} }
textBinding(3, bind(load<Directive>(1).value)); // TODO: remove loadDirective when removing directive references
textBinding(1, bind(loadDirective<Directive>(0).value));
} }
embeddedViewEnd(); embeddedViewEnd();
} }
@ -424,10 +436,11 @@ describe('di', () => {
function C1(ctx1: any, cm1: boolean) { function C1(ctx1: any, cm1: boolean) {
if (cm1) { if (cm1) {
elementStart(0, 'div', $e0_attrs$, [Directive, DirectiveSameInstance]); elementStart(0, 'div', $e0_attrs$, [Directive, DirectiveSameInstance]);
{ text(3); } { text(1); }
elementEnd(); elementEnd();
} }
textBinding(3, bind(load<Directive>(1).value)); // TODO: remove loadDirective when removing directive references
textBinding(1, bind(loadDirective<Directive>(0).value));
} }
} }
}); });
@ -591,19 +604,21 @@ describe('di', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, 'div', null, [ParentDirective]); elementStart(0, 'div', null, [ParentDirective]);
{ container(2); } { container(1); }
elementEnd(); elementEnd();
} }
containerRefreshStart(2); containerRefreshStart(1);
{ {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
elementStart(0, 'span', null, [ChildDirective, Child2Directive]); elementStart(0, 'span', null, [ChildDirective, Child2Directive]);
{ text(3); } { text(1); }
elementEnd(); elementEnd();
} }
// TODO: remove loadDirective when removing directive references
textBinding( textBinding(
3, interpolation2( 1, interpolation2(
'', load<ChildDirective>(1).value, '-', load<Child2Directive>(2).value, '')); '', loadDirective<ChildDirective>(0).value, '-',
loadDirective<Child2Directive>(1).value, ''));
embeddedViewEnd(); embeddedViewEnd();
} }
containerRefreshEnd(); containerRefreshEnd();

View File

@ -7,7 +7,7 @@
*/ */
import {defineDirective} from '../../src/render3/index'; import {defineDirective} from '../../src/render3/index';
import {bind, elementEnd, elementProperty, elementStart, load} from '../../src/render3/instructions'; import {bind, elementEnd, elementProperty, elementStart, loadDirective} from '../../src/render3/instructions';
import {renderToHtml} from './render_util'; import {renderToHtml} from './render_util';
@ -24,7 +24,8 @@ describe('directive', () => {
type: Directive, type: Directive,
factory: () => directiveInstance = new Directive, factory: () => directiveInstance = new Directive,
hostBindings: (directiveIndex: number, elementIndex: number) => { hostBindings: (directiveIndex: number, elementIndex: number) => {
elementProperty(elementIndex, 'className', bind(load<Directive>(directiveIndex).klass)); elementProperty(
elementIndex, 'className', bind(loadDirective<Directive>(directiveIndex).klass));
} }
}); });
} }

View File

@ -7,7 +7,7 @@
*/ */
import {defineComponent, defineDirective} from '../../src/render3/index'; 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 {bind, container, containerRefreshEnd, containerRefreshStart, elementAttribute, elementClassNamed, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, load, loadDirective, text, textBinding} from '../../src/render3/instructions';
import {renderToHtml} from './render_util'; import {renderToHtml} from './render_util';
@ -35,9 +35,10 @@ describe('exports', () => {
if (cm) { if (cm) {
elementStart(0, MyComponent, null, null, ['myComp', '']); elementStart(0, MyComponent, null, null, ['myComp', '']);
elementEnd(); elementEnd();
text(2); text(1);
} }
textBinding(2, load<MyComponent>(1).name); // TODO: replace loadDirective when removing directive refs
textBinding(1, loadDirective<MyComponent>(0).name);
} }
class MyComponent { class MyComponent {
@ -80,10 +81,11 @@ describe('exports', () => {
if (cm) { if (cm) {
elementStart(0, MyComponent, null, null, ['myComp', '']); elementStart(0, MyComponent, null, null, ['myComp', '']);
elementEnd(); elementEnd();
elementStart(2, 'div', null, [MyDir]); elementStart(1, 'div', null, [MyDir]);
elementEnd(); elementEnd();
} }
elementProperty(2, 'myDir', bind(load<MyComponent>(1))); // TODO: replace loadDirective when removing directive refs
elementProperty(1, 'myDir', bind(loadDirective<MyComponent>(0)));
} }
renderToHtml(Template, {}); renderToHtml(Template, {});
@ -97,14 +99,16 @@ describe('exports', () => {
if (cm) { if (cm) {
elementStart(0, 'div', null, [SomeDir], ['myDir', 'someDir']); elementStart(0, 'div', null, [SomeDir], ['myDir', 'someDir']);
elementEnd(); elementEnd();
text(2); text(1);
} }
textBinding(2, load<SomeDir>(1).name); // TODO: replace loadDirective when removing directive refs
textBinding(1, loadDirective<SomeDir>(0).name);
} }
class SomeDir { class SomeDir {
name = 'Drew'; name = 'Drew';
static ngDirectiveDef = defineDirective({type: SomeDir, factory: () => new SomeDir}); static ngDirectiveDef =
defineDirective({type: SomeDir, factory: () => new SomeDir, exportAs: 'someDir'});
} }
expect(renderToHtml(Template, {})).toEqual('<div></div>Drew'); expect(renderToHtml(Template, {})).toEqual('<div></div>Drew');
@ -206,10 +210,11 @@ describe('exports', () => {
if (cm) { if (cm) {
elementStart(0, 'div', null, [MyDir]); elementStart(0, 'div', null, [MyDir]);
elementEnd(); elementEnd();
elementStart(2, MyComponent, null, null, ['myComp', '']); elementStart(1, MyComponent, null, null, ['myComp', '']);
elementEnd(); elementEnd();
} }
elementProperty(0, 'myDir', bind(load<MyComponent>(3))); // TODO: replace loadDirective when removing directive refs
elementProperty(0, 'myDir', bind(loadDirective<MyComponent>(1)));
} }
renderToHtml(Template, {}); renderToHtml(Template, {});
@ -225,11 +230,12 @@ describe('exports', () => {
text(1); text(1);
elementStart(2, MyComponent, null, null, ['myComp', '']); elementStart(2, MyComponent, null, null, ['myComp', '']);
elementEnd(); elementEnd();
elementStart(4, 'input', ['value', 'one'], null, ['myInput', '']); elementStart(3, 'input', ['value', 'one'], null, ['myInput', '']);
elementEnd(); elementEnd();
} }
let myInput = elementStart(4); let myInput = elementStart(3);
let myComp = load<MyComponent>(3); // TODO: replace loadDirective when removing directive refs
let myComp = loadDirective<MyComponent>(0);
textBinding(0, bind(myInput && (myInput as any).value)); textBinding(0, bind(myInput && (myInput as any).value));
textBinding(1, bind(myComp && myComp.name)); textBinding(1, bind(myComp && myComp.name));
} }

View File

@ -7,7 +7,7 @@
*/ */
import {defineComponent, defineDirective} from '../../src/render3/index'; 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, projection, projectionDef, text, textBinding} from '../../src/render3/instructions'; 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 {ComponentFixture, containerEl, renderToHtml} from './render_util'; import {ComponentFixture, containerEl, renderToHtml} from './render_util';
@ -210,7 +210,7 @@ describe('render3 integration test', () => {
if (cm) { if (cm) {
elementStart(0, TodoComponent); elementStart(0, TodoComponent);
elementEnd(); elementEnd();
text(2, 'two'); text(1, 'two');
} }
} }
expect(renderToHtml(Template, null)).toEqual('<todo><p>Todo one</p></todo>two'); expect(renderToHtml(Template, null)).toEqual('<todo><p>Todo one</p></todo>two');
@ -225,7 +225,7 @@ describe('render3 integration test', () => {
if (cm) { if (cm) {
elementStart(0, TodoComponent); elementStart(0, TodoComponent);
elementEnd(); elementEnd();
elementStart(2, TodoComponent); elementStart(1, TodoComponent);
elementEnd(); elementEnd();
} }
} }
@ -252,7 +252,8 @@ describe('render3 integration test', () => {
hostBindings: function(directiveIndex: number, elementIndex: number): void { hostBindings: function(directiveIndex: number, elementIndex: number): void {
// host bindings // host bindings
elementProperty( elementProperty(
elementIndex, 'title', bind(load<TodoComponentHostBinding>(directiveIndex).title)); elementIndex, 'title',
bind(loadDirective<TodoComponentHostBinding>(directiveIndex).title));
} }
}); });
} }
@ -460,12 +461,12 @@ describe('render3 integration test', () => {
function parentTemplate(ctx: ParentCtx, cm: boolean) { function parentTemplate(ctx: ParentCtx, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, ChildComponent); elementStart(0, ChildComponent);
{ container(2); } { container(1); }
elementEnd(); elementEnd();
} }
elementProperty(0, 'beforeTree', bind(ctx.beforeTree)); elementProperty(0, 'beforeTree', bind(ctx.beforeTree));
elementProperty(0, 'afterTree', bind(ctx.afterTree)); elementProperty(0, 'afterTree', bind(ctx.afterTree));
containerRefreshStart(2); containerRefreshStart(1);
{ {
const cm0 = embeddedViewStart(0); const cm0 = embeddedViewStart(0);
{ showTree({tree: ctx.projectedTree}, cm0); } { showTree({tree: ctx.projectedTree}, cm0); }
@ -636,7 +637,8 @@ describe('render3 integration test', () => {
return hostBindingDir = new HostBindingDir(); return hostBindingDir = new HostBindingDir();
}, },
hostBindings: function HostBindingDir_HostBindings(dirIndex: number, elIndex: number) { hostBindings: function HostBindingDir_HostBindings(dirIndex: number, elIndex: number) {
elementAttribute(elIndex, 'aria-label', bind(load<HostBindingDir>(dirIndex).label)); elementAttribute(
elIndex, 'aria-label', bind(loadDirective<HostBindingDir>(dirIndex).label));
} }
}); });
} }

View File

@ -120,11 +120,11 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Parent); elementStart(0, Parent);
elementEnd(); elementEnd();
elementStart(2, Parent); elementStart(1, Parent);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(2, 'val', 2); elementProperty(1, 'val', 2);
} }
renderToHtml(Template, {}); renderToHtml(Template, {});
@ -175,7 +175,7 @@ describe('lifecycles', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Comp); elementStart(0, Comp);
{ elementStart(2, ProjectedComp); } { elementStart(1, ProjectedComp); }
elementEnd(); elementEnd();
} }
} }
@ -196,16 +196,16 @@ describe('lifecycles', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Comp); elementStart(0, Comp);
{ elementStart(2, ProjectedComp); } { elementStart(1, ProjectedComp); }
elementEnd(); elementEnd();
elementStart(4, Comp); elementStart(2, Comp);
{ elementStart(6, ProjectedComp); } { elementStart(3, ProjectedComp); }
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(2, 'val', 1); elementProperty(1, 'val', 1);
elementProperty(4, 'val', 2); elementProperty(2, 'val', 2);
elementProperty(6, 'val', 2); elementProperty(3, 'val', 2);
} }
renderToHtml(Template, {}); renderToHtml(Template, {});
@ -258,13 +258,13 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Comp); elementStart(0, Comp);
elementEnd(); elementEnd();
container(2); container(1);
elementStart(3, Comp); elementStart(2, Comp);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(3, 'val', 5); elementProperty(2, 'val', 5);
containerRefreshStart(2); containerRefreshStart(1);
{ {
for (let j = 2; j < 5; j++) { for (let j = 2; j < 5; j++) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
@ -298,13 +298,13 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Parent); elementStart(0, Parent);
elementEnd(); elementEnd();
container(2); container(1);
elementStart(3, Parent); elementStart(2, Parent);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(3, 'val', 5); elementProperty(2, 'val', 5);
containerRefreshStart(2); containerRefreshStart(1);
{ {
for (let j = 2; j < 5; j++) { for (let j = 2; j < 5; j++) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
@ -475,7 +475,7 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
projectionDef(0); projectionDef(0);
elementStart(1, Comp); elementStart(1, Comp);
{ projection(3, 0); } { projection(2, 0); }
elementEnd(); elementEnd();
} }
elementProperty(1, 'val', bind(ctx.val)); elementProperty(1, 'val', bind(ctx.val));
@ -512,7 +512,7 @@ describe('lifecycles', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Comp); elementStart(0, Comp);
{ text(2, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
} }
@ -548,7 +548,7 @@ describe('lifecycles', () => {
if (ctx.condition) { if (ctx.condition) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
elementStart(0, Comp); elementStart(0, Comp);
{ text(2, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
embeddedViewEnd(); embeddedViewEnd();
@ -576,7 +576,7 @@ describe('lifecycles', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Parent); elementStart(0, Parent);
{ text(2, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
} }
@ -595,14 +595,14 @@ describe('lifecycles', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Parent); elementStart(0, Parent);
{ text(2, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
elementStart(3, Parent); elementStart(2, Parent);
{ text(5, 'content'); } { text(3, 'content'); }
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(3, 'val', 2); elementProperty(2, 'val', 2);
} }
renderToHtml(Template, {}); renderToHtml(Template, {});
@ -624,8 +624,8 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Parent); elementStart(0, Parent);
{ {
elementStart(2, ProjectedComp); elementStart(1, ProjectedComp);
{ text(4, 'content'); } { text(2, 'content'); }
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
@ -654,23 +654,23 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Parent); elementStart(0, Parent);
{ {
elementStart(2, ProjectedComp); elementStart(1, ProjectedComp);
{ text(4, 'content'); } { text(2, 'content'); }
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
elementStart(5, Parent); elementStart(3, Parent);
{ {
elementStart(7, ProjectedComp); elementStart(4, ProjectedComp);
{ text(9, 'content'); } { text(5, 'content'); }
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(2, 'val', 1); elementProperty(1, 'val', 1);
elementProperty(5, 'val', 2); elementProperty(3, 'val', 2);
elementProperty(7, 'val', 2); elementProperty(4, 'val', 2);
} }
renderToHtml(Template, {}); renderToHtml(Template, {});
@ -688,21 +688,21 @@ describe('lifecycles', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Comp); elementStart(0, Comp);
{ text(2, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
container(3); container(2);
elementStart(4, Comp); elementStart(3, Comp);
{ text(6, 'content'); } { text(4, 'content'); }
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(4, 'val', 4); elementProperty(3, 'val', 4);
containerRefreshStart(3); containerRefreshStart(2);
{ {
for (let i = 2; i < 4; i++) { for (let i = 2; i < 4; i++) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
elementStart(0, Comp); elementStart(0, Comp);
{ text(2, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', i); elementProperty(0, 'val', i);
@ -719,21 +719,21 @@ describe('lifecycles', () => {
function ForLoopWithChildrenTemplate(ctx: any, cm: boolean) { function ForLoopWithChildrenTemplate(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Parent); elementStart(0, Parent);
{ text(2, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
container(3); container(2);
elementStart(4, Parent); elementStart(3, Parent);
{ text(6, 'content'); } { text(4, 'content'); }
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(4, 'val', 4); elementProperty(3, 'val', 4);
containerRefreshStart(3); containerRefreshStart(2);
{ {
for (let i = 2; i < 4; i++) { for (let i = 2; i < 4; i++) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
elementStart(0, Parent); elementStart(0, Parent);
{ text(2, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', i); elementProperty(0, 'val', i);
@ -764,7 +764,7 @@ describe('lifecycles', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Comp); elementStart(0, Comp);
{ text(2, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
} }
@ -956,11 +956,11 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Parent); elementStart(0, Parent);
elementEnd(); elementEnd();
elementStart(2, Parent); elementStart(1, Parent);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(2, 'val', 2); elementProperty(1, 'val', 2);
} }
renderToHtml(Template, {}); renderToHtml(Template, {});
expect(events).toEqual(['comp1', 'comp2', 'parent1', 'parent2']); expect(events).toEqual(['comp1', 'comp2', 'parent1', 'parent2']);
@ -977,7 +977,7 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Comp); elementStart(0, Comp);
{ {
elementStart(2, ProjectedComp); elementStart(1, ProjectedComp);
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
@ -1001,21 +1001,21 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Comp); elementStart(0, Comp);
{ {
elementStart(2, ProjectedComp); elementStart(1, ProjectedComp);
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
elementStart(4, Comp); elementStart(2, Comp);
{ {
elementStart(6, ProjectedComp); elementStart(3, ProjectedComp);
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(2, 'val', 1); elementProperty(1, 'val', 1);
elementProperty(4, 'val', 2); elementProperty(2, 'val', 2);
elementProperty(6, 'val', 2); elementProperty(3, 'val', 2);
} }
renderToHtml(Template, {}); renderToHtml(Template, {});
@ -1032,13 +1032,13 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Comp); elementStart(0, Comp);
{ {
elementStart(2, ProjectedComp); elementStart(1, ProjectedComp);
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', bind(ctx.val)); elementProperty(0, 'val', bind(ctx.val));
elementProperty(2, 'val', bind(ctx.val)); elementProperty(1, 'val', bind(ctx.val));
}); });
/** /**
@ -1049,11 +1049,11 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, ParentComp); elementStart(0, ParentComp);
elementEnd(); elementEnd();
elementStart(2, ParentComp); elementStart(1, ParentComp);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(2, 'val', 2); elementProperty(1, 'val', 2);
} }
renderToHtml(Template, {}); renderToHtml(Template, {});
@ -1072,13 +1072,13 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Comp); elementStart(0, Comp);
elementEnd(); elementEnd();
container(2); container(1);
elementStart(3, Comp); elementStart(2, Comp);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(3, 'val', 4); elementProperty(2, 'val', 4);
containerRefreshStart(2); containerRefreshStart(1);
{ {
for (let i = 2; i < 4; i++) { for (let i = 2; i < 4; i++) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
@ -1109,13 +1109,13 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Parent); elementStart(0, Parent);
elementEnd(); elementEnd();
container(2); container(1);
elementStart(3, Parent); elementStart(2, Parent);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(3, 'val', 4); elementProperty(2, 'val', 4);
containerRefreshStart(2); containerRefreshStart(1);
{ {
for (let i = 2; i < 4; i++) { for (let i = 2; i < 4; i++) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
@ -1191,13 +1191,13 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Parent); elementStart(0, Parent);
elementEnd(); elementEnd();
container(2); container(1);
elementStart(3, Parent); elementStart(2, Parent);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(3, 'val', 4); elementProperty(2, 'val', 4);
containerRefreshStart(2); containerRefreshStart(1);
{ {
for (let i = 2; i < 4; i++) { for (let i = 2; i < 4; i++) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
@ -1339,11 +1339,11 @@ describe('lifecycles', () => {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
elementStart(0, Comp); elementStart(0, Comp);
elementEnd(); elementEnd();
elementStart(2, Comp); elementStart(1, Comp);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', bind('1')); elementProperty(0, 'val', bind('1'));
elementProperty(2, 'val', bind('2')); elementProperty(1, 'val', bind('2'));
embeddedViewEnd(); embeddedViewEnd();
} }
} }
@ -1448,21 +1448,21 @@ describe('lifecycles', () => {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
elementStart(0, Comp); elementStart(0, Comp);
{ {
elementStart(2, ProjectedComp); elementStart(1, ProjectedComp);
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
elementStart(4, Comp); elementStart(2, Comp);
{ {
elementStart(6, ProjectedComp); elementStart(3, ProjectedComp);
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(2, 'val', 1); elementProperty(1, 'val', 1);
elementProperty(4, 'val', 2); elementProperty(2, 'val', 2);
elementProperty(6, 'val', 2); elementProperty(3, 'val', 2);
embeddedViewEnd(); embeddedViewEnd();
} }
} }
@ -1497,13 +1497,13 @@ describe('lifecycles', () => {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
elementStart(0, Comp); elementStart(0, Comp);
elementEnd(); elementEnd();
container(2); container(1);
elementStart(3, Comp); elementStart(2, Comp);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', bind('1')); elementProperty(0, 'val', bind('1'));
elementProperty(3, 'val', bind('3')); elementProperty(2, 'val', bind('3'));
containerRefreshStart(2); containerRefreshStart(1);
{ {
if (ctx.condition2) { if (ctx.condition2) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
@ -1567,13 +1567,13 @@ describe('lifecycles', () => {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
elementStart(0, Comp); elementStart(0, Comp);
elementEnd(); elementEnd();
container(2); container(1);
elementStart(3, Comp); elementStart(2, Comp);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', bind('1')); elementProperty(0, 'val', bind('1'));
elementProperty(3, 'val', bind('5')); elementProperty(2, 'val', bind('5'));
containerRefreshStart(2); containerRefreshStart(1);
{ {
for (let j = 2; j < ctx.len; j++) { for (let j = 2; j < ctx.len; j++) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
@ -1645,10 +1645,10 @@ describe('lifecycles', () => {
elementEnd(); elementEnd();
elementStart(2, Comp); elementStart(2, Comp);
elementEnd(); elementEnd();
elementStart(4, 'button'); elementStart(3, 'button');
{ {
listener('click', ctx.onClick.bind(ctx)); listener('click', ctx.onClick.bind(ctx));
text(5, 'Click me'); text(4, 'Click me');
} }
elementEnd(); elementEnd();
} }
@ -1868,13 +1868,13 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Parent); elementStart(0, Parent);
elementEnd(); elementEnd();
elementStart(2, Parent); elementStart(1, Parent);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val1', bind(1)); elementProperty(0, 'val1', bind(1));
elementProperty(0, 'publicName', bind(1)); elementProperty(0, 'publicName', bind(1));
elementProperty(2, 'val1', bind(2)); elementProperty(1, 'val1', bind(2));
elementProperty(2, 'publicName', bind(2)); elementProperty(1, 'publicName', bind(2));
} }
renderToHtml(Template, {}); renderToHtml(Template, {});
@ -1935,13 +1935,13 @@ describe('lifecycles', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Comp); elementStart(0, Comp);
{ elementStart(2, ProjectedComp); } { elementStart(1, ProjectedComp); }
elementEnd(); elementEnd();
} }
elementProperty(0, 'val1', bind(1)); elementProperty(0, 'val1', bind(1));
elementProperty(0, 'publicName', bind(1)); elementProperty(0, 'publicName', bind(1));
elementProperty(2, 'val1', bind(2)); elementProperty(1, 'val1', bind(2));
elementProperty(2, 'publicName', bind(2)); elementProperty(1, 'publicName', bind(2));
} }
renderToHtml(Template, {}); renderToHtml(Template, {});
@ -1963,20 +1963,20 @@ describe('lifecycles', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, Comp); elementStart(0, Comp);
{ elementStart(2, ProjectedComp); } { elementStart(1, ProjectedComp); }
elementEnd(); elementEnd();
elementStart(4, Comp); elementStart(2, Comp);
{ elementStart(6, ProjectedComp); } { elementStart(3, ProjectedComp); }
elementEnd(); elementEnd();
} }
elementProperty(0, 'val1', bind(1)); elementProperty(0, 'val1', bind(1));
elementProperty(0, 'publicName', bind(1)); elementProperty(0, 'publicName', bind(1));
elementProperty(2, 'val1', bind(2)); elementProperty(1, 'val1', bind(2));
elementProperty(2, 'publicName', bind(2)); elementProperty(1, 'publicName', bind(2));
elementProperty(4, 'val1', bind(3)); elementProperty(2, 'val1', bind(3));
elementProperty(4, 'publicName', bind(3)); elementProperty(2, 'publicName', bind(3));
elementProperty(6, 'val1', bind(4)); elementProperty(3, 'val1', bind(4));
elementProperty(6, 'publicName', bind(4)); elementProperty(3, 'publicName', bind(4));
} }
renderToHtml(Template, {}); renderToHtml(Template, {});
@ -2042,15 +2042,15 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Comp); elementStart(0, Comp);
elementEnd(); elementEnd();
container(2); container(1);
elementStart(3, Comp); elementStart(2, Comp);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val1', bind(1)); elementProperty(0, 'val1', bind(1));
elementProperty(0, 'publicName', bind(1)); elementProperty(0, 'publicName', bind(1));
elementProperty(3, 'val1', bind(5)); elementProperty(2, 'val1', bind(5));
elementProperty(3, 'publicName', bind(5)); elementProperty(2, 'publicName', bind(5));
containerRefreshStart(2); containerRefreshStart(1);
{ {
for (let j = 2; j < 5; j++) { for (let j = 2; j < 5; j++) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
@ -2091,15 +2091,15 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Parent); elementStart(0, Parent);
elementEnd(); elementEnd();
container(2); container(1);
elementStart(3, Parent); elementStart(2, Parent);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val1', bind(1)); elementProperty(0, 'val1', bind(1));
elementProperty(0, 'publicName', bind(1)); elementProperty(0, 'publicName', bind(1));
elementProperty(3, 'val1', bind(5)); elementProperty(2, 'val1', bind(5));
elementProperty(3, 'publicName', bind(5)); elementProperty(2, 'publicName', bind(5));
containerRefreshStart(2); containerRefreshStart(1);
{ {
for (let j = 2; j < 5; j++) { for (let j = 2; j < 5; j++) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
@ -2176,11 +2176,11 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Comp); elementStart(0, Comp);
elementEnd(); elementEnd();
elementStart(2, Comp); elementStart(1, Comp);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(2, 'val', 2); elementProperty(1, 'val', 2);
} }
renderToHtml(Template, {}); renderToHtml(Template, {});
@ -2218,11 +2218,11 @@ describe('lifecycles', () => {
if (cm) { if (cm) {
elementStart(0, Parent); elementStart(0, Parent);
elementEnd(); elementEnd();
elementStart(2, Parent); elementStart(1, Parent);
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', 1); elementProperty(0, 'val', 1);
elementProperty(2, 'val', 2); elementProperty(1, 'val', 2);
} }
renderToHtml(Template, {}); renderToHtml(Template, {});

View File

@ -246,7 +246,7 @@ describe('event listeners', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, 'button', ['hostListenerDir', ''], [HostListenerDir]); elementStart(0, 'button', ['hostListenerDir', ''], [HostListenerDir]);
text(2, 'Click'); text(1, 'Click');
elementEnd(); elementEnd();
} }
} }
@ -339,7 +339,7 @@ describe('event listeners', () => {
text(0, 'Hello'); text(0, 'Hello');
elementStart(1, MyComp); elementStart(1, MyComp);
elementEnd(); elementEnd();
elementStart(3, MyComp); elementStart(2, MyComp);
elementEnd(); elementEnd();
} }
embeddedViewEnd(); embeddedViewEnd();

View File

@ -248,7 +248,7 @@ describe('outputs', () => {
listener('change', function() { return ctx.onChange(); }); listener('change', function() { return ctx.onChange(); });
} }
elementEnd(); elementEnd();
elementStart(4, DestroyComp); elementStart(3, DestroyComp);
elementEnd(); elementEnd();
} }
embeddedViewEnd(); embeddedViewEnd();

View File

@ -10,7 +10,7 @@ import {Directive, OnChanges, OnDestroy, Pipe, PipeTransform, SimpleChange, Simp
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
import {NgOnChangesFeature, defineComponent, defineDirective, definePipe} from '../../src/render3/definition'; import {NgOnChangesFeature, defineComponent, defineDirective, definePipe} from '../../src/render3/definition';
import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, load, text, textBinding} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, load, loadDirective, text, textBinding} from '../../src/render3/instructions';
import {pipe, pipeBind1, pipeBind3, pipeBind4, pipeBindV} from '../../src/render3/pipe'; import {pipe, pipeBind1, pipeBind3, pipeBind4, pipeBindV} from '../../src/render3/pipe';
import {RenderLog, getRendererFactory2, patchLoggingRenderer2} from './imported_renderer2'; import {RenderLog, getRendererFactory2, patchLoggingRenderer2} from './imported_renderer2';
@ -68,11 +68,11 @@ describe('pipe', () => {
function Template(ctx: string, cm: boolean) { function Template(ctx: string, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, 'div', null, [MyDir]); elementStart(0, 'div', null, [MyDir]);
pipe(2, DoublePipe.ngPipeDef); pipe(1, DoublePipe.ngPipeDef);
elementEnd(); elementEnd();
} }
elementProperty(0, 'elprop', bind(pipeBind1(2, ctx))); elementProperty(0, 'elprop', bind(pipeBind1(1, ctx)));
directive = load(1); directive = loadDirective(0);
} }
renderToHtml(Template, 'a'); renderToHtml(Template, 'a');
expect(directive !.dirProp).toEqual('aa'); expect(directive !.dirProp).toEqual('aa');

View File

@ -9,7 +9,7 @@
import {EventEmitter} from '@angular/core'; import {EventEmitter} from '@angular/core';
import {defineComponent, defineDirective, tick} from '../../src/render3/index'; import {defineComponent, defineDirective, tick} from '../../src/render3/index';
import {NO_CHANGE, bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, listener, load, text, textBinding} from '../../src/render3/instructions'; import {NO_CHANGE, bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, listener, loadDirective, text, textBinding} from '../../src/render3/instructions';
import {ComponentFixture, renderToHtml} from './render_util'; import {ComponentFixture, renderToHtml} from './render_util';
@ -71,7 +71,7 @@ describe('elementProperty', () => {
tag: 'host-binding-comp', tag: 'host-binding-comp',
factory: () => new HostBindingComp(), factory: () => new HostBindingComp(),
hostBindings: (dirIndex: number, elIndex: number) => { hostBindings: (dirIndex: number, elIndex: number) => {
const instance = load(dirIndex) as HostBindingComp; const instance = loadDirective(dirIndex) as HostBindingComp;
elementProperty(elIndex, 'id', bind(instance.id)); elementProperty(elIndex, 'id', bind(instance.id));
}, },
template: (ctx: HostBindingComp, cm: boolean) => {} template: (ctx: HostBindingComp, cm: boolean) => {}
@ -115,7 +115,7 @@ describe('elementProperty', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, 'button', null, [MyButton, OtherDir]); elementStart(0, 'button', null, [MyButton, OtherDir]);
{ text(3, 'Click me'); } { text(1, 'Click me'); }
elementEnd(); elementEnd();
} }
@ -141,7 +141,7 @@ describe('elementProperty', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, 'button', null, [MyButton]); elementStart(0, 'button', null, [MyButton]);
{ text(2, 'Click me'); } { text(1, 'Click me'); }
elementEnd(); elementEnd();
} }
@ -206,7 +206,7 @@ describe('elementProperty', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, 'button', null, [MyButton, OtherDisabledDir]); elementStart(0, 'button', null, [MyButton, OtherDisabledDir]);
{ text(3, 'Click me'); } { text(1, 'Click me'); }
elementEnd(); elementEnd();
} }
elementProperty(0, 'disabled', bind(ctx.isDisabled)); elementProperty(0, 'disabled', bind(ctx.isDisabled));
@ -230,7 +230,7 @@ describe('elementProperty', () => {
elementStart(0, 'button', null, [OtherDir]); elementStart(0, 'button', null, [OtherDir]);
{ {
listener('click', ctx.onClick.bind(ctx)); listener('click', ctx.onClick.bind(ctx));
text(2, 'Click me'); text(1, 'Click me');
} }
elementEnd(); elementEnd();
} }
@ -271,12 +271,12 @@ describe('elementProperty', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, 'button', null, [IdDir]); elementStart(0, 'button', null, [IdDir]);
{ text(2, 'Click me'); } { text(1, 'Click me'); }
elementEnd(); elementEnd();
container(3); container(2);
} }
elementProperty(0, 'id', bind(ctx.id1)); elementProperty(0, 'id', bind(ctx.id1));
containerRefreshStart(3); containerRefreshStart(2);
{ {
if (ctx.condition) { if (ctx.condition) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
@ -289,7 +289,7 @@ describe('elementProperty', () => {
} else { } else {
if (embeddedViewStart(1)) { if (embeddedViewStart(1)) {
elementStart(0, 'button', null, [OtherDir]); elementStart(0, 'button', null, [OtherDir]);
{ text(2, 'Click me too'); } { text(1, 'Click me too'); }
elementEnd(); elementEnd();
} }
elementProperty(0, 'id', bind(ctx.id3)); elementProperty(0, 'id', bind(ctx.id3));
@ -322,7 +322,8 @@ describe('elementProperty', () => {
type: MyDir, type: MyDir,
factory: () => myDir = new MyDir(), factory: () => myDir = new MyDir(),
inputs: {role: 'role', direction: 'dir'}, inputs: {role: 'role', direction: 'dir'},
outputs: {changeStream: 'change'} outputs: {changeStream: 'change'},
exportAs: 'myDir'
}); });
} }
@ -419,7 +420,6 @@ describe('elementProperty', () => {
it('should process attributes properly for directives with later indices', () => { it('should process attributes properly for directives with later indices', () => {
/** /**
* <div role="button" dir="rtl" myDir></div> * <div role="button" dir="rtl" myDir></div>
* <div role="listbox" myDirB></div> * <div role="listbox" myDirB></div>
@ -428,7 +428,7 @@ describe('elementProperty', () => {
if (cm) { if (cm) {
elementStart(0, 'div', ['role', 'button', 'dir', 'rtl'], [MyDir]); elementStart(0, 'div', ['role', 'button', 'dir', 'rtl'], [MyDir]);
elementEnd(); elementEnd();
elementStart(2, 'div', ['role', 'listbox'], [MyDirB]); elementStart(1, 'div', ['role', 'listbox'], [MyDirB]);
elementEnd(); elementEnd();
} }
} }
@ -454,9 +454,9 @@ describe('elementProperty', () => {
if (cm) { if (cm) {
elementStart(0, 'div', ['role', 'listbox'], [MyDir]); elementStart(0, 'div', ['role', 'listbox'], [MyDir]);
elementEnd(); elementEnd();
container(2); container(1);
} }
containerRefreshStart(2); containerRefreshStart(1);
{ {
if (ctx.condition) { if (ctx.condition) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
@ -495,13 +495,15 @@ describe('elementProperty', () => {
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: Comp, type: Comp,
tag: 'comp', tag: 'comp',
/** <div role="button" dir #dir="myDir"></div> {{ dir.role }} */
template: function(ctx: any, cm: boolean) { template: function(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, 'div', ['role', 'button'], [MyDir]); elementStart(0, 'div', ['role', 'button'], [MyDir], ['dir', 'myDir']);
elementEnd(); elementEnd();
text(2); text(1);
} }
textBinding(2, bind(load<MyDir>(1).role)); // TODO: remove this loadDirective when removing MyDir
textBinding(1, bind(loadDirective<MyDir>(0).role));
}, },
factory: () => new Comp() factory: () => new Comp()
}); });

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {defineComponent} from '../../src/render3/index'; import {defineComponent} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, load} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, load, loadDirective} from '../../src/render3/instructions';
import {pureFunction1, pureFunction2, pureFunction3, pureFunction4, pureFunction5, pureFunction6, pureFunction7, pureFunction8, pureFunctionV} from '../../src/render3/pure_function'; import {pureFunction1, pureFunction2, pureFunction3, pureFunction4, pureFunction5, pureFunction6, pureFunction7, pureFunction8, pureFunctionV} from '../../src/render3/pure_function';
import {renderToHtml} from '../../test/render3/render_util'; import {renderToHtml} from '../../test/render3/render_util';
@ -120,7 +120,7 @@ describe('array literals', () => {
template: function(ctx: any, cm: boolean) { template: function(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, MyComp); elementStart(0, MyComp);
myComps.push(load(1)); myComps.push(loadDirective(0));
elementEnd(); elementEnd();
} }
elementProperty(0, 'names', bind(ctx.someFn(pureFunction1(e0_ff, ctx.customName)))); elementProperty(0, 'names', bind(ctx.someFn(pureFunction1(e0_ff, ctx.customName))));
@ -132,7 +132,7 @@ describe('array literals', () => {
if (cm) { if (cm) {
elementStart(0, ParentComp); elementStart(0, ParentComp);
elementEnd(); elementEnd();
elementStart(2, ParentComp); elementStart(1, ParentComp);
elementEnd(); elementEnd();
} }
} }
@ -211,32 +211,32 @@ describe('array literals', () => {
function Template(c: any, cm: boolean) { function Template(c: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, MyComp); elementStart(0, MyComp);
f3Comp = load(1); f3Comp = loadDirective(0);
elementEnd();
elementStart(1, MyComp);
f4Comp = loadDirective(1);
elementEnd(); elementEnd();
elementStart(2, MyComp); elementStart(2, MyComp);
f4Comp = load(3); f5Comp = loadDirective(2);
elementEnd();
elementStart(3, MyComp);
f6Comp = loadDirective(3);
elementEnd(); elementEnd();
elementStart(4, MyComp); elementStart(4, MyComp);
f5Comp = load(5); f7Comp = loadDirective(4);
elementEnd(); elementEnd();
elementStart(6, MyComp); elementStart(5, MyComp);
f6Comp = load(7); f8Comp = loadDirective(5);
elementEnd();
elementStart(8, MyComp);
f7Comp = load(9);
elementEnd();
elementStart(10, MyComp);
f8Comp = load(11);
elementEnd(); elementEnd();
} }
elementProperty(0, 'names', bind(pureFunction3(e0_ff, c[5], c[6], c[7]))); elementProperty(0, 'names', bind(pureFunction3(e0_ff, c[5], c[6], c[7])));
elementProperty(2, 'names', bind(pureFunction4(e2_ff, c[4], c[5], c[6], c[7]))); elementProperty(1, 'names', bind(pureFunction4(e2_ff, c[4], c[5], c[6], c[7])));
elementProperty(4, 'names', bind(pureFunction5(e4_ff, c[3], 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(6, 'names', bind(pureFunction6(e6_ff, c[2], 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( elementProperty(
8, 'names', bind(pureFunction7(e8_ff, c[1], c[2], c[3], c[4], c[5], c[6], c[7]))); 4, 'names', bind(pureFunction7(e8_ff, c[1], c[2], c[3], c[4], c[5], c[6], c[7])));
elementProperty( elementProperty(
10, 'names', bind(pureFunction8(e10_ff, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]))); 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']); renderToHtml(Template, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']);
@ -422,7 +422,7 @@ describe('object literals', () => {
for (let i = 0; i < 2; i++) { for (let i = 0; i < 2; i++) {
if (embeddedViewStart(0)) { if (embeddedViewStart(0)) {
elementStart(0, ObjectComp); elementStart(0, ObjectComp);
objectComps.push(load(1)); objectComps.push(loadDirective(0));
elementEnd(); elementEnd();
} }
elementProperty( elementProperty(

View File

@ -7,7 +7,7 @@
*/ */
import {QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF} from '../../src/render3/di'; 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 {QueryList, defineComponent, detectChanges} from '../../src/render3/index';
import {container, containerRefreshEnd, containerRefreshStart, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, load} from '../../src/render3/instructions'; import {container, containerRefreshEnd, containerRefreshStart, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, load, loadDirective} from '../../src/render3/instructions';
import {query, queryRefresh} from '../../src/render3/query'; import {query, queryRefresh} from '../../src/render3/query';
import {createComponent, createDirective, renderComponent} from './render_util'; import {createComponent, createDirective, renderComponent} from './render_util';
@ -64,9 +64,9 @@ describe('query', () => {
query(1, Child, true); query(1, Child, true);
elementStart(2, Child); elementStart(2, Child);
{ {
child1 = load(3); child1 = loadDirective(0);
elementStart(4, Child); elementStart(3, Child);
{ child2 = load(5); } { child2 = loadDirective(1); }
elementEnd(); elementEnd();
} }
elementEnd(); elementEnd();
@ -124,7 +124,7 @@ describe('query', () => {
if (cm) { if (cm) {
query(0, Child, false, OtherChild); query(0, Child, false, OtherChild);
elementStart(1, 'div', null, [Child, OtherChild]); elementStart(1, 'div', null, [Child, OtherChild]);
{ otherChildInstance = load(3); } { otherChildInstance = loadDirective(1); }
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
@ -418,7 +418,7 @@ describe('query', () => {
if (cm) { if (cm) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE);
elementStart(1, Child, null, null, ['foo', '']); elementStart(1, Child, null, null, ['foo', '']);
{ childInstance = load(2); } { childInstance = loadDirective(0); }
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
@ -481,7 +481,7 @@ describe('query', () => {
if (cm) { if (cm) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE);
elementStart(1, 'div', null, [Child], ['foo', 'child']); elementStart(1, 'div', null, [Child], ['foo', 'child']);
childInstance = load(2); childInstance = loadDirective(0);
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
@ -510,8 +510,8 @@ describe('query', () => {
query(0, ['foo', 'bar'], true, QUERY_READ_FROM_NODE); query(0, ['foo', 'bar'], true, QUERY_READ_FROM_NODE);
elementStart(1, 'div', null, [Child1, Child2], ['foo', 'child1', 'bar', 'child2']); elementStart(1, 'div', null, [Child1, Child2], ['foo', 'child1', 'bar', 'child2']);
{ {
child1Instance = load(2); child1Instance = loadDirective(0);
child2Instance = load(3); child2Instance = loadDirective(1);
} }
elementEnd(); elementEnd();
} }
@ -542,7 +542,7 @@ describe('query', () => {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE);
query(1, ['bar'], true, QUERY_READ_FROM_NODE); query(1, ['bar'], true, QUERY_READ_FROM_NODE);
elementStart(2, 'div', null, [Child], ['foo', 'child', 'bar', 'child']); elementStart(2, 'div', null, [Child], ['foo', 'child', 'bar', 'child']);
{ childInstance = load(3); } { childInstance = loadDirective(0); }
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.fooQuery = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.fooQuery = tmp as QueryList<any>);
@ -601,7 +601,7 @@ describe('query', () => {
if (cm) { if (cm) {
query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE); query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE);
div = elementStart(1, 'div', null, [Child], ['foo', '', 'bar', 'child']); div = elementStart(1, 'div', null, [Child], ['foo', '', 'bar', 'child']);
{ childInstance = load(2); } { childInstance = loadDirective(0); }
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);

View File

@ -8,7 +8,7 @@
import {TemplateRef, ViewContainerRef} from '../../src/core'; import {TemplateRef, ViewContainerRef} from '../../src/core';
import {defineComponent, defineDirective, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index'; import {defineComponent, defineDirective, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, load, text, textBinding} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, loadDirective, text, textBinding} from '../../src/render3/instructions';
import {renderComponent, toHtml} from './render_util'; import {renderComponent, toHtml} from './render_util';
@ -40,7 +40,7 @@ describe('ViewContainerRef', () => {
container(0, [TestDirective], subTemplate); container(0, [TestDirective], subTemplate);
} }
containerRefreshStart(0); containerRefreshStart(0);
cmp.testDir = load<TestDirective>(1); cmp.testDir = loadDirective<TestDirective>(0);
containerRefreshEnd(); containerRefreshEnd();
}, },
}); });