diff --git a/packages/core/src/hydration/annotate.ts b/packages/core/src/hydration/annotate.ts index 94ab7de715f..f61f6006db1 100644 --- a/packages/core/src/hydration/annotate.ts +++ b/packages/core/src/hydration/annotate.ts @@ -12,7 +12,7 @@ import {CONTAINER_HEADER_OFFSET, LContainer} from '../render3/interfaces/contain import {TI18n} from '../render3/interfaces/i18n'; import {TNode, TNodeType} from '../render3/interfaces/node'; import {RElement} from '../render3/interfaces/renderer_dom'; -import {isLContainer, isProjectionTNode, isRootView} from '../render3/interfaces/type_checks'; +import {isComponentHost, isLContainer, isProjectionTNode, isRootView} from '../render3/interfaces/type_checks'; import {HEADER_OFFSET, HOST, LView, RENDERER, TView, TVIEW, TViewType} from '../render3/interfaces/view'; import {unwrapRNode} from '../render3/util/view_utils'; import {TransferState} from '../transfer_state'; @@ -240,7 +240,7 @@ function serializeLView(lView: LView, context: HydrationContext): SerializedView // layer (in Domino) for now. Longer-term solution should not rely on the DOM emulation and // only use internal data structures and state to compute this information. if (!(tNode.type & TNodeType.Projection) && !!lView[i] && - !(unwrapRNode(lView[i]) as Node).isConnected) { + !(unwrapRNode(lView[i]) as Node).isConnected && isContentProjectedNode(tNode)) { ngh[DISCONNECTED_NODES] ??= []; ngh[DISCONNECTED_NODES].push(noOffsetIndex); continue; @@ -413,3 +413,20 @@ function insertCorruptedTextNodeMarkers( textNode.after(doc.createComment(marker)); } } + +/** + * Detects whether a given TNode represents a node that + * is being content projected. + */ +function isContentProjectedNode(tNode: TNode): boolean { + let currentTNode = tNode; + while (currentTNode != null) { + // If we come across a component host node in parent nodes - + // this TNode is in the content projection section. + if (isComponentHost(currentTNode)) { + return true; + } + currentTNode = currentTNode.parent as TNode; + } + return false; +} diff --git a/packages/platform-server/test/hydration_spec.ts b/packages/platform-server/test/hydration_spec.ts index d33de16f8f2..445c06fa975 100644 --- a/packages/platform-server/test/hydration_spec.ts +++ b/packages/platform-server/test/hydration_spec.ts @@ -3173,9 +3173,7 @@ describe('platform-server integration', () => { }); }); - // TODO(akushnir): we should only mark nodes within a content projection block as - // "disconnected" (avoid marking other disconnected nodes in a template) - xit('should handle element node mismatch', async () => { + it('should handle element node mismatch', async () => { @Component({ standalone: true, selector: 'app',