/
githubmirror
/
angular
Обзор
Документация
Войти
/
githubmirror
/
angular
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
devtools/projects/ng-devtools-backend/src/lib/hydration/hydration-highlighting.ts
99 строк
3 KB
hawkgs
refactor(devtools): reorganize backend code
20 июл 2026, 12:15
20 июл 2026, 12:15
a7ebf1c
Код
Авторство
О чём код?
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ import {HydrationStatus} from '../../../../protocol'; import {getDirectiveForestManager} from '../directive-forest/manager'; import {highlightElement, removeHighlightsByType} from '../shared/highlighter'; import { HighlightTemplate, hydrationMismatchedHighlightTemplate, hydrationCompletedHighlightTemplate, hydrationSkippedHighlightTemplate, HighlightType, } from '../shared/highlighter/highlights'; import {ComponentTreeNode} from '../shared/interfaces'; export function highlightHydrationNodes(): void { const forest: ComponentTreeNode[] = getDirectiveForestManager().getDirectiveForest(); // drop the root nodes, we don't want to highlight it const forestWithoutRoots = forest.flatMap((rootNode) => rootNode.children); const errorNodes = findErrorNodesForHydrationOverlay(forestWithoutRoots); // We get the first level of hydrated nodes // nested mismatched nodes nested in hydrated nodes aren't includes const nodes = findNodesForHydrationOverlay(forestWithoutRoots); // This ensures top level mismatched nodes are removed as we have a dedicated array const otherNodes = nodes.filter(({status}) => status?.status !== 'mismatched'); for (const {node, status} of [...otherNodes, ...errorNodes]) { highlightHydrationElement(node as Element, status); } } export function removeHydrationHighlights() { removeHighlightsByType(HighlightType.HydrationCompleted); removeHighlightsByType(HighlightType.HydrationMismatched); removeHighlightsByType(HighlightType.HydrationSkipped); } function highlightHydrationElement(node: Element, {status}: HydrationStatus) { let template: HighlightTemplate; switch (status) { case 'hydrated': template = hydrationCompletedHighlightTemplate; break; case 'mismatched': template = hydrationMismatchedHighlightTemplate; break; case 'skipped': template = hydrationSkippedHighlightTemplate; break; default: throw new Error(`Unsupported hydration status highlighting: ${status}`); } highlightElement(node, template, {'icon': [status]}); } /** * Returns the first level of hydrated nodes * Note: Mismatched nodes nested in hydrated nodes aren't included */ function findNodesForHydrationOverlay( forest: ComponentTreeNode[], ): {node: Node; status: HydrationStatus}[] { return forest.flatMap((node) => { if (node?.hydration?.status) { // We highlight first level return {node: node.nativeElement!, status: node.hydration}; } if (node.children.length) { return findNodesForHydrationOverlay(node.children); } return []; }); } function findErrorNodesForHydrationOverlay( forest: ComponentTreeNode[], ): {node: Node; status: HydrationStatus}[] { return forest.flatMap((node) => { if (node?.hydration?.status === 'mismatched') { // We highlight first level return {node: node.nativeElement!, status: node.hydration}; } if (node.children.length) { return findNodesForHydrationOverlay(node.children); } return []; }); }