mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(core): consolidate logic to determine whether node can be hydrated (#61409)
Several instructions were repeating the logic that checks if a specific can be hydrated. These changes move it into a common location. PR Close #61409
This commit is contained in:
committed by
Jessica Janiuk
parent
6783fb7eae
commit
7a308ccc3b
@@ -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';
|
||||
@@ -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,
|
||||
@@ -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
|
||||
|
||||
@@ -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';
|
||||
@@ -40,7 +39,6 @@ import {
|
||||
getLView,
|
||||
getNamespace,
|
||||
getTView,
|
||||
isInSkipHydrationBlock,
|
||||
isSkipHydrationRootTNode,
|
||||
lastNodeWasCreated,
|
||||
leaveSkipHydrationBlock,
|
||||
@@ -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.
|
||||
@@ -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);
|
||||
|
||||
@@ -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';
|
||||
@@ -26,7 +25,6 @@ import {
|
||||
getCurrentTNode,
|
||||
getLView,
|
||||
getTView,
|
||||
isInSkipHydrationBlock,
|
||||
lastNodeWasCreated,
|
||||
} from '../state';
|
||||
import {elementLikeEndShared, elementLikeStartShared} from './shared';
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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';
|
||||
@@ -263,12 +262,7 @@ 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.
|
||||
@@ -276,6 +270,7 @@ function locateOrCreateContainerAnchorImpl(
|
||||
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.
|
||||
|
||||
@@ -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';
|
||||
@@ -19,7 +18,6 @@ import {
|
||||
getBindingIndex,
|
||||
getLView,
|
||||
getTView,
|
||||
isInSkipHydrationBlock,
|
||||
lastNodeWasCreated,
|
||||
setCurrentTNode,
|
||||
wasLastNodeCreated,
|
||||
@@ -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.
|
||||
@@ -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);
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"callHook",
|
||||
"callHookInternal",
|
||||
"callHooks",
|
||||
"canHydrateNode",
|
||||
"checkStable",
|
||||
"cleanUpView",
|
||||
"cleanupDehydratedIcuData",
|
||||
|
||||
Reference in New Issue
Block a user