perf(ivy): avoid repeat global state accesses in i18n instructions (#32916)
Removes repeat global state accesses from the i18n instructions in the cases where we have the information available already. PR Close #32916
This commit is contained in:
parent
b3549e6680
commit
ffc34b3676
|
@ -360,13 +360,14 @@ const parentIndexStack: number[] = [];
|
|||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵi18nStart(index: number, message: string, subTemplateIndex?: number): void {
|
||||
const tView = getLView()[TVIEW];
|
||||
const lView = getLView();
|
||||
const tView = lView[TVIEW];
|
||||
ngDevMode && assertDefined(tView, `tView should be defined`);
|
||||
i18nIndexStack[++i18nIndexStackPointer] = index;
|
||||
// We need to delay projections until `i18nEnd`
|
||||
setDelayProjection(true);
|
||||
if (tView.firstTemplatePass && tView.data[index + HEADER_OFFSET] === null) {
|
||||
i18nStartFirstPass(tView, index, message, subTemplateIndex);
|
||||
i18nStartFirstPass(lView, tView, index, message, subTemplateIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -379,15 +380,14 @@ let i18nVarsCount: number;
|
|||
* See `i18nStart` above.
|
||||
*/
|
||||
function i18nStartFirstPass(
|
||||
tView: TView, index: number, message: string, subTemplateIndex?: number) {
|
||||
const viewData = getLView();
|
||||
lView: LView, tView: TView, index: number, message: string, subTemplateIndex?: number) {
|
||||
const startIndex = tView.blueprint.length - HEADER_OFFSET;
|
||||
i18nVarsCount = 0;
|
||||
const previousOrParentTNode = getPreviousOrParentTNode();
|
||||
const parentTNode = getIsParent() ? getPreviousOrParentTNode() :
|
||||
previousOrParentTNode && previousOrParentTNode.parent;
|
||||
const parentTNode =
|
||||
getIsParent() ? previousOrParentTNode : previousOrParentTNode && previousOrParentTNode.parent;
|
||||
let parentIndex =
|
||||
parentTNode && parentTNode !== viewData[T_HOST] ? parentTNode.index - HEADER_OFFSET : index;
|
||||
parentTNode && parentTNode !== lView[T_HOST] ? parentTNode.index - HEADER_OFFSET : index;
|
||||
let parentIndexPointer = 0;
|
||||
parentIndexStack[parentIndexPointer] = parentIndex;
|
||||
const createOpCodes: I18nMutateOpCodes = [];
|
||||
|
@ -471,12 +471,12 @@ function i18nStartFirstPass(
|
|||
}
|
||||
|
||||
if (i18nVarsCount > 0) {
|
||||
allocExpando(viewData, i18nVarsCount);
|
||||
allocExpando(lView, i18nVarsCount);
|
||||
}
|
||||
|
||||
ngDevMode &&
|
||||
attachI18nOpCodesDebug(
|
||||
createOpCodes, updateOpCodes, icuExpressions.length ? icuExpressions : null, viewData);
|
||||
createOpCodes, updateOpCodes, icuExpressions.length ? icuExpressions : null, lView);
|
||||
|
||||
// NOTE: local var needed to properly assert the type of `TI18n`.
|
||||
const tI18n: TI18n = {
|
||||
|
@ -656,9 +656,10 @@ export function ɵɵi18nPostprocess(
|
|||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵi18nEnd(): void {
|
||||
const tView = getLView()[TVIEW];
|
||||
const lView = getLView();
|
||||
const tView = lView[TVIEW];
|
||||
ngDevMode && assertDefined(tView, `tView should be defined`);
|
||||
i18nEndFirstPass(tView);
|
||||
i18nEndFirstPass(lView, tView);
|
||||
// Stop delaying projections
|
||||
setDelayProjection(false);
|
||||
}
|
||||
|
@ -666,10 +667,9 @@ export function ɵɵi18nEnd(): void {
|
|||
/**
|
||||
* See `i18nEnd` above.
|
||||
*/
|
||||
function i18nEndFirstPass(tView: TView) {
|
||||
const viewData = getLView();
|
||||
function i18nEndFirstPass(lView: LView, tView: TView) {
|
||||
ngDevMode && assertEqual(
|
||||
viewData[BINDING_INDEX], viewData[TVIEW].bindingStartIndex,
|
||||
lView[BINDING_INDEX], tView.bindingStartIndex,
|
||||
'i18nEnd should be called before any binding');
|
||||
|
||||
const rootIndex = i18nIndexStack[i18nIndexStackPointer--];
|
||||
|
@ -677,15 +677,15 @@ function i18nEndFirstPass(tView: TView) {
|
|||
ngDevMode && assertDefined(tI18n, `You should call i18nStart before i18nEnd`);
|
||||
|
||||
// Find the last node that was added before `i18nEnd`
|
||||
let lastCreatedNode = getPreviousOrParentTNode();
|
||||
const lastCreatedNode = getPreviousOrParentTNode();
|
||||
|
||||
// Read the instructions to insert/move/remove DOM elements
|
||||
const visitedNodes = readCreateOpCodes(rootIndex, tI18n.create, tI18n.icus, viewData);
|
||||
const visitedNodes = readCreateOpCodes(rootIndex, tI18n.create, lView);
|
||||
|
||||
// Remove deleted nodes
|
||||
for (let i = rootIndex + 1; i <= lastCreatedNode.index - HEADER_OFFSET; i++) {
|
||||
if (visitedNodes.indexOf(i) === -1) {
|
||||
removeNode(i, viewData, /* markAsDetached */ true);
|
||||
removeNode(i, lView, /* markAsDetached */ true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -711,9 +711,8 @@ function createDynamicNodeAtIndex(
|
|||
}
|
||||
|
||||
function readCreateOpCodes(
|
||||
index: number, createOpCodes: I18nMutateOpCodes, icus: TIcu[] | null,
|
||||
viewData: LView): number[] {
|
||||
const renderer = getLView()[RENDERER];
|
||||
index: number, createOpCodes: I18nMutateOpCodes, lView: LView): number[] {
|
||||
const renderer = lView[RENDERER];
|
||||
let currentTNode: TNode|null = null;
|
||||
let previousTNode: TNode|null = null;
|
||||
const visitedNodes: number[] = [];
|
||||
|
@ -725,7 +724,7 @@ function readCreateOpCodes(
|
|||
ngDevMode && ngDevMode.rendererCreateTextNode++;
|
||||
previousTNode = currentTNode;
|
||||
currentTNode =
|
||||
createDynamicNodeAtIndex(viewData, textNodeIndex, TNodeType.Element, textRNode, null);
|
||||
createDynamicNodeAtIndex(lView, textNodeIndex, TNodeType.Element, textRNode, null);
|
||||
visitedNodes.push(textNodeIndex);
|
||||
setIsNotParent();
|
||||
} else if (typeof opCode == 'number') {
|
||||
|
@ -736,28 +735,28 @@ function readCreateOpCodes(
|
|||
if (destinationNodeIndex === index) {
|
||||
// If the destination node is `i18nStart`, we don't have a
|
||||
// top-level node and we should use the host node instead
|
||||
destinationTNode = viewData[T_HOST] !;
|
||||
destinationTNode = lView[T_HOST] !;
|
||||
} else {
|
||||
destinationTNode = getTNode(destinationNodeIndex, viewData);
|
||||
destinationTNode = getTNode(destinationNodeIndex, lView);
|
||||
}
|
||||
ngDevMode &&
|
||||
assertDefined(
|
||||
currentTNode !,
|
||||
`You need to create or select a node before you can insert it into the DOM`);
|
||||
previousTNode = appendI18nNode(currentTNode !, destinationTNode, previousTNode, viewData);
|
||||
previousTNode = appendI18nNode(currentTNode !, destinationTNode, previousTNode, lView);
|
||||
break;
|
||||
case I18nMutateOpCode.Select:
|
||||
const nodeIndex = opCode >>> I18nMutateOpCode.SHIFT_REF;
|
||||
visitedNodes.push(nodeIndex);
|
||||
previousTNode = currentTNode;
|
||||
currentTNode = getTNode(nodeIndex, viewData);
|
||||
currentTNode = getTNode(nodeIndex, lView);
|
||||
if (currentTNode) {
|
||||
setPreviousOrParentTNode(currentTNode, currentTNode.type === TNodeType.Element);
|
||||
}
|
||||
break;
|
||||
case I18nMutateOpCode.ElementEnd:
|
||||
const elementIndex = opCode >>> I18nMutateOpCode.SHIFT_REF;
|
||||
previousTNode = currentTNode = getTNode(elementIndex, viewData);
|
||||
previousTNode = currentTNode = getTNode(elementIndex, lView);
|
||||
setPreviousOrParentTNode(currentTNode, false);
|
||||
break;
|
||||
case I18nMutateOpCode.Attr:
|
||||
|
@ -766,7 +765,7 @@ function readCreateOpCodes(
|
|||
const attrValue = createOpCodes[++i] as string;
|
||||
// This code is used for ICU expressions only, since we don't support
|
||||
// directives/components in ICUs, we don't need to worry about inputs here
|
||||
elementAttributeInternal(elementNodeIndex, attrName, attrValue, viewData);
|
||||
elementAttributeInternal(elementNodeIndex, attrName, attrValue, lView);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unable to determine the type of mutate operation for "${opCode}"`);
|
||||
|
@ -783,9 +782,9 @@ function readCreateOpCodes(
|
|||
ngDevMode && ngDevMode.rendererCreateComment++;
|
||||
previousTNode = currentTNode;
|
||||
currentTNode = createDynamicNodeAtIndex(
|
||||
viewData, commentNodeIndex, TNodeType.IcuContainer, commentRNode, null);
|
||||
lView, commentNodeIndex, TNodeType.IcuContainer, commentRNode, null);
|
||||
visitedNodes.push(commentNodeIndex);
|
||||
attachPatchData(commentRNode, viewData);
|
||||
attachPatchData(commentRNode, lView);
|
||||
(currentTNode as TIcuContainerNode).activeCaseIndex = null;
|
||||
// We will add the case nodes later, during the update phase
|
||||
setIsNotParent();
|
||||
|
@ -800,7 +799,7 @@ function readCreateOpCodes(
|
|||
ngDevMode && ngDevMode.rendererCreateElement++;
|
||||
previousTNode = currentTNode;
|
||||
currentTNode = createDynamicNodeAtIndex(
|
||||
viewData, elementNodeIndex, TNodeType.Element, elementRNode, tagNameValue);
|
||||
lView, elementNodeIndex, TNodeType.Element, elementRNode, tagNameValue);
|
||||
visitedNodes.push(elementNodeIndex);
|
||||
break;
|
||||
default:
|
||||
|
@ -886,7 +885,7 @@ function readUpdateOpCodes(
|
|||
icuTNode.activeCaseIndex = caseIndex !== -1 ? caseIndex : null;
|
||||
|
||||
// Add the nodes for the new case
|
||||
readCreateOpCodes(-1, tIcu.create[caseIndex], icus, viewData);
|
||||
readCreateOpCodes(-1, tIcu.create[caseIndex], viewData);
|
||||
caseCreated = true;
|
||||
break;
|
||||
case I18nUpdateOpCode.IcuUpdate:
|
||||
|
@ -968,15 +967,16 @@ export function ɵɵi18n(index: number, message: string, subTemplateIndex?: numb
|
|||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵi18nAttributes(index: number, values: string[]): void {
|
||||
const tView = getLView()[TVIEW];
|
||||
const lView = getLView();
|
||||
const tView = lView[TVIEW];
|
||||
ngDevMode && assertDefined(tView, `tView should be defined`);
|
||||
i18nAttributesFirstPass(tView, index, values);
|
||||
i18nAttributesFirstPass(lView, tView, index, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* See `i18nAttributes` above.
|
||||
*/
|
||||
function i18nAttributesFirstPass(tView: TView, index: number, values: string[]) {
|
||||
function i18nAttributesFirstPass(lView: LView, tView: TView, index: number, values: string[]) {
|
||||
const previousElement = getPreviousOrParentTNode();
|
||||
const previousElementIndex = previousElement.index - HEADER_OFFSET;
|
||||
const updateOpCodes: I18nUpdateOpCodes = [];
|
||||
|
@ -1000,7 +1000,6 @@ function i18nAttributesFirstPass(tView: TView, index: number, values: string[])
|
|||
generateBindingUpdateOpCodes(value, previousElementIndex, attrName), updateOpCodes);
|
||||
}
|
||||
} else {
|
||||
const lView = getLView();
|
||||
elementAttributeInternal(previousElementIndex, attrName, value, lView);
|
||||
// Check if that attribute is a directive input
|
||||
const tNode = getTNode(previousElementIndex, lView);
|
||||
|
|
Loading…
Reference in New Issue