( injector: Injector, hydrationQueue: string[], replayQueuedEventsFn?: Function, )
| 437 | * events. |
| 438 | */ |
| 439 | export async function triggerHydrationForBlockQueue( |
| 440 | injector: Injector, |
| 441 | hydrationQueue: string[], |
| 442 | replayQueuedEventsFn?: Function, |
| 443 | ): Promise<void> { |
| 444 | const dehydratedBlockRegistry = injector.get(DEHYDRATED_BLOCK_REGISTRY); |
| 445 | const blocksBeingHydrated = dehydratedBlockRegistry.hydrating; |
| 446 | |
| 447 | // Indicate that we have some pending async work. |
| 448 | const pendingTasks = injector.get(PendingTasksInternal); |
| 449 | const taskId = pendingTasks.add(); |
| 450 | |
| 451 | // Actually do the triggering and hydration of the queue of blocks |
| 452 | for (let blockQueueIdx = 0; blockQueueIdx < hydrationQueue.length; blockQueueIdx++) { |
| 453 | const dehydratedBlockId = hydrationQueue[blockQueueIdx]; |
| 454 | const dehydratedDeferBlock = dehydratedBlockRegistry.get(dehydratedBlockId); |
| 455 | |
| 456 | if (dehydratedDeferBlock != null) { |
| 457 | // trigger the block resources and await next render for hydration. This should result |
| 458 | // in the next block ɵɵdefer instruction being called and that block being added to the dehydrated registry. |
| 459 | await triggerResourceLoadingForHydration(dehydratedDeferBlock); |
| 460 | await nextRender(injector); |
| 461 | |
| 462 | // if the content has changed since server rendering, we need to check for the expected block |
| 463 | // being in the registry or if errors occurred. In that case, we need to clean up the remaining expected |
| 464 | // content that won't be rendered or fetched. |
| 465 | if (deferBlockHasErrored(dehydratedDeferBlock)) { |
| 466 | // Either the expected block has not yet had its ɵɵdefer instruction called or the block errored out when fetching |
| 467 | // resources. In the former case, either we're hydrating too soon or the client and server differ. In both cases, |
| 468 | // we need to clean up child content and promises. |
| 469 | removeDehydratedViewList(dehydratedDeferBlock); |
| 470 | cleanupRemainingHydrationQueue( |
| 471 | hydrationQueue.slice(blockQueueIdx), |
| 472 | dehydratedBlockRegistry, |
| 473 | ); |
| 474 | break; |
| 475 | } |
| 476 | // The defer block has not errored and we've finished fetching resources and rendering. |
| 477 | // At this point it is safe to resolve the hydration promise. |
| 478 | blocksBeingHydrated.get(dehydratedBlockId)!.resolve(); |
| 479 | } else { |
| 480 | // The expected block has not yet had its ɵɵdefer instruction called. This is likely due to content changing between |
| 481 | // client and server. We need to clean up the dehydrated DOM in the container since it no longer is valid. |
| 482 | cleanupParentContainer(blockQueueIdx, hydrationQueue, dehydratedBlockRegistry); |
| 483 | cleanupRemainingHydrationQueue(hydrationQueue.slice(blockQueueIdx), dehydratedBlockRegistry); |
| 484 | break; |
| 485 | } |
| 486 | } |
| 487 | |
| 488 | const lastBlockName = hydrationQueue[hydrationQueue.length - 1]; |
| 489 | |
| 490 | // Await hydration completion for the last block. |
| 491 | await blocksBeingHydrated.get(lastBlockName)?.promise; |
| 492 | |
| 493 | // All async work is done, remove the taskId from the registry. |
| 494 | pendingTasks.remove(taskId); |
| 495 | |
| 496 | // Replay any queued events, if any exist and the replay operation was requested. |
no test coverage detected
searching dependent graphs…