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

Function validateMatchingNode

packages/core/src/hydration/error_handling.ts:59–121  ·  view source on GitHub ↗
(
  node: RNode | null,
  nodeType: number,
  tagName: string | null,
  lView: LView,
  tNode: TNode,
  isViewContainerAnchor = false,
)

Source from the content-addressed store, hash-verified

57 * Validates that provided nodes match during the hydration process.
58 */
59export function validateMatchingNode(
60 node: RNode | null,
61 nodeType: number,
62 tagName: string | null,
63 lView: LView,
64 tNode: TNode,
65 isViewContainerAnchor = false,
66): void {
67 if (
68 !node ||
69 (node as Node).nodeType !== nodeType ||
70 ((node as Node).nodeType === Node.ELEMENT_NODE &&
71 (node as HTMLElement).tagName.toLowerCase() !== tagName?.toLowerCase())
72 ) {
73 const expectedNode = shortRNodeDescription(nodeType, tagName, null);
74 let header = `During hydration Angular expected ${expectedNode} but `;
75
76 const hostComponentDef = getDeclarationComponentDef(lView);
77 const componentClassName = hostComponentDef?.type?.name;
78
79 const expectedDom = describeExpectedDom(lView, tNode, isViewContainerAnchor);
80 const expected = `Angular expected this DOM:\n\n${expectedDom}\n\n`;
81
82 let actual = '';
83 const componentHostElement = unwrapRNode(lView[HOST]!);
84 if (!node) {
85 // No node found during hydration.
86 header += `the node was not found.\n\n`;
87
88 // Since the node is missing, we use the closest node to attach the error to
89 markRNodeAsHavingHydrationMismatch(componentHostElement, expectedDom);
90 } else {
91 const actualNode = shortRNodeDescription(
92 (node as Node).nodeType,
93 (node as HTMLElement).tagName ?? null,
94 (node as HTMLElement).textContent ?? null,
95 );
96
97 header += `found ${actualNode}.\n\n`;
98 const actualDom = describeDomFromNode(node);
99 actual = `Actual DOM is:\n\n${actualDom}\n\n`;
100
101 // DevTools only report hydration issues on the component level, so we attach extra debug
102 // info to a component host element to make it available to DevTools.
103 markRNodeAsHavingHydrationMismatch(componentHostElement, expectedDom, actualDom);
104 }
105
106 const footer = getHydrationErrorFooter(componentClassName);
107 let message = header + expected + actual + getHydrationAttributeNote() + footer;
108
109 // Check both when a mismatching node is found AND when the expected node is missing,
110 // since third-party scripts can both inject extra nodes and remove existing ones.
111 if (!node || (node && isLikelyExternalSourceNode(node))) {
112 message +=
113 `Note: It looks like this mismatch may have been caused by a third-party script or ` +
114 `browser extension that modified the DOM outside of Angular's control. ` +
115 `Angular hydration does not support nodes injected or removed outside of the Angular-managed DOM. ` +
116 `Note: If you know which element in the DOM this will be inserted, consider adding ngSkipHydration to prevent this error. \n\n`;

Calls 9

unwrapRNodeFunction · 0.90
shortRNodeDescriptionFunction · 0.85
describeExpectedDomFunction · 0.85
describeDomFromNodeFunction · 0.85
getHydrationErrorFooterFunction · 0.85

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…