
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).
202 lines
6.6 KiB
TypeScript
202 lines
6.6 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
|
|
import {BindingDef, BindingFlags, NodeDef, NodeFlags, PureExpressionData, ViewData, asPureExpressionData} from './types';
|
|
import {calcBindingFlags, checkAndUpdateBinding} from './util';
|
|
|
|
export function purePipeDef(checkIndex: number, argCount: number): NodeDef {
|
|
// argCount + 1 to include the pipe as first arg
|
|
return _pureExpressionDef(NodeFlags.TypePurePipe, checkIndex, new Array(argCount + 1));
|
|
}
|
|
|
|
export function pureArrayDef(checkIndex: number, argCount: number): NodeDef {
|
|
return _pureExpressionDef(NodeFlags.TypePureArray, checkIndex, new Array(argCount));
|
|
}
|
|
|
|
export function pureObjectDef(checkIndex: number, propToIndex: {[p: string]: number}): NodeDef {
|
|
const keys = Object.keys(propToIndex);
|
|
const nbKeys = keys.length;
|
|
const propertyNames = new Array(nbKeys);
|
|
for (let i = 0; i < nbKeys; i++) {
|
|
const key = keys[i];
|
|
const index = propToIndex[key];
|
|
propertyNames[index] = key;
|
|
}
|
|
|
|
return _pureExpressionDef(NodeFlags.TypePureObject, checkIndex, propertyNames);
|
|
}
|
|
|
|
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];
|
|
bindings[i] = {
|
|
flags: BindingFlags.TypeProperty,
|
|
name: prop,
|
|
ns: null,
|
|
nonMinifiedName: prop,
|
|
securityContext: null,
|
|
suffix: null
|
|
};
|
|
}
|
|
return {
|
|
// will bet set by the view definition
|
|
nodeIndex: -1,
|
|
parent: null,
|
|
renderParent: null,
|
|
bindingIndex: -1,
|
|
outputIndex: -1,
|
|
// regular values
|
|
checkIndex,
|
|
flags,
|
|
childFlags: 0,
|
|
directChildFlags: 0,
|
|
childMatchedQueries: 0,
|
|
matchedQueries: {},
|
|
matchedQueryIds: 0,
|
|
references: {},
|
|
ngContentIndex: -1,
|
|
childCount: 0, bindings,
|
|
bindingFlags: calcBindingFlags(bindings),
|
|
outputs: [],
|
|
element: null,
|
|
provider: null,
|
|
text: null,
|
|
query: null,
|
|
ngContent: null
|
|
};
|
|
}
|
|
|
|
export function createPureExpression(view: ViewData, def: NodeDef): PureExpressionData {
|
|
return {value: undefined};
|
|
}
|
|
|
|
export function checkAndUpdatePureExpressionInline(
|
|
view: ViewData, def: NodeDef, v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any,
|
|
v7: any, v8: any, v9: any): boolean {
|
|
const bindings = def.bindings;
|
|
let changed = false;
|
|
const bindLen = bindings.length;
|
|
if (bindLen > 0 && checkAndUpdateBinding(view, def, 0, v0)) changed = true;
|
|
if (bindLen > 1 && checkAndUpdateBinding(view, def, 1, v1)) changed = true;
|
|
if (bindLen > 2 && checkAndUpdateBinding(view, def, 2, v2)) changed = true;
|
|
if (bindLen > 3 && checkAndUpdateBinding(view, def, 3, v3)) changed = true;
|
|
if (bindLen > 4 && checkAndUpdateBinding(view, def, 4, v4)) changed = true;
|
|
if (bindLen > 5 && checkAndUpdateBinding(view, def, 5, v5)) changed = true;
|
|
if (bindLen > 6 && checkAndUpdateBinding(view, def, 6, v6)) changed = true;
|
|
if (bindLen > 7 && checkAndUpdateBinding(view, def, 7, v7)) changed = true;
|
|
if (bindLen > 8 && checkAndUpdateBinding(view, def, 8, v8)) changed = true;
|
|
if (bindLen > 9 && checkAndUpdateBinding(view, def, 9, v9)) changed = true;
|
|
|
|
if (changed) {
|
|
const data = asPureExpressionData(view, def.nodeIndex);
|
|
let value: any;
|
|
switch (def.flags & NodeFlags.Types) {
|
|
case NodeFlags.TypePureArray:
|
|
value = new Array(bindings.length);
|
|
if (bindLen > 0) value[0] = v0;
|
|
if (bindLen > 1) value[1] = v1;
|
|
if (bindLen > 2) value[2] = v2;
|
|
if (bindLen > 3) value[3] = v3;
|
|
if (bindLen > 4) value[4] = v4;
|
|
if (bindLen > 5) value[5] = v5;
|
|
if (bindLen > 6) value[6] = v6;
|
|
if (bindLen > 7) value[7] = v7;
|
|
if (bindLen > 8) value[8] = v8;
|
|
if (bindLen > 9) value[9] = v9;
|
|
break;
|
|
case NodeFlags.TypePureObject:
|
|
value = {};
|
|
if (bindLen > 0) value[bindings[0].name !] = v0;
|
|
if (bindLen > 1) value[bindings[1].name !] = v1;
|
|
if (bindLen > 2) value[bindings[2].name !] = v2;
|
|
if (bindLen > 3) value[bindings[3].name !] = v3;
|
|
if (bindLen > 4) value[bindings[4].name !] = v4;
|
|
if (bindLen > 5) value[bindings[5].name !] = v5;
|
|
if (bindLen > 6) value[bindings[6].name !] = v6;
|
|
if (bindLen > 7) value[bindings[7].name !] = v7;
|
|
if (bindLen > 8) value[bindings[8].name !] = v8;
|
|
if (bindLen > 9) value[bindings[9].name !] = v9;
|
|
break;
|
|
case NodeFlags.TypePurePipe:
|
|
const pipe = v0;
|
|
switch (bindLen) {
|
|
case 1:
|
|
value = pipe.transform(v0);
|
|
break;
|
|
case 2:
|
|
value = pipe.transform(v1);
|
|
break;
|
|
case 3:
|
|
value = pipe.transform(v1, v2);
|
|
break;
|
|
case 4:
|
|
value = pipe.transform(v1, v2, v3);
|
|
break;
|
|
case 5:
|
|
value = pipe.transform(v1, v2, v3, v4);
|
|
break;
|
|
case 6:
|
|
value = pipe.transform(v1, v2, v3, v4, v5);
|
|
break;
|
|
case 7:
|
|
value = pipe.transform(v1, v2, v3, v4, v5, v6);
|
|
break;
|
|
case 8:
|
|
value = pipe.transform(v1, v2, v3, v4, v5, v6, v7);
|
|
break;
|
|
case 9:
|
|
value = pipe.transform(v1, v2, v3, v4, v5, v6, v7, v8);
|
|
break;
|
|
case 10:
|
|
value = pipe.transform(v1, v2, v3, v4, v5, v6, v7, v8, v9);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
data.value = value;
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
export function checkAndUpdatePureExpressionDynamic(
|
|
view: ViewData, def: NodeDef, values: any[]): boolean {
|
|
const bindings = def.bindings;
|
|
let changed = false;
|
|
for (let i = 0; i < values.length; i++) {
|
|
// Note: We need to loop over all values, so that
|
|
// the old values are updates as well!
|
|
if (checkAndUpdateBinding(view, def, i, values[i])) {
|
|
changed = true;
|
|
}
|
|
}
|
|
if (changed) {
|
|
const data = asPureExpressionData(view, def.nodeIndex);
|
|
let value: any;
|
|
switch (def.flags & NodeFlags.Types) {
|
|
case NodeFlags.TypePureArray:
|
|
value = values;
|
|
break;
|
|
case NodeFlags.TypePureObject:
|
|
value = {};
|
|
for (let i = 0; i < values.length; i++) {
|
|
value[bindings[i].name !] = values[i];
|
|
}
|
|
break;
|
|
case NodeFlags.TypePurePipe:
|
|
const pipe = values[0];
|
|
const params = values.slice(1);
|
|
value = (<any>pipe.transform)(...params);
|
|
break;
|
|
}
|
|
data.value = value;
|
|
}
|
|
return changed;
|
|
}
|