From 0daa1ea19d69b04085ae73ad2e3325dbdfdc14f6 Mon Sep 17 00:00:00 2001 From: Gerald Monaco Date: Wed, 6 Mar 2024 15:59:08 +0000 Subject: [PATCH] refactor(core): refactor i18n node creation to prepare for hydration (#54722) Adds a `locateOrCreateNode` helper and uses it for all DOM operations in preparation for supporting hydration. PR Close #54722 --- packages/core/src/render3/i18n/i18n_apply.ts | 29 ++++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/core/src/render3/i18n/i18n_apply.ts b/packages/core/src/render3/i18n/i18n_apply.ts index 27d376d0d59..4aacc33904a 100644 --- a/packages/core/src/render3/i18n/i18n_apply.ts +++ b/packages/core/src/render3/i18n/i18n_apply.ts @@ -18,7 +18,7 @@ import {RElement, RNode, RText} from '../interfaces/renderer_dom'; import {SanitizerFn} from '../interfaces/sanitization'; import {HEADER_OFFSET, LView, RENDERER, TView} from '../interfaces/view'; import {createCommentNode, createElementNode, createTextNode, nativeInsertBefore, nativeParentNode, nativeRemoveNode, updateTextNode} from '../node_manipulation'; -import {getBindingIndex} from '../state'; +import {getBindingIndex, lastNodeWasCreated} from '../state'; import {renderStringify} from '../util/stringify_utils'; import {getNativeByIndex, unwrapRNode} from '../util/view_utils'; @@ -78,6 +78,25 @@ export function applyI18n(tView: TView, lView: LView, index: number) { changeMaskCounter = 0; } +function locateOrCreateNode( + lView: LView, index: number, textOrName: string, + nodeType: typeof Node.COMMENT_NODE|typeof Node.TEXT_NODE|typeof Node.ELEMENT_NODE) { + // TODO: Add support for hydration + lastNodeWasCreated(true); + + const renderer = lView[RENDERER]; + + switch (nodeType) { + case Node.COMMENT_NODE: + return createCommentNode(renderer, textOrName); + + case Node.TEXT_NODE: + return createTextNode(renderer, textOrName); + + case Node.ELEMENT_NODE: + return createElementNode(renderer, textOrName, null); + } +} /** * Apply `I18nCreateOpCodes` op-codes as stored in `TI18n.create`. @@ -106,7 +125,7 @@ export function applyCreateOpCodes( // We only create new DOM nodes if they don't already exist: If ICU switches case back to a // case which was already instantiated, no need to create new DOM nodes. rNode = lView[index] = - isComment ? renderer.createComment(text) : createTextNode(renderer, text); + locateOrCreateNode(lView, index, text, isComment ? Node.COMMENT_NODE : Node.TEXT_NODE); } if (appendNow && parentRNode !== null) { nativeInsertBefore(renderer, parentRNode, rNode, insertInFrontOf, false); @@ -141,7 +160,7 @@ export function applyMutableOpCodes( if (lView[textNodeIndex] === null) { ngDevMode && ngDevMode.rendererCreateTextNode++; ngDevMode && assertIndexInRange(lView, textNodeIndex); - lView[textNodeIndex] = createTextNode(renderer, opCode); + lView[textNodeIndex] = locateOrCreateNode(lView, textNodeIndex, opCode, Node.TEXT_NODE); } } else if (typeof opCode == 'number') { switch (opCode & IcuCreateOpCode.MASK_INSTRUCTION) { @@ -219,7 +238,7 @@ export function applyMutableOpCodes( ngDevMode && ngDevMode.rendererCreateComment++; ngDevMode && assertIndexInExpandoRange(lView, commentNodeIndex); const commentRNode = lView[commentNodeIndex] = - createCommentNode(renderer, commentValue); + locateOrCreateNode(lView, commentNodeIndex, commentValue, Node.COMMENT_NODE); // FIXME(misko): Attaching patch data is only needed for the root (Also add tests) attachPatchData(commentRNode, lView); } @@ -236,7 +255,7 @@ export function applyMutableOpCodes( ngDevMode && ngDevMode.rendererCreateElement++; ngDevMode && assertIndexInExpandoRange(lView, elementNodeIndex); const elementRNode = lView[elementNodeIndex] = - createElementNode(renderer, tagName, null); + locateOrCreateNode(lView, elementNodeIndex, tagName, Node.ELEMENT_NODE); // FIXME(misko): Attaching patch data is only needed for the root (Also add tests) attachPatchData(elementRNode, lView); }