Content-Length: 546243 | pFad | http://github.com/angular/angular/pull/61409/commits/15a244ec07182e8c32ac767a2b4945a43725f855

95 Consolidate element instruction code by crisbeto · Pull Request #61409 · angular/angular · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
refactor(core): consolidate logic to determine whether node can be hy…
…drated

Several instructions were repeating the logic that checks if a specific can be hydrated. These changes move it into a common location.
  • Loading branch information
crisbeto committed May 19, 2025
commit 15a244ec07182e8c32ac767a2b4945a43725f855
21 changes: 20 additions & 1 deletion packages/core/src/hydration/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {LContainer} from '../render3/interfaces/container';
import {getDocument} from '../render3/interfaces/document';
import {RElement, RNode} from '../render3/interfaces/renderer_dom';
import {isRootView} from '../render3/interfaces/type_checks';
import {HEADER_OFFSET, LView, TVIEW, TViewType} from '../render3/interfaces/view';
import {HEADER_OFFSET, HYDRATION, LView, TVIEW, TViewType} from '../render3/interfaces/view';
import {makeStateKey, StateKey, TransferState} from '../transfer_state';
import {assertDefined, assertEqual} from '../util/assert';
import type {HydrationContext} from './annotate';
Expand All @@ -39,6 +39,9 @@ import {DeferBlockTrigger, HydrateTriggerDetails} from '../defer/interfaces';
import {hoverEventNames, interactionEventNames} from '../defer/dom_triggers';
import {DEHYDRATED_BLOCK_REGISTRY} from '../defer/registry';
import {sharedMapFunction} from '../event_delegation_utils';
import {isDetachedByI18n} from '../i18n/utils';
import {isInSkipHydrationBlock} from '../render3/state';
import {TNode} from '../render3/interfaces/node';

/**
* The name of the key used in the TransferState collection,
Expand Down Expand Up @@ -496,6 +499,22 @@ export function isDisconnectedNode(hydrationInfo: DehydratedView, index: number)
return !!initDisconnectedNodes(hydrationInfo)?.has(index);
}

/**
* Checks whether a node can be hydrated.
* @param lView View in which the node instance is placed.
* @param tNode Node to be checked.
*/
export function canHydrateNode(lView: LView, tNode: TNode): boolean {
const hydrationInfo = lView[HYDRATION];

return (
hydrationInfo !== null &&
!isInSkipHydrationBlock() &&
!isDetachedByI18n(tNode) &&
!isDisconnectedNode(hydrationInfo, tNode.index - HEADER_OFFSET)
);
}

