refactor(core): view engine - misc

- fix bug when detaching view from `ApplicationRef`
- fix integration of adding `ng-reflect` attributes
  in debug mode.
This commit is contained in:
Tobias Bosch 2017-02-22 10:05:56 -08:00 committed by Igor Minar
parent 5049a50bf6
commit ab3527c99b
18 changed files with 307 additions and 223 deletions

View File

@ -255,7 +255,7 @@ export class Identifiers {
static pureArrayDef:
IdentifierSpec = {name: 'ɵpureArrayDef', moduleUrl: CORE, runtime: ɵpureArrayDef};
static pureObjectDef:
IdentifierSpec = {name: 'ɵpureObjectRef', moduleUrl: CORE, runtime: ɵpureObjectDef};
IdentifierSpec = {name: 'ɵpureObjectDef', moduleUrl: CORE, runtime: ɵpureObjectDef};
static purePipeDef:
IdentifierSpec = {name: 'ɵpurePipeDef', moduleUrl: CORE, runtime: ɵpurePipeDef};
static pipeDef: IdentifierSpec = {name: 'ɵpipeDef', moduleUrl: CORE, runtime: ɵpipeDef};

View File

@ -447,7 +447,9 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
dirAst.directive.queries.forEach((query, queryIndex) => {
let flags = NodeFlags.HasContentQuery;
const queryId = dirAst.contentQueryStartId + queryIndex;
if (queryIds.staticQueryIds.has(queryId)) {
// Note: We only make queries static that query for a single item.
// This is because of backwards compatibility with the old view compiler...
if (queryIds.staticQueryIds.has(queryId) && query.first) {
flags |= NodeFlags.HasStaticQuery;
} else {
flags |= NodeFlags.HasDynamicQuery;

View File

@ -493,7 +493,7 @@ export class ApplicationRef_ extends ApplicationRef {
detachView(viewRef: ViewRef): void {
const view = (viewRef as InternalViewRef);
ListWrapper.remove(this._views, view);
view.detachFromContainer();
view.detachFromAppRef();
}
bootstrap<C>(componentOrFactory: ComponentFactory<C>|Type<C>): ComponentRef<C> {

View File

@ -89,7 +89,7 @@ export abstract class EmbeddedViewRef<C> extends ViewRef {
}
export interface InternalViewRef extends ViewRef {
detachFromContainer(): void;
detachFromAppRef(): void;
attachToAppRef(appRef: ApplicationRef): void;
}
@ -131,7 +131,7 @@ export class ViewRef_<C> implements EmbeddedViewRef<C>, ChangeDetectorRef, Inter
destroy() { this._view.detachAndDestroy(); }
detachFromContainer() { this._view.detach(); }
detachFromAppRef() { this._view.detach(); }
attachToAppRef(appRef: ApplicationRef) { this._view.attachToAppRef(appRef); }
}

View File

@ -213,29 +213,33 @@ function renderEventHandlerClosure(view: ViewData, index: number, eventName: str
export function checkAndUpdateElementInline(
view: ViewData, def: NodeDef, v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any,
v7: any, v8: any, v9: any) {
v7: any, v8: any, v9: any): boolean {
const bindLen = def.bindings.length;
if (bindLen > 0) checkAndUpdateElementValue(view, def, 0, v0);
if (bindLen > 1) checkAndUpdateElementValue(view, def, 1, v1);
if (bindLen > 2) checkAndUpdateElementValue(view, def, 2, v2);
if (bindLen > 3) checkAndUpdateElementValue(view, def, 3, v3);
if (bindLen > 4) checkAndUpdateElementValue(view, def, 4, v4);
if (bindLen > 5) checkAndUpdateElementValue(view, def, 5, v5);
if (bindLen > 6) checkAndUpdateElementValue(view, def, 6, v6);
if (bindLen > 7) checkAndUpdateElementValue(view, def, 7, v7);
if (bindLen > 8) checkAndUpdateElementValue(view, def, 8, v8);
if (bindLen > 9) checkAndUpdateElementValue(view, def, 9, v9);
let changed = false;
if (bindLen > 0 && checkAndUpdateElementValue(view, def, 0, v0)) changed = true;
if (bindLen > 1 && checkAndUpdateElementValue(view, def, 1, v1)) changed = true;
if (bindLen > 2 && checkAndUpdateElementValue(view, def, 2, v2)) changed = true;
if (bindLen > 3 && checkAndUpdateElementValue(view, def, 3, v3)) changed = true;
if (bindLen > 4 && checkAndUpdateElementValue(view, def, 4, v4)) changed = true;
if (bindLen > 5 && checkAndUpdateElementValue(view, def, 5, v5)) changed = true;
if (bindLen > 6 && checkAndUpdateElementValue(view, def, 6, v6)) changed = true;
if (bindLen > 7 && checkAndUpdateElementValue(view, def, 7, v7)) changed = true;
if (bindLen > 8 && checkAndUpdateElementValue(view, def, 8, v8)) changed = true;
if (bindLen > 9 && checkAndUpdateElementValue(view, def, 9, v9)) changed = true;
return changed;
}
export function checkAndUpdateElementDynamic(view: ViewData, def: NodeDef, values: any[]) {
export function checkAndUpdateElementDynamic(view: ViewData, def: NodeDef, values: any[]): boolean {
let changed = false;
for (let i = 0; i < values.length; i++) {
checkAndUpdateElementValue(view, def, i, values[i]);
if (checkAndUpdateElementValue(view, def, i, values[i])) changed = true;
}
return changed;
}
function checkAndUpdateElementValue(view: ViewData, def: NodeDef, bindingIdx: number, value: any) {
if (!checkAndUpdateBinding(view, def, bindingIdx, value)) {
return;
return false;
}
const binding = def.bindings[bindingIdx];
const elData = asElementData(view, def.index);
@ -258,6 +262,7 @@ function checkAndUpdateElementValue(view: ViewData, def: NodeDef, bindingIdx: nu
setElementProperty(elData.componentView, binding, renderNode, name, value);
break;
}
return true;
}
function setElementAttribute(

View File

@ -16,7 +16,7 @@ import {Renderer as RendererV1, RendererFactoryV2, RendererTypeV2, RendererV2} f
import {createChangeDetectorRef, createInjector, createRendererV1, createTemplateRef, createViewContainerRef} from './refs';
import {BindingDef, BindingType, DepDef, DepFlags, DisposableFn, NodeData, NodeDef, NodeFlags, NodeType, OutputDef, OutputType, ProviderData, ProviderType, QueryBindingType, QueryDef, QueryValueType, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewState, asElementData, asProviderData} from './types';
import {checkAndUpdateBinding, dispatchEvent, filterQueryId, isComponentView, splitMatchedQueriesDsl, tokenKey, viewParentEl} from './util';
import {checkBinding, dispatchEvent, filterQueryId, isComponentView, splitMatchedQueriesDsl, tokenKey, viewParentEl} from './util';
const RendererV1TokenKey = tokenKey(RendererV1);
const RendererV2TokenKey = tokenKey(RendererV2);
@ -156,21 +156,52 @@ function eventHandlerClosure(view: ViewData, index: number, eventName: string) {
export function checkAndUpdateDirectiveInline(
view: ViewData, def: NodeDef, v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any,
v7: any, v8: any, v9: any) {
v7: any, v8: any, v9: any): boolean {
const providerData = asProviderData(view, def.index);
const directive = providerData.instance;
let changed = false;
let changes: SimpleChanges;
const bindLen = def.bindings.length;
if (bindLen > 0) changes = checkAndUpdateProp(view, providerData, def, 0, v0, changes);
if (bindLen > 1) changes = checkAndUpdateProp(view, providerData, def, 1, v1, changes);
if (bindLen > 2) changes = checkAndUpdateProp(view, providerData, def, 2, v2, changes);
if (bindLen > 3) changes = checkAndUpdateProp(view, providerData, def, 3, v3, changes);
if (bindLen > 4) changes = checkAndUpdateProp(view, providerData, def, 4, v4, changes);
if (bindLen > 5) changes = checkAndUpdateProp(view, providerData, def, 5, v5, changes);
if (bindLen > 6) changes = checkAndUpdateProp(view, providerData, def, 6, v6, changes);
if (bindLen > 7) changes = checkAndUpdateProp(view, providerData, def, 7, v7, changes);
if (bindLen > 8) changes = checkAndUpdateProp(view, providerData, def, 8, v8, changes);
if (bindLen > 9) changes = checkAndUpdateProp(view, providerData, def, 9, v9, changes);
if (bindLen > 0 && checkBinding(view, def, 0, v0)) {
changed = true;
changes = updateProp(view, providerData, def, 0, v0, changes);
};
if (bindLen > 1 && checkBinding(view, def, 1, v1)) {
changed = true;
changes = updateProp(view, providerData, def, 1, v1, changes);
};
if (bindLen > 2 && checkBinding(view, def, 2, v2)) {
changed = true;
changes = updateProp(view, providerData, def, 2, v2, changes);
};
if (bindLen > 3 && checkBinding(view, def, 3, v3)) {
changed = true;
changes = updateProp(view, providerData, def, 3, v3, changes);
};
if (bindLen > 4 && checkBinding(view, def, 4, v4)) {
changed = true;
changes = updateProp(view, providerData, def, 4, v4, changes);
};
if (bindLen > 5 && checkBinding(view, def, 5, v5)) {
changed = true;
changes = updateProp(view, providerData, def, 5, v5, changes);
};
if (bindLen > 6 && checkBinding(view, def, 6, v6)) {
changed = true;
changes = updateProp(view, providerData, def, 6, v6, changes);
};
if (bindLen > 7 && checkBinding(view, def, 7, v7)) {
changed = true;
changes = updateProp(view, providerData, def, 7, v7, changes);
};
if (bindLen > 8 && checkBinding(view, def, 8, v8)) {
changed = true;
changes = updateProp(view, providerData, def, 8, v8, changes);
};
if (bindLen > 9 && checkBinding(view, def, 9, v9)) {
changed = true;
changes = updateProp(view, providerData, def, 9, v9, changes);
};
if (changes) {
directive.ngOnChanges(changes);
}
@ -180,14 +211,20 @@ export function checkAndUpdateDirectiveInline(
if (def.flags & NodeFlags.DoCheck) {
directive.ngDoCheck();
}
return changed;
}
export function checkAndUpdateDirectiveDynamic(view: ViewData, def: NodeDef, values: any[]) {
export function checkAndUpdateDirectiveDynamic(
view: ViewData, def: NodeDef, values: any[]): boolean {
const providerData = asProviderData(view, def.index);
const directive = providerData.instance;
let changed = false;
let changes: SimpleChanges;
for (let i = 0; i < values.length; i++) {
changes = checkAndUpdateProp(view, providerData, def, i, values[i], changes);
if (checkBinding(view, def, i, values[i])) {
changed = true;
changes = updateProp(view, providerData, def, i, values[i], changes);
}
}
if (changes) {
directive.ngOnChanges(changes);
@ -198,6 +235,7 @@ export function checkAndUpdateDirectiveDynamic(view: ViewData, def: NodeDef, val
if (def.flags & NodeFlags.DoCheck) {
directive.ngDoCheck();
}
return changed;
}
function _createProviderInstance(view: ViewData, def: NodeDef): any {
@ -366,21 +404,9 @@ function findCompView(view: ViewData, elDef: NodeDef, allowPrivateServices: bool
return compView;
}
function checkAndUpdateProp(
function updateProp(
view: ViewData, providerData: ProviderData, def: NodeDef, bindingIdx: number, value: any,
changes: SimpleChanges): SimpleChanges {
let change: SimpleChange;
let changed: boolean;
if (def.flags & NodeFlags.OnChanges) {
const oldValue = view.oldValues[def.bindingIndex + bindingIdx];
changed = checkAndUpdateBinding(view, def, bindingIdx, value);
change = changed ?
new SimpleChange(oldValue, value, (view.state & ViewState.FirstCheck) !== 0) :
null;
} else {
changed = checkAndUpdateBinding(view, def, bindingIdx, value);
}
if (changed) {
if (def.flags & NodeFlags.IsComponent) {
const compView = asElementData(view, def.parent.index).componentView;
if (compView.def.flags & ViewFlags.OnPush) {
@ -393,11 +419,14 @@ function checkAndUpdateProp(
// the user passed in the property name as an object has to `providerDef`,
// so Closure Compiler will have renamed the property correctly already.
providerData.instance[propName] = value;
if (change) {
if (def.flags & NodeFlags.OnChanges) {
changes = changes || {};
changes[binding.nonMinifiedName] = change;
}
const oldValue = view.oldValues[def.bindingIndex + bindingIdx];
const binding = def.bindings[bindingIdx];
changes[binding.nonMinifiedName] =
new SimpleChange(oldValue, value, (view.state & ViewState.FirstCheck) !== 0);
}
view.oldValues[def.bindingIndex + bindingIdx] = value;
return changes;
}

View File

@ -69,7 +69,7 @@ export function createPureExpression(view: ViewData, def: NodeDef): PureExpressi
export function checkAndUpdatePureExpressionInline(
view: ViewData, def: NodeDef, v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any,
v7: any, v8: any, v9: any) {
v7: any, v8: any, v9: any): boolean {
const bindings = def.bindings;
let changed = false;
const bindLen = bindings.length;
@ -84,8 +84,8 @@ export function checkAndUpdatePureExpressionInline(
if (bindLen > 8 && checkAndUpdateBinding(view, def, 8, v8)) changed = true;
if (bindLen > 9 && checkAndUpdateBinding(view, def, 9, v9)) changed = true;
const data = asPureExpressionData(view, def.index);
if (changed) {
const data = asPureExpressionData(view, def.index);
let value: any;
switch (def.pureExpression.type) {
case PureExpressionType.Array:
@ -152,10 +152,11 @@ export function checkAndUpdatePureExpressionInline(
}
data.value = value;
}
return data.value;
return changed;
}
export function checkAndUpdatePureExpressionDynamic(view: ViewData, def: NodeDef, values: any[]) {
export function checkAndUpdatePureExpressionDynamic(
view: ViewData, def: NodeDef, values: any[]): boolean {
const bindings = def.bindings;
let changed = false;
for (let i = 0; i < values.length; i++) {
@ -165,8 +166,8 @@ export function checkAndUpdatePureExpressionDynamic(view: ViewData, def: NodeDef
changed = true;
}
}
const data = asPureExpressionData(view, def.index);
if (changed) {
const data = asPureExpressionData(view, def.index);
let value: any;
switch (def.pureExpression.type) {
case PureExpressionType.Array:
@ -186,5 +187,5 @@ export function checkAndUpdatePureExpressionDynamic(view: ViewData, def: NodeDef
}
data.value = value;
}
return data.value;
return changed;
}

View File

@ -20,7 +20,8 @@ import {Type} from '../type';
import {VERSION} from '../version';
import {ArgumentType, BindingType, DebugContext, DepFlags, ElementData, NodeCheckFn, NodeData, NodeDef, NodeFlags, NodeType, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewState, asElementData, asProviderData, asTextData} from './types';
import {isComponentView, renderNode, resolveViewDefinition, rootRenderNodes, splitNamespace, tokenKey, viewParentEl} from './util';
import {isComponentView, markParentViewsForCheck, renderNode, resolveViewDefinition, rootRenderNodes, splitNamespace, tokenKey, viewParentEl} from './util';
import {attachEmbeddedView, detachEmbeddedView, moveEmbeddedView, renderDetachView} from './view_attach';
const EMPTY_CONTEXT = new Object();
@ -98,14 +99,13 @@ class ViewContainerRef_ implements ViewContainerRef {
clear(): void {
const len = this._data.embeddedViews.length;
for (let i = len - 1; i >= 0; i--) {
const view = Services.detachEmbeddedView(this._data, i);
const view = detachEmbeddedView(this._data, i);
Services.destroyView(view);
}
}
get(index: number): ViewRef { return this._getViewRef(this._data.embeddedViews[index]); }
private _getViewRef(view: ViewData) {
get(index: number): ViewRef {
const view = this._data.embeddedViews[index];
if (view) {
const ref = new ViewRef_(view);
ref.attachToViewContainerRef(this);
@ -135,14 +135,14 @@ class ViewContainerRef_ implements ViewContainerRef {
insert(viewRef: ViewRef, index?: number): ViewRef {
const viewRef_ = <ViewRef_>viewRef;
const viewData = viewRef_._view;
Services.attachEmbeddedView(this._data, index, viewData);
attachEmbeddedView(this._view, this._data, index, viewData);
viewRef_.attachToViewContainerRef(this);
return viewRef;
}
move(viewRef: ViewRef_, currentIndex: number): ViewRef {
const previousIndex = this._data.embeddedViews.indexOf(viewRef._view);
Services.moveEmbeddedView(this._data, previousIndex, currentIndex);
moveEmbeddedView(this._data, previousIndex, currentIndex);
return viewRef;
}
@ -151,20 +151,15 @@ class ViewContainerRef_ implements ViewContainerRef {
}
remove(index?: number): void {
const viewData = Services.detachEmbeddedView(this._data, index);
const viewData = detachEmbeddedView(this._data, index);
if (viewData) {
Services.destroyView(viewData);
}
}
detach(index?: number): ViewRef {
const view = Services.detachEmbeddedView(this._data, index);
if (view) {
const viewRef = this._getViewRef(view);
viewRef.detachFromContainer();
return viewRef;
}
return null;
const view = detachEmbeddedView(this._data, index);
return view ? new ViewRef_(view) : null;
}
}
@ -190,7 +185,7 @@ export class ViewRef_ implements EmbeddedViewRef<any>, InternalViewRef {
get destroyed(): boolean { return (this._view.state & ViewState.Destroyed) !== 0; }
markForCheck(): void { this.reattach(); }
markForCheck(): void { markParentViewsForCheck(this._view); }
detach(): void { this._view.state &= ~ViewState.ChecksEnabled; }
detectChanges(): void { Services.checkAndUpdateView(this._view); }
checkNoChanges(): void { Services.checkNoChangesView(this._view); }
@ -212,9 +207,10 @@ export class ViewRef_ implements EmbeddedViewRef<any>, InternalViewRef {
Services.destroyView(this._view);
}
detachFromContainer() {
detachFromAppRef() {
this._appRef = null;
this._viewContainerRef = null;
renderDetachView(this._view);
Services.dirtyParentQueries(this._view);
}
attachToAppRef(appRef: ApplicationRef) {

View File

@ -14,12 +14,11 @@ import {Sanitizer, SecurityContext} from '../security';
import {isViewDebugError, viewDestroyedError, viewWrappedDebugError} from './errors';
import {resolveDep} from './provider';
import {getQueryValue} from './query';
import {dirtyParentQueries, getQueryValue} from './query';
import {createInjector} from './refs';
import {ArgumentType, BindingType, DebugContext, DepFlags, ElementData, NodeCheckFn, NodeData, NodeDef, NodeFlags, NodeType, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewState, asElementData, asProviderData} from './types';
import {ArgumentType, BindingType, CheckType, DebugContext, DepFlags, ElementData, NodeCheckFn, NodeData, NodeDef, NodeFlags, NodeType, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewState, asElementData, asProviderData, asPureExpressionData} from './types';
import {checkBinding, isComponentView, renderNode, viewParentEl} from './util';
import {checkAndUpdateView, checkNoChangesView, createEmbeddedView, createRootView, destroyView} from './view';
import {attachEmbeddedView, detachEmbeddedView, moveEmbeddedView} from './view_attach';
import {checkAndUpdateNode, checkAndUpdateView, checkNoChangesNode, checkNoChangesView, createEmbeddedView, createRootView, destroyView} from './view';
let initialized = false;
@ -35,14 +34,12 @@ export function initServicesIfNeeded() {
Services.checkAndUpdateView = services.checkAndUpdateView;
Services.checkNoChangesView = services.checkNoChangesView;
Services.destroyView = services.destroyView;
Services.attachEmbeddedView = services.attachEmbeddedView,
Services.detachEmbeddedView = services.detachEmbeddedView,
Services.moveEmbeddedView = services.moveEmbeddedView;
Services.resolveDep = services.resolveDep;
Services.resolveDep = resolveDep;
Services.createDebugContext = services.createDebugContext;
Services.handleEvent = services.handleEvent;
Services.updateDirectives = services.updateDirectives;
Services.updateRenderer = services.updateRenderer;
Services.dirtyParentQueries = dirtyParentQueries;
}
function createProdServices() {
@ -53,16 +50,17 @@ function createProdServices() {
checkAndUpdateView: checkAndUpdateView,
checkNoChangesView: checkNoChangesView,
destroyView: destroyView,
attachEmbeddedView: attachEmbeddedView,
detachEmbeddedView: detachEmbeddedView,
moveEmbeddedView: moveEmbeddedView,
resolveDep: resolveDep,
createDebugContext: (view: ViewData, nodeIndex: number) => new DebugContext_(view, nodeIndex),
handleEvent: (view: ViewData, nodeIndex: number, eventName: string, event: any) =>
view.def.handleEvent(view, nodeIndex, eventName, event),
updateDirectives: (check: NodeCheckFn, view: ViewData) =>
view.def.updateDirectives(check, view),
updateRenderer: (check: NodeCheckFn, view: ViewData) => view.def.updateRenderer(check, view),
updateDirectives: (view: ViewData, checkType: CheckType) => view.def.updateDirectives(
checkType === CheckType.CheckAndUpdate ? prodCheckAndUpdateNode :
prodCheckNoChangesNode,
view),
updateRenderer: (view: ViewData, checkType: CheckType) => view.def.updateRenderer(
checkType === CheckType.CheckAndUpdate ? prodCheckAndUpdateNode :
prodCheckNoChangesNode,
view),
};
}
@ -74,10 +72,6 @@ function createDebugServices() {
checkAndUpdateView: debugCheckAndUpdateView,
checkNoChangesView: debugCheckNoChangesView,
destroyView: debugDestroyView,
attachEmbeddedView: attachEmbeddedView,
detachEmbeddedView: detachEmbeddedView,
moveEmbeddedView: moveEmbeddedView,
resolveDep: resolveDep,
createDebugContext: (view: ViewData, nodeIndex: number) => new DebugContext_(view, nodeIndex),
handleEvent: debugHandleEvent,
updateDirectives: debugUpdateDirectives,
@ -115,6 +109,24 @@ function createRootData(
};
}
function prodCheckAndUpdateNode(
view: ViewData, nodeIndex: number, argStyle: ArgumentType, v0?: any, v1?: any, v2?: any,
v3?: any, v4?: any, v5?: any, v6?: any, v7?: any, v8?: any, v9?: any): any {
const nodeDef = view.def.nodes[nodeIndex];
checkAndUpdateNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
return (nodeDef.type === NodeType.PureExpression) ? asPureExpressionData(view, nodeIndex).value :
undefined;
}
function prodCheckNoChangesNode(
view: ViewData, nodeIndex: number, argStyle: ArgumentType, v0?: any, v1?: any, v2?: any,
v3?: any, v4?: any, v5?: any, v6?: any, v7?: any, v8?: any, v9?: any): any {
const nodeDef = view.def.nodes[nodeIndex];
checkNoChangesNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
return (nodeDef.type === NodeType.PureExpression) ? asPureExpressionData(view, nodeIndex).value :
undefined;
}
function debugCreateEmbeddedView(parent: ViewData, anchorDef: NodeDef, context?: any): ViewData {
return callWithDebugContext(
DebugAction.create, createEmbeddedView, null, [parent, anchorDef, context]);
@ -158,7 +170,7 @@ function debugHandleEvent(view: ViewData, nodeIndex: number, eventName: string,
DebugAction.handleEvent, view.def.handleEvent, null, [view, nodeIndex, eventName, event]);
}
function debugUpdateDirectives(check: NodeCheckFn, view: ViewData) {
function debugUpdateDirectives(view: ViewData, checkType: CheckType) {
if (view.state & ViewState.Destroyed) {
throw viewDestroyedError(DebugAction[_currentAction]);
}
@ -167,15 +179,22 @@ function debugUpdateDirectives(check: NodeCheckFn, view: ViewData) {
function debugCheckDirectivesFn(
view: ViewData, nodeIndex: number, argStyle: ArgumentType, ...values: any[]) {
const result = debugCheckFn(check, view, nodeIndex, argStyle, values);
if (view.def.nodes[nodeIndex].type === NodeType.Directive) {
const nodeDef = view.def.nodes[nodeIndex];
if (checkType === CheckType.CheckAndUpdate) {
debugCheckAndUpdateNode(view, nodeDef, argStyle, values);
} else {
debugCheckNoChangesNode(view, nodeDef, argStyle, values);
}
if (nodeDef.type === NodeType.Directive) {
debugSetCurrentNode(view, nextDirectiveWithBinding(view, nodeIndex));
}
return result;
return (nodeDef.type === NodeType.PureExpression) ?
asPureExpressionData(view, nodeDef.index).value :
undefined;
};
}
function debugUpdateRenderer(check: NodeCheckFn, view: ViewData) {
function debugUpdateRenderer(view: ViewData, checkType: CheckType) {
if (view.state & ViewState.Destroyed) {
throw viewDestroyedError(DebugAction[_currentAction]);
}
@ -184,21 +203,26 @@ function debugUpdateRenderer(check: NodeCheckFn, view: ViewData) {
function debugCheckRenderNodeFn(
view: ViewData, nodeIndex: number, argStyle: ArgumentType, ...values: any[]) {
const result = debugCheckFn(check, view, nodeIndex, argStyle, values);
const nodeDef = view.def.nodes[nodeIndex];
if (checkType === CheckType.CheckAndUpdate) {
debugCheckAndUpdateNode(view, nodeDef, argStyle, values);
} else {
debugCheckNoChangesNode(view, nodeDef, argStyle, values);
}
if (nodeDef.type === NodeType.Element || nodeDef.type === NodeType.Text) {
debugSetCurrentNode(view, nextRenderNodeWithBinding(view, nodeIndex));
}
return result;
return (nodeDef.type === NodeType.PureExpression) ?
asPureExpressionData(view, nodeDef.index).value :
undefined;
}
}
function debugCheckFn(
delegate: NodeCheckFn, view: ViewData, nodeIndex: number, argStyle: ArgumentType,
givenValues: any[]) {
if (_currentAction === DebugAction.detectChanges) {
function debugCheckAndUpdateNode(
view: ViewData, nodeDef: NodeDef, argStyle: ArgumentType, givenValues: any[]): void {
const changed = (<any>checkAndUpdateNode)(view, nodeDef, argStyle, ...givenValues);
if (changed) {
const values = argStyle === ArgumentType.Dynamic ? givenValues[0] : givenValues;
const nodeDef = view.def.nodes[nodeIndex];
if (nodeDef.type === NodeType.Directive || nodeDef.type === NodeType.Element) {
const bindingValues: {[key: string]: string} = {};
for (let i = 0; i < nodeDef.bindings.length; i++) {
@ -206,8 +230,7 @@ function debugCheckFn(
const value = values[i];
if ((binding.type === BindingType.ElementProperty ||
binding.type === BindingType.ComponentHostProperty ||
binding.type === BindingType.DirectiveProperty) &&
checkBinding(view, nodeDef, i, value)) {
binding.type === BindingType.DirectiveProperty)) {
bindingValues[normalizeDebugBindingName(binding.nonMinifiedName)] =
normalizeDebugBindingValue(value);
}
@ -225,8 +248,12 @@ function debugCheckFn(
}
}
}
return (<any>delegate)(view, nodeIndex, argStyle, ...givenValues);
};
}
function debugCheckNoChangesNode(
view: ViewData, nodeDef: NodeDef, argStyle: ArgumentType, values: any[]): void {
(<any>checkNoChangesNode)(view, nodeDef, argStyle, ...values);
}
function normalizeDebugBindingName(name: string) {
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers

View File

@ -66,7 +66,7 @@ export function createText(view: ViewData, renderHost: any, def: NodeDef): TextD
export function checkAndUpdateTextInline(
view: ViewData, def: NodeDef, v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any,
v7: any, v8: any, v9: any) {
v7: any, v8: any, v9: any): boolean {
let changed = false;
const bindings = def.bindings;
const bindLen = bindings.length;
@ -96,9 +96,10 @@ export function checkAndUpdateTextInline(
const renderNode = asTextData(view, def.index).renderText;
view.renderer.setValue(renderNode, value);
}
return changed;
}
export function checkAndUpdateTextDynamic(view: ViewData, def: NodeDef, values: any[]) {
export function checkAndUpdateTextDynamic(view: ViewData, def: NodeDef, values: any[]): boolean {
const bindings = def.bindings;
let changed = false;
for (let i = 0; i < values.length; i++) {
@ -117,6 +118,7 @@ export function checkAndUpdateTextDynamic(view: ViewData, def: NodeDef, values:
const renderNode = asTextData(view, def.index).renderText;
view.renderer.setValue(renderNode, value);
}
return changed;
}
function _addInterpolationPart(value: any, binding: BindingDef): string {

View File

@ -312,6 +312,7 @@ export interface ViewData {
// index of component provider / anchor.
parentNodeDef: NodeDef;
parent: ViewData;
viewContainerParent: ViewData;
component: any;
context: any;
// Attention: Never loop over this, as this will
@ -448,6 +449,11 @@ export abstract class DebugContext {
// Other
// -------------------------------------
export enum CheckType {
CheckAndUpdate,
CheckNoChanges
}
export interface Services {
setCurrentNode(view: ViewData, nodeIndex: number): void;
createRootView(
@ -456,17 +462,15 @@ export interface Services {
createEmbeddedView(parent: ViewData, anchorDef: NodeDef, context?: any): ViewData;
checkAndUpdateView(view: ViewData): void;
checkNoChangesView(view: ViewData): void;
attachEmbeddedView(elementData: ElementData, viewIndex: number, view: ViewData): void;
detachEmbeddedView(elementData: ElementData, viewIndex: number): ViewData;
moveEmbeddedView(elementData: ElementData, oldViewIndex: number, newViewIndex: number): ViewData;
destroyView(view: ViewData): void;
resolveDep(
view: ViewData, elDef: NodeDef, allowPrivateServices: boolean, depDef: DepDef,
notFoundValue?: any): any;
createDebugContext(view: ViewData, nodeIndex: number): DebugContext;
handleEvent: ViewHandleEventFn;
updateDirectives: ViewUpdateFn;
updateRenderer: ViewUpdateFn;
updateDirectives: (view: ViewData, checkType: CheckType) => void;
updateRenderer: (view: ViewData, checkType: CheckType) => void;
dirtyParentQueries: (view: ViewData) => void;
}
/**
@ -480,12 +484,10 @@ export const Services: Services = {
checkAndUpdateView: undefined,
checkNoChangesView: undefined,
destroyView: undefined,
attachEmbeddedView: undefined,
detachEmbeddedView: undefined,
moveEmbeddedView: undefined,
resolveDep: undefined,
createDebugContext: undefined,
handleEvent: undefined,
updateDirectives: undefined,
updateRenderer: undefined,
dirtyParentQueries: undefined,
};

View File

@ -60,9 +60,22 @@ export function createRendererTypeV2(values: {
export function checkBinding(
view: ViewData, def: NodeDef, bindingIdx: number, value: any): boolean {
const oldValue = view.oldValues[def.bindingIndex + bindingIdx];
return unwrapCounter > 0 || !!(view.state & ViewState.FirstCheck) ||
!devModeEqual(oldValue, value);
const oldValues = view.oldValues;
if (unwrapCounter > 0 || !!(view.state & ViewState.FirstCheck) ||
!looseIdentical(oldValues[def.bindingIndex + bindingIdx], value)) {
unwrapCounter = 0;
return true;
}
return false;
}
export function checkAndUpdateBinding(
view: ViewData, def: NodeDef, bindingIdx: number, value: any): boolean {
if (checkBinding(view, def, bindingIdx, value)) {
view.oldValues[def.bindingIndex + bindingIdx] = value;
return true;
}
return false;
}
export function checkBindingNoChanges(
@ -76,27 +89,19 @@ export function checkBindingNoChanges(
}
}
export function checkAndUpdateBinding(
view: ViewData, def: NodeDef, bindingIdx: number, value: any): boolean {
const oldValues = view.oldValues;
if (unwrapCounter || (view.state & ViewState.FirstCheck) ||
!looseIdentical(oldValues[def.bindingIndex + bindingIdx], value)) {
unwrapCounter = 0;
oldValues[def.bindingIndex + bindingIdx] = value;
return true;
}
return false;
}
export function dispatchEvent(
view: ViewData, nodeIndex: number, eventName: string, event: any): boolean {
export function markParentViewsForCheck(view: ViewData) {
let currView = view;
while (currView) {
if (currView.def.flags & ViewFlags.OnPush) {
currView.state |= ViewState.ChecksEnabled;
}
currView = currView.parent;
currView = currView.viewContainerParent || currView.parent;
}
}
export function dispatchEvent(
view: ViewData, nodeIndex: number, eventName: string, event: any): boolean {
markParentViewsForCheck(view);
return Services.handleEvent(view, nodeIndex, eventName, event);
}

View File

@ -16,7 +16,7 @@ import {callLifecycleHooksChildrenFirst, checkAndUpdateDirectiveDynamic, checkAn
import {checkAndUpdatePureExpressionDynamic, checkAndUpdatePureExpressionInline, createPureExpression} from './pure_expression';
import {checkAndUpdateQuery, createQuery, queryDef} from './query';
import {checkAndUpdateTextDynamic, checkAndUpdateTextInline, createText} from './text';
import {ArgumentType, ElementData, ElementDef, NodeData, NodeDef, NodeFlags, NodeType, ProviderData, ProviderDef, RootData, Services, TextDef, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewState, ViewUpdateFn, asElementData, asProviderData, asPureExpressionData, asQueryList, asTextData} from './types';
import {ArgumentType, CheckType, ElementData, ElementDef, NodeData, NodeDef, NodeFlags, NodeType, ProviderData, ProviderDef, RootData, Services, TextDef, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewState, ViewUpdateFn, asElementData, asProviderData, asPureExpressionData, asQueryList, asTextData} from './types';
import {checkBindingNoChanges, isComponentView, resolveViewDefinition, viewParentEl} from './util';
const NOOP = (): any => undefined;
@ -246,7 +246,7 @@ function createView(
const view: ViewData = {
def,
parent,
parentNodeDef,
viewContainerParent: undefined, parentNodeDef,
context: undefined,
component: undefined, nodes,
state: ViewState.FirstCheck | ViewState.ChecksEnabled, root, renderer,
@ -339,35 +339,35 @@ function createViewNodes(view: ViewData) {
// fill static content and view queries
execQueriesAction(
view, NodeFlags.HasContentQuery | NodeFlags.HasViewQuery, NodeFlags.HasStaticQuery,
QueryAction.CheckAndUpdate);
CheckType.CheckAndUpdate);
}
export function checkNoChangesView(view: ViewData) {
Services.updateDirectives(checkNoChangesNode, view);
Services.updateDirectives(view, CheckType.CheckNoChanges);
execEmbeddedViewsAction(view, ViewAction.CheckNoChanges);
execQueriesAction(
view, NodeFlags.HasContentQuery, NodeFlags.HasDynamicQuery, QueryAction.CheckNoChanges);
Services.updateRenderer(checkNoChangesNode, view);
view, NodeFlags.HasContentQuery, NodeFlags.HasDynamicQuery, CheckType.CheckNoChanges);
Services.updateRenderer(view, CheckType.CheckNoChanges);
execComponentViewsAction(view, ViewAction.CheckNoChanges);
execQueriesAction(
view, NodeFlags.HasViewQuery, NodeFlags.HasDynamicQuery, QueryAction.CheckNoChanges);
view, NodeFlags.HasViewQuery, NodeFlags.HasDynamicQuery, CheckType.CheckNoChanges);
}
export function checkAndUpdateView(view: ViewData) {
Services.updateDirectives(checkAndUpdateNode, view);
Services.updateDirectives(view, CheckType.CheckAndUpdate);
execEmbeddedViewsAction(view, ViewAction.CheckAndUpdate);
execQueriesAction(
view, NodeFlags.HasContentQuery, NodeFlags.HasDynamicQuery, QueryAction.CheckAndUpdate);
view, NodeFlags.HasContentQuery, NodeFlags.HasDynamicQuery, CheckType.CheckAndUpdate);
callLifecycleHooksChildrenFirst(
view, NodeFlags.AfterContentChecked |
(view.state & ViewState.FirstCheck ? NodeFlags.AfterContentInit : 0));
Services.updateRenderer(checkAndUpdateNode, view);
Services.updateRenderer(view, CheckType.CheckAndUpdate);
execComponentViewsAction(view, ViewAction.CheckAndUpdate);
execQueriesAction(
view, NodeFlags.HasViewQuery, NodeFlags.HasDynamicQuery, QueryAction.CheckAndUpdate);
view, NodeFlags.HasViewQuery, NodeFlags.HasDynamicQuery, CheckType.CheckAndUpdate);
callLifecycleHooksChildrenFirst(
view, NodeFlags.AfterViewChecked |
@ -379,61 +379,83 @@ export function checkAndUpdateView(view: ViewData) {
view.state &= ~ViewState.FirstCheck;
}
function checkAndUpdateNode(
view: ViewData, nodeIndex: number, argStyle: ArgumentType, v0?: any, v1?: any, v2?: any,
v3?: any, v4?: any, v5?: any, v6?: any, v7?: any, v8?: any, v9?: any): any {
export function checkAndUpdateNode(
view: ViewData, nodeDef: NodeDef, argStyle: ArgumentType, v0?: any, v1?: any, v2?: any,
v3?: any, v4?: any, v5?: any, v6?: any, v7?: any, v8?: any, v9?: any): boolean {
if (argStyle === ArgumentType.Inline) {
return checkAndUpdateNodeInline(view, nodeIndex, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
return checkAndUpdateNodeInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
} else {
return checkAndUpdateNodeDynamic(view, nodeIndex, v0);
return checkAndUpdateNodeDynamic(view, nodeDef, v0);
}
}
function checkAndUpdateNodeInline(
view: ViewData, nodeIndex: number, v0?: any, v1?: any, v2?: any, v3?: any, v4?: any, v5?: any,
v6?: any, v7?: any, v8?: any, v9?: any): any {
const nodeDef = view.def.nodes[nodeIndex];
view: ViewData, nodeDef: NodeDef, v0?: any, v1?: any, v2?: any, v3?: any, v4?: any, v5?: any,
v6?: any, v7?: any, v8?: any, v9?: any): boolean {
let changed = false;
switch (nodeDef.type) {
case NodeType.Element:
return checkAndUpdateElementInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
changed = checkAndUpdateElementInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
break;
case NodeType.Text:
return checkAndUpdateTextInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
changed = checkAndUpdateTextInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
break;
case NodeType.Directive:
return checkAndUpdateDirectiveInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
changed =
checkAndUpdateDirectiveInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
break;
case NodeType.PureExpression:
return checkAndUpdatePureExpressionInline(
view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
changed =
checkAndUpdatePureExpressionInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
break;
}
return changed;
}
function checkAndUpdateNodeDynamic(view: ViewData, nodeIndex: number, values: any[]): any {
const nodeDef = view.def.nodes[nodeIndex];
function checkAndUpdateNodeDynamic(view: ViewData, nodeDef: NodeDef, values: any[]): boolean {
let changed = false;
switch (nodeDef.type) {
case NodeType.Element:
return checkAndUpdateElementDynamic(view, nodeDef, values);
changed = checkAndUpdateElementDynamic(view, nodeDef, values);
break;
case NodeType.Text:
return checkAndUpdateTextDynamic(view, nodeDef, values);
changed = checkAndUpdateTextDynamic(view, nodeDef, values);
break;
case NodeType.Directive:
return checkAndUpdateDirectiveDynamic(view, nodeDef, values);
changed = checkAndUpdateDirectiveDynamic(view, nodeDef, values);
break;
case NodeType.PureExpression:
return checkAndUpdatePureExpressionDynamic(view, nodeDef, values);
changed = checkAndUpdatePureExpressionDynamic(view, nodeDef, values);
break;
}
if (changed) {
// Update oldValues after all bindings have been updated,
// as a setter for a property might update other properties.
const bindLen = nodeDef.bindings.length;
const bindingStart = nodeDef.bindingIndex;
const oldValues = view.oldValues;
for (let i = 0; i < bindLen; i++) {
oldValues[bindingStart + i] = values[i];
}
}
return changed;
}
function checkNoChangesNode(
view: ViewData, nodeIndex: number, argStyle: ArgumentType, v0?: any, v1?: any, v2?: any,
export function checkNoChangesNode(
view: ViewData, nodeDef: NodeDef, argStyle: ArgumentType, v0?: any, v1?: any, v2?: any,
v3?: any, v4?: any, v5?: any, v6?: any, v7?: any, v8?: any, v9?: any): any {
if (argStyle === ArgumentType.Inline) {
return checkNoChangesNodeInline(view, nodeIndex, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
checkNoChangesNodeInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
} else {
return checkNoChangesNodeDynamic(view, nodeIndex, v0);
checkNoChangesNodeDynamic(view, nodeDef, v0);
}
// Returning false is ok here as we would have thrown in case of a change.
return false;
}
function checkNoChangesNodeInline(
view: ViewData, nodeIndex: number, v0: any, v1: any, v2: any, v3: any, v4: any, v5: any,
v6: any, v7: any, v8: any, v9: any): void {
const nodeDef = view.def.nodes[nodeIndex];
view: ViewData, nodeDef: NodeDef, v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any,
v7: any, v8: any, v9: any): void {
const bindLen = nodeDef.bindings.length;
if (bindLen > 0) checkBindingNoChanges(view, nodeDef, 0, v0);
if (bindLen > 1) checkBindingNoChanges(view, nodeDef, 1, v1);
@ -445,17 +467,12 @@ function checkNoChangesNodeInline(
if (bindLen > 7) checkBindingNoChanges(view, nodeDef, 7, v7);
if (bindLen > 8) checkBindingNoChanges(view, nodeDef, 8, v8);
if (bindLen > 9) checkBindingNoChanges(view, nodeDef, 9, v9);
return nodeDef.type === NodeType.PureExpression ? asPureExpressionData(view, nodeIndex).value :
undefined;
}
function checkNoChangesNodeDynamic(view: ViewData, nodeIndex: number, values: any[]): void {
const nodeDef = view.def.nodes[nodeIndex];
function checkNoChangesNodeDynamic(view: ViewData, nodeDef: NodeDef, values: any[]): void {
for (let i = 0; i < values.length; i++) {
checkBindingNoChanges(view, nodeDef, i, values[i]);
}
return nodeDef.type === NodeType.PureExpression ? asPureExpressionData(view, nodeIndex).value :
undefined;
}
function checkNoChangesQuery(view: ViewData, nodeDef: NodeDef) {
@ -574,13 +591,9 @@ function callViewAction(view: ViewData, action: ViewAction) {
}
}
enum QueryAction {
CheckAndUpdate,
CheckNoChanges
}
function execQueriesAction(
view: ViewData, queryFlags: NodeFlags, staticDynamicQueryFlag: NodeFlags, action: QueryAction) {
view: ViewData, queryFlags: NodeFlags, staticDynamicQueryFlag: NodeFlags,
checkType: CheckType) {
if (!(view.def.nodeFlags & queryFlags) || !(view.def.nodeFlags & staticDynamicQueryFlag)) {
return;
}
@ -589,11 +602,11 @@ function execQueriesAction(
const nodeDef = view.def.nodes[i];
if ((nodeDef.flags & queryFlags) && (nodeDef.flags & staticDynamicQueryFlag)) {
Services.setCurrentNode(view, nodeDef.index);
switch (action) {
case QueryAction.CheckAndUpdate:
switch (checkType) {
case CheckType.CheckAndUpdate:
checkAndUpdateQuery(view, nodeDef);
break;
case QueryAction.CheckNoChanges:
case CheckType.CheckNoChanges:
checkNoChangesQuery(view, nodeDef);
break;
}

View File

@ -6,15 +6,16 @@
* found in the LICENSE file at https://angular.io/license
*/
import {dirtyParentQueries} from './query';
import {ElementData, NodeData, NodeDef, NodeFlags, NodeType, ViewData, asElementData, asProviderData, asTextData} from './types';
import {ElementData, NodeData, NodeDef, NodeFlags, NodeType, Services, ViewData, asElementData, asProviderData, asTextData} from './types';
import {RenderNodeAction, declaredViewContainer, isComponentView, renderNode, rootRenderNodes, visitProjectedRenderNodes, visitRootRenderNodes} from './util';
export function attachEmbeddedView(elementData: ElementData, viewIndex: number, view: ViewData) {
export function attachEmbeddedView(
parentView: ViewData, elementData: ElementData, viewIndex: number, view: ViewData) {
let embeddedViews = elementData.embeddedViews;
if (viewIndex == null) {
viewIndex = embeddedViews.length;
}
view.viewContainerParent = parentView;
addToArray(embeddedViews, viewIndex, view);
const dvcElementData = declaredViewContainer(view);
if (dvcElementData && dvcElementData !== elementData) {
@ -25,7 +26,7 @@ export function attachEmbeddedView(elementData: ElementData, viewIndex: number,
projectedViews.push(view);
}
dirtyParentQueries(view);
Services.dirtyParentQueries(view);
const prevView = viewIndex > 0 ? embeddedViews[viewIndex - 1] : null;
renderAttachEmbeddedView(elementData, prevView, view);
@ -40,6 +41,7 @@ export function detachEmbeddedView(elementData: ElementData, viewIndex: number):
return null;
}
const view = embeddedViews[viewIndex];
view.viewContainerParent = undefined;
removeFromArray(embeddedViews, viewIndex);
const dvcElementData = declaredViewContainer(view);
@ -48,9 +50,9 @@ export function detachEmbeddedView(elementData: ElementData, viewIndex: number):
removeFromArray(projectedViews, projectedViews.indexOf(view));
}
dirtyParentQueries(view);
Services.dirtyParentQueries(view);
renderDetachEmbeddedView(elementData, view);
renderDetachView(view);
return view;
}
@ -68,9 +70,9 @@ export function moveEmbeddedView(
// Note: Don't need to change projectedViews as the order in there
// as always invalid...
dirtyParentQueries(view);
Services.dirtyParentQueries(view);
renderDetachEmbeddedView(elementData, view);
renderDetachView(view);
const prevView = newViewIndex > 0 ? embeddedViews[newViewIndex - 1] : null;
renderAttachEmbeddedView(elementData, prevView, view);
@ -87,9 +89,8 @@ function renderAttachEmbeddedView(elementData: ElementData, prevView: ViewData,
visitRootRenderNodes(view, RenderNodeAction.InsertBefore, parentNode, nextSibling, undefined);
}
function renderDetachEmbeddedView(elementData: ElementData, view: ViewData) {
const parentNode = view.renderer.parentNode(elementData.renderElement);
visitRootRenderNodes(view, RenderNodeAction.RemoveChild, parentNode, null, undefined);
export function renderDetachView(view: ViewData) {
visitRootRenderNodes(view, RenderNodeAction.RemoveChild, null, null, undefined);
}
function addToArray(arr: any[], index: number, value: any) {

View File

@ -78,7 +78,7 @@ export function main() {
it('should throw when reentering tick', inject([ApplicationRef], (ref: ApplicationRef_) => {
const view = jasmine.createSpyObj('view', ['detach', 'attachToAppRef']);
const viewRef = jasmine.createSpyObj(
'viewRef', ['detectChanges', 'detachFromContainer', 'attachToAppRef']);
'viewRef', ['detectChanges', 'detachFromAppRef', 'attachToAppRef']);
viewRef.internalView = view;
view.ref = viewRef;
try {

View File

@ -66,8 +66,8 @@ export function main() {
const childView0 = Services.createEmbeddedView(parentView, parentView.def.nodes[1]);
const childView1 = Services.createEmbeddedView(parentView, parentView.def.nodes[2]);
attachEmbeddedView(viewContainerData, 0, childView0);
attachEmbeddedView(viewContainerData, 1, childView1);
attachEmbeddedView(parentView, viewContainerData, 0, childView0);
attachEmbeddedView(parentView, viewContainerData, 1, childView1);
// 2 anchors + 2 elements
const rootChildren = getDOM().childNodes(rootNodes[0]);
@ -96,8 +96,8 @@ export function main() {
const childView0 = Services.createEmbeddedView(parentView, parentView.def.nodes[1]);
const childView1 = Services.createEmbeddedView(parentView, parentView.def.nodes[2]);
attachEmbeddedView(viewContainerData, 0, childView0);
attachEmbeddedView(viewContainerData, 1, childView1);
attachEmbeddedView(parentView, viewContainerData, 0, childView0);
attachEmbeddedView(parentView, viewContainerData, 1, childView1);
moveEmbeddedView(viewContainerData, 0, 1);
@ -118,7 +118,7 @@ export function main() {
]));
const childView0 = Services.createEmbeddedView(parentView, parentView.def.nodes[0]);
attachEmbeddedView(asElementData(parentView, 0), 0, childView0);
attachEmbeddedView(parentView, asElementData(parentView, 0), 0, childView0);
const rootNodes = rootRenderNodes(parentView);
expect(rootNodes.length).toBe(3);
@ -146,7 +146,7 @@ export function main() {
const childView0 = Services.createEmbeddedView(parentView, parentView.def.nodes[1]);
attachEmbeddedView(asElementData(parentView, 1), 0, childView0);
attachEmbeddedView(parentView, asElementData(parentView, 1), 0, childView0);
Services.checkAndUpdateView(parentView);
@ -180,7 +180,7 @@ export function main() {
const childView0 = Services.createEmbeddedView(parentView, parentView.def.nodes[1]);
attachEmbeddedView(asElementData(parentView, 1), 0, childView0);
attachEmbeddedView(parentView, asElementData(parentView, 1), 0, childView0);
Services.destroyView(parentView);
expect(log).toEqual(['ngOnDestroy']);

View File

@ -114,7 +114,7 @@ export function main() {
const componentView = asElementData(view, 0).componentView;
const view0 = Services.createEmbeddedView(componentView, componentView.def.nodes[1]);
attachEmbeddedView(asElementData(componentView, 1), 0, view0);
attachEmbeddedView(view, asElementData(componentView, 1), 0, view0);
expect(getDOM().childNodes(getDOM().firstChild(rootNodes[0])).length).toBe(3);
expect(getDOM().childNodes(getDOM().firstChild(rootNodes[0]))[1])
.toBe(asTextData(view, 2).renderText);

View File

@ -156,7 +156,7 @@ export function main() {
]));
const childView = Services.createEmbeddedView(view, view.def.nodes[3]);
attachEmbeddedView(asElementData(view, 3), 0, childView);
attachEmbeddedView(view, asElementData(view, 3), 0, childView);
Services.checkAndUpdateView(view);
// queries on parent elements of anchors
@ -185,7 +185,7 @@ export function main() {
const childView = Services.createEmbeddedView(view, view.def.nodes[3]);
// attach at a different place than the one where the template was defined
attachEmbeddedView(asElementData(view, 7), 0, childView);
attachEmbeddedView(view, asElementData(view, 7), 0, childView);
Services.checkAndUpdateView(view);
@ -215,12 +215,13 @@ export function main() {
expect(qs.a.length).toBe(0);
const childView = Services.createEmbeddedView(view, view.def.nodes[3]);
attachEmbeddedView(asElementData(view, 3), 0, childView);
attachEmbeddedView(view, asElementData(view, 3), 0, childView);
Services.checkAndUpdateView(view);
expect(qs.a.length).toBe(1);
detachEmbeddedView(asElementData(view, 3), 0);
Services.checkAndUpdateView(view);
expect(qs.a.length).toBe(0);
@ -245,7 +246,7 @@ export function main() {
const compView = asElementData(view, 0).componentView;
const childView = Services.createEmbeddedView(compView, compView.def.nodes[1]);
attachEmbeddedView(asElementData(compView, 1), 0, childView);
attachEmbeddedView(view, asElementData(compView, 1), 0, childView);
Services.checkAndUpdateView(view);
expect(comp.a.length).toBe(1);
@ -381,7 +382,7 @@ export function main() {
Services.checkNoChangesView(view);
const childView = Services.createEmbeddedView(view, view.def.nodes[3]);
attachEmbeddedView(asElementData(view, 3), 0, childView);
attachEmbeddedView(view, asElementData(view, 3), 0, childView);
let err: any;
try {