angular/packages/core/src/view/pure_expression.ts
Miško Hevery 64770571b2 perf: don't create holey arrays (#32155)
Don't use `Array` constructor with the size value (ex. `new Array(5)`) - this will create a `HOLEY_ELEMENTS` array (even if this array is filled in later on!);

https://v8.dev/blog/elements-kinds
https://stackoverflow.com/questions/32054170/how-to-resize-an-array

PR Close #32155
2019-08-21 08:27:43 -07:00

204 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 {newArray} from '../util/array_utils';
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, newArray(argCount + 1));
}
export function pureArrayDef(checkIndex: number, argCount: number): NodeDef {
return _pureExpressionDef(NodeFlags.TypePureArray, checkIndex, newArray(argCount));
}
export function pureObjectDef(checkIndex: number, propToIndex: {[p: string]: number}): NodeDef {
const keys = Object.keys(propToIndex);
const nbKeys = keys.length;
const propertyNames = [];
for (let i = 0; i < nbKeys; i++) {
const key = keys[i];
const index = propToIndex[key];
propertyNames.push(key);
}
return _pureExpressionDef(NodeFlags.TypePureObject, checkIndex, propertyNames);
}
function _pureExpressionDef(
flags: NodeFlags, checkIndex: number, propertyNames: string[]): NodeDef {
const bindings: BindingDef[] = [];
for (let i = 0; i < propertyNames.length; i++) {
const prop = propertyNames[i];
bindings.push({
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 = [];
if (bindLen > 0) value.push(v0);
if (bindLen > 1) value.push(v1);
if (bindLen > 2) value.push(v2);
if (bindLen > 3) value.push(v3);
if (bindLen > 4) value.push(v4);
if (bindLen > 5) value.push(v5);
if (bindLen > 6) value.push(v6);
if (bindLen > 7) value.push(v7);
if (bindLen > 8) value.push(v8);
if (bindLen > 9) value.push(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;
}