MCPcopy Index your code
hub / github.com/angular/angular / processTextNodeBeforeSerialization

Function processTextNodeBeforeSerialization

packages/core/src/hydration/utils.ts:538–576  ·  view source on GitHub ↗
(context: HydrationContext, node: RNode)

Source from the content-addressed store, hash-verified

536 * serialization.
537 */
538export function processTextNodeBeforeSerialization(context: HydrationContext, node: RNode) {
539 // Handle cases where text nodes can be lost after DOM serialization:
540 // 1. When there is an *empty text node* in DOM: in this case, this
541 // node would not make it into the serialized string and as a result,
542 // this node wouldn't be created in a browser. This would result in
543 // a mismatch during the hydration, where the runtime logic would expect
544 // a text node to be present in live DOM, but no text node would exist.
545 // Example: `<span>{{ name }}</span>` when the `name` is an empty string.
546 // This would result in `<span></span>` string after serialization and
547 // in a browser only the `span` element would be created. To resolve that,
548 // an extra comment node is appended in place of an empty text node and
549 // that special comment node is replaced with an empty text node *before*
550 // hydration.
551 // 2. When there are 2 consecutive text nodes present in the DOM.
552 // Example: `<div>Hello <ng-container *ngIf="true">world</ng-container></div>`.
553 // In this scenario, the live DOM would look like this:
554 // <div>#text('Hello ') #text('world') #comment('container')</div>
555 // Serialized string would look like this: `<div>Hello world<!--container--></div>`.
556 // The live DOM in a browser after that would be:
557 // <div>#text('Hello world') #comment('container')</div>
558 // Notice how 2 text nodes are now "merged" into one. This would cause hydration
559 // logic to fail, since it'd expect 2 text nodes being present, not one.
560 // To fix this, we insert a special comment node in between those text nodes, so
561 // serialized representation is: `<div>Hello <!--ngtns-->world<!--container--></div>`.
562 // This forces browser to create 2 text nodes separated by a comment node.
563 // Before running a hydration process, this special comment node is removed, so the
564 // live DOM has exactly the same state as it was before serialization.
565
566 // Collect this node as required special annotation only when its
567 // contents is empty. Otherwise, such text node would be present on
568 // the client after server-side rendering and no special handling needed.
569 const el = node as HTMLElement;
570 const corruptedTextNodes = context.corruptedTextNodes;
571 if (el.textContent === '') {
572 corruptedTextNodes.set(el, TextNodeMarker.EmptyNode);
573 } else if (el.nextSibling?.nodeType === Node.TEXT_NODE) {
574 corruptedTextNodes.set(el, TextNodeMarker.Separator);
575 }
576}
577
578export function convertHydrateTriggersToJsAction(
579 triggers: Map<DeferBlockTrigger, HydrateTriggerDetails | null> | null,

Callers 2

serializeI18nNodeFunction · 0.90
serializeLViewFunction · 0.90

Calls 1

setMethod · 0.65

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…