MCPcopy Index your code
hub / github.com/angular/angular / calcPathForNode

Function calcPathForNode

packages/core/src/hydration/node_lookup_utils.ts:324–399  ·  view source on GitHub ↗
(
  tNode: TNode,
  lView: LView,
  excludedParentNodes: Set<number> | null,
)

Source from the content-addressed store, hash-verified

322 * instructions needs to be generated for a TNode.
323 */
324export function calcPathForNode(
325 tNode: TNode,
326 lView: LView,
327 excludedParentNodes: Set<number> | null,
328): string {
329 let parentTNode = tNode.parent;
330 let parentIndex: number | string;
331 let parentRNode: RNode;
332 let referenceNodeName: string;
333
334 // Skip over all parent nodes that are disconnected from the DOM, such nodes
335 // can not be used as anchors.
336 //
337 // This might happen in certain content projection-based use-cases, where
338 // a content of an element is projected and used, when a parent element
339 // itself remains detached from DOM. In this scenario we try to find a parent
340 // element that is attached to DOM and can act as an anchor instead.
341 //
342 // It can also happen that the parent node should be excluded, for example,
343 // because it belongs to an i18n block, which requires paths which aren't
344 // relative to other views in an i18n block.
345 while (
346 parentTNode !== null &&
347 (isDisconnectedNode(parentTNode, lView) || excludedParentNodes?.has(parentTNode.index))
348 ) {
349 parentTNode = parentTNode.parent;
350 }
351
352 if (parentTNode === null || !(parentTNode.type & TNodeType.AnyRNode)) {
353 // If there is no parent TNode or a parent TNode does not represent an RNode
354 // (i.e. not a DOM node), use component host element as a reference node.
355 parentIndex = referenceNodeName = REFERENCE_NODE_HOST;
356 parentRNode = lView[DECLARATION_COMPONENT_VIEW][HOST]!;
357 } else {
358 // Use parent TNode as a reference node.
359 parentIndex = parentTNode.index;
360 parentRNode = unwrapRNode(lView[parentIndex]);
361 referenceNodeName = renderStringify(parentIndex - HEADER_OFFSET);
362 }
363 let rNode = unwrapRNode(lView[tNode.index]);
364 if (tNode.type & (TNodeType.AnyContainer | TNodeType.Icu)) {
365 // For <ng-container> nodes, instead of serializing a reference
366 // to the anchor comment node, serialize a location of the first
367 // DOM element. Paired with the container size (serialized as a part
368 // of `ngh.containers`), it should give enough information for runtime
369 // to hydrate nodes in this container.
370 const firstRNode = getFirstNativeNode(lView, tNode);
371
372 // If container is not empty, use a reference to the first element,
373 // otherwise, rNode would point to an anchor comment node.
374 if (firstRNode) {
375 rNode = firstRNode;
376 }
377 }
378 let path: string | null = calcPathBetween(parentRNode as Node, rNode as Node, referenceNodeName);
379 if (path === null && parentRNode !== rNode) {
380 // Searching for a path between elements within a host node failed.
381 // Trying to find a path to an element starting from the `document.body` instead.

Callers 1

appendSerializedNodePathFunction · 0.90

Calls 7

unwrapRNodeFunction · 0.90
renderStringifyFunction · 0.90
getFirstNativeNodeFunction · 0.90
nodeNotFoundErrorFunction · 0.90
calcPathBetweenFunction · 0.85
isDisconnectedNodeFunction · 0.70
hasMethod · 0.65

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…