perf(ivy): store views directly on LContainer (#30179)

Stores the views that are part of a container directly on the `LContainer`, rather than maintaining a dedicated sub-array.

This PR resolves FW-1288.

PR Close #30179
This commit is contained in:
crisbeto
2019-04-29 21:17:13 +02:00
committed by Kara Erickson
parent 00ffc03523
commit ad94e02981
11 changed files with 83 additions and 84 deletions

View File

@ -7,11 +7,10 @@
*/
import {ViewEncapsulation} from '../metadata/view';
import {assertDefined} from '../util/assert';
import {assertLContainer, assertLView} from './assert';
import {attachPatchData} from './context_discovery';
import {LContainer, NATIVE, VIEWS, unusedValueExportToPlacateAjd as unused1} from './interfaces/container';
import {CONTAINER_HEADER_OFFSET, LContainer, NATIVE, unusedValueExportToPlacateAjd as unused1} from './interfaces/container';
import {ComponentDef} from './interfaces/definition';
import {NodeInjectorFactory} from './interfaces/injector';
import {TElementNode, TNode, TNodeFlags, TNodeType, TProjectionNode, TViewNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node';
@ -99,8 +98,9 @@ function walkTNodeTree(
// This element has an LContainer, and its comment needs to be handled
executeNodeAction(
action, renderer, renderParent, nodeOrContainer[NATIVE], tNode, beforeNode);
if (nodeOrContainer[VIEWS].length) {
currentView = nodeOrContainer[VIEWS][0];
const firstView = nodeOrContainer[CONTAINER_HEADER_OFFSET];
if (firstView) {
currentView = firstView;
nextTNode = currentView[TVIEW].node;
// When the walker enters a container, then the beforeNode has to become the local native
@ -111,9 +111,9 @@ function walkTNodeTree(
} else if (tNode.type === TNodeType.Container) {
const lContainer = currentView ![tNode.index] as LContainer;
executeNodeAction(action, renderer, renderParent, lContainer[NATIVE], tNode, beforeNode);
if (lContainer[VIEWS].length) {
currentView = lContainer[VIEWS][0];
const firstView = lContainer[CONTAINER_HEADER_OFFSET];
if (firstView) {
currentView = firstView;
nextTNode = currentView[TVIEW].node;
// When the walker enters a container, then the beforeNode has to become the local native
@ -302,8 +302,8 @@ export function destroyViewTree(rootView: LView): void {
} else {
ngDevMode && assertLContainer(lViewOrLContainer);
// If container, traverse down to its first LView.
const views = lViewOrLContainer[VIEWS] as LView[];
if (views.length > 0) next = views[0];
const firstView: LView|undefined = lViewOrLContainer[CONTAINER_HEADER_OFFSET];
if (firstView) next = firstView;
}
if (!next) {
@ -335,18 +335,18 @@ export function destroyViewTree(rootView: LView): void {
export function insertView(lView: LView, lContainer: LContainer, index: number) {
ngDevMode && assertLView(lView);
ngDevMode && assertLContainer(lContainer);
const views = lContainer[VIEWS];
ngDevMode && assertDefined(views, 'Container must have views');
const indexInContainer = CONTAINER_HEADER_OFFSET + index;
const containerLength = lContainer.length;
if (index > 0) {
// This is a new view, we need to add it to the children.
views[index - 1][NEXT] = lView;
lContainer[indexInContainer - 1][NEXT] = lView;
}
if (index < views.length) {
lView[NEXT] = views[index];
views.splice(index, 0, lView);
if (index < containerLength - CONTAINER_HEADER_OFFSET) {
lView[NEXT] = lContainer[indexInContainer];
lContainer.splice(CONTAINER_HEADER_OFFSET + index, 0, lView);
} else {
views.push(lView);
lContainer.push(lView);
lView[NEXT] = null;
}
@ -372,13 +372,15 @@ export function insertView(lView: LView, lContainer: LContainer, index: number)
* @returns Detached LView instance.
*/
export function detachView(lContainer: LContainer, removeIndex: number): LView|undefined {
const views = lContainer[VIEWS];
const viewToDetach = views[removeIndex];
if (lContainer.length <= CONTAINER_HEADER_OFFSET) return;
const indexInContainer = CONTAINER_HEADER_OFFSET + removeIndex;
const viewToDetach = lContainer[indexInContainer];
if (viewToDetach) {
if (removeIndex > 0) {
views[removeIndex - 1][NEXT] = viewToDetach[NEXT] as LView;
lContainer[indexInContainer - 1][NEXT] = viewToDetach[NEXT] as LView;
}
views.splice(removeIndex, 1);
lContainer.splice(CONTAINER_HEADER_OFFSET + removeIndex, 1);
addRemoveViewFromContainer(viewToDetach, false);
if ((viewToDetach[FLAGS] & LViewFlags.Attached) &&
@ -400,11 +402,8 @@ export function detachView(lContainer: LContainer, removeIndex: number): LView|u
* @param removeIndex The index of the view to remove
*/
export function removeView(lContainer: LContainer, removeIndex: number) {
const view = lContainer[VIEWS][removeIndex];
if (view) {
detachView(lContainer, removeIndex);
destroyLView(view);
}
const detachedView = detachView(lContainer, removeIndex);
detachedView && destroyLView(detachedView);
}
/**
@ -678,9 +677,8 @@ export function nativeNextSibling(renderer: Renderer3, node: RNode): RNode|null
function getNativeAnchorNode(parentTNode: TNode, lView: LView): RNode|null {
if (parentTNode.type === TNodeType.View) {
const lContainer = getLContainer(parentTNode as TViewNode, lView) !;
const views = lContainer[VIEWS];
const index = views.indexOf(lView);
return getBeforeNodeForView(index, views, lContainer[NATIVE]);
const index = lContainer.indexOf(lView, CONTAINER_HEADER_OFFSET) - CONTAINER_HEADER_OFFSET;
return getBeforeNodeForView(index, lContainer);
} else if (
parentTNode.type === TNodeType.ElementContainer ||
parentTNode.type === TNodeType.IcuContainer) {
@ -729,9 +727,11 @@ function getHighestElementOrICUContainer(tNode: TNode): TNode {
return tNode;
}
export function getBeforeNodeForView(index: number, views: LView[], containerNative: RComment) {
if (index + 1 < views.length) {
const view = views[index + 1] as LView;
export function getBeforeNodeForView(index: number, lContainer: LContainer) {
const containerNative = lContainer[NATIVE];
if (index + 1 < lContainer.length - CONTAINER_HEADER_OFFSET) {
const view = lContainer[CONTAINER_HEADER_OFFSET + index + 1] as LView;
const viewTNode = view[T_HOST] as TViewNode;
return viewTNode.child ? getNativeByTNode(viewTNode.child, view) : containerNative;
} else {
@ -817,9 +817,8 @@ function appendProjectedNode(
// Alternatively a container is projected at the root of a component's template
// and can't be re-projected (as not content of any component).
// Assign the final projection location in those cases.
const views = nodeOrContainer[VIEWS];
for (let i = 0; i < views.length; i++) {
addRemoveViewFromContainer(views[i], true, nodeOrContainer[NATIVE]);
for (let i = CONTAINER_HEADER_OFFSET; i < nodeOrContainer.length; i++) {
addRemoveViewFromContainer(nodeOrContainer[i], true, nodeOrContainer[NATIVE]);
}
} else {
if (projectedTNode.type === TNodeType.ElementContainer) {