refactor(core): add a checkIndex to the compiler view nodes

Each node now has two index: nodeIndex and checkIndex.

nodeIndex is the index in both the view definition and the view data.
checkIndex is the index in in the update function (update directives and update
renderer).

While nodeIndex and checkIndex have the same value for now, having both of them
will allow changing the structure of view definition after compilation (ie for
runtime translations).
This commit is contained in:
Victor Berchet 2017-09-22 14:29:16 -07:00 committed by Alex Rickabaugh
parent caa51950e8
commit 0833b59aab
27 changed files with 666 additions and 781 deletions

View File

@ -6,7 +6,7 @@ more functionality from codegen into runtime to reduce generated code size.
As we introduce more runtime code, we need to be very careful to not
regress in performance, compared to the pure codegen solution.
## Initial resuls: size of Deep Tree Benchmark
## Initial results: size of Deep Tree Benchmark
File size for Tree benchmark template,
view class of the component + the 2 embedded view classes (without imports nor host view factory):

View File

@ -26,8 +26,8 @@ let viewFlags = ViewFlags.None;
function TreeComponent_Host(): ViewDefinition {
return viewDef(viewFlags, [
elementDef(NodeFlags.None, null, null, 1, 'tree', null, null, null, null, TreeComponent_0),
directiveDef(NodeFlags.Component, null, 0, TreeComponent, []),
elementDef(0, NodeFlags.None, null, null, 1, 'tree', null, null, null, null, TreeComponent_0),
directiveDef(1, NodeFlags.Component, null, 0, TreeComponent, []),
]);
}
@ -35,8 +35,9 @@ function TreeComponent_1() {
return viewDef(
viewFlags,
[
elementDef(NodeFlags.None, null, null, 1, 'tree', null, null, null, null, TreeComponent_0),
directiveDef(NodeFlags.Component, null, 0, TreeComponent, [], {data: [0, 'data']}),
elementDef(
0, NodeFlags.None, null, null, 1, 'tree', null, null, null, null, TreeComponent_0),
directiveDef(1, NodeFlags.Component, null, 0, TreeComponent, [], {data: [0, 'data']}),
],
(check, view) => {
const cmp = view.component;
@ -48,8 +49,9 @@ function TreeComponent_2() {
return viewDef(
viewFlags,
[
elementDef(NodeFlags.None, null, null, 1, 'tree', null, null, null, null, TreeComponent_0),
directiveDef(NodeFlags.Component, null, 0, TreeComponent, [], {data: [0, 'data']}),
elementDef(
0, NodeFlags.None, null, null, 1, 'tree', null, null, null, null, TreeComponent_0),
directiveDef(1, NodeFlags.Component, null, 0, TreeComponent, [], {data: [0, 'data']}),
],
(check, view) => {
const cmp = view.component;
@ -62,15 +64,15 @@ function TreeComponent_0(): ViewDefinition {
viewFlags,
[
elementDef(
NodeFlags.None, null, null, 1, 'span', null,
0, NodeFlags.None, null, null, 1, 'span', null,
[[BindingFlags.TypeElementStyle, 'backgroundColor', null]]),
textDef(null, [' ', ' ']),
textDef(1, null, [' ', ' ']),
anchorDef(NodeFlags.EmbeddedViews, null, null, 1, null, TreeComponent_1),
directiveDef(
NodeFlags.None, null, 0, NgIf, [ViewContainerRef, TemplateRef], {ngIf: [0, 'ngIf']}),
3, NodeFlags.None, null, 0, NgIf, [ViewContainerRef, TemplateRef], {ngIf: [0, 'ngIf']}),
anchorDef(NodeFlags.EmbeddedViews, null, null, 1, null, TreeComponent_2),
directiveDef(
NodeFlags.None, null, 0, NgIf, [ViewContainerRef, TemplateRef], {ngIf: [0, 'ngIf']}),
5, NodeFlags.None, null, 0, NgIf, [ViewContainerRef, TemplateRef], {ngIf: [0, 'ngIf']}),
],
(check, view) => {
const cmp = view.component;

View File

@ -230,12 +230,15 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
}
visitText(ast: TextAst, context: any): any {
// textDef(ngContentIndex: number, constants: string[]): NodeDef;
// Static text nodes have no check function
const checkIndex = -1;
this.nodes.push(() => ({
sourceSpan: ast.sourceSpan,
nodeFlags: NodeFlags.TypeText,
nodeDef: o.importExpr(Identifiers.textDef).callFn([
o.literal(ast.ngContentIndex), o.literalArr([o.literal(ast.value)])
o.literal(checkIndex),
o.literal(ast.ngContentIndex),
o.literalArr([o.literal(ast.value)]),
])
}));
}
@ -252,12 +255,17 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
(expr, bindingIndex) => this._preprocessUpdateExpression(
{nodeIndex, bindingIndex, sourceSpan: ast.sourceSpan, context: COMP_VAR, value: expr}));
// textDef(ngContentIndex: number, constants: string[]): NodeDef;
// Check index is the same as the node index during compilation
// They might only differ at runtime
const checkIndex = nodeIndex;
this.nodes[nodeIndex] = () => ({
sourceSpan: ast.sourceSpan,
nodeFlags: NodeFlags.TypeText,
nodeDef: o.importExpr(Identifiers.textDef).callFn([
o.literal(ast.ngContentIndex), o.literalArr(inter.strings.map(s => o.literal(s)))
o.literal(checkIndex),
o.literal(ast.ngContentIndex),
o.literalArr(inter.strings.map(s => o.literal(s))),
]),
updateRenderer: updateRendererExpressions
});
@ -344,18 +352,15 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
compRendererType = this.outputCtx.importExpr(compAst.directive.rendererType);
}
// elementDef(
// flags: NodeFlags, matchedQueriesDsl: [string | number, QueryValueType][],
// ngContentIndex: number, childCount: number, namespaceAndName: string,
// fixedAttrs: [string, string][] = [],
// bindings?: [BindingFlags, string, string | SecurityContext][],
// outputs?: ([OutputType.ElementOutput | OutputType.DirectiveHostOutput, string, string])[],
// handleEvent?: ElementHandleEventFn,
// componentView?: () => ViewDefinition, componentRendererType?: RendererType2): NodeDef;
// Check index is the same as the node index during compilation
// They might only differ at runtime
const checkIndex = nodeIndex;
this.nodes[nodeIndex] = () => ({
sourceSpan: ast.sourceSpan,
nodeFlags: NodeFlags.TypeElement | flags,
nodeDef: o.importExpr(Identifiers.elementDef).callFn([
o.literal(checkIndex),
o.literal(flags),
queryMatchesExpr,
o.literal(ast.ngContentIndex),
@ -561,20 +566,22 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
eventAst: hostEventAst, dirAst,
}));
// Check index is the same as the node index during compilation
// They might only differ at runtime
const checkIndex = nodeIndex;
// directiveDef(
// flags: NodeFlags, matchedQueries: [string, QueryValueType][], childCount: number, ctor:
// any,
// deps: ([DepFlags, any] | any)[], props?: {[name: string]: [number, string]},
// outputs?: {[name: string]: string}, component?: () => ViewDefinition): NodeDef;
this.nodes[nodeIndex] = () => ({
sourceSpan: dirAst.sourceSpan,
nodeFlags: NodeFlags.TypeDirective | flags,
nodeDef: o.importExpr(Identifiers.directiveDef).callFn([
o.literal(flags), queryMatchExprs.length ? o.literalArr(queryMatchExprs) : o.NULL_EXPR,
o.literal(childCount), providerExpr, depsExpr,
o.literal(checkIndex),
o.literal(flags),
queryMatchExprs.length ? o.literalArr(queryMatchExprs) : o.NULL_EXPR,
o.literal(childCount),
providerExpr,
depsExpr,
inputDefs.length ? new o.LiteralMapExpr(inputDefs) : o.NULL_EXPR,
outputDefs.length ? new o.LiteralMapExpr(outputDefs) : o.NULL_EXPR
outputDefs.length ? new o.LiteralMapExpr(outputDefs) : o.NULL_EXPR,
]),
updateDirectives: updateDirectiveExpressions,
directive: dirAst.directive.type,
@ -687,15 +694,18 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
return () => valueExpr;
}
const nodeIndex = this.nodes.length;
// pureArrayDef(argCount: number): NodeDef;
const checkIndex = this.nodes.length;
this.nodes.push(() => ({
sourceSpan,
nodeFlags: NodeFlags.TypePureArray,
nodeDef: o.importExpr(Identifiers.pureArrayDef).callFn([o.literal(argCount)])
nodeDef: o.importExpr(Identifiers.pureArrayDef).callFn([
o.literal(checkIndex),
o.literal(argCount),
])
}));
return (args: o.Expression[]) => callCheckStmt(nodeIndex, args);
return (args: o.Expression[]) => callCheckStmt(checkIndex, args);
}
private _createLiteralMapConverter(
@ -705,28 +715,32 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
return () => valueExpr;
}
// function pureObjectDef(propToIndex: {[p: string]: number}): NodeDef
const map = o.literalMap(keys.map((e, i) => ({...e, value: o.literal(i)})));
const nodeIndex = this.nodes.length;
const checkIndex = this.nodes.length;
this.nodes.push(() => ({
sourceSpan,
nodeFlags: NodeFlags.TypePureObject,
nodeDef: o.importExpr(Identifiers.pureObjectDef).callFn([map])
nodeDef: o.importExpr(Identifiers.pureObjectDef).callFn([
o.literal(checkIndex),
map,
])
}));
return (args: o.Expression[]) => callCheckStmt(nodeIndex, args);
return (args: o.Expression[]) => callCheckStmt(checkIndex, args);
}
private _createPipeConverter(expression: UpdateExpression, name: string, argCount: number):
BuiltinConverter {
const pipe = this.usedPipes.find((pipeSummary) => pipeSummary.name === name) !;
if (pipe.pure) {
const nodeIndex = this.nodes.length;
// function purePipeDef(argCount: number): NodeDef;
const checkIndex = this.nodes.length;
this.nodes.push(() => ({
sourceSpan: expression.sourceSpan,
nodeFlags: NodeFlags.TypePurePipe,
nodeDef: o.importExpr(Identifiers.purePipeDef).callFn([o.literal(argCount)])
nodeDef: o.importExpr(Identifiers.purePipeDef).callFn([
o.literal(checkIndex),
o.literal(argCount),
])
}));
// find underlying pipe in the component view
@ -742,7 +756,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
return (args: o.Expression[]) => callUnwrapValue(
expression.nodeIndex, expression.bindingIndex,
callCheckStmt(nodeIndex, [pipeValueExpr].concat(args)));
callCheckStmt(checkIndex, [pipeValueExpr].concat(args)));
} else {
const nodeIndex = this._createPipe(expression.sourceSpan, pipe);
const nodeValueExpr =

View File

@ -13,8 +13,8 @@ import {BindingDef, BindingFlags, ElementData, ElementHandleEventFn, NodeDef, No
import {NOOP, calcBindingFlags, checkAndUpdateBinding, dispatchEvent, elementEventFullName, getParentRenderElement, resolveDefinition, resolveRendererType2, splitMatchedQueriesDsl, splitNamespace} from './util';
export function anchorDef(
flags: NodeFlags, matchedQueriesDsl: [string | number, QueryValueType][],
ngContentIndex: number, childCount: number, handleEvent?: ElementHandleEventFn,
flags: NodeFlags, matchedQueriesDsl: null | [string | number, QueryValueType][],
ngContentIndex: null | number, childCount: number, handleEvent?: null | ElementHandleEventFn,
templateFactory?: ViewDefinitionFactory): NodeDef {
flags |= NodeFlags.TypeElement;
const {matchedQueries, references, matchedQueryIds} = splitMatchedQueriesDsl(matchedQueriesDsl);
@ -22,13 +22,14 @@ export function anchorDef(
return {
// will bet set by the view definition
index: -1,
nodeIndex: -1,
parent: null,
renderParent: null,
bindingIndex: -1,
outputIndex: -1,
// regular values
flags,
checkIndex: -1,
childFlags: 0,
directChildFlags: 0,
childMatchedQueries: 0, matchedQueries, matchedQueryIds, references, ngContentIndex, childCount,
@ -54,11 +55,12 @@ export function anchorDef(
}
export function elementDef(
flags: NodeFlags, matchedQueriesDsl: [string | number, QueryValueType][],
ngContentIndex: number, childCount: number, namespaceAndName: string | null,
fixedAttrs: [string, string][] = [],
bindings?: [BindingFlags, string, string | SecurityContext][], outputs?: ([string, string])[],
handleEvent?: ElementHandleEventFn, componentView?: ViewDefinitionFactory,
checkIndex: number, flags: NodeFlags,
matchedQueriesDsl: null | [string | number, QueryValueType][], ngContentIndex: null | number,
childCount: number, namespaceAndName: string | null, fixedAttrs: null | [string, string][] = [],
bindings?: null | [BindingFlags, string, string | SecurityContext | null][],
outputs?: null | ([string, string])[], handleEvent?: null | ElementHandleEventFn,
componentView?: null | ViewDefinitionFactory,
componentRendererType?: RendererType2 | null): NodeDef {
if (!handleEvent) {
handleEvent = NOOP;
@ -111,12 +113,13 @@ export function elementDef(
flags |= NodeFlags.TypeElement;
return {
// will bet set by the view definition
index: -1,
nodeIndex: -1,
parent: null,
renderParent: null,
bindingIndex: -1,
outputIndex: -1,
// regular values
checkIndex,
flags,
childFlags: 0,
directChildFlags: 0,
@ -175,7 +178,7 @@ export function listenToElementOutputs(view: ViewData, compView: ViewData, def:
for (let i = 0; i < def.outputs.length; i++) {
const output = def.outputs[i];
const handleEventClosure = renderEventHandlerClosure(
view, def.index, elementEventFullName(output.target, output.eventName));
view, def.nodeIndex, elementEventFullName(output.target, output.eventName));
let listenTarget: 'window'|'document'|'body'|'component'|null = output.target;
let listenerView = view;
if (output.target === 'component') {
@ -224,7 +227,7 @@ function checkAndUpdateElementValue(view: ViewData, def: NodeDef, bindingIdx: nu
return false;
}
const binding = def.bindings[bindingIdx];
const elData = asElementData(view, def.index);
const elData = asElementData(view, def.nodeIndex);
const renderNode = elData.renderElement;
const name = binding.name !;
switch (binding.flags & BindingFlags.Types) {

View File

@ -9,15 +9,16 @@
import {NodeDef, NodeFlags, ViewData} from './types';
import {RenderNodeAction, getParentRenderElement, visitProjectedRenderNodes} from './util';
export function ngContentDef(ngContentIndex: number, index: number): NodeDef {
export function ngContentDef(ngContentIndex: null | number, index: number): NodeDef {
return {
// will bet set by the view definition
index: -1,
nodeIndex: -1,
parent: null,
renderParent: null,
bindingIndex: -1,
outputIndex: -1,
// regular values
checkIndex: -1,
flags: NodeFlags.TypeNgContent,
childFlags: 0,
directChildFlags: 0,

View File

@ -7,10 +7,10 @@
*/
import {resolveForwardRef} from '../di/forward_ref';
import {Injector, THROW_IF_NOT_FOUND} from '../di/injector';
import {Injector} from '../di/injector';
import {NgModuleRef} from '../linker/ng_module_factory';
import {DepDef, DepFlags, NgModuleData, NgModuleDefinition, NgModuleDefinitionFactory, NgModuleProviderDef, NodeFlags} from './types';
import {DepDef, DepFlags, NgModuleData, NgModuleDefinition, NgModuleProviderDef, NodeFlags} from './types';
import {splitDepsDsl, tokenKey} from './util';
const NOT_CREATED = new Object();
@ -89,80 +89,60 @@ export function resolveNgModuleDep(
function _createProviderInstance(ngModule: NgModuleData, providerDef: NgModuleProviderDef): any {
let injectable: any;
switch (providerDef.flags & NodeFlags.Types) {
case NodeFlags.TypeClassProvider:
injectable = _createClass(ngModule, providerDef.value, providerDef.deps);
break;
return _createClass(ngModule, providerDef.value, providerDef.deps);
case NodeFlags.TypeFactoryProvider:
injectable = _callFactory(ngModule, providerDef.value, providerDef.deps);
break;
return _callFactory(ngModule, providerDef.value, providerDef.deps);
case NodeFlags.TypeUseExistingProvider:
injectable = resolveNgModuleDep(ngModule, providerDef.deps[0]);
break;
return resolveNgModuleDep(ngModule, providerDef.deps[0]);
case NodeFlags.TypeValueProvider:
injectable = providerDef.value;
break;
return providerDef.value;
}
return injectable;
}
function _createClass(ngModule: NgModuleData, ctor: any, deps: DepDef[]): any {
const len = deps.length;
let injectable: any;
switch (len) {
case 0:
injectable = new ctor();
break;
return new ctor();
case 1:
injectable = new ctor(resolveNgModuleDep(ngModule, deps[0]));
break;
return new ctor(resolveNgModuleDep(ngModule, deps[0]));
case 2:
injectable =
new ctor(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]));
break;
return new ctor(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]));
case 3:
injectable = new ctor(
return new ctor(
resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]),
resolveNgModuleDep(ngModule, deps[2]));
break;
default:
const depValues = new Array(len);
for (let i = 0; i < len; i++) {
depValues[i] = resolveNgModuleDep(ngModule, deps[i]);
}
injectable = new ctor(...depValues);
return new ctor(...depValues);
}
return injectable;
}
function _callFactory(ngModule: NgModuleData, factory: any, deps: DepDef[]): any {
const len = deps.length;
let injectable: any;
switch (len) {
case 0:
injectable = factory();
break;
return factory();
case 1:
injectable = factory(resolveNgModuleDep(ngModule, deps[0]));
break;
return factory(resolveNgModuleDep(ngModule, deps[0]));
case 2:
injectable =
factory(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]));
break;
return factory(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]));
case 3:
injectable = factory(
return factory(
resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]),
resolveNgModuleDep(ngModule, deps[2]));
break;
default:
const depValues = Array(len);
for (let i = 0; i < len; i++) {
depValues[i] = resolveNgModuleDep(ngModule, deps[i]);
}
injectable = factory(...depValues);
return factory(...depValues);
}
return injectable;
}
export function callNgModuleLifecycle(ngModule: NgModuleData, lifecycles: NodeFlags) {

View File

@ -28,9 +28,10 @@ const InjectorRefTokenKey = tokenKey(Injector);
const NOT_CREATED = new Object();
export function directiveDef(
flags: NodeFlags, matchedQueries: [string | number, QueryValueType][], childCount: number,
ctor: any, deps: ([DepFlags, any] | any)[], props?: {[name: string]: [number, string]},
outputs?: {[name: string]: string}): NodeDef {
checkIndex: number, flags: NodeFlags,
matchedQueries: null | [string | number, QueryValueType][], childCount: number, ctor: any,
deps: ([DepFlags, any] | any)[], props?: null | {[name: string]: [number, string]},
outputs?: null | {[name: string]: string}): NodeDef {
const bindings: BindingDef[] = [];
if (props) {
for (let prop in props) {
@ -52,24 +53,26 @@ export function directiveDef(
}
}
flags |= NodeFlags.TypeDirective;
return _def(flags, matchedQueries, childCount, ctor, ctor, deps, bindings, outputDefs);
return _def(
checkIndex, flags, matchedQueries, childCount, ctor, ctor, deps, bindings, outputDefs);
}
export function pipeDef(flags: NodeFlags, ctor: any, deps: ([DepFlags, any] | any)[]): NodeDef {
flags |= NodeFlags.TypePipe;
return _def(flags, null, 0, ctor, ctor, deps);
return _def(-1, flags, null, 0, ctor, ctor, deps);
}
export function providerDef(
flags: NodeFlags, matchedQueries: [string | number, QueryValueType][], token: any, value: any,
deps: ([DepFlags, any] | any)[]): NodeDef {
return _def(flags, matchedQueries, 0, token, value, deps);
flags: NodeFlags, matchedQueries: null | [string | number, QueryValueType][], token: any,
value: any, deps: ([DepFlags, any] | any)[]): NodeDef {
return _def(-1, flags, matchedQueries, 0, token, value, deps);
}
export function _def(
flags: NodeFlags, matchedQueriesDsl: [string | number, QueryValueType][] | null,
childCount: number, token: any, value: any, deps: ([DepFlags, any] | any)[],
bindings?: BindingDef[], outputs?: OutputDef[]): NodeDef {
checkIndex: number, flags: NodeFlags,
matchedQueriesDsl: [string | number, QueryValueType][] | null, childCount: number, token: any,
value: any, deps: ([DepFlags, any] | any)[], bindings?: BindingDef[],
outputs?: OutputDef[]): NodeDef {
const {matchedQueries, references, matchedQueryIds} = splitMatchedQueriesDsl(matchedQueriesDsl);
if (!outputs) {
outputs = [];
@ -86,12 +89,13 @@ export function _def(
return {
// will bet set by the view definition
index: -1,
nodeIndex: -1,
parent: null,
renderParent: null,
bindingIndex: -1,
outputIndex: -1,
// regular values
checkIndex,
flags,
childFlags: 0,
directChildFlags: 0,
@ -134,7 +138,7 @@ export function createDirectiveInstance(view: ViewData, def: NodeDef): any {
for (let i = 0; i < def.outputs.length; i++) {
const output = def.outputs[i];
const subscription = instance[output.propName !].subscribe(
eventHandlerClosure(view, def.parent !.index, output.eventName));
eventHandlerClosure(view, def.parent !.nodeIndex, output.eventName));
view.disposables ![def.outputIndex + i] = subscription.unsubscribe.bind(subscription);
}
}
@ -148,7 +152,7 @@ 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): boolean {
const providerData = asProviderData(view, def.index);
const providerData = asProviderData(view, def.nodeIndex);
const directive = providerData.instance;
let changed = false;
let changes: SimpleChanges = undefined !;
@ -207,7 +211,7 @@ export function checkAndUpdateDirectiveInline(
export function checkAndUpdateDirectiveDynamic(
view: ViewData, def: NodeDef, values: any[]): boolean {
const providerData = asProviderData(view, def.index);
const providerData = asProviderData(view, def.nodeIndex);
const directive = providerData.instance;
let changed = false;
let changes: SimpleChanges = undefined !;
@ -233,89 +237,71 @@ function _createProviderInstance(view: ViewData, def: NodeDef): any {
// private services can see other private services
const allowPrivateServices = (def.flags & NodeFlags.PrivateProvider) > 0;
const providerDef = def.provider;
let injectable: any;
switch (def.flags & NodeFlags.Types) {
case NodeFlags.TypeClassProvider:
injectable = createClass(
return createClass(
view, def.parent !, allowPrivateServices, providerDef !.value, providerDef !.deps);
break;
case NodeFlags.TypeFactoryProvider:
injectable = callFactory(
return callFactory(
view, def.parent !, allowPrivateServices, providerDef !.value, providerDef !.deps);
break;
case NodeFlags.TypeUseExistingProvider:
injectable = resolveDep(view, def.parent !, allowPrivateServices, providerDef !.deps[0]);
break;
return resolveDep(view, def.parent !, allowPrivateServices, providerDef !.deps[0]);
case NodeFlags.TypeValueProvider:
injectable = providerDef !.value;
break;
return providerDef !.value;
}
return injectable;
}
function createClass(
view: ViewData, elDef: NodeDef, allowPrivateServices: boolean, ctor: any, deps: DepDef[]): any {
const len = deps.length;
let injectable: any;
switch (len) {
case 0:
injectable = new ctor();
break;
return new ctor();
case 1:
injectable = new ctor(resolveDep(view, elDef, allowPrivateServices, deps[0]));
break;
return new ctor(resolveDep(view, elDef, allowPrivateServices, deps[0]));
case 2:
injectable = new ctor(
return new ctor(
resolveDep(view, elDef, allowPrivateServices, deps[0]),
resolveDep(view, elDef, allowPrivateServices, deps[1]));
break;
case 3:
injectable = new ctor(
return new ctor(
resolveDep(view, elDef, allowPrivateServices, deps[0]),
resolveDep(view, elDef, allowPrivateServices, deps[1]),
resolveDep(view, elDef, allowPrivateServices, deps[2]));
break;
default:
const depValues = new Array(len);
for (let i = 0; i < len; i++) {
depValues[i] = resolveDep(view, elDef, allowPrivateServices, deps[i]);
}
injectable = new ctor(...depValues);
return new ctor(...depValues);
}
return injectable;
}
function callFactory(
view: ViewData, elDef: NodeDef, allowPrivateServices: boolean, factory: any,
deps: DepDef[]): any {
const len = deps.length;
let injectable: any;
switch (len) {
case 0:
injectable = factory();
break;
return factory();
case 1:
injectable = factory(resolveDep(view, elDef, allowPrivateServices, deps[0]));
break;
return factory(resolveDep(view, elDef, allowPrivateServices, deps[0]));
case 2:
injectable = factory(
return factory(
resolveDep(view, elDef, allowPrivateServices, deps[0]),
resolveDep(view, elDef, allowPrivateServices, deps[1]));
break;
case 3:
injectable = factory(
return factory(
resolveDep(view, elDef, allowPrivateServices, deps[0]),
resolveDep(view, elDef, allowPrivateServices, deps[1]),
resolveDep(view, elDef, allowPrivateServices, deps[2]));
break;
default:
const depValues = Array(len);
for (let i = 0; i < len; i++) {
depValues[i] = resolveDep(view, elDef, allowPrivateServices, deps[i]);
}
injectable = factory(...depValues);
return factory(...depValues);
}
return injectable;
}
// This default value is when checking the hierarchy for a token.
@ -372,12 +358,12 @@ export function resolveDep(
return compView.renderer;
}
case ElementRefTokenKey:
return new ElementRef(asElementData(view, elDef.index).renderElement);
return new ElementRef(asElementData(view, elDef.nodeIndex).renderElement);
case ViewContainerRefTokenKey:
return asElementData(view, elDef.index).viewContainer;
return asElementData(view, elDef.nodeIndex).viewContainer;
case TemplateRefTokenKey: {
if (elDef.element !.template) {
return asElementData(view, elDef.index).template;
return asElementData(view, elDef.nodeIndex).template;
}
break;
}
@ -392,7 +378,7 @@ export function resolveDep(
(allowPrivateServices ? elDef.element !.allProviders :
elDef.element !.publicProviders) ![tokenKey];
if (providerDef) {
const providerData = asProviderData(view, providerDef.index);
const providerData = asProviderData(view, providerDef.nodeIndex);
if (providerData.instance === NOT_CREATED) {
providerData.instance = _createProviderInstance(view, providerDef);
}
@ -423,7 +409,7 @@ export function resolveDep(
function findCompView(view: ViewData, elDef: NodeDef, allowPrivateServices: boolean) {
let compView: ViewData;
if (allowPrivateServices) {
compView = asElementData(view, elDef.index).componentView;
compView = asElementData(view, elDef.nodeIndex).componentView;
} else {
compView = view;
while (compView.parent && !isComponentView(compView)) {
@ -437,7 +423,7 @@ function updateProp(
view: ViewData, providerData: ProviderData, def: NodeDef, bindingIdx: number, value: any,
changes: SimpleChanges): SimpleChanges {
if (def.flags & NodeFlags.Component) {
const compView = asElementData(view, def.parent !.index).componentView;
const compView = asElementData(view, def.parent !.nodeIndex).componentView;
if (compView.def.flags & ViewFlags.OnPush) {
compView.state |= ViewState.ChecksEnabled;
}
@ -479,7 +465,7 @@ export function callLifecycleHooksChildrenFirst(view: ViewData, lifecycles: Node
i += nodeDef.childCount;
}
while (parent && (parent.flags & NodeFlags.TypeElement) &&
i === parent.index + parent.childCount) {
i === parent.nodeIndex + parent.childCount) {
// last child of an element
if (parent.directChildFlags & lifecycles) {
callElementProvidersLifecycles(view, parent, lifecycles);
@ -490,7 +476,7 @@ export function callLifecycleHooksChildrenFirst(view: ViewData, lifecycles: Node
}
function callElementProvidersLifecycles(view: ViewData, elDef: NodeDef, lifecycles: NodeFlags) {
for (let i = elDef.index + 1; i <= elDef.index + elDef.childCount; i++) {
for (let i = elDef.nodeIndex + 1; i <= elDef.nodeIndex + elDef.childCount; i++) {
const nodeDef = view.def.nodes[i];
if (nodeDef.flags & lifecycles) {
callProviderLifecycles(view, i, nodeDef.flags & lifecycles);

View File

@ -9,16 +9,16 @@
import {BindingDef, BindingFlags, NodeDef, NodeFlags, PureExpressionData, ViewData, asPureExpressionData} from './types';
import {calcBindingFlags, checkAndUpdateBinding} from './util';
export function purePipeDef(argCount: number): NodeDef {
export function purePipeDef(checkIndex: number, argCount: number): NodeDef {
// argCount + 1 to include the pipe as first arg
return _pureExpressionDef(NodeFlags.TypePurePipe, new Array(argCount + 1));
return _pureExpressionDef(NodeFlags.TypePurePipe, checkIndex, new Array(argCount + 1));
}
export function pureArrayDef(argCount: number): NodeDef {
return _pureExpressionDef(NodeFlags.TypePureArray, new Array(argCount));
export function pureArrayDef(checkIndex: number, argCount: number): NodeDef {
return _pureExpressionDef(NodeFlags.TypePureArray, checkIndex, new Array(argCount));
}
export function pureObjectDef(propToIndex: {[p: string]: number}): NodeDef {
export function pureObjectDef(checkIndex: number, propToIndex: {[p: string]: number}): NodeDef {
const keys = Object.keys(propToIndex);
const nbKeys = keys.length;
const propertyNames = new Array(nbKeys);
@ -28,10 +28,11 @@ export function pureObjectDef(propToIndex: {[p: string]: number}): NodeDef {
propertyNames[index] = key;
}
return _pureExpressionDef(NodeFlags.TypePureObject, propertyNames);
return _pureExpressionDef(NodeFlags.TypePureObject, checkIndex, propertyNames);
}
function _pureExpressionDef(flags: NodeFlags, propertyNames: string[]): NodeDef {
function _pureExpressionDef(
flags: NodeFlags, checkIndex: number, propertyNames: string[]): NodeDef {
const bindings: BindingDef[] = new Array(propertyNames.length);
for (let i = 0; i < propertyNames.length; i++) {
const prop = propertyNames[i];
@ -46,12 +47,13 @@ function _pureExpressionDef(flags: NodeFlags, propertyNames: string[]): NodeDef
}
return {
// will bet set by the view definition
index: -1,
nodeIndex: -1,
parent: null,
renderParent: null,
bindingIndex: -1,
outputIndex: -1,
// regular values
checkIndex,
flags,
childFlags: 0,
directChildFlags: 0,
@ -93,7 +95,7 @@ export function checkAndUpdatePureExpressionInline(
if (bindLen > 9 && checkAndUpdateBinding(view, def, 9, v9)) changed = true;
if (changed) {
const data = asPureExpressionData(view, def.index);
const data = asPureExpressionData(view, def.nodeIndex);
let value: any;
switch (def.flags & NodeFlags.Types) {
case NodeFlags.TypePureArray:
@ -175,7 +177,7 @@ export function checkAndUpdatePureExpressionDynamic(
}
}
if (changed) {
const data = asPureExpressionData(view, def.index);
const data = asPureExpressionData(view, def.nodeIndex);
let value: any;
switch (def.flags & NodeFlags.Types) {
case NodeFlags.TypePureArray:

View File

@ -22,13 +22,14 @@ export function queryDef(
return {
// will bet set by the view definition
index: -1,
nodeIndex: -1,
parent: null,
renderParent: null,
bindingIndex: -1,
outputIndex: -1,
// regular values
flags,
// TODO(vicb): check
checkIndex: -1, flags,
childFlags: 0,
directChildFlags: 0,
childMatchedQueries: 0,
@ -58,7 +59,7 @@ export function dirtyParentQueries(view: ViewData) {
let tplDef = view.parentNodeDef !;
view = view.parent;
// content queries
const end = tplDef.index + tplDef.childCount;
const end = tplDef.nodeIndex + tplDef.childCount;
for (let i = 0; i <= end; i++) {
const nodeDef = view.def.nodes[i];
if ((nodeDef.flags & NodeFlags.TypeContentQuery) &&
@ -66,7 +67,7 @@ export function dirtyParentQueries(view: ViewData) {
(nodeDef.query !.filterId & queryIds) === nodeDef.query !.filterId) {
asQueryList(view, i).setDirty();
}
if ((nodeDef.flags & NodeFlags.TypeElement && i + nodeDef.childCount < tplDef.index) ||
if ((nodeDef.flags & NodeFlags.TypeElement && i + nodeDef.childCount < tplDef.nodeIndex) ||
!(nodeDef.childFlags & NodeFlags.TypeContentQuery) ||
!(nodeDef.childFlags & NodeFlags.DynamicQuery)) {
// skip elements that don't contain the template element or no query.
@ -89,7 +90,7 @@ export function dirtyParentQueries(view: ViewData) {
}
export function checkAndUpdateQuery(view: ViewData, nodeDef: NodeDef) {
const queryList = asQueryList(view, nodeDef.index);
const queryList = asQueryList(view, nodeDef.nodeIndex);
if (!queryList.dirty) {
return;
}
@ -98,8 +99,9 @@ export function checkAndUpdateQuery(view: ViewData, nodeDef: NodeDef) {
if (nodeDef.flags & NodeFlags.TypeContentQuery) {
const elementDef = nodeDef.parent !.parent !;
newValues = calcQueryValues(
view, elementDef.index, elementDef.index + elementDef.childCount, nodeDef.query !, []);
directiveInstance = asProviderData(view, nodeDef.parent !.index).instance;
view, elementDef.nodeIndex, elementDef.nodeIndex + elementDef.childCount, nodeDef.query !,
[]);
directiveInstance = asProviderData(view, nodeDef.parent !.nodeIndex).instance;
} else if (nodeDef.flags & NodeFlags.TypeViewQuery) {
newValues = calcQueryValues(view, 0, view.def.nodes.length - 1, nodeDef.query !, []);
directiveInstance = view.component;
@ -175,24 +177,17 @@ export function getQueryValue(
view: ViewData, nodeDef: NodeDef, queryValueType: QueryValueType): any {
if (queryValueType != null) {
// a match
let value: any;
switch (queryValueType) {
case QueryValueType.RenderElement:
value = asElementData(view, nodeDef.index).renderElement;
break;
return asElementData(view, nodeDef.nodeIndex).renderElement;
case QueryValueType.ElementRef:
value = new ElementRef(asElementData(view, nodeDef.index).renderElement);
break;
return new ElementRef(asElementData(view, nodeDef.nodeIndex).renderElement);
case QueryValueType.TemplateRef:
value = asElementData(view, nodeDef.index).template;
break;
return asElementData(view, nodeDef.nodeIndex).template;
case QueryValueType.ViewContainerRef:
value = asElementData(view, nodeDef.index).viewContainer;
break;
return asElementData(view, nodeDef.nodeIndex).viewContainer;
case QueryValueType.Provider:
value = asProviderData(view, nodeDef.index).instance;
break;
return asProviderData(view, nodeDef.nodeIndex).instance;
}
return value;
}
}

View File

@ -88,7 +88,7 @@ class ComponentFactory_ extends ComponentFactory<any> {
throw new Error('ngModule should be provided');
}
const viewDef = resolveDefinition(this.viewDefFactory);
const componentNodeIndex = viewDef.nodes[0].element !.componentProvider !.index;
const componentNodeIndex = viewDef.nodes[0].element !.componentProvider !.nodeIndex;
const view = Services.createRootView(
injector, projectableNodes || [], rootSelectorOrNode, viewDef, ngModule, EMPTY_CONTEXT);
const component = asProviderData(view, componentNodeIndex).instance;
@ -113,7 +113,7 @@ class ComponentRef_ extends ComponentRef<any> {
this.instance = _component;
}
get location(): ElementRef {
return new ElementRef(asElementData(this._view, this._elDef.index).renderElement);
return new ElementRef(asElementData(this._view, this._elDef.nodeIndex).renderElement);
}
get injector(): Injector { return new Injector_(this._view, this._elDef); }
get componentType(): Type<any> { return <any>this._component.constructor; }
@ -318,7 +318,7 @@ class TemplateRef_ extends TemplateRef<any> implements TemplateData {
}
get elementRef(): ElementRef {
return new ElementRef(asElementData(this._parentView, this._def.index).renderElement);
return new ElementRef(asElementData(this._parentView, this._def.nodeIndex).renderElement);
}
}
@ -340,12 +340,12 @@ class Injector_ implements Injector {
export function nodeValue(view: ViewData, index: number): any {
const def = view.def.nodes[index];
if (def.flags & NodeFlags.TypeElement) {
const elData = asElementData(view, def.index);
const elData = asElementData(view, def.nodeIndex);
return def.element !.template ? elData.template : elData.renderElement;
} else if (def.flags & NodeFlags.TypeText) {
return asTextData(view, def.index).renderText;
return asTextData(view, def.nodeIndex).renderText;
} else if (def.flags & (NodeFlags.CatProvider | NodeFlags.TypePipe)) {
return asProviderData(view, def.index).instance;
return asProviderData(view, def.nodeIndex).instance;
}
throw new Error(`Illegal state: read nodeValue for node index ${index}`);
}

View File

@ -194,7 +194,7 @@ function applyProviderOverridesToView(def: ViewDefinition): ViewDefinition {
}
if (lastElementDef && nodeDef.flags & NodeFlags.CatProviderNoDirective &&
providerOverrides.has(nodeDef.provider !.token)) {
elIndicesWithOverwrittenProviders.push(lastElementDef !.index);
elIndicesWithOverwrittenProviders.push(lastElementDef !.nodeIndex);
lastElementDef = null;
}
}
@ -260,22 +260,22 @@ function applyProviderOverridesToNgModule(def: NgModuleDefinition): NgModuleDefi
}
function prodCheckAndUpdateNode(
view: ViewData, nodeIndex: number, argStyle: ArgumentType, v0?: any, v1?: any, v2?: any,
view: ViewData, checkIndex: 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];
const nodeDef = view.def.nodes[checkIndex];
checkAndUpdateNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
return (nodeDef.flags & NodeFlags.CatPureExpression) ?
asPureExpressionData(view, nodeIndex).value :
asPureExpressionData(view, checkIndex).value :
undefined;
}
function prodCheckNoChangesNode(
view: ViewData, nodeIndex: number, argStyle: ArgumentType, v0?: any, v1?: any, v2?: any,
view: ViewData, checkIndex: 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];
const nodeDef = view.def.nodes[checkIndex];
checkNoChangesNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
return (nodeDef.flags & NodeFlags.CatPureExpression) ?
asPureExpressionData(view, nodeIndex).value :
asPureExpressionData(view, checkIndex).value :
undefined;
}
@ -333,7 +333,7 @@ function debugUpdateDirectives(view: ViewData, checkType: CheckType) {
debugSetCurrentNode(view, nextDirectiveWithBinding(view, nodeIndex));
}
return (nodeDef.flags & NodeFlags.CatPureExpression) ?
asPureExpressionData(view, nodeDef.index).value :
asPureExpressionData(view, nodeDef.nodeIndex).value :
undefined;
}
}
@ -357,7 +357,7 @@ function debugUpdateRenderer(view: ViewData, checkType: CheckType) {
debugSetCurrentNode(view, nextRenderNodeWithBinding(view, nodeIndex));
}
return (nodeDef.flags & NodeFlags.CatPureExpression) ?
asPureExpressionData(view, nodeDef.index).value :
asPureExpressionData(view, nodeDef.nodeIndex).value :
undefined;
}
}
@ -378,7 +378,7 @@ function debugCheckAndUpdateNode(
}
}
const elDef = nodeDef.parent !;
const el = asElementData(view, elDef.index).renderElement;
const el = asElementData(view, elDef.nodeIndex).renderElement;
if (!elDef.element !.name) {
// a comment.
view.renderer.setValue(el, `bindings=${JSON.stringify(bindingValues, null, 2)}`);
@ -468,7 +468,7 @@ class DebugContext_ implements DebugContext {
}
private get elOrCompView() {
// Has to be done lazily as we use the DebugContext also during creation of elements...
return asElementData(this.elView, this.elDef.index).componentView || this.view;
return asElementData(this.elView, this.elDef.nodeIndex).componentView || this.view;
}
get injector(): Injector { return createInjector(this.elView, this.elDef); }
get component(): any { return this.elOrCompView.component; }
@ -476,7 +476,8 @@ class DebugContext_ implements DebugContext {
get providerTokens(): any[] {
const tokens: any[] = [];
if (this.elDef) {
for (let i = this.elDef.index + 1; i <= this.elDef.index + this.elDef.childCount; i++) {
for (let i = this.elDef.nodeIndex + 1; i <= this.elDef.nodeIndex + this.elDef.childCount;
i++) {
const childDef = this.elView.def.nodes[i];
if (childDef.flags & NodeFlags.CatProvider) {
tokens.push(childDef.provider !.token);
@ -491,7 +492,8 @@ class DebugContext_ implements DebugContext {
if (this.elDef) {
collectReferences(this.elView, this.elDef, references);
for (let i = this.elDef.index + 1; i <= this.elDef.index + this.elDef.childCount; i++) {
for (let i = this.elDef.nodeIndex + 1; i <= this.elDef.nodeIndex + this.elDef.childCount;
i++) {
const childDef = this.elView.def.nodes[i];
if (childDef.flags & NodeFlags.CatProvider) {
collectReferences(this.elView, childDef, references);
@ -514,10 +516,10 @@ class DebugContext_ implements DebugContext {
let logNodeIndex: number;
if (this.nodeDef.flags & NodeFlags.TypeText) {
logViewDef = this.view.def;
logNodeIndex = this.nodeDef.index;
logNodeIndex = this.nodeDef.nodeIndex;
} else {
logViewDef = this.elView.def;
logNodeIndex = this.elDef.index;
logNodeIndex = this.elDef.nodeIndex;
}
// Note: we only generate a log function for text and element nodes
// to make the generated code as small as possible.
@ -555,7 +557,7 @@ function findHostElement(view: ViewData): ElementData|null {
view = view.parent !;
}
if (view.parent) {
return asElementData(view.parent, viewParentEl(view) !.index);
return asElementData(view.parent, viewParentEl(view) !.nodeIndex);
}
return null;
}

View File

@ -9,7 +9,8 @@
import {BindingDef, BindingFlags, NodeDef, NodeFlags, TextData, ViewData, asTextData} from './types';
import {checkAndUpdateBinding, getParentRenderElement} from './util';
export function textDef(ngContentIndex: number, staticText: string[]): NodeDef {
export function textDef(
checkIndex: number, ngContentIndex: number | null, staticText: string[]): NodeDef {
const bindings: BindingDef[] = new Array(staticText.length - 1);
for (let i = 1; i < staticText.length; i++) {
bindings[i - 1] = {
@ -24,12 +25,13 @@ export function textDef(ngContentIndex: number, staticText: string[]): NodeDef {
return {
// will bet set by the view definition
index: -1,
nodeIndex: -1,
parent: null,
renderParent: null,
bindingIndex: -1,
outputIndex: -1,
// regular values
checkIndex,
flags: NodeFlags.TypeText,
childFlags: 0,
directChildFlags: 0,
@ -88,7 +90,7 @@ export function checkAndUpdateTextInline(
if (bindLen > 7) value += _addInterpolationPart(v7, bindings[7]);
if (bindLen > 8) value += _addInterpolationPart(v8, bindings[8]);
if (bindLen > 9) value += _addInterpolationPart(v9, bindings[9]);
const renderNode = asTextData(view, def.index).renderText;
const renderNode = asTextData(view, def.nodeIndex).renderText;
view.renderer.setValue(renderNode, value);
}
return changed;
@ -110,7 +112,7 @@ export function checkAndUpdateTextDynamic(view: ViewData, def: NodeDef, values:
value = value + _addInterpolationPart(values[i], bindings[i]);
}
value = def.text !.prefix + value;
const renderNode = asTextData(view, def.index).renderText;
const renderNode = asTextData(view, def.nodeIndex).renderText;
view.renderer.setValue(renderNode, value);
}
return changed;

View File

@ -103,11 +103,15 @@ export const enum ViewFlags {
*/
export interface NodeDef {
flags: NodeFlags;
index: number;
// Index of the node in view data and view definition (those are the same)
nodeIndex: number;
// Index of the node in the check functions
// Differ from nodeIndex when nodes are added or removed at runtime (ie after compilation)
checkIndex: number;
parent: NodeDef|null;
renderParent: NodeDef|null;
/** this is checked against NgContentDef.index to find matched nodes */
ngContentIndex: number;
ngContentIndex: number|null;
/** number of transitive children */
childCount: number;
/** aggregated NodeFlags for all transitive children (does not include self) **/

View File

@ -102,7 +102,7 @@ export function checkBindingNoChanges(
const oldValue = view.oldValues[def.bindingIndex + bindingIdx];
if ((view.state & ViewState.BeforeFirstCheck) || !devModeEqual(oldValue, value)) {
throw expressionChangedAfterItHasBeenCheckedError(
Services.createDebugContext(view, def.index), oldValue, value,
Services.createDebugContext(view, def.nodeIndex), oldValue, value,
(view.state & ViewState.BeforeFirstCheck) !== 0);
}
}
@ -143,7 +143,7 @@ export function dispatchEvent(
export function declaredViewContainer(view: ViewData): ElementData|null {
if (view.parent) {
const parentView = view.parent;
return asElementData(parentView, view.parentNodeDef !.index);
return asElementData(parentView, view.parentNodeDef !.nodeIndex);
}
return null;
}
@ -165,9 +165,9 @@ export function viewParentEl(view: ViewData): NodeDef|null {
export function renderNode(view: ViewData, def: NodeDef): any {
switch (def.flags & NodeFlags.Types) {
case NodeFlags.TypeElement:
return asElementData(view, def.index).renderElement;
return asElementData(view, def.nodeIndex).renderElement;
case NodeFlags.TypeText:
return asTextData(view, def.index).renderText;
return asTextData(view, def.nodeIndex).renderText;
}
}
@ -233,7 +233,7 @@ export function getParentRenderElement(view: ViewData, renderHost: any, def: Nod
ViewEncapsulation.Native)) {
// only children of non components, or children of components with native encapsulation should
// be attached.
return asElementData(view, def.renderParent !.index).renderElement;
return asElementData(view, def.renderParent !.nodeIndex).renderElement;
}
} else {
return renderHost;
@ -292,8 +292,8 @@ export function visitProjectedRenderNodes(
}
const hostView = compView !.parent;
const hostElDef = viewParentEl(compView !);
const startIndex = hostElDef !.index + 1;
const endIndex = hostElDef !.index + hostElDef !.childCount;
const startIndex = hostElDef !.nodeIndex + 1;
const endIndex = hostElDef !.nodeIndex + hostElDef !.childCount;
for (let i = startIndex; i <= endIndex; i++) {
const nodeDef = hostView !.def.nodes[i];
if (nodeDef.ngContentIndex === ngContentIndex) {
@ -328,21 +328,21 @@ function visitRenderNode(
execRenderNodeAction(view, rn, action, parentNode, nextSibling, target);
}
if (nodeDef.bindingFlags & (BindingFlags.SyntheticHostProperty)) {
const compView = asElementData(view, nodeDef.index).componentView;
const compView = asElementData(view, nodeDef.nodeIndex).componentView;
execRenderNodeAction(compView, rn, action, parentNode, nextSibling, target);
}
} else {
execRenderNodeAction(view, rn, action, parentNode, nextSibling, target);
}
if (nodeDef.flags & NodeFlags.EmbeddedViews) {
const embeddedViews = asElementData(view, nodeDef.index).viewContainer !._embeddedViews;
const embeddedViews = asElementData(view, nodeDef.nodeIndex).viewContainer !._embeddedViews;
for (let k = 0; k < embeddedViews.length; k++) {
visitRootRenderNodes(embeddedViews[k], action, parentNode, nextSibling, target);
}
}
if (nodeDef.flags & NodeFlags.TypeElement && !nodeDef.element !.name) {
visitSiblingRenderNodes(
view, action, nodeDef.index + 1, nodeDef.index + nodeDef.childCount, parentNode,
view, action, nodeDef.nodeIndex + 1, nodeDef.nodeIndex + nodeDef.childCount, parentNode,
nextSibling, target);
}
}

View File

@ -21,8 +21,8 @@ import {NOOP, checkBindingNoChanges, isComponentView, markParentViewsForCheckPro
import {detachProjectedView} from './view_attach';
export function viewDef(
flags: ViewFlags, nodes: NodeDef[], updateDirectives?: ViewUpdateFn,
updateRenderer?: ViewUpdateFn): ViewDefinition {
flags: ViewFlags, nodes: NodeDef[], updateDirectives?: null | ViewUpdateFn,
updateRenderer?: null | ViewUpdateFn): ViewDefinition {
// clone nodes and set auto calculated values
let viewBindingCount = 0;
let viewDisposableCount = 0;
@ -36,7 +36,7 @@ export function viewDef(
let lastRenderRootNode: NodeDef|null = null;
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
node.index = i;
node.nodeIndex = i;
node.parent = currentParent;
node.bindingIndex = viewBindingCount;
node.outputIndex = viewDisposableCount;
@ -117,7 +117,7 @@ export function viewDef(
// The loop is required because an element could be the last transitive children of several
// elements. We loop to either the root or the highest opened element (= with remaining
// children)
while (currentParent && i === currentParent.index + currentParent.childCount) {
while (currentParent && i === currentParent.nodeIndex + currentParent.childCount) {
const newParent: NodeDef|null = currentParent.parent;
if (newParent) {
newParent.childFlags |= currentParent.childFlags;
@ -164,32 +164,32 @@ function validateNode(parent: NodeDef | null, node: NodeDef, nodeCount: number)
if (template.lastRenderRootNode &&
template.lastRenderRootNode.flags & NodeFlags.EmbeddedViews) {
throw new Error(
`Illegal State: Last root node of a template can't have embedded views, at index ${node.index}!`);
`Illegal State: Last root node of a template can't have embedded views, at index ${node.nodeIndex}!`);
}
}
if (node.flags & NodeFlags.CatProvider) {
const parentFlags = parent ? parent.flags : 0;
if ((parentFlags & NodeFlags.TypeElement) === 0) {
throw new Error(
`Illegal State: StaticProvider/Directive nodes need to be children of elements or anchors, at index ${node.index}!`);
`Illegal State: StaticProvider/Directive nodes need to be children of elements or anchors, at index ${node.nodeIndex}!`);
}
}
if (node.query) {
if (node.flags & NodeFlags.TypeContentQuery &&
(!parent || (parent.flags & NodeFlags.TypeDirective) === 0)) {
throw new Error(
`Illegal State: Content Query nodes need to be children of directives, at index ${node.index}!`);
`Illegal State: Content Query nodes need to be children of directives, at index ${node.nodeIndex}!`);
}
if (node.flags & NodeFlags.TypeViewQuery && parent) {
throw new Error(
`Illegal State: View Query nodes have to be top level nodes, at index ${node.index}!`);
`Illegal State: View Query nodes have to be top level nodes, at index ${node.nodeIndex}!`);
}
}
if (node.childCount) {
const parentEnd = parent ? parent.index + parent.childCount : nodeCount - 1;
if (node.index <= parentEnd && node.index + node.childCount > parentEnd) {
const parentEnd = parent ? parent.nodeIndex + parent.childCount : nodeCount - 1;
if (node.nodeIndex <= parentEnd && node.nodeIndex + node.childCount > parentEnd) {
throw new Error(
`Illegal State: childCount of node leads outside of parent, at index ${node.index}!`);
`Illegal State: childCount of node leads outside of parent, at index ${node.nodeIndex}!`);
}
}
}
@ -250,7 +250,7 @@ function createViewNodes(view: ViewData) {
let renderHost: any;
if (isComponentView(view)) {
const hostDef = view.parentNodeDef;
renderHost = asElementData(view.parent !, hostDef !.parent !.index).renderElement;
renderHost = asElementData(view.parent !, hostDef !.parent !.nodeIndex).renderElement;
}
const def = view.def;
const nodes = view.nodes;
@ -297,7 +297,7 @@ function createViewNodes(view: ViewData) {
const instance = createDirectiveInstance(view, nodeDef);
nodeData = <ProviderData>{instance};
if (nodeDef.flags & NodeFlags.Component) {
const compView = asElementData(view, nodeDef.parent !.index).componentView;
const compView = asElementData(view, nodeDef.parent !.nodeIndex).componentView;
initView(compView, instance, instance);
}
break;
@ -410,47 +410,38 @@ function markProjectedViewsForCheck(view: ViewData) {
function checkAndUpdateNodeInline(
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.flags & NodeFlags.Types) {
case NodeFlags.TypeElement:
changed = checkAndUpdateElementInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
break;
return checkAndUpdateElementInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
case NodeFlags.TypeText:
changed = checkAndUpdateTextInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
break;
return checkAndUpdateTextInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
case NodeFlags.TypeDirective:
changed =
checkAndUpdateDirectiveInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
break;
return checkAndUpdateDirectiveInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
case NodeFlags.TypePureArray:
case NodeFlags.TypePureObject:
case NodeFlags.TypePurePipe:
changed =
checkAndUpdatePureExpressionInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
break;
return checkAndUpdatePureExpressionInline(
view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
default:
throw 'unreachable';
}
return changed;
}
function checkAndUpdateNodeDynamic(view: ViewData, nodeDef: NodeDef, values: any[]): boolean {
let changed = false;
switch (nodeDef.flags & NodeFlags.Types) {
case NodeFlags.TypeElement:
changed = checkAndUpdateElementDynamic(view, nodeDef, values);
break;
return checkAndUpdateElementDynamic(view, nodeDef, values);
case NodeFlags.TypeText:
changed = checkAndUpdateTextDynamic(view, nodeDef, values);
break;
return checkAndUpdateTextDynamic(view, nodeDef, values);
case NodeFlags.TypeDirective:
changed = checkAndUpdateDirectiveDynamic(view, nodeDef, values);
break;
return checkAndUpdateDirectiveDynamic(view, nodeDef, values);
case NodeFlags.TypePureArray:
case NodeFlags.TypePureObject:
case NodeFlags.TypePurePipe:
changed = checkAndUpdatePureExpressionDynamic(view, nodeDef, values);
break;
return checkAndUpdatePureExpressionDynamic(view, nodeDef, values);
default:
throw 'unreachable';
}
return changed;
}
export function checkNoChangesNode(
@ -492,11 +483,12 @@ function checkNoChangesNodeDynamic(view: ViewData, nodeDef: NodeDef, values: any
* @suppress {misplacedTypeAnnotation}
*/
function checkNoChangesQuery(view: ViewData, nodeDef: NodeDef) {
const queryList = asQueryList(view, nodeDef.index);
const queryList = asQueryList(view, nodeDef.nodeIndex);
if (queryList.dirty) {
throw expressionChangedAfterItHasBeenCheckedError(
Services.createDebugContext(view, nodeDef.index), `Query ${nodeDef.query!.id} not dirty`,
`Query ${nodeDef.query!.id} dirty`, (view.state & ViewState.BeforeFirstCheck) !== 0);
Services.createDebugContext(view, nodeDef.nodeIndex),
`Query ${nodeDef.query!.id} not dirty`, `Query ${nodeDef.query!.id} dirty`,
(view.state & ViewState.BeforeFirstCheck) !== 0);
}
}
@ -651,7 +643,7 @@ function execQueriesAction(
for (let i = 0; i < nodeCount; i++) {
const nodeDef = view.def.nodes[i];
if ((nodeDef.flags & queryFlags) && (nodeDef.flags & staticDynamicQueryFlag)) {
Services.setCurrentNode(view, nodeDef.index);
Services.setCurrentNode(view, nodeDef.nodeIndex);
switch (checkType) {
case CheckType.CheckAndUpdate:
checkAndUpdateQuery(view, nodeDef);

View File

@ -6,47 +6,35 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation, getDebugNode} from '@angular/core';
import {DebugContext, NodeDef, NodeFlags, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, elementDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index';
import {getDebugNode} from '@angular/core';
import {NodeFlags, anchorDef, asElementData, elementDef} from '@angular/core/src/view/index';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {createRootView, isBrowser} from './helper';
import {compViewDef, createAndGetRootNodes} from './helper';
export function main() {
describe(`View Anchor`, () => {
function compViewDef(
nodes: NodeDef[], updateDirectives?: ViewUpdateFn,
updateRenderer?: ViewUpdateFn): ViewDefinition {
return viewDef(ViewFlags.None, nodes, updateDirectives, updateRenderer);
}
function createAndGetRootNodes(
viewDef: ViewDefinition, ctx?: any): {rootNodes: any[], view: ViewData} {
const view = createRootView(viewDef, ctx);
const rootNodes = rootRenderNodes(view);
return {rootNodes, view};
}
describe('create', () => {
it('should create anchor nodes without parents', () => {
const rootNodes = createAndGetRootNodes(compViewDef([
anchorDef(NodeFlags.None, null !, null !, 0)
anchorDef(NodeFlags.None, null, null, 0)
])).rootNodes;
expect(rootNodes.length).toBe(1);
});
it('should create views with multiple root anchor nodes', () => {
const rootNodes = createAndGetRootNodes(compViewDef([
anchorDef(NodeFlags.None, null !, null !, 0),
anchorDef(NodeFlags.None, null !, null !, 0)
])).rootNodes;
const rootNodes =
createAndGetRootNodes(compViewDef([
anchorDef(NodeFlags.None, null, null, 0), anchorDef(NodeFlags.None, null, null, 0)
])).rootNodes;
expect(rootNodes.length).toBe(2);
});
it('should create anchor nodes with parents', () => {
const rootNodes = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'div'),
anchorDef(NodeFlags.None, null !, null !, 0),
elementDef(0, NodeFlags.None, null, null, 1, 'div'),
anchorDef(NodeFlags.None, null, null, 0),
])).rootNodes;
expect(getDOM().childNodes(rootNodes[0]).length).toBe(1);
});
@ -54,7 +42,7 @@ export function main() {
it('should add debug information to the renderer', () => {
const someContext = new Object();
const {view, rootNodes} = createAndGetRootNodes(
compViewDef([anchorDef(NodeFlags.None, null !, null !, 0)]), someContext);
compViewDef([anchorDef(NodeFlags.None, null, null, 0)]), someContext);
expect(getDebugNode(rootNodes[0]) !.nativeNode).toBe(asElementData(view, 0).renderElement);
});
});

View File

@ -6,11 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation} from '@angular/core';
import {ArgumentType, BindingFlags, NodeCheckFn, NodeDef, NodeFlags, OutputType, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewState, ViewUpdateFn, anchorDef, asElementData, asProviderData, directiveDef, elementDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index';
import {SecurityContext} from '@angular/core';
import {ArgumentType, BindingFlags, NodeCheckFn, NodeFlags, Services, ViewData, ViewFlags, ViewState, asElementData, directiveDef, elementDef, rootRenderNodes} from '@angular/core/src/view/index';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {callMostRecentEventListenerHandler, createRootView, isBrowser, recordNodeToRemove} from './helper';
import {callMostRecentEventListenerHandler, compViewDef, createAndGetRootNodes, createRootView, isBrowser, recordNodeToRemove} from './helper';
/**
@ -21,18 +22,6 @@ const addEventListener = '__zone_symbol__addEventListener';
export function main() {
describe(`Component Views`, () => {
function compViewDef(
nodes: NodeDef[], updateDirectives?: ViewUpdateFn, updateRenderer?: ViewUpdateFn,
viewFlags: ViewFlags = ViewFlags.None): ViewDefinition {
return viewDef(viewFlags, nodes, updateDirectives, updateRenderer);
}
function createAndGetRootNodes(viewDef: ViewDefinition): {rootNodes: any[], view: ViewData} {
const view = createRootView(viewDef);
const rootNodes = rootRenderNodes(view);
return {rootNodes, view};
}
it('should create and attach component views', () => {
let instance: AComp = undefined !;
class AComp {
@ -41,11 +30,11 @@ export function main() {
const {view, rootNodes} = createAndGetRootNodes(compViewDef([
elementDef(
NodeFlags.None, null !, null !, 1, 'div', null !, null !, null !, null !,
0, NodeFlags.None, null, null, 1, 'div', null, null, null, null,
() => compViewDef([
elementDef(NodeFlags.None, null !, null !, 0, 'span'),
elementDef(0, NodeFlags.None, null, null, 0, 'span'),
])),
directiveDef(NodeFlags.Component, null !, 0, AComp, []),
directiveDef(1, NodeFlags.Component, null, 0, AComp, []),
]));
const compView = asElementData(view, 0).componentView;
@ -69,7 +58,7 @@ export function main() {
it('should select root elements based on a selector', () => {
const view = createRootView(
compViewDef([
elementDef(NodeFlags.None, null !, null !, 0, 'div'),
elementDef(0, NodeFlags.None, null, null, 0, 'div'),
]),
{}, [], 'root');
const rootNodes = rootRenderNodes(view);
@ -79,7 +68,7 @@ export function main() {
it('should select root elements based on a node', () => {
const view = createRootView(
compViewDef([
elementDef(NodeFlags.None, null !, null !, 0, 'div'),
elementDef(0, NodeFlags.None, null, null, 0, 'div'),
]),
{}, [], rootNode);
const rootNodes = rootRenderNodes(view);
@ -87,9 +76,9 @@ export function main() {
});
it('should set attributes on the root node', () => {
const view = createRootView(
createRootView(
compViewDef([
elementDef(NodeFlags.None, null !, null !, 0, 'div', [['a', 'b']]),
elementDef(0, NodeFlags.None, null, null, 0, 'div', [['a', 'b']]),
]),
{}, [], rootNode);
expect(rootNode.getAttribute('a')).toBe('b');
@ -97,9 +86,9 @@ export function main() {
it('should clear the content of the root node', () => {
rootNode.appendChild(document.createElement('div'));
const view = createRootView(
createRootView(
compViewDef([
elementDef(NodeFlags.None, null !, null !, 0, 'div', [['a', 'b']]),
elementDef(0, NodeFlags.None, null, null, 0, 'div', [['a', 'b']]),
]),
{}, [], rootNode);
expect(rootNode.childNodes.length).toBe(0);
@ -121,12 +110,12 @@ export function main() {
const {view, rootNodes} = createAndGetRootNodes(
compViewDef([
elementDef(NodeFlags.None, null!, null!, 1, 'div', null!, null!, null!, null!, () => compViewDef(
elementDef(0, NodeFlags.None, null, null, 1, 'div', null, null, null, null, () => compViewDef(
[
elementDef(NodeFlags.None, null!, null!, 0, 'span', null!, [[BindingFlags.TypeElementAttribute, 'a', SecurityContext.NONE]]),
], null!, update
elementDef(0, NodeFlags.None, null, null, 0, 'span', null, [[BindingFlags.TypeElementAttribute, 'a', SecurityContext.NONE]]),
], null, update
)),
directiveDef(NodeFlags.Component, null!, 0, AComp, []),
directiveDef(1, NodeFlags.Component, null, 0, AComp, []),
]));
const compView = asElementData(view, 0).componentView;
@ -155,13 +144,13 @@ export function main() {
const {view, rootNodes} = createAndGetRootNodes(compViewDef([
elementDef(
NodeFlags.None, null !, null !, 1, 'div', null !, null !, null !, null !,
0, NodeFlags.None, null, null, 1, 'div', null, null, null, null,
() => compViewDef(
[
elementDef(NodeFlags.None, null !, null !, 0, 'span'),
elementDef(0, NodeFlags.None, null, null, 0, 'span'),
],
update)),
directiveDef(NodeFlags.Component, null !, 0, AComp, [], null !, null !),
directiveDef(1, NodeFlags.Component, null, 0, AComp, [], null, null),
]));
const compView = asElementData(view, 0).componentView;
@ -192,17 +181,17 @@ export function main() {
const {view} = createAndGetRootNodes(compViewDef(
[
elementDef(
NodeFlags.None, null !, null !, 1, 'div', null !, null !, null !, null !,
0, NodeFlags.None, null, null, 1, 'div', null, null, null, null,
() => {
return compViewDef(
[
elementDef(
NodeFlags.None, null !, null !, 0, 'span', null !, null !,
0, NodeFlags.None, null, null, 0, 'span', null, null,
[[null !, 'click']]),
],
update, null !, ViewFlags.OnPush);
update, null, ViewFlags.OnPush);
}),
directiveDef(NodeFlags.Component, null !, 0, AComp, [], {a: [0, 'a']}),
directiveDef(1, NodeFlags.Component, null, 0, AComp, [], {a: [0, 'a']}),
],
(check, view) => { check(view, 1, ArgumentType.Inline, compInputValue); }));
@ -245,18 +234,16 @@ export function main() {
const update = jasmine.createSpy('updater');
const {view, rootNodes} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null!, null!, 1, 'div', null!, null!, null!, null!, () => compViewDef(
[
elementDef(NodeFlags.None, null!, null!, 0, 'span', null!, [[BindingFlags.TypeElementAttribute, 'a', SecurityContext.NONE]]),
],
null!, update)),
directiveDef(
NodeFlags.Component, null!, 0, AComp, [], null!, null!,
),
elementDef(
0, NodeFlags.None, null, null, 1, 'div', null, null, null, null,
() => compViewDef(
[elementDef(
0, NodeFlags.None, null, null, 0, 'span', null,
[[BindingFlags.TypeElementAttribute, 'a', SecurityContext.NONE]])],
null, update)),
directiveDef(1, NodeFlags.Component, null, 0, AComp, [], null, null, ),
]));
const compView = asElementData(view, 0).componentView;
update.and.callFake((check: NodeCheckFn, view: ViewData) => { throw new Error('Test'); });
expect(() => Services.checkAndUpdateView(view)).toThrowError('Test');
expect(update).toHaveBeenCalled();
@ -280,12 +267,12 @@ export function main() {
const {view, rootNodes} = createAndGetRootNodes(compViewDef([
elementDef(
NodeFlags.None, null !, null !, 1, 'div', null !, null !, null !, null !,
0, NodeFlags.None, null, null, 1, 'div', null, null, null, null,
() => compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.OnDestroy, null !, 0, ChildProvider, [])
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.OnDestroy, null, 0, ChildProvider, [])
])),
directiveDef(NodeFlags.Component, null !, 0, AComp, [], null !, null !, ),
directiveDef(1, NodeFlags.Component, null, 0, AComp, [], null, null, ),
]));
Services.destroyView(view);
@ -294,11 +281,8 @@ export function main() {
});
it('should throw on dirty checking destroyed views', () => {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(
[
elementDef(NodeFlags.None, null !, null !, 0, 'div'),
],
(view) => {}));
const {view, rootNodes} = createAndGetRootNodes(
compViewDef([elementDef(0, NodeFlags.None, null, null, 0, 'div')]));
Services.destroyView(view);

View File

@ -6,13 +6,14 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ErrorHandler, Injector, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation, WrappedValue, getDebugNode} from '@angular/core';
import {ErrorHandler, SecurityContext, getDebugNode} from '@angular/core';
import {getDebugContext} from '@angular/core/src/errors';
import {ArgumentType, BindingFlags, DebugContext, NodeDef, NodeFlags, OutputType, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, elementDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index';
import {BindingFlags, NodeFlags, Services, ViewData, ViewDefinition, asElementData, elementDef} from '@angular/core/src/view/index';
import {TestBed} from '@angular/core/testing';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {ARG_TYPE_VALUES, callMostRecentEventListenerHandler, checkNodeInlineOrDynamic, createRootView, isBrowser, recordNodeToRemove} from './helper';
import {ARG_TYPE_VALUES, callMostRecentEventListenerHandler, checkNodeInlineOrDynamic, compViewDef, createAndGetRootNodes, isBrowser, recordNodeToRemove} from './helper';
/**
@ -24,23 +25,11 @@ const removeEventListener = '__zone_symbol__removeEventListener';
export function main() {
describe(`View Elements`, () => {
function compViewDef(
nodes: NodeDef[], updateDirectives?: ViewUpdateFn, updateRenderer?: ViewUpdateFn,
viewFlags: ViewFlags = ViewFlags.None): ViewDefinition {
return viewDef(viewFlags, nodes, updateDirectives, updateRenderer);
}
function createAndGetRootNodes(
viewDef: ViewDefinition, context?: any): {rootNodes: any[], view: ViewData} {
const view = createRootView(viewDef, context);
const rootNodes = rootRenderNodes(view);
return {rootNodes, view};
}
describe('create', () => {
it('should create elements without parents', () => {
const rootNodes = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 0, 'span')
elementDef(0, NodeFlags.None, null, null, 0, 'span')
])).rootNodes;
expect(rootNodes.length).toBe(1);
expect(getDOM().nodeName(rootNodes[0]).toLowerCase()).toBe('span');
@ -48,16 +37,16 @@ export function main() {
it('should create views with multiple root elements', () => {
const rootNodes = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 0, 'span'),
elementDef(NodeFlags.None, null !, null !, 0, 'span')
elementDef(0, NodeFlags.None, null, null, 0, 'span'),
elementDef(1, NodeFlags.None, null, null, 0, 'span'),
])).rootNodes;
expect(rootNodes.length).toBe(2);
});
it('should create elements with parents', () => {
const rootNodes = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'div'),
elementDef(NodeFlags.None, null !, null !, 0, 'span'),
elementDef(0, NodeFlags.None, null, null, 1, 'div'),
elementDef(1, NodeFlags.None, null, null, 0, 'span'),
])).rootNodes;
expect(rootNodes.length).toBe(1);
const spanEl = getDOM().childNodes(rootNodes[0])[0];
@ -66,7 +55,7 @@ export function main() {
it('should set fixed attributes', () => {
const rootNodes = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 0, 'div', [['title', 'a']]),
elementDef(0, NodeFlags.None, null, null, 0, 'div', [['title', 'a']]),
])).rootNodes;
expect(rootNodes.length).toBe(1);
expect(getDOM().getAttribute(rootNodes[0], 'title')).toBe('a');
@ -75,7 +64,7 @@ export function main() {
it('should add debug information to the renderer', () => {
const someContext = new Object();
const {view, rootNodes} = createAndGetRootNodes(
compViewDef([elementDef(NodeFlags.None, null !, null !, 0, 'div')]), someContext);
compViewDef([elementDef(0, NodeFlags.None, null, null, 0, 'div')]), someContext);
expect(getDebugNode(rootNodes[0]) !.nativeNode).toBe(asElementData(view, 0).renderElement);
});
});
@ -87,13 +76,13 @@ export function main() {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(
[
elementDef(
NodeFlags.None, null !, null !, 0, 'input', null !,
0, NodeFlags.None, null, null, 0, 'input', null,
[
[BindingFlags.TypeProperty, 'title', SecurityContext.NONE],
[BindingFlags.TypeProperty, 'value', SecurityContext.NONE]
[BindingFlags.TypeProperty, 'value', SecurityContext.NONE],
]),
],
null !, (check, view) => {
null, (check, view) => {
checkNodeInlineOrDynamic(check, view, 0, inlineDynamic, ['v1', 'v2']);
}));
@ -112,13 +101,13 @@ export function main() {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(
[
elementDef(
NodeFlags.None, null !, null !, 0, 'div', null !,
0, NodeFlags.None, null, null, 0, 'div', null,
[
[BindingFlags.TypeElementAttribute, 'a1', SecurityContext.NONE],
[BindingFlags.TypeElementAttribute, 'a2', SecurityContext.NONE]
[BindingFlags.TypeElementAttribute, 'a2', SecurityContext.NONE],
]),
],
null !, (check, view) => {
null, (check, view) => {
checkNodeInlineOrDynamic(check, view, 0, inlineDynamic, ['v1', 'v2']);
}));
@ -137,10 +126,10 @@ export function main() {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(
[
elementDef(
NodeFlags.None, null !, null !, 0, 'div', null !,
0, NodeFlags.None, null, null, 0, 'div', null,
[
[BindingFlags.TypeElementClass, 'c1', null !],
[BindingFlags.TypeElementClass, 'c2', null !]
[BindingFlags.TypeElementClass, 'c1', null],
[BindingFlags.TypeElementClass, 'c2', null],
]),
],
(check, view) => {
@ -162,13 +151,13 @@ export function main() {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(
[
elementDef(
NodeFlags.None, null !, null !, 0, 'div', null !,
0, NodeFlags.None, null, null, 0, 'div', null,
[
[BindingFlags.TypeElementStyle, 'width', 'px'],
[BindingFlags.TypeElementStyle, 'color', null !]
[BindingFlags.TypeElementStyle, 'color', null],
]),
],
null !, (check, view) => {
null, (check, view) => {
checkNodeInlineOrDynamic(check, view, 0, inlineDynamic, [10, 'red']);
}));
@ -200,7 +189,7 @@ export function main() {
const removeListenerSpy =
spyOn(HTMLElement.prototype, removeEventListener).and.callThrough();
const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef(
NodeFlags.None, null !, null !, 0, 'button', null !, null !, [[null !, 'click']],
0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']],
handleEventSpy)]));
rootNodes[0].click();
@ -221,8 +210,8 @@ export function main() {
const addListenerSpy = spyOn(window, addEventListener);
const removeListenerSpy = spyOn(window, removeEventListener);
const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef(
NodeFlags.None, null !, null !, 0, 'button', null !, null !,
[['window', 'windowClick']], handleEventSpy)]));
0, NodeFlags.None, null, null, 0, 'button', null, null, [['window', 'windowClick']],
handleEventSpy)]));
expect(addListenerSpy).toHaveBeenCalled();
expect(addListenerSpy.calls.mostRecent().args[0]).toBe('windowClick');
@ -244,7 +233,7 @@ export function main() {
const addListenerSpy = spyOn(document, addEventListener);
const removeListenerSpy = spyOn(document, removeEventListener);
const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef(
NodeFlags.None, null !, null !, 0, 'button', null !, null !,
0, NodeFlags.None, null, null, 0, 'button', null, null,
[['document', 'documentClick']], handleEventSpy)]));
expect(addListenerSpy).toHaveBeenCalled();
@ -267,7 +256,7 @@ export function main() {
let preventDefaultSpy: jasmine.Spy = undefined !;
const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef(
NodeFlags.None, null !, null !, 0, 'button', null !, null !, [[null !, 'click']],
0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']],
(view, eventName, event) => {
preventDefaultSpy = spyOn(event, 'preventDefault').and.callThrough();
return eventHandlerResult;
@ -294,7 +283,7 @@ export function main() {
const handleErrorSpy = spyOn(TestBed.get(ErrorHandler), 'handleError');
const addListenerSpy = spyOn(HTMLElement.prototype, addEventListener).and.callThrough();
const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef(
NodeFlags.None, null !, null !, 0, 'button', null !, null !, [[null !, 'click']],
0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']],
() => { throw new Error('Test'); })]));
callMostRecentEventListenerHandler(addListenerSpy, 'SomeEvent');

View File

@ -6,31 +6,14 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation} from '@angular/core';
import {ArgumentType, BindingFlags, NodeCheckFn, NodeDef, NodeFlags, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, attachEmbeddedView, detachEmbeddedView, directiveDef, elementDef, moveEmbeddedView, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index';
import {inject} from '@angular/core/testing';
import {SecurityContext} from '@angular/core';
import {ArgumentType, BindingFlags, NodeCheckFn, NodeFlags, Services, ViewData, anchorDef, asElementData, attachEmbeddedView, detachEmbeddedView, directiveDef, elementDef, moveEmbeddedView, rootRenderNodes} from '@angular/core/src/view/index';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {createEmbeddedView, createRootView, isBrowser} from './helper';
import {compViewDef, compViewDefFactory, createAndGetRootNodes, createEmbeddedView} from './helper';
export function main() {
describe(`Embedded Views`, () => {
function compViewDef(
nodes: NodeDef[], updateDirectives?: ViewUpdateFn, updateRenderer?: ViewUpdateFn,
viewFlags: ViewFlags = ViewFlags.None): ViewDefinition {
return viewDef(viewFlags, nodes, updateDirectives, updateRenderer);
}
function embeddedViewDef(nodes: NodeDef[], update?: ViewUpdateFn): ViewDefinitionFactory {
return () => viewDef(ViewFlags.None, nodes, update);
}
function createAndGetRootNodes(
viewDef: ViewDefinition, context: any = null): {rootNodes: any[], view: ViewData} {
const view = createRootView(viewDef, context);
const rootNodes = rootRenderNodes(view);
return {rootNodes, view};
}
it('should create embedded views with the right context', () => {
const parentContext = new Object();
@ -38,10 +21,10 @@ export function main() {
const {view: parentView} = createAndGetRootNodes(
compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'div'),
elementDef(0, NodeFlags.None, null, null, 1, 'div'),
anchorDef(
NodeFlags.EmbeddedViews, null !, null !, 0, null !,
embeddedViewDef([elementDef(NodeFlags.None, null !, null !, 0, 'span')])),
NodeFlags.EmbeddedViews, null, null, 0, null,
compViewDefFactory([elementDef(0, NodeFlags.None, null, null, 0, 'span')])),
]),
parentContext);
@ -52,14 +35,13 @@ export function main() {
it('should attach and detach embedded views', () => {
const {view: parentView, rootNodes} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 2, 'div'),
anchorDef(NodeFlags.EmbeddedViews, null !, null !, 0, null !, embeddedViewDef([
elementDef(NodeFlags.None, null !, null !, 0, 'span', [['name', 'child0']])
elementDef(0, NodeFlags.None, null, null, 2, 'div'),
anchorDef(NodeFlags.EmbeddedViews, null, null, 0, null, compViewDefFactory([
elementDef(0, NodeFlags.None, null, null, 0, 'span', [['name', 'child0']])
])),
anchorDef(
NodeFlags.None, null !, null !, 0, null !,
embeddedViewDef(
[elementDef(NodeFlags.None, null !, null !, 0, 'span', [['name', 'child1']])]))
anchorDef(NodeFlags.None, null, null, 0, null, compViewDefFactory([elementDef(
0, NodeFlags.None, null, null, 0, 'span',
[['name', 'child1']])]))
]));
const viewContainerData = asElementData(parentView, 1);
const rf = parentView.root.rendererFactory;
@ -86,14 +68,13 @@ export function main() {
it('should move embedded views', () => {
const {view: parentView, rootNodes} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 2, 'div'),
anchorDef(NodeFlags.EmbeddedViews, null !, null !, 0, null !, embeddedViewDef([
elementDef(NodeFlags.None, null !, null !, 0, 'span', [['name', 'child0']])
elementDef(0, NodeFlags.None, null, null, 2, 'div'),
anchorDef(NodeFlags.EmbeddedViews, null, null, 0, null, compViewDefFactory([
elementDef(0, NodeFlags.None, null, null, 0, 'span', [['name', 'child0']])
])),
anchorDef(
NodeFlags.None, null !, null !, 0, null !,
embeddedViewDef(
[elementDef(NodeFlags.None, null !, null !, 0, 'span', [['name', 'child1']])]))
anchorDef(NodeFlags.None, null, null, 0, null, compViewDefFactory([elementDef(
0, NodeFlags.None, null, null, 0, 'span',
[['name', 'child1']])]))
]));
const viewContainerData = asElementData(parentView, 1);
@ -115,10 +96,10 @@ export function main() {
it('should include embedded views in root nodes', () => {
const {view: parentView} = createAndGetRootNodes(compViewDef([
anchorDef(NodeFlags.EmbeddedViews, null !, null !, 0, null !, embeddedViewDef([
elementDef(NodeFlags.None, null !, null !, 0, 'span', [['name', 'child0']])
anchorDef(NodeFlags.EmbeddedViews, null, null, 0, null, compViewDefFactory([
elementDef(0, NodeFlags.None, null, null, 0, 'span', [['name', 'child0']])
])),
elementDef(NodeFlags.None, null !, null !, 0, 'span', [['name', 'after']])
elementDef(1, NodeFlags.None, null, null, 0, 'span', [['name', 'after']])
]));
const childView0 = createEmbeddedView(parentView, parentView.def.nodes[0]);
@ -138,12 +119,12 @@ export function main() {
});
const {view: parentView, rootNodes} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'div'),
elementDef(0, NodeFlags.None, null, null, 1, 'div'),
anchorDef(
NodeFlags.EmbeddedViews, null !, null !, 0, null !,
embeddedViewDef(
NodeFlags.EmbeddedViews, null, null, 0, null,
compViewDefFactory(
[elementDef(
NodeFlags.None, null !, null !, 0, 'span', null !,
0, NodeFlags.None, null, null, 0, 'span', null,
[[BindingFlags.TypeElementAttribute, 'name', SecurityContext.NONE]])],
update))
]));
@ -175,10 +156,10 @@ export function main() {
}
const {view: parentView} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'div'),
anchorDef(NodeFlags.EmbeddedViews, null !, null !, 0, null !, embeddedViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.OnDestroy, null !, 0, ChildProvider, [])
elementDef(0, NodeFlags.None, null, null, 1, 'div'),
anchorDef(NodeFlags.EmbeddedViews, null, null, 0, null, compViewDefFactory([
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.OnDestroy, null, 0, ChildProvider, [])
]))
]));

View File

@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, NgModuleRef, RootRenderer, Sanitizer} from '@angular/core';
import {ArgumentType, NodeCheckFn, NodeDef, RootData, Services, ViewData, ViewDefinition, initServicesIfNeeded} from '@angular/core/src/view/index';
import {Injector, NgModuleRef} from '@angular/core';
import {ArgumentType, NodeCheckFn, NodeDef, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewUpdateFn, initServicesIfNeeded, rootRenderNodes, viewDef} from '@angular/core/src/view/index';
import {TestBed} from '@angular/core/testing';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
@ -41,6 +41,39 @@ export function createEmbeddedView(parent: ViewData, anchorDef: NodeDef, context
return Services.createEmbeddedView(parent, anchorDef, anchorDef.element !.template !, context);
}
export function compViewDef(
nodes: NodeDef[], updateDirectives?: null | ViewUpdateFn, updateRenderer?: null | ViewUpdateFn,
viewFlags: ViewFlags = ViewFlags.None): ViewDefinition {
const def = viewDef(viewFlags, nodes, updateDirectives, updateRenderer);
def.nodes.forEach((node, index) => {
if (node.nodeIndex !== index) {
throw new Error('nodeIndex should be the same as the index of the node');
}
// This check should be removed when we start reordering nodes at runtime
if (node.checkIndex > -1 && node.checkIndex !== node.nodeIndex) {
throw new Error(
`nodeIndex and checkIndex should be the same, got ${node.nodeIndex} !== ${node.checkIndex}`);
}
});
return def;
}
export function compViewDefFactory(
nodes: NodeDef[], updateDirectives?: null | ViewUpdateFn, updateRenderer?: null | ViewUpdateFn,
viewFlags: ViewFlags = ViewFlags.None): ViewDefinitionFactory {
return () => compViewDef(nodes, updateDirectives, updateRenderer, viewFlags);
}
export function createAndGetRootNodes(
viewDef: ViewDefinition, ctx?: any): {rootNodes: any[], view: ViewData} {
const view = createRootView(viewDef, ctx);
const rootNodes = rootRenderNodes(view);
return {rootNodes, view};
}
let removeNodes: Node[];
beforeEach(() => { removeNodes = []; });

View File

@ -10,30 +10,21 @@ import {Injector, RenderComponentType, RootRenderer, Sanitizer, SecurityContext,
import {DebugContext, NodeDef, NodeFlags, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, asTextData, attachEmbeddedView, detachEmbeddedView, directiveDef, elementDef, ngContentDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {createEmbeddedView, createRootView, isBrowser} from './helper';
import {compViewDef, compViewDefFactory, createEmbeddedView, createRootView, isBrowser} from './helper';
export function main() {
describe(`View NgContent`, () => {
function compViewDef(
nodes: NodeDef[], updateDirectives?: ViewUpdateFn, updateRenderer?: ViewUpdateFn,
viewFlags: ViewFlags = ViewFlags.None): ViewDefinition {
return viewDef(viewFlags, nodes, updateDirectives, updateRenderer);
}
function embeddedViewDef(nodes: NodeDef[], update?: ViewUpdateFn): ViewDefinitionFactory {
return () => viewDef(ViewFlags.None, nodes, update);
}
function hostElDef(contentNodes: NodeDef[], viewNodes: NodeDef[]): NodeDef[] {
function hostElDef(
checkIndex: number, contentNodes: NodeDef[], viewNodes: NodeDef[]): NodeDef[] {
class AComp {}
const aCompViewDef = compViewDef(viewNodes);
return [
elementDef(
NodeFlags.None, null !, null !, 1 + contentNodes.length, 'acomp', null !, null !,
null !, null !, () => aCompViewDef),
directiveDef(NodeFlags.Component, null !, 0, AComp, []), ...contentNodes
checkIndex, NodeFlags.None, null, null, 1 + contentNodes.length, 'acomp', null, null,
null, null, () => aCompViewDef),
directiveDef(checkIndex + 1, NodeFlags.Component, null, 0, AComp, []), ...contentNodes
];
}
@ -46,15 +37,15 @@ export function main() {
it('should create ng-content nodes without parents', () => {
const {view, rootNodes} = createAndGetRootNodes(
compViewDef(hostElDef([textDef(0, ['a'])], [ngContentDef(null !, 0)])));
compViewDef(hostElDef(0, [textDef(2, 0, ['a'])], [ngContentDef(null, 0)])));
expect(getDOM().firstChild(rootNodes[0])).toBe(asTextData(view, 2).renderText);
});
it('should create views with multiple root ng-content nodes', () => {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(hostElDef(
[textDef(0, ['a']), textDef(1, ['b'])],
[ngContentDef(null !, 0), ngContentDef(null !, 1)])));
0, [textDef(2, 0, ['a']), textDef(3, 1, ['b'])],
[ngContentDef(null, 0), ngContentDef(null, 1)])));
expect(getDOM().childNodes(rootNodes[0])[0]).toBe(asTextData(view, 2).renderText);
expect(getDOM().childNodes(rootNodes[0])[1]).toBe(asTextData(view, 3).renderText);
@ -62,8 +53,8 @@ export function main() {
it('should create ng-content nodes with parents', () => {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(hostElDef(
[textDef(0, ['a'])],
[elementDef(NodeFlags.None, null !, null !, 1, 'div'), ngContentDef(null !, 0)])));
0, [textDef(2, 0, ['a'])],
[elementDef(0, NodeFlags.None, null, null, 1, 'div'), ngContentDef(null, 0)])));
expect(getDOM().firstChild(getDOM().firstChild(rootNodes[0])))
.toBe(asTextData(view, 2).renderText);
@ -71,8 +62,8 @@ export function main() {
it('should reproject ng-content nodes', () => {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(
hostElDef([textDef(0, ['a'])], hostElDef([ngContentDef(0, 0)], [
elementDef(NodeFlags.None, null !, null !, 1, 'span'), ngContentDef(null !, 0)
hostElDef(0, [textDef(2, 0, ['a'])], hostElDef(0, [ngContentDef(0, 0)], [
elementDef(0, NodeFlags.None, null, null, 1, 'span'), ngContentDef(null, 0)
]))));
expect(getDOM().firstChild(getDOM().firstChild(getDOM().firstChild(rootNodes[0]))))
.toBe(asTextData(view, 2).renderText);
@ -88,18 +79,18 @@ export function main() {
const {view, rootNodes} =
createAndGetRootNodes(
compViewDef(
hostElDef(
hostElDef(0,
[
anchorDef(
NodeFlags.EmbeddedViews, null !, 0, 1, null !,
embeddedViewDef([textDef(null !, ['a'])])),
directiveDef(
NodeFlags.None, null !, 0, CreateViewService,
[TemplateRef, ViewContainerRef])
NodeFlags.EmbeddedViews, null, 0, 1, null,
compViewDefFactory([textDef(0, null, ['a'])])),
directiveDef(3,
NodeFlags.None, null, 0, CreateViewService,
[TemplateRef, ViewContainerRef]),
],
[
elementDef(NodeFlags.None, null !, null !, 1, 'div'),
ngContentDef(null !, 0)
elementDef(0, NodeFlags.None, null, null, 1, 'div'),
ngContentDef(null, 0),
])));
const anchor = asElementData(view, 2);
@ -111,14 +102,15 @@ export function main() {
});
it('should include projected nodes when attaching / detaching embedded views', () => {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(hostElDef([textDef(0, ['a'])], [
elementDef(NodeFlags.None, null !, null !, 1, 'div'),
anchorDef(NodeFlags.EmbeddedViews, null !, 0, 0, null !, embeddedViewDef([
ngContentDef(null !, 0),
// The anchor would be added by the compiler after the ngContent
anchorDef(NodeFlags.None, null !, null !, 0),
])),
])));
const {view, rootNodes} =
createAndGetRootNodes(compViewDef(hostElDef(0, [textDef(2, 0, ['a'])], [
elementDef(0, NodeFlags.None, null, null, 1, 'div'),
anchorDef(NodeFlags.EmbeddedViews, null, 0, 0, null, compViewDefFactory([
ngContentDef(null, 0),
// The anchor would be added by the compiler after the ngContent
anchorDef(NodeFlags.None, null, null, 0),
])),
])));
const componentView = asElementData(view, 0).componentView;
const rf = componentView.root.rendererFactory;
@ -139,7 +131,7 @@ export function main() {
it('should use root projectable nodes', () => {
const projectableNodes = [[document.createTextNode('a')], [document.createTextNode('b')]];
const view = createRootView(
compViewDef(hostElDef([], [ngContentDef(null !, 0), ngContentDef(null !, 1)])), {},
compViewDef(hostElDef(0, [], [ngContentDef(null, 0), ngContentDef(null, 1)])), {},
projectableNodes);
const rootNodes = rootRenderNodes(view);

View File

@ -6,31 +6,16 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectorRef, DoCheck, ElementRef, ErrorHandler, EventEmitter, Injector, OnChanges, OnDestroy, OnInit, RenderComponentType, Renderer, Renderer2, RootRenderer, Sanitizer, SecurityContext, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation, WrappedValue, getDebugNode} from '@angular/core';
import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectorRef, DoCheck, ElementRef, ErrorHandler, EventEmitter, Injector, OnChanges, OnDestroy, OnInit, Renderer, Renderer2, SimpleChange, TemplateRef, ViewContainerRef,} from '@angular/core';
import {getDebugContext} from '@angular/core/src/errors';
import {ArgumentType, BindingFlags, DebugContext, DepFlags, NodeDef, NodeFlags, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, directiveDef, elementDef, providerDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index';
import {TestBed, inject, withModule} from '@angular/core/testing';
import {ArgumentType, DepFlags, NodeFlags, Services, anchorDef, asElementData, directiveDef, elementDef, providerDef, textDef} from '@angular/core/src/view/index';
import {TestBed, withModule} from '@angular/core/testing';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {ARG_TYPE_VALUES, checkNodeInlineOrDynamic, createRootView, isBrowser} from './helper';
import {ARG_TYPE_VALUES, checkNodeInlineOrDynamic, createRootView, createAndGetRootNodes, compViewDef, compViewDefFactory} from './helper';
export function main() {
describe(`View Providers`, () => {
function compViewDef(
nodes: NodeDef[], updateDirectives?: ViewUpdateFn, updateRenderer?: ViewUpdateFn,
viewFlags: ViewFlags = ViewFlags.None): ViewDefinition {
return viewDef(viewFlags, nodes, updateDirectives, updateRenderer);
}
function embeddedViewDef(nodes: NodeDef[], update?: ViewUpdateFn): ViewDefinitionFactory {
return () => viewDef(ViewFlags.None, nodes, update);
}
function createAndGetRootNodes(viewDef: ViewDefinition): {rootNodes: any[], view: ViewData} {
const view = createRootView(viewDef, {});
const rootNodes = rootRenderNodes(view);
return {rootNodes, view};
}
describe('create', () => {
let instance: SomeService;
@ -43,8 +28,8 @@ export function main() {
it('should create providers eagerly', () => {
createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.None, null !, 0, SomeService, [])
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.None, null, 0, SomeService, [])
]));
expect(instance instanceof SomeService).toBe(true);
@ -57,11 +42,11 @@ export function main() {
}
createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
elementDef(0, NodeFlags.None, null, null, 2, 'span'),
providerDef(
NodeFlags.TypeClassProvider | NodeFlags.LazyProvider, null !, LazyService,
LazyService, []),
directiveDef(NodeFlags.None, null !, 0, SomeService, [Injector])
NodeFlags.TypeClassProvider | NodeFlags.LazyProvider, null, LazyService, LazyService,
[]),
directiveDef(2, NodeFlags.None, null, 0, SomeService, [Injector])
]));
expect(lazy).toBeUndefined();
@ -71,9 +56,9 @@ export function main() {
it('should create value providers', () => {
createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
providerDef(NodeFlags.TypeValueProvider, null !, 'someToken', 'someValue', []),
directiveDef(NodeFlags.None, null !, 0, SomeService, ['someToken']),
elementDef(0, NodeFlags.None, null, null, 2, 'span'),
providerDef(NodeFlags.TypeValueProvider, null, 'someToken', 'someValue', []),
directiveDef(2, NodeFlags.None, null, 0, SomeService, ['someToken']),
]));
expect(instance.dep).toBe('someValue');
@ -83,9 +68,9 @@ export function main() {
function someFactory() { return 'someValue'; }
createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
providerDef(NodeFlags.TypeFactoryProvider, null !, 'someToken', someFactory, []),
directiveDef(NodeFlags.None, null !, 0, SomeService, ['someToken']),
elementDef(0, NodeFlags.None, null, null, 2, 'span'),
providerDef(NodeFlags.TypeFactoryProvider, null, 'someToken', someFactory, []),
directiveDef(2, NodeFlags.None, null, 0, SomeService, ['someToken']),
]));
expect(instance.dep).toBe('someValue');
@ -93,12 +78,11 @@ export function main() {
it('should create useExisting providers', () => {
createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 3, 'span'),
providerDef(NodeFlags.TypeValueProvider, null !, 'someExistingToken', 'someValue', []),
elementDef(0, NodeFlags.None, null, null, 3, 'span'),
providerDef(NodeFlags.TypeValueProvider, null, 'someExistingToken', 'someValue', []),
providerDef(
NodeFlags.TypeUseExistingProvider, null !, 'someToken', null !,
['someExistingToken']),
directiveDef(NodeFlags.None, null !, 0, SomeService, ['someToken']),
NodeFlags.TypeUseExistingProvider, null, 'someToken', null, ['someExistingToken']),
directiveDef(3, NodeFlags.None, null, 0, SomeService, ['someToken']),
]));
expect(instance.dep).toBe('someValue');
@ -114,9 +98,9 @@ export function main() {
createRootView(
compViewDef([
elementDef(
NodeFlags.None, null !, null !, 1, 'div', null !, null !, null !, null !,
() => compViewDef([textDef(null !, ['a'])])),
directiveDef(NodeFlags.Component, null !, 0, SomeService, [])
0, NodeFlags.None, null, null, 1, 'div', null, null, null, null,
() => compViewDef([textDef(0, null, ['a'])])),
directiveDef(1, NodeFlags.Component, null, 0, SomeService, [])
]),
TestBed.get(Injector), [], getDOM().createElement('div'));
} catch (e) {
@ -134,9 +118,9 @@ export function main() {
it('should inject deps from the same element', () => {
createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
directiveDef(NodeFlags.None, null !, 0, Dep, []),
directiveDef(NodeFlags.None, null !, 0, SomeService, [Dep])
elementDef(0, NodeFlags.None, null, null, 2, 'span'),
directiveDef(1, NodeFlags.None, null, 0, Dep, []),
directiveDef(2, NodeFlags.None, null, 0, SomeService, [Dep])
]));
expect(instance.dep instanceof Dep).toBeTruthy();
@ -144,34 +128,38 @@ export function main() {
it('should inject deps from a parent element', () => {
createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 3, 'span'),
directiveDef(NodeFlags.None, null !, 0, Dep, []),
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.None, null !, 0, SomeService, [Dep])
elementDef(0, NodeFlags.None, null, null, 3, 'span'),
directiveDef(1, NodeFlags.None, null, 0, Dep, []),
elementDef(2, NodeFlags.None, null, null, 1, 'span'),
directiveDef(3, NodeFlags.None, null, 0, SomeService, [Dep])
]));
expect(instance.dep instanceof Dep).toBeTruthy();
});
it('should not inject deps from sibling root elements', () => {
const nodes = [
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.None, null !, 0, Dep, []),
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.None, null !, 0, SomeService, [Dep])
const rootElNodes = [
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.None, null, 0, Dep, []),
elementDef(2, NodeFlags.None, null, null, 1, 'span'),
directiveDef(3, NodeFlags.None, null, 0, SomeService, [Dep]),
];
// root elements
expect(() => createAndGetRootNodes(compViewDef(nodes)))
expect(() => createAndGetRootNodes(compViewDef(rootElNodes)))
.toThrowError(
'StaticInjectorError[Dep]: \n' +
' StaticInjectorError[Dep]: \n' +
' NullInjectorError: No provider for Dep!');
// non root elements
expect(
() => createAndGetRootNodes(compViewDef(
[elementDef(NodeFlags.None, null !, null !, 4, 'span')].concat(nodes))))
const nonRootElNodes = [
elementDef(0, NodeFlags.None, null, null, 4, 'span'),
elementDef(1, NodeFlags.None, null, null, 1, 'span'),
directiveDef(2, NodeFlags.None, null, 0, Dep, []),
elementDef(3, NodeFlags.None, null, null, 1, 'span'),
directiveDef(4, NodeFlags.None, null, 0, SomeService, [Dep]),
];
expect(() => createAndGetRootNodes(compViewDef(nonRootElNodes)))
.toThrowError(
'StaticInjectorError[Dep]: \n' +
' StaticInjectorError[Dep]: \n' +
@ -181,12 +169,12 @@ export function main() {
it('should inject from a parent element in a parent view', () => {
createAndGetRootNodes(compViewDef([
elementDef(
NodeFlags.None, null !, null !, 1, 'div', null !, null !, null !, null !,
0, NodeFlags.None, null, null, 1, 'div', null, null, null, null,
() => compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.None, null !, 0, SomeService, [Dep])
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.None, null, 0, SomeService, [Dep])
])),
directiveDef(NodeFlags.Component, null !, 0, Dep, []),
directiveDef(1, NodeFlags.Component, null, 0, Dep, []),
]));
expect(instance.dep instanceof Dep).toBeTruthy();
@ -194,8 +182,8 @@ export function main() {
it('should throw for missing dependencies', () => {
expect(() => createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.None, null !, 0, SomeService, ['nonExistingDep'])
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.None, null, 0, SomeService, ['nonExistingDep'])
])))
.toThrowError(
'StaticInjectorError[nonExistingDep]: \n' +
@ -205,21 +193,22 @@ export function main() {
it('should use null for optional missing dependencies', () => {
createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(
NodeFlags.None, null !, 0, SomeService, [[DepFlags.Optional, 'nonExistingDep']])
1, NodeFlags.None, null, 0, SomeService,
[[DepFlags.Optional, 'nonExistingDep']])
]));
expect(instance.dep).toBe(null);
});
it('should skip the current element when using SkipSelf', () => {
createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 4, 'span'),
providerDef(NodeFlags.TypeValueProvider, null !, 'someToken', 'someParentValue', []),
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
providerDef(NodeFlags.TypeValueProvider, null !, 'someToken', 'someValue', []),
elementDef(0, NodeFlags.None, null, null, 4, 'span'),
providerDef(NodeFlags.TypeValueProvider, null, 'someToken', 'someParentValue', []),
elementDef(2, NodeFlags.None, null, null, 2, 'span'),
providerDef(NodeFlags.TypeValueProvider, null, 'someToken', 'someValue', []),
directiveDef(
NodeFlags.None, null !, 0, SomeService, [[DepFlags.SkipSelf, 'someToken']])
4, NodeFlags.None, null, 0, SomeService, [[DepFlags.SkipSelf, 'someToken']])
]));
expect(instance.dep).toBe('someParentValue');
});
@ -227,8 +216,8 @@ export function main() {
it('should ask the root injector',
withModule({providers: [{provide: 'rootDep', useValue: 'rootValue'}]}, () => {
createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.None, null !, 0, SomeService, ['rootDep'])
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.None, null, 0, SomeService, ['rootDep'])
]));
expect(instance.dep).toBe('rootValue');
@ -237,8 +226,8 @@ export function main() {
describe('builtin tokens', () => {
it('should inject ViewContainerRef', () => {
createAndGetRootNodes(compViewDef([
anchorDef(NodeFlags.EmbeddedViews, null !, null !, 1),
directiveDef(NodeFlags.None, null !, 0, SomeService, [ViewContainerRef])
anchorDef(NodeFlags.EmbeddedViews, null, null, 1),
directiveDef(1, NodeFlags.None, null, 0, SomeService, [ViewContainerRef]),
]));
expect(instance.dep.createEmbeddedView).toBeTruthy();
@ -246,10 +235,9 @@ export function main() {
it('should inject TemplateRef', () => {
createAndGetRootNodes(compViewDef([
anchorDef(
NodeFlags.None, null !, null !, 1, null !,
embeddedViewDef([anchorDef(NodeFlags.None, null !, null !, 0)])),
directiveDef(NodeFlags.None, null !, 0, SomeService, [TemplateRef])
anchorDef(NodeFlags.None, null, null, 1, null, compViewDefFactory([anchorDef(
NodeFlags.None, null, null, 0)])),
directiveDef(1, NodeFlags.None, null, 0, SomeService, [TemplateRef]),
]));
expect(instance.dep.createEmbeddedView).toBeTruthy();
@ -257,8 +245,8 @@ export function main() {
it('should inject ElementRef', () => {
const {view} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.None, null !, 0, SomeService, [ElementRef])
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.None, null, 0, SomeService, [ElementRef]),
]));
expect(instance.dep.nativeElement).toBe(asElementData(view, 0).renderElement);
@ -266,8 +254,8 @@ export function main() {
it('should inject Injector', () => {
const {view} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.None, null !, 0, SomeService, [Injector])
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.None, null, 0, SomeService, [Injector]),
]));
expect(instance.dep.get(SomeService)).toBe(instance);
@ -275,8 +263,8 @@ export function main() {
it('should inject ChangeDetectorRef for non component providers', () => {
const {view} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.None, null !, 0, SomeService, [ChangeDetectorRef])
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.None, null, 0, SomeService, [ChangeDetectorRef])
]));
expect(instance.dep._view).toBe(view);
@ -285,11 +273,11 @@ export function main() {
it('should inject ChangeDetectorRef for component providers', () => {
const {view, rootNodes} = createAndGetRootNodes(compViewDef([
elementDef(
NodeFlags.None, null !, null !, 1, 'div', null !, null !, null !, null !,
0, NodeFlags.None, null, null, 1, 'div', null, null, null, null,
() => compViewDef([
elementDef(NodeFlags.None, null !, null !, 0, 'span'),
elementDef(0, NodeFlags.None, null, null, 0, 'span'),
])),
directiveDef(NodeFlags.Component, null !, 0, SomeService, [ChangeDetectorRef]),
directiveDef(1, NodeFlags.Component, null, 0, SomeService, [ChangeDetectorRef]),
]));
const compView = asElementData(view, 0).componentView;
@ -299,9 +287,9 @@ export function main() {
it('should inject RendererV1', () => {
createAndGetRootNodes(compViewDef([
elementDef(
NodeFlags.None, null !, null !, 1, 'span', null !, null !, null !, null !,
() => compViewDef([anchorDef(NodeFlags.None, null !, null !, 0)])),
directiveDef(NodeFlags.Component, null !, 0, SomeService, [Renderer])
0, NodeFlags.None, null, null, 1, 'span', null, null, null, null,
() => compViewDef([anchorDef(NodeFlags.None, null, null, 0)])),
directiveDef(1, NodeFlags.Component, null, 0, SomeService, [Renderer])
]));
expect(instance.dep.createElement).toBeTruthy();
@ -310,9 +298,9 @@ export function main() {
it('should inject Renderer2', () => {
createAndGetRootNodes(compViewDef([
elementDef(
NodeFlags.None, null !, null !, 1, 'span', null !, null !, null !, null !,
() => compViewDef([anchorDef(NodeFlags.None, null !, null !, 0)])),
directiveDef(NodeFlags.Component, null !, 0, SomeService, [Renderer2])
0, NodeFlags.None, null, null, 1, 'span', null, null, null, null,
() => compViewDef([anchorDef(NodeFlags.None, null, null, 0)])),
directiveDef(1, NodeFlags.Component, null, 0, SomeService, [Renderer2])
]));
expect(instance.dep.createElement).toBeTruthy();
@ -337,9 +325,9 @@ export function main() {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(
[
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(
NodeFlags.None, null !, 0, SomeService, [], {a: [0, 'a'], b: [1, 'b']})
1, NodeFlags.None, null, 0, SomeService, [], {a: [0, 'a'], b: [1, 'b']})
],
(check, view) => {
checkNodeInlineOrDynamic(check, view, 1, inlineDynamic, ['v1', 'v2']);
@ -373,13 +361,11 @@ export function main() {
}
const handleEvent = jasmine.createSpy('handleEvent');
const subscribe = spyOn(emitter, 'subscribe').and.callThrough();
const {view, rootNodes} = createAndGetRootNodes(compViewDef([
elementDef(
NodeFlags.None, null !, null !, 1, 'span', null !, null !, null !, handleEvent),
elementDef(0, NodeFlags.None, null, null, 1, 'span', null, null, null, handleEvent),
directiveDef(
NodeFlags.None, null !, 0, SomeService, [], null !, {emitter: 'someEventName'})
1, NodeFlags.None, null, 0, SomeService, [], null, {emitter: 'someEventName'})
]));
emitter.emit('someEventInstance');
@ -399,10 +385,10 @@ export function main() {
const {view, rootNodes} = createAndGetRootNodes(compViewDef([
elementDef(
NodeFlags.None, null !, null !, 1, 'span', null !, null !, null !,
0, NodeFlags.None, null, null, 1, 'span', null, null, null,
() => { throw new Error('Test'); }),
directiveDef(
NodeFlags.None, null !, 0, SomeService, [], null !, {emitter: 'someEventName'})
1, NodeFlags.None, null, 0, SomeService, [], null, {emitter: 'someEventName'})
]));
emitter.emit('someEventInstance');
@ -440,10 +426,10 @@ export function main() {
NodeFlags.AfterViewChecked | NodeFlags.OnDestroy;
const {view, rootNodes} = createAndGetRootNodes(compViewDef(
[
elementDef(NodeFlags.None, null !, null !, 3, 'span'),
directiveDef(allFlags, null !, 0, SomeService, [], {a: [0, 'a']}),
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(allFlags, null !, 0, SomeService, [], {a: [0, 'a']})
elementDef(0, NodeFlags.None, null, null, 3, 'span'),
directiveDef(1, allFlags, null, 0, SomeService, [], {a: [0, 'a']}),
elementDef(2, NodeFlags.None, null, null, 1, 'span'),
directiveDef(3, allFlags, null, 0, SomeService, [], {a: [0, 'a']})
],
(check, view) => {
check(view, 1, ArgumentType.Inline, 'someValue');
@ -499,9 +485,9 @@ export function main() {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(
[
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(
NodeFlags.OnChanges, null !, 0, SomeService, [], {a: [0, 'nonMinifiedA']})
1, NodeFlags.OnChanges, null, 0, SomeService, [], {a: [0, 'nonMinifiedA']})
],
(check, view) => { check(view, 1, ArgumentType.Inline, currValue); }));
@ -520,8 +506,8 @@ export function main() {
}
const {view, rootNodes} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.AfterContentChecked, null !, 0, SomeService, [], {a: [0, 'a']}),
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.AfterContentChecked, null, 0, SomeService, [], {a: [0, 'a']}),
]));
let err: any;
@ -543,8 +529,8 @@ export function main() {
}
const {view, rootNodes} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.OnDestroy, null !, 0, SomeService, [], {a: [0, 'a']}),
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.OnDestroy, null, 0, SomeService, [], {a: [0, 'a']}),
]));
let err: any;

View File

@ -7,23 +7,12 @@
*/
import {PipeTransform} from '@angular/core';
import {NodeDef, NodeFlags, Services, ViewData, ViewDefinition, ViewFlags, ViewUpdateFn, asProviderData, directiveDef, elementDef, nodeValue, pipeDef, pureArrayDef, pureObjectDef, purePipeDef, rootRenderNodes, viewDef} from '@angular/core/src/view/index';
import {NodeFlags, Services, asProviderData, directiveDef, elementDef, nodeValue, pipeDef, pureArrayDef, pureObjectDef, purePipeDef} from '@angular/core/src/view/index';
import {ARG_TYPE_VALUES, checkNodeInlineOrDynamic, createRootView} from './helper';
import {ARG_TYPE_VALUES, checkNodeInlineOrDynamic, compViewDef, createAndGetRootNodes} from './helper';
export function main() {
describe(`View Pure Expressions`, () => {
function compViewDef(
nodes: NodeDef[], updateDirectives?: ViewUpdateFn, updateRenderer?: ViewUpdateFn,
viewFlags: ViewFlags = ViewFlags.None): ViewDefinition {
return viewDef(viewFlags, nodes, updateDirectives, updateRenderer);
}
function createAndGetRootNodes(viewDef: ViewDefinition): {rootNodes: any[], view: ViewData} {
const view = createRootView(viewDef);
const rootNodes = rootRenderNodes(view);
return {rootNodes, view};
}
class Service {
data: any;
@ -37,9 +26,9 @@ export function main() {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(
[
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
pureArrayDef(2),
directiveDef(NodeFlags.None, null !, 0, Service, [], {data: [0, 'data']}),
elementDef(0, NodeFlags.None, null, null, 2, 'span'),
pureArrayDef(1, 2),
directiveDef(2, NodeFlags.None, null, 0, Service, [], {data: [0, 'data']}),
],
(check, view) => {
const pureValue = checkNodeInlineOrDynamic(check, view, 1, inlineDynamic, values);
@ -75,8 +64,9 @@ export function main() {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(
[
elementDef(NodeFlags.None, null !, null !, 2, 'span'), pureObjectDef({a: 0, b: 1}),
directiveDef(NodeFlags.None, null !, 0, Service, [], {data: [0, 'data']})
elementDef(0, NodeFlags.None, null, null, 2, 'span'),
pureObjectDef(1, {a: 0, b: 1}),
directiveDef(2, NodeFlags.None, null, 0, Service, [], {data: [0, 'data']})
],
(check, view) => {
const pureValue = checkNodeInlineOrDynamic(check, view, 1, inlineDynamic, values);
@ -115,10 +105,10 @@ export function main() {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(
[
elementDef(NodeFlags.None, null !, null !, 3, 'span'),
elementDef(0, NodeFlags.None, null !, null !, 3, 'span'),
pipeDef(NodeFlags.None, SomePipe, []),
purePipeDef(2),
directiveDef(NodeFlags.None, null !, 0, Service, [], {data: [0, 'data']}),
purePipeDef(2, 2),
directiveDef(3, NodeFlags.None, null, 0, Service, [], {data: [0, 'data']}),
],
(check, view) => {
const pureValue = checkNodeInlineOrDynamic(

View File

@ -6,32 +6,14 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ElementRef, Injector, QueryList, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, TemplateRef, ViewContainerRef, ViewEncapsulation, getDebugNode} from '@angular/core';
import {ElementRef, QueryList, TemplateRef, ViewContainerRef} from '@angular/core';
import {getDebugContext} from '@angular/core/src/errors';
import {BindingFlags, DebugContext, NodeDef, NodeFlags, QueryBindingType, QueryValueType, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, attachEmbeddedView, detachEmbeddedView, directiveDef, elementDef, queryDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index';
import {inject} from '@angular/core/testing';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {NodeDef, NodeFlags, QueryBindingType, QueryValueType, Services, anchorDef, asElementData, asProviderData, attachEmbeddedView, detachEmbeddedView, directiveDef, elementDef, queryDef} from '@angular/core/src/view/index';
import {createEmbeddedView, createRootView} from './helper';
import {compViewDef, compViewDefFactory, createAndGetRootNodes, createEmbeddedView} from './helper';
export function main() {
describe(`Query Views`, () => {
function compViewDef(
nodes: NodeDef[], updateDirectives?: ViewUpdateFn, updateRenderer?: ViewUpdateFn,
viewFlags: ViewFlags = ViewFlags.None): ViewDefinition {
return viewDef(viewFlags, nodes, updateDirectives, updateRenderer);
}
function embeddedViewDef(nodes: NodeDef[], update?: ViewUpdateFn): ViewDefinitionFactory {
return () => viewDef(ViewFlags.None, nodes, update);
}
function createAndGetRootNodes(
viewDef: ViewDefinition, context: any = null): {rootNodes: any[], view: ViewData} {
const view = createRootView(viewDef, context);
const rootNodes = rootRenderNodes(view);
return {rootNodes, view};
}
const someQueryId = 1;
@ -41,43 +23,50 @@ export function main() {
a: QueryList<AService>;
}
function contentQueryProviders() {
function contentQueryProviders(checkIndex: number) {
return [
directiveDef(NodeFlags.None, null !, 1, QueryService, []),
directiveDef(checkIndex, NodeFlags.None, null, 1, QueryService, []),
queryDef(
NodeFlags.TypeContentQuery | NodeFlags.DynamicQuery, someQueryId,
{'a': QueryBindingType.All})
];
}
function compViewQueryProviders(extraChildCount: number, nodes: NodeDef[]) {
const cQPLength = contentQueryProviders(0).length;
// nodes first checkIndex should be 1 (to account for the `queryDef`
function compViewQueryProviders(checkIndex: number, extraChildCount: number, nodes: NodeDef[]) {
return [
elementDef(
NodeFlags.None, null !, null !, 1 + extraChildCount, 'div', null !, null !, null !,
null !, () => compViewDef([
queryDef(
NodeFlags.TypeViewQuery | NodeFlags.DynamicQuery, someQueryId,
{'a': QueryBindingType.All}),
...nodes
])),
directiveDef(NodeFlags.Component, null !, 0, QueryService, [], null !, null !, ),
checkIndex, NodeFlags.None, null, null, 1 + extraChildCount, 'div', null, null, null,
null, () => compViewDef([
queryDef(
NodeFlags.TypeViewQuery | NodeFlags.DynamicQuery, someQueryId,
{'a': QueryBindingType.All}),
...nodes
])),
directiveDef(
checkIndex + 1, NodeFlags.Component, null !, 0, QueryService, [], null !, null !, ),
];
}
function aServiceProvider() {
const cVQLength = compViewQueryProviders(0, 0, []).length;
function aServiceProvider(checkIndex: number) {
return directiveDef(
NodeFlags.None, [[someQueryId, QueryValueType.Provider]], 0, AService, []);
checkIndex, NodeFlags.None, [[someQueryId, QueryValueType.Provider]], 0, AService, []);
}
describe('content queries', () => {
it('should query providers on the same element and child elements', () => {
const {view} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 5, 'div'),
...contentQueryProviders(),
aServiceProvider(),
elementDef(NodeFlags.None, null !, null !, 1, 'div'),
aServiceProvider(),
elementDef(0, NodeFlags.None, null, null, 5, 'div'),
...contentQueryProviders(1),
aServiceProvider(1 + cQPLength),
elementDef(2 + cQPLength, NodeFlags.None, null, null, 1, 'div'),
aServiceProvider(3 + cQPLength),
]));
const qs: QueryService = asProviderData(view, 1).instance;
@ -92,13 +81,14 @@ export function main() {
});
it('should not query providers on sibling or parent elements', () => {
const {view} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 6, 'div'),
aServiceProvider(),
elementDef(NodeFlags.None, null !, null !, 2, 'div'),
...contentQueryProviders(),
elementDef(NodeFlags.None, null !, null !, 1, 'div'),
aServiceProvider(),
elementDef(0, NodeFlags.None, null, null, 6, 'div'),
aServiceProvider(1),
elementDef(2, NodeFlags.None, null, null, 2, 'div'),
...contentQueryProviders(3),
elementDef(3 + cQPLength, NodeFlags.None, null, null, 1, 'div'),
aServiceProvider(4 + cQPLength),
]));
Services.checkAndUpdateView(view);
@ -112,10 +102,10 @@ export function main() {
it('should query providers in the view', () => {
const {view} = createAndGetRootNodes(compViewDef([
...compViewQueryProviders(
0,
0, 0,
[
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
aServiceProvider(),
elementDef(1, NodeFlags.None, null, null, 1, 'span'),
aServiceProvider(2),
]),
]));
@ -129,12 +119,8 @@ export function main() {
it('should not query providers on the host element', () => {
const {view} = createAndGetRootNodes(compViewDef([
...compViewQueryProviders(
1,
[
elementDef(NodeFlags.None, null !, null !, 0, 'span'),
]),
aServiceProvider(),
...compViewQueryProviders(0, 1, [elementDef(1, NodeFlags.None, null, null, 0, 'span')]),
aServiceProvider(cVQLength),
]));
Services.checkAndUpdateView(view);
@ -146,13 +132,13 @@ export function main() {
describe('embedded views', () => {
it('should query providers in embedded views', () => {
const {view} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 5, 'div'),
...contentQueryProviders(),
anchorDef(NodeFlags.EmbeddedViews, null !, null !, 2, null !, embeddedViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'div'),
aServiceProvider(),
elementDef(0, NodeFlags.None, null, null, 5, 'div'),
...contentQueryProviders(1),
anchorDef(NodeFlags.EmbeddedViews, null, null, 2, null, compViewDefFactory([
elementDef(0, NodeFlags.None, null, null, 1, 'div'),
aServiceProvider(1),
])),
...contentQueryProviders(),
...contentQueryProviders(2 + cQPLength),
]));
const childView = createEmbeddedView(view, view.def.nodes[3]);
@ -172,15 +158,15 @@ export function main() {
it('should query providers in embedded views only at the template declaration', () => {
const {view} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 3, 'div'),
...contentQueryProviders(),
anchorDef(NodeFlags.EmbeddedViews, null !, null !, 0, null !, embeddedViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'div'),
aServiceProvider(),
elementDef(0, NodeFlags.None, null, null, 3, 'div'),
...contentQueryProviders(1),
anchorDef(NodeFlags.EmbeddedViews, null, null, 0, null, compViewDefFactory([
elementDef(0, NodeFlags.None, null, null, 1, 'div'),
aServiceProvider(1),
])),
elementDef(NodeFlags.None, null !, null !, 3, 'div'),
...contentQueryProviders(),
anchorDef(NodeFlags.EmbeddedViews, null !, null !, 0),
elementDef(2 + cQPLength, NodeFlags.None, null, null, 3, 'div'),
...contentQueryProviders(3 + cQPLength),
anchorDef(NodeFlags.EmbeddedViews, null, null, 0),
]));
const childView = createEmbeddedView(view, view.def.nodes[3]);
@ -201,11 +187,11 @@ export function main() {
it('should update content queries if embedded views are added or removed', () => {
const {view} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 3, 'div'),
...contentQueryProviders(),
anchorDef(NodeFlags.EmbeddedViews, null !, null !, 0, null !, embeddedViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'div'),
aServiceProvider(),
elementDef(0, NodeFlags.None, null, null, 3, 'div'),
...contentQueryProviders(1),
anchorDef(NodeFlags.EmbeddedViews, null, null, 0, null, compViewDefFactory([
elementDef(0, NodeFlags.None, null, null, 1, 'div'),
aServiceProvider(1),
])),
]));
@ -230,11 +216,11 @@ export function main() {
it('should update view queries if embedded views are added or removed', () => {
const {view} = createAndGetRootNodes(compViewDef([
...compViewQueryProviders(
0,
0, 0,
[
anchorDef(NodeFlags.EmbeddedViews, null !, null !, 0, null !, embeddedViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'div'),
aServiceProvider(),
anchorDef(NodeFlags.EmbeddedViews, null, null, 0, null, compViewDefFactory([
elementDef(0, NodeFlags.None, null, null, 1, 'div'),
aServiceProvider(1),
])),
]),
]));
@ -265,13 +251,13 @@ export function main() {
}
const {view} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 4, 'div'),
directiveDef(NodeFlags.None, null !, 1, QueryService, []),
elementDef(0, NodeFlags.None, null, null, 4, 'div'),
directiveDef(1, NodeFlags.None, null, 1, QueryService, []),
queryDef(
NodeFlags.TypeContentQuery | NodeFlags.DynamicQuery, someQueryId,
{'a': QueryBindingType.All}),
aServiceProvider(),
aServiceProvider(),
aServiceProvider(3),
aServiceProvider(4),
]));
Services.checkAndUpdateView(view);
@ -290,13 +276,13 @@ export function main() {
}
const {view} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 4, 'div'),
directiveDef(NodeFlags.None, null !, 1, QueryService, []),
elementDef(0, NodeFlags.None, null, null, 4, 'div'),
directiveDef(1, NodeFlags.None, null, 1, QueryService, []),
queryDef(
NodeFlags.TypeContentQuery | NodeFlags.DynamicQuery, someQueryId,
{'a': QueryBindingType.First}),
aServiceProvider(),
aServiceProvider(),
aServiceProvider(3),
aServiceProvider(4),
]));
Services.checkAndUpdateView(view);
@ -313,8 +299,8 @@ export function main() {
}
const {view} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, [[someQueryId, QueryValueType.ElementRef]], null !, 2, 'div'),
directiveDef(NodeFlags.None, null !, 1, QueryService, []),
elementDef(0, NodeFlags.None, [[someQueryId, QueryValueType.ElementRef]], null, 2, 'div'),
directiveDef(1, NodeFlags.None, null, 1, QueryService, []),
queryDef(
NodeFlags.TypeContentQuery | NodeFlags.DynamicQuery, someQueryId,
{'a': QueryBindingType.First}),
@ -333,9 +319,9 @@ export function main() {
const {view} = createAndGetRootNodes(compViewDef([
anchorDef(
NodeFlags.None, [[someQueryId, QueryValueType.TemplateRef]], null !, 2, null !,
embeddedViewDef([anchorDef(NodeFlags.None, null !, null !, 0)])),
directiveDef(NodeFlags.None, null !, 1, QueryService, []),
NodeFlags.None, [[someQueryId, QueryValueType.TemplateRef]], null, 2, null,
compViewDefFactory([anchorDef(NodeFlags.None, null, null, 0)])),
directiveDef(1, NodeFlags.None, null, 1, QueryService, []),
queryDef(
NodeFlags.TypeContentQuery | NodeFlags.DynamicQuery, someQueryId,
{'a': QueryBindingType.First}),
@ -354,8 +340,8 @@ export function main() {
const {view} = createAndGetRootNodes(compViewDef([
anchorDef(
NodeFlags.EmbeddedViews, [[someQueryId, QueryValueType.ViewContainerRef]], null !, 2),
directiveDef(NodeFlags.None, null !, 1, QueryService, []),
NodeFlags.EmbeddedViews, [[someQueryId, QueryValueType.ViewContainerRef]], null, 2),
directiveDef(1, NodeFlags.None, null, 1, QueryService, []),
queryDef(
NodeFlags.TypeContentQuery | NodeFlags.DynamicQuery, someQueryId,
{'a': QueryBindingType.First}),
@ -375,12 +361,12 @@ export function main() {
}
const {view} = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 3, 'div'),
directiveDef(NodeFlags.None, null !, 1, QueryService, []),
elementDef(0, NodeFlags.None, null, null, 3, 'div'),
directiveDef(1, NodeFlags.None, null, 1, QueryService, []),
queryDef(
NodeFlags.TypeContentQuery | NodeFlags.DynamicQuery, someQueryId,
{'a': QueryBindingType.All}),
aServiceProvider(),
aServiceProvider(3),
]));

View File

@ -6,27 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation, getDebugNode} from '@angular/core';
import {DebugContext, NodeDef, NodeFlags, QueryValueType, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, asTextData, directiveDef, elementDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index';
import {inject} from '@angular/core/testing';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {DebugContext, NodeFlags, QueryValueType, Services, asElementData, asTextData, directiveDef, elementDef, textDef} from '@angular/core/src/view/index';
import {createRootView, isBrowser} from './helper';
import {compViewDef, createAndGetRootNodes} from './helper';
export function main() {
describe('View Services', () => {
function compViewDef(
nodes: NodeDef[], updateDirectives?: ViewUpdateFn, updateRenderer?: ViewUpdateFn,
viewFlags: ViewFlags = ViewFlags.None): ViewDefinition {
return viewDef(viewFlags, nodes, updateDirectives, updateRenderer);
}
function createAndGetRootNodes(
viewDef: ViewDefinition, context: any = null): {rootNodes: any[], view: ViewData} {
const view = createRootView(viewDef, context);
const rootNodes = rootRenderNodes(view);
return {rootNodes, view};
}
describe('DebugContext', () => {
class AComp {}
@ -36,12 +21,13 @@ export function main() {
function createViewWithData() {
const {view} = createAndGetRootNodes(compViewDef([
elementDef(
NodeFlags.None, null !, null !, 1, 'div', null !, null !, null !, null !,
0, NodeFlags.None, null, null, 1, 'div', null, null, null, null,
() => compViewDef([
elementDef(NodeFlags.None, [['ref', QueryValueType.ElementRef]], null !, 2, 'span'),
directiveDef(NodeFlags.None, null !, 0, AService, []), textDef(null !, ['a'])
elementDef(
0, NodeFlags.None, [['ref', QueryValueType.ElementRef]], null, 2, 'span'),
directiveDef(1, NodeFlags.None, null, 0, AService, []), textDef(2, null, ['a'])
])),
directiveDef(NodeFlags.Component, null !, 0, AComp, []),
directiveDef(1, NodeFlags.Component, null, 0, AComp, []),
]));
return view;
}

View File

@ -6,46 +6,34 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation, WrappedValue, getDebugNode} from '@angular/core';
import {ArgumentType, DebugContext, NodeDef, NodeFlags, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asTextData, elementDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index';
import {inject} from '@angular/core/testing';
import {getDebugNode} from '@angular/core';
import {NodeFlags, Services, asTextData, elementDef, textDef} from '@angular/core/src/view/index';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {ARG_TYPE_VALUES, checkNodeInlineOrDynamic, createRootView, isBrowser} from './helper';
import {ARG_TYPE_VALUES, checkNodeInlineOrDynamic, compViewDef, createAndGetRootNodes} from './helper';
export function main() {
describe(`View Text`, () => {
function compViewDef(
nodes: NodeDef[], updateDirectives?: ViewUpdateFn, updateRenderer?: ViewUpdateFn,
viewFlags: ViewFlags = ViewFlags.None): ViewDefinition {
return viewDef(viewFlags, nodes, updateDirectives, updateRenderer);
}
function createAndGetRootNodes(
viewDef: ViewDefinition, context?: any): {rootNodes: any[], view: ViewData} {
const view = createRootView(viewDef, context);
const rootNodes = rootRenderNodes(view);
return {rootNodes, view};
}
describe('create', () => {
it('should create text nodes without parents', () => {
const rootNodes = createAndGetRootNodes(compViewDef([textDef(null !, ['a'])])).rootNodes;
const rootNodes = createAndGetRootNodes(compViewDef([textDef(0, null, ['a'])])).rootNodes;
expect(rootNodes.length).toBe(1);
expect(getDOM().getText(rootNodes[0])).toBe('a');
});
it('should create views with multiple root text nodes', () => {
const rootNodes = createAndGetRootNodes(compViewDef([
textDef(null !, ['a']), textDef(null !, ['b'])
textDef(0, null, ['a']),
textDef(1, null, ['b']),
])).rootNodes;
expect(rootNodes.length).toBe(2);
});
it('should create text nodes with parents', () => {
const rootNodes = createAndGetRootNodes(compViewDef([
elementDef(NodeFlags.None, null !, null !, 1, 'div'),
textDef(null !, ['a']),
elementDef(0, NodeFlags.None, null, null, 1, 'div'),
textDef(1, null, ['a']),
])).rootNodes;
expect(rootNodes.length).toBe(1);
const textNode = getDOM().firstChild(rootNodes[0]);
@ -55,7 +43,7 @@ export function main() {
it('should add debug information to the renderer', () => {
const someContext = new Object();
const {view, rootNodes} =
createAndGetRootNodes(compViewDef([textDef(null !, ['a'])]), someContext);
createAndGetRootNodes(compViewDef([textDef(0, null, ['a'])]), someContext);
expect(getDebugNode(rootNodes[0]) !.nativeNode).toBe(asTextData(view, 0).renderText);
});
});
@ -65,7 +53,7 @@ export function main() {
it(`should update via strategy ${inlineDynamic}`, () => {
const {view, rootNodes} = createAndGetRootNodes(compViewDef(
[
textDef(null !, ['0', '1', '2']),
textDef(0, null, ['0', '1', '2']),
],
null !, (check, view) => {
checkNodeInlineOrDynamic(check, view, 0, inlineDynamic, ['a', 'b']);
@ -73,7 +61,6 @@ export function main() {
Services.checkAndUpdateView(view);
const node = rootNodes[0];
expect(getDOM().getText(rootNodes[0])).toBe('0a1b2');
});

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {NodeFlags, QueryValueType, ViewData, ViewDefinition, ViewFlags, anchorDef, directiveDef, elementDef, textDef, viewDef} from '@angular/core/src/view/index';
import {NodeFlags, QueryValueType, ViewDefinition, ViewFlags, anchorDef, directiveDef, elementDef, textDef, viewDef} from '@angular/core/src/view/index';
import {filterQueryId} from '@angular/core/src/view/util';
export function main() {
@ -14,14 +14,14 @@ export function main() {
describe('parent', () => {
function parents(viewDef: ViewDefinition): (number | null)[] {
return viewDef.nodes.map(node => node.parent ? node.parent.index : null);
return viewDef.nodes.map(node => node.parent ? node.parent.nodeIndex : null);
}
it('should calculate parents for one level', () => {
const vd = viewDef(ViewFlags.None, [
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
textDef(null !, ['a']),
textDef(null !, ['a']),
elementDef(0, NodeFlags.None, null, null, 2, 'span'),
textDef(1, null, ['a']),
textDef(2, null, ['a']),
]);
expect(parents(vd)).toEqual([null, 0, 0]);
@ -29,11 +29,11 @@ export function main() {
it('should calculate parents for one level, multiple roots', () => {
const vd = viewDef(ViewFlags.None, [
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
textDef(null !, ['a']),
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
textDef(null !, ['a']),
textDef(null !, ['a']),
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
textDef(1, null, ['a']),
elementDef(2, NodeFlags.None, null, null, 1, 'span'),
textDef(3, null, ['a']),
textDef(4, null, ['a']),
]);
expect(parents(vd)).toEqual([null, 0, null, 2, null]);
@ -41,12 +41,12 @@ export function main() {
it('should calculate parents for multiple levels', () => {
const vd = viewDef(ViewFlags.None, [
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
textDef(null !, ['a']),
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
textDef(null !, ['a']),
textDef(null !, ['a']),
elementDef(0, NodeFlags.None, null, null, 2, 'span'),
elementDef(1, NodeFlags.None, null, null, 1, 'span'),
textDef(2, null, ['a']),
elementDef(3, NodeFlags.None, null, null, 1, 'span'),
textDef(4, null, ['a']),
textDef(5, null, ['a']),
]);
expect(parents(vd)).toEqual([null, 0, 1, null, 3, null]);
@ -65,8 +65,8 @@ export function main() {
it('should calculate childFlags for one level', () => {
const vd = viewDef(ViewFlags.None, [
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.AfterContentChecked, null !, 0, AService, [])
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.AfterContentChecked, null, 0, AService, [])
]);
expect(childFlags(vd)).toEqual([
@ -80,9 +80,9 @@ export function main() {
it('should calculate childFlags for two levels', () => {
const vd = viewDef(ViewFlags.None, [
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.AfterContentChecked, null !, 0, AService, [])
elementDef(0, NodeFlags.None, null, null, 2, 'span'),
elementDef(1, NodeFlags.None, null, null, 1, 'span'),
directiveDef(2, NodeFlags.AfterContentChecked, null, 0, AService, [])
]);
expect(childFlags(vd)).toEqual([
@ -98,11 +98,11 @@ export function main() {
it('should calculate childFlags for one level, multiple roots', () => {
const vd = viewDef(ViewFlags.None, [
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.AfterContentChecked, null !, 0, AService, []),
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
directiveDef(NodeFlags.AfterContentInit, null !, 0, AService, []),
directiveDef(NodeFlags.AfterViewChecked, null !, 0, AService, []),
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.AfterContentChecked, null, 0, AService, []),
elementDef(2, NodeFlags.None, null, null, 2, 'span'),
directiveDef(3, NodeFlags.AfterContentInit, null, 0, AService, []),
directiveDef(4, NodeFlags.AfterViewChecked, null, 0, AService, []),
]);
expect(childFlags(vd)).toEqual([
@ -120,12 +120,12 @@ export function main() {
it('should calculate childFlags for multiple levels', () => {
const vd = viewDef(ViewFlags.None, [
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.AfterContentChecked, null !, 0, AService, []),
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
directiveDef(NodeFlags.AfterContentInit, null !, 0, AService, []),
directiveDef(NodeFlags.AfterViewInit, null !, 0, AService, []),
elementDef(0, NodeFlags.None, null, null, 2, 'span'),
elementDef(1, NodeFlags.None, null, null, 1, 'span'),
directiveDef(2, NodeFlags.AfterContentChecked, null !, 0, AService, []),
elementDef(3, NodeFlags.None, null, null, 2, 'span'),
directiveDef(4, NodeFlags.AfterContentInit, null, 0, AService, []),
directiveDef(5, NodeFlags.AfterViewInit, null, 0, AService, []),
]);
expect(childFlags(vd)).toEqual([
@ -151,8 +151,8 @@ export function main() {
it('should calculate childMatchedQueries for one level', () => {
const vd = viewDef(ViewFlags.None, [
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.None, [[1, QueryValueType.Provider]], 0, AService, [])
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.None, [[1, QueryValueType.Provider]], 0, AService, [])
]);
expect(childMatchedQueries(vd)).toEqual([filterQueryId(1), 0]);
@ -160,9 +160,9 @@ export function main() {
it('should calculate childMatchedQueries for two levels', () => {
const vd = viewDef(ViewFlags.None, [
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.None, [[1, QueryValueType.Provider]], 0, AService, [])
elementDef(0, NodeFlags.None, null, null, 2, 'span'),
elementDef(1, NodeFlags.None, null, null, 1, 'span'),
directiveDef(2, NodeFlags.None, [[1, QueryValueType.Provider]], 0, AService, [])
]);
expect(childMatchedQueries(vd)).toEqual([filterQueryId(1), filterQueryId(1), 0]);
@ -170,11 +170,11 @@ export function main() {
it('should calculate childMatchedQueries for one level, multiple roots', () => {
const vd = viewDef(ViewFlags.None, [
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.None, [[1, QueryValueType.Provider]], 0, AService, []),
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
directiveDef(NodeFlags.None, [[2, QueryValueType.Provider]], 0, AService, []),
directiveDef(NodeFlags.None, [[3, QueryValueType.Provider]], 0, AService, []),
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
directiveDef(1, NodeFlags.None, [[1, QueryValueType.Provider]], 0, AService, []),
elementDef(2, NodeFlags.None, null, null, 2, 'span'),
directiveDef(3, NodeFlags.None, [[2, QueryValueType.Provider]], 0, AService, []),
directiveDef(4, NodeFlags.None, [[3, QueryValueType.Provider]], 0, AService, []),
]);
expect(childMatchedQueries(vd)).toEqual([
@ -184,12 +184,12 @@ export function main() {
it('should calculate childMatchedQueries for multiple levels', () => {
const vd = viewDef(ViewFlags.None, [
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
directiveDef(NodeFlags.None, [[1, QueryValueType.Provider]], 0, AService, []),
elementDef(NodeFlags.None, null !, null !, 2, 'span'),
directiveDef(NodeFlags.None, [[2, QueryValueType.Provider]], 0, AService, []),
directiveDef(NodeFlags.None, [[3, QueryValueType.Provider]], 0, AService, []),
elementDef(0, NodeFlags.None, null, null, 2, 'span'),
elementDef(1, NodeFlags.None, null, null, 1, 'span'),
directiveDef(2, NodeFlags.None, [[1, QueryValueType.Provider]], 0, AService, []),
elementDef(3, NodeFlags.None, null, null, 2, 'span'),
directiveDef(4, NodeFlags.None, [[2, QueryValueType.Provider]], 0, AService, []),
directiveDef(5, NodeFlags.None, [[3, QueryValueType.Provider]], 0, AService, []),
]);
expect(childMatchedQueries(vd)).toEqual([
@ -199,13 +199,13 @@ export function main() {
it('should included embedded views into childMatchedQueries', () => {
const vd = viewDef(ViewFlags.None, [
elementDef(NodeFlags.None, null !, null !, 1, 'span'),
elementDef(0, NodeFlags.None, null, null, 1, 'span'),
anchorDef(
NodeFlags.None, null !, null !, 0, null !,
NodeFlags.None, null, null, 0, null,
() => viewDef(
ViewFlags.None,
[
elementDef(NodeFlags.None, [[1, QueryValueType.Provider]], null !, 0, 'span'),
elementDef(0, NodeFlags.None, [[1, QueryValueType.Provider]], null, 0, 'span'),
]))
]);