/**
* Helper function to prepare text nodes for serialization by ensuring
* that seperate logical text blocks in the DOM remain separate after
Expand Down
12 changes: 3 additions & 9 deletions packages/core/src/render3/instructions/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@ import {
hasSkipHydrationAttrOnTNode,
} from '../../hydration/skip_hydration';
import {
canHydrateNode,
getSerializedContainerViews,
isDisconnectedNode,
markRNodeAsClaimedByHydration,
markRNodeAsSkippedByHydration,
setSegmentHead,
} from '../../hydration/utils';
import {isDetachedByI18n} from '../../i18n/utils';
import {assertDefined, assertEqual} from '../../util/assert';
import {clearElementContents, createElementNode} from '../dom_node_manipulation';
import {hasClassInput, hasStyleInput, TNode, TNodeType} from '../interfaces/node';
Expand All @@ -40,7 +39,6 @@ import {
getLView,
getNamespace,
getTView,
isInSkipHydrationBlock,
isSkipHydrationRootTNode,
lastNodeWasCreated,
leaveSkipHydrationBlock,
Expand Down Expand Up @@ -192,12 +190,7 @@ function locateOrCreateElementNodeImpl(
name: string,
index: number,
): RElement {
const hydrationInfo = lView[HYDRATION];
const isNodeCreationMode =
!hydrationInfo ||
isInSkipHydrationBlock() ||
isDetachedByI18n(tNode) ||
isDisconnectedNode(hydrationInfo, index);
const isNodeCreationMode = !canHydrateNode(lView, tNode);
lastNodeWasCreated(isNodeCreationMode);

// Regular creation mode.
Expand All @@ -206,6 +199,7 @@ function locateOrCreateElementNodeImpl(
}

// Hydration mode, looking up an existing element in DOM.
const hydrationInfo = lView[HYDRATION]!;
const native = locateNextRNode<RElement>(hydrationInfo, tView, lView, tNode)!;
ngDevMode && validateMatchingNode(native, Node.ELEMENT_NODE, name, lView, tNode);
ngDevMode && markRNodeAsClaimedByHydration(native);
Expand Down
12 changes: 3 additions & 9 deletions packages/core/src/render3/instructions/element_container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@
import {validateMatchingNode, validateNodeExists} from '../../hydration/error_handling';
import {locateNextRNode, siblingAfter} from '../../hydration/node_lookup_utils';
import {
canHydrateNode,
getNgContainerSize,
isDisconnectedNode,
markRNodeAsClaimedByHydration,
setSegmentHead,
} from '../../hydration/utils';
import {isDetachedByI18n} from '../../i18n/utils';
import {assertDefined, assertEqual, assertNumber} from '../../util/assert';
import {createCommentNode} from '../dom_node_manipulation';
import {TNode, TNodeType} from '../interfaces/node';
Expand All @@ -26,7 +25,6 @@ import {
getCurrentTNode,
getLView,
getTView,
isInSkipHydrationBlock,
lastNodeWasCreated,
} from '../state';
import {elementLikeEndShared, elementLikeStartShared} from './shared';
Expand Down Expand Up @@ -134,12 +132,7 @@ function locateOrCreateElementContainerNode(
index: number,
): RComment {
let comment: RComment;
const hydrationInfo = lView[HYDRATION];
const isNodeCreationMode =
!hydrationInfo ||
isInSkipHydrationBlock() ||
isDisconnectedNode(hydrationInfo, index) ||
isDetachedByI18n(tNode);
const isNodeCreationMode = !canHydrateNode(lView, tNode);

lastNodeWasCreated(isNodeCreationMode);

Expand All @@ -149,6 +142,7 @@ function locateOrCreateElementContainerNode(
}

// Hydration mode, looking up existing elements in DOM.
const hydrationInfo = lView[HYDRATION]!;
const currentRNode = locateNextRNode(hydrationInfo, tView, lView, tNode)!;
ngDevMode && validateNodeExists(currentRNode, lView, tNode);

Expand Down
11 changes: 3 additions & 8 deletions packages/core/src/render3/instructions/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import {TEMPLATES} from '../../hydration/interfaces';
import {locateNextRNode, siblingAfter} from '../../hydration/node_lookup_utils';
import {
calcSerializedContainerSize,
isDisconnectedNode,
canHydrateNode,
markRNodeAsClaimedByHydration,
setSegmentHead,
} from '../../hydration/utils';
import {isDetachedByI18n} from '../../i18n/utils';
import {populateDehydratedViewsInLContainer} from '../../linker/view_container_ref';
import {assertEqual} from '../../util/assert';
import {assertFirstCreatePass} from '../assert';
Expand Down Expand Up @@ -263,19 +262,15 @@ function locateOrCreateContainerAnchorImpl(
tNode: TNode,
index: number,
): RComment {
const hydrationInfo = lView[HYDRATION];
const isNodeCreationMode =
!hydrationInfo ||
isInSkipHydrationBlock() ||
isDetachedByI18n(tNode) ||
isDisconnectedNode(hydrationInfo, index);
const isNodeCreationMode = !canHydrateNode(lView, tNode);
lastNodeWasCreated(isNodeCreationMode);

// Regular creation mode.
if (isNodeCreationMode) {
return createContainerAnchorImpl(tView, lView, tNode, index);
}

const hydrationInfo = lView[HYDRATION]!;
const ssrId = hydrationInfo.data[TEMPLATES]?.[index] ?? null;

// Apply `ssrId` value to the underlying TView if it was not previously set.
Expand Down
12 changes: 3 additions & 9 deletions packages/core/src/render3/instructions/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
*/
import {validateMatchingNode} from '../../hydration/error_handling';
import {locateNextRNode} from '../../hydration/node_lookup_utils';
import {isDisconnectedNode, markRNodeAsClaimedByHydration} from '../../hydration/utils';
import {isDetachedByI18n} from '../../i18n/utils';
import {canHydrateNode, markRNodeAsClaimedByHydration} from '../../hydration/utils';
import {assertEqual, assertIndexInRange} from '../../util/assert';
import {TElementNode, TNode, TNodeType} from '../interfaces/node';
import {RText} from '../interfaces/renderer_dom';
Expand All @@ -19,7 +18,6 @@ import {
getBindingIndex,
getLView,
getTView,
isInSkipHydrationBlock,
lastNodeWasCreated,
setCurrentTNode,
wasLastNodeCreated,
Expand Down Expand Up @@ -84,12 +82,7 @@ function locateOrCreateTextNodeImpl(
value: string,
index: number,
): RText {
const hydrationInfo = lView[HYDRATION];
const isNodeCreationMode =
!hydrationInfo ||
isInSkipHydrationBlock() ||
isDetachedByI18n(tNode) ||
isDisconnectedNode(hydrationInfo, index);
const isNodeCreationMode = !canHydrateNode(lView, tNode);
lastNodeWasCreated(isNodeCreationMode);

// Regular creation mode.
Expand All @@ -98,6 +91,7 @@ function locateOrCreateTextNodeImpl(
}

// Hydration mode, looking up an existing element in DOM.
const hydrationInfo = lView[HYDRATION]!;
const textNative = locateNextRNode(hydrationInfo, tView, lView, tNode) as RText;

ngDevMode && validateMatchingNode(textNative, Node.TEXT_NODE, null, lView, tNode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@
"callHook",
"callHookInternal",
"callHooks",
"canHydrateNode",
"checkStable",
"cleanUpView",
"cleanupDehydratedIcuData",
Expand Down








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/angular/angular/pull/61409/commits/15a244ec07182e8c32ac767a2b4945a43725f855

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy