( context: I18nHydrationContext, state: I18nHydrationState, nodeOrNodes: I18nNode | I18nNode[], )
| 472 | } |
| 473 | |
| 474 | function collectI18nNodesFromDom( |
| 475 | context: I18nHydrationContext, |
| 476 | state: I18nHydrationState, |
| 477 | nodeOrNodes: I18nNode | I18nNode[], |
| 478 | ) { |
| 479 | if (Array.isArray(nodeOrNodes)) { |
| 480 | let nextState = state; |
| 481 | for (const node of nodeOrNodes) { |
| 482 | // Whenever a node doesn't directly follow the previous RNode, it |
| 483 | // is given a path. We need to resume collecting nodes from that location |
| 484 | // until and unless we find another disjoint node. |
| 485 | const targetNode = tryLocateRNodeByPath( |
| 486 | context.hydrationInfo, |
| 487 | context.lView, |
| 488 | node.index - HEADER_OFFSET, |
| 489 | ); |
| 490 | if (targetNode) { |
| 491 | nextState = forkHydrationState(state, targetNode as Node); |
| 492 | } |
| 493 | collectI18nNodesFromDom(context, nextState, node); |
| 494 | } |
| 495 | } else { |
| 496 | if (context.disconnectedNodes.has(nodeOrNodes.index - HEADER_OFFSET)) { |
| 497 | // i18n nodes can be considered disconnected if e.g. they were projected. |
| 498 | // In that case, we have to make sure to skip over them. |
| 499 | return; |
| 500 | } |
| 501 | |
| 502 | switch (nodeOrNodes.kind) { |
| 503 | case I18nNodeKind.TEXT: { |
| 504 | // Claim a text node for hydration |
| 505 | const currentNode = appendI18nNodeToCollection(context, state, nodeOrNodes); |
| 506 | setCurrentNode(state, currentNode?.nextSibling ?? null); |
| 507 | break; |
| 508 | } |
| 509 | |
| 510 | case I18nNodeKind.ELEMENT: { |
| 511 | // Recurse into the current element's children... |
| 512 | collectI18nNodesFromDom( |
| 513 | context, |
| 514 | forkHydrationState(state, state.currentNode?.firstChild ?? null), |
| 515 | nodeOrNodes.children, |
| 516 | ); |
| 517 | |
| 518 | // And claim the parent element itself. |
| 519 | const currentNode = appendI18nNodeToCollection(context, state, nodeOrNodes); |
| 520 | setCurrentNode(state, currentNode?.nextSibling ?? null); |
| 521 | break; |
| 522 | } |
| 523 | |
| 524 | case I18nNodeKind.PLACEHOLDER: { |
| 525 | const noOffsetIndex = nodeOrNodes.index - HEADER_OFFSET; |
| 526 | const {hydrationInfo} = context; |
| 527 | const containerSize = getNgContainerSize(hydrationInfo, noOffsetIndex); |
| 528 | |
| 529 | switch (nodeOrNodes.type) { |
| 530 | case I18nPlaceholderType.ELEMENT: { |
| 531 | // Hydration expects to find the head of the element. |
no test coverage detected
searching dependent graphs…