MCPcopy Create free account
hub / github.com/angular/angular / locateNextRNode

Function locateNextRNode

packages/core/src/hydration/node_lookup_utils.ts:119–179  ·  view source on GitHub ↗
(
  hydrationInfo: DehydratedView,
  tView: TView,
  lView: LView<unknown>,
  tNode: TNode,
)

Source from the content-addressed store, hash-verified

117 * @returns an RNode that represents a given tNode
118 */
119export function locateNextRNode<T extends RNode>(
120 hydrationInfo: DehydratedView,
121 tView: TView,
122 lView: LView<unknown>,
123 tNode: TNode,
124): T | null {
125 const noOffsetIndex = getNoOffsetIndex(tNode);
126 let native = locateI18nRNodeByIndex(hydrationInfo, noOffsetIndex);
127
128 if (native === undefined) {
129 const nodes = hydrationInfo.data[NODES];
130 if (nodes?.[noOffsetIndex]) {
131 // We know the exact location of the node.
132 native = locateRNodeByPath(nodes[noOffsetIndex], lView);
133 } else if (tView.firstChild === tNode) {
134 // We create a first node in this view, so we use a reference
135 // to the first child in this DOM segment.
136 native = hydrationInfo.firstChild;
137 } else {
138 // Locate a node based on a previous sibling or a parent node.
139 const previousTNodeParent = tNode.prev === null;
140 const previousTNode = (tNode.prev ?? tNode.parent)!;
141 ngDevMode &&
142 assertDefined(
143 previousTNode,
144 'Unexpected state: current TNode does not have a connection ' +
145 'to the previous node or a parent node.',
146 );
147 if (isFirstElementInNgContainer(tNode)) {
148 const noOffsetParentIndex = getNoOffsetIndex(tNode.parent!);
149 native = getSegmentHead(hydrationInfo, noOffsetParentIndex);
150 } else {
151 let previousRElement = getNativeByTNode(previousTNode, lView);
152 if (previousTNodeParent) {
153 native = (previousRElement as RElement).firstChild;
154 } else {
155 // If the previous node is an element, but it also has container info,
156 // this means that we are processing a node like `<div #vcrTarget>`, which is
157 // represented in the DOM as `<div></div>...<!--container-->`.
158 // In this case, there are nodes *after* this element and we need to skip
159 // all of them to reach an element that we are looking for.
160 const noOffsetPrevSiblingIndex = getNoOffsetIndex(previousTNode);
161 const segmentHead = getSegmentHead(hydrationInfo, noOffsetPrevSiblingIndex);
162 if (previousTNode.type === TNodeType.Element && segmentHead) {
163 const numRootNodesToSkip = calcSerializedContainerSize(
164 hydrationInfo,
165 noOffsetPrevSiblingIndex,
166 );
167 // `+1` stands for an anchor comment node after all the views in this container.
168 const nodesToSkip = numRootNodesToSkip + 1;
169 // First node after this segment.
170 native = siblingAfter(nodesToSkip, segmentHead);
171 } else {
172 native = previousRElement.nextSibling;
173 }
174 }
175 }
176 }

Calls 9

assertDefinedFunction · 0.90
getSegmentHeadFunction · 0.90
getNativeByTNodeFunction · 0.90
getNoOffsetIndexFunction · 0.85
locateI18nRNodeByIndexFunction · 0.85
locateRNodeByPathFunction · 0.85
siblingAfterFunction · 0.85

Tested by

no test coverage detected