diff --git a/packages/core/src/defer/cleanup.ts b/packages/core/src/defer/cleanup.ts index 29fbc8be7aa..54633a38fe2 100644 --- a/packages/core/src/defer/cleanup.ts +++ b/packages/core/src/defer/cleanup.ts @@ -13,7 +13,7 @@ import { PREFETCH_TRIGGER_CLEANUP_FNS, TRIGGER_CLEANUP_FNS, TriggerType, - UNIQUE_SSR_ID, + SSR_UNIQUE_ID, } from './interfaces'; import {DeferBlockRegistry} from './registry'; @@ -57,7 +57,7 @@ export function invokeAllTriggerCleanupFns( // TODO(incremental-hydration): cleanup functions are invoked in multiple places // should we centralize where cleanup functions are invoked to this registry? if (registry !== null) { - registry.invokeCleanupFns(lDetails[UNIQUE_SSR_ID]!); + registry.invokeCleanupFns(lDetails[SSR_UNIQUE_ID]!); } invokeTriggerCleanupFns(TriggerType.Prefetch, lDetails); diff --git a/packages/core/src/defer/instructions.ts b/packages/core/src/defer/instructions.ts index 23382b513ab..02eb3a1180c 100644 --- a/packages/core/src/defer/instructions.ts +++ b/packages/core/src/defer/instructions.ts @@ -79,12 +79,12 @@ import { LOADING_AFTER_CLEANUP_FN, NEXT_DEFER_BLOCK_STATE, ON_COMPLETE_FNS, - SSR_STATE, + SSR_BLOCK_STATE, STATE_IS_FROZEN_UNTIL, TDeferBlockDetails, TriggerType, DeferBlock, - UNIQUE_SSR_ID, + SSR_UNIQUE_ID, } from './interfaces'; import {onTimer, scheduleTimerTrigger} from './timer_scheduler'; import { @@ -144,7 +144,8 @@ function shouldTriggerWhenOnClient( if (!isPlatformBrowser(injector)) { return false; } - const isServerRendered = lDetails[SSR_STATE] && lDetails[SSR_STATE] === DeferBlockState.Complete; + const isServerRendered = + lDetails[SSR_BLOCK_STATE] && lDetails[SSR_BLOCK_STATE] === DeferBlockState.Complete; const hasHydrateTriggers = tDetails.hydrateTriggers && tDetails.hydrateTriggers.size > 0; if (hasHydrateTriggers && isServerRendered && isIncrementalHydrationEnabled(injector)) { return false; @@ -280,13 +281,12 @@ export function ɵɵdefer( // In client-only mode, this function is a noop. populateDehydratedViewsInLContainer(lContainer, tNode, lView); - let ssrState = null; - let uniqueId: string | null = null; + let ssrBlockState = null; + let ssrUniqueId: string | null = null; if (lContainer[DEHYDRATED_VIEWS]?.length > 0) { - // TODO(incremental-hydration): this is a hack, we should serialize defer const info = lContainer[DEHYDRATED_VIEWS][0].data; - uniqueId = info[DEFER_BLOCK_ID] ?? null; - ssrState = info[SERIALIZED_DEFER_BLOCK_STATE]; + ssrUniqueId = info[DEFER_BLOCK_ID] ?? null; + ssrBlockState = info[SERIALIZED_DEFER_BLOCK_STATE]; } // Init instance-specific defer details and store it. @@ -297,21 +297,21 @@ export function ɵɵdefer( null, // LOADING_AFTER_CLEANUP_FN null, // TRIGGER_CLEANUP_FNS null, // PREFETCH_TRIGGER_CLEANUP_FNS - uniqueId, // UNIQUE_ID - ssrState, // SSR_STATE + ssrUniqueId, // SSR_UNIQUE_ID + ssrBlockState, // SSR_BLOCK_STATE null, // ON_COMPLETE_FNS null, // HYDRATE_TRIGGER_CLEANUP_FNS ]; setLDeferBlockDetails(lView, adjustedIndex, lDetails); let registry: DeferBlockRegistry | null = null; - if (uniqueId !== null) { + if (ssrUniqueId !== null) { // TODO(incremental-hydration): explore how we can make // `DeferBlockRegistry` tree-shakable for client-only cases. registry = injector.get(DeferBlockRegistry); // Also store this defer block in the registry. - registry.add(uniqueId, {lView, tNode, lContainer}); + registry.add(ssrUniqueId, {lView, tNode, lContainer}); } const cleanupTriggersFn = () => invokeAllTriggerCleanupFns(lDetails, registry); @@ -415,7 +415,7 @@ export function ɵɵdeferHydrateWhen(rawValue: unknown) { // state. incrementallyHydrateFromBlockName( injector, - getLDeferBlockDetails(lView, tNode)[UNIQUE_SSR_ID]!, + getLDeferBlockDetails(lView, tNode)[SSR_UNIQUE_ID]!, (deferBlock: DeferBlock) => triggerAndWaitForCompletion(deferBlock), ); } @@ -534,7 +534,7 @@ export function ɵɵdeferHydrateOnImmediate() { } else { incrementallyHydrateFromBlockName( injector, - lDetails[UNIQUE_SSR_ID]!, + lDetails[SSR_UNIQUE_ID]!, (deferBlock: DeferBlock) => triggerAndWaitForCompletion(deferBlock), ); } @@ -643,6 +643,8 @@ export function ɵɵdeferHydrateOnHover() { // We are on the server and SSR for defer blocks is enabled. triggerDeferBlock(lView, tNode); } + // The actual triggering of hydration on hover is handled by JSAction in + // event_replay.ts. } /** @@ -711,6 +713,8 @@ export function ɵɵdeferHydrateOnInteraction() { // We are on the server and SSR for defer blocks is enabled. triggerDeferBlock(lView, tNode); } + // The actual triggering of hydration on interaction is handled by JSAction in + // event_replay.ts. } /** @@ -780,6 +784,8 @@ export function ɵɵdeferHydrateOnViewport() { // We are on the server and SSR for defer blocks is enabled. triggerDeferBlock(lView, tNode); } + // The actual triggering of hydration on viewport happens in incremental.ts, + // since these instructions won't exist for dehydrated content. } /********** Helper functions **********/ @@ -853,7 +859,7 @@ export function scheduleDelayedHydrating( () => incrementallyHydrateFromBlockName( injector, - lDetails[UNIQUE_SSR_ID]!, + lDetails[SSR_UNIQUE_ID]!, (deferBlock: DeferBlock) => triggerAndWaitForCompletion(deferBlock), ), injector, @@ -896,7 +902,7 @@ export function renderDeferBlockState( const currentState = lDetails[DEFER_BLOCK_STATE]; - const ssrState = lDetails[SSR_STATE]; + const ssrState = lDetails[SSR_BLOCK_STATE]; if (ssrState !== null && newState < ssrState) { return; // trying to render a previous state, exit } diff --git a/packages/core/src/defer/interfaces.ts b/packages/core/src/defer/interfaces.ts index 63a35b6dc6d..c30946f4878 100644 --- a/packages/core/src/defer/interfaces.ts +++ b/packages/core/src/defer/interfaces.ts @@ -210,8 +210,8 @@ export const STATE_IS_FROZEN_UNTIL = 2; export const LOADING_AFTER_CLEANUP_FN = 3; export const TRIGGER_CLEANUP_FNS = 4; export const PREFETCH_TRIGGER_CLEANUP_FNS = 5; -export const UNIQUE_SSR_ID = 6; -export const SSR_STATE = 7; +export const SSR_UNIQUE_ID = 6; +export const SSR_BLOCK_STATE = 7; export const ON_COMPLETE_FNS = 8; export const HYDRATE_TRIGGER_CLEANUP_FNS = 9; @@ -259,12 +259,12 @@ export interface LDeferBlockDetails extends Array { /** * Unique id of this defer block assigned during SSR. */ - [UNIQUE_SSR_ID]: string | null; + [SSR_UNIQUE_ID]: string | null; /** * Defer block state after SSR. */ - [SSR_STATE]: number | null; + [SSR_BLOCK_STATE]: number | null; /** * A set of callbacks to be invoked once the main content is rendered. diff --git a/packages/core/src/defer/registry.ts b/packages/core/src/defer/registry.ts index 884aa978bf4..5ec8ba579cb 100644 --- a/packages/core/src/defer/registry.ts +++ b/packages/core/src/defer/registry.ts @@ -9,13 +9,19 @@ import {ɵɵdefineInjectable} from '../di'; import {DeferBlock} from './interfaces'; // TODO(incremental-hydration): refactor this so that it's not used in CSR cases +/** + * The DeferBlockRegistry is used for incremental hydration purposes. It keeps + * track of the Defer Blocks that need hydration so we can effectively + * navigate up to the top dehydrated defer block and fire appropriate cleanup + * functions post hydration. + */ export class DeferBlockRegistry { private registry = new Map(); private cleanupFns = new Map(); - add(blockId: string, info: any) { + add(blockId: string, info: DeferBlock) { this.registry.set(blockId, info); } - get(blockId: string) { + get(blockId: string): DeferBlock | null { return this.registry.get(blockId) ?? null; } // TODO(incremental-hydration): we need to determine when this should be invoked @@ -38,7 +44,8 @@ export class DeferBlockRegistry { invokeCleanupFns(blockId: string) { // TODO(incremental-hydration): determine if we can safely remove entries from - // the cleanupFns after they've been invoked + // the cleanupFns after they've been invoked. Can we reset + // `this.cleanupFns.get(blockId)`? const fns = this.cleanupFns.get(blockId) ?? []; for (let fn of fns) { fn(); @@ -46,6 +53,8 @@ export class DeferBlockRegistry { } // Blocks that are being hydrated. + // TODO(incremental-hydration): cleanup task - we currently retain ids post hydration + // and need to determine when we can remove them. hydrating = new Set(); /** @nocollapse */ diff --git a/packages/core/src/event_delegation_utils.ts b/packages/core/src/event_delegation_utils.ts index cae2fa0d4ee..6e8184e3249 100644 --- a/packages/core/src/event_delegation_utils.ts +++ b/packages/core/src/event_delegation_utils.ts @@ -11,14 +11,9 @@ import {EventContract} from '@angular/core/primitives/event-dispatch'; import {Attribute} from '@angular/core/primitives/event-dispatch'; import {InjectionToken, Injector} from './di'; import {RElement} from './render3/interfaces/renderer_dom'; -import { - BLOCK_ELEMENT_MAP, - EVENT_REPLAY_ENABLED_DEFAULT, - IS_EVENT_REPLAY_ENABLED, -} from './hydration/tokens'; -import {OnDestroy} from './interface/lifecycle_hooks'; +import {BLOCK_ELEMENT_MAP} from './hydration/tokens'; -export const BLOCKNAME_ATTRIBUTE = 'ngb'; +export const DEFER_BLOCK_SSR_ID_ATTRIBUTE = 'ngb'; declare global { interface Element { @@ -41,7 +36,9 @@ export function setJSActionAttributes( eventTypes: string[], parentDeferBlockId: string | null = null, ) { - if (!eventTypes.length || nativeElement.nodeType !== Node.ELEMENT_NODE) { + // jsaction attributes specifically should be applied to elements and not comment nodes. + // Comment nodes also have no setAttribute function. So this avoids errors. + if (eventTypes.length === 0 || nativeElement.nodeType !== Node.ELEMENT_NODE) { return; } const existingAttr = nativeElement.getAttribute(Attribute.JSACTION); @@ -57,7 +54,7 @@ export function setJSActionAttributes( const blockName = parentDeferBlockId ?? ''; if (blockName !== '' && parts.length > 0) { - nativeElement.setAttribute(BLOCKNAME_ATTRIBUTE, blockName); + nativeElement.setAttribute(DEFER_BLOCK_SSR_ID_ATTRIBUTE, blockName); } } @@ -71,7 +68,7 @@ export const sharedStashFunction = (rEl: RElement, eventType: string, listenerFn }; export const sharedMapFunction = (rEl: RElement, jsActionMap: Map>) => { - let blockName = rEl.getAttribute(BLOCKNAME_ATTRIBUTE) ?? ''; + let blockName = rEl.getAttribute(DEFER_BLOCK_SSR_ID_ATTRIBUTE) ?? ''; const el = rEl as unknown as Element; const blockSet = jsActionMap.get(blockName) ?? new Set(); if (!blockSet.has(el)) { @@ -94,7 +91,7 @@ export function removeListenersFromBlocks(blockNames: string[], injector: Inject export const removeListeners = (el: Element) => { el.removeAttribute(Attribute.JSACTION); - el.removeAttribute(BLOCKNAME_ATTRIBUTE); + el.removeAttribute(DEFER_BLOCK_SSR_ID_ATTRIBUTE); el.__jsaction_fns = undefined; }; diff --git a/packages/core/src/hydration/annotate.ts b/packages/core/src/hydration/annotate.ts index fee6d5b44e4..c9476dfcab6 100644 --- a/packages/core/src/hydration/annotate.ts +++ b/packages/core/src/hydration/annotate.ts @@ -12,6 +12,7 @@ import { DEFER_BLOCK_STATE as CURRENT_DEFER_BLOCK_STATE, DeferBlockTrigger, HydrateTriggerDetails, + TDeferBlockDetails, } from '../defer/interfaces'; import {getLDeferBlockDetails, getTDeferBlockDetails} from '../defer/utils'; import {isDetachedByI18n} from '../i18n/utils'; @@ -34,6 +35,7 @@ import { CONTEXT, HEADER_OFFSET, HOST, + INJECTOR, LView, PARENT, RENDERER, @@ -44,7 +46,11 @@ import { import {unwrapLView, unwrapRNode} from '../render3/util/view_utils'; import {TransferState} from '../transfer_state'; -import {unsupportedProjectionOfDomNodes} from './error_handling'; +import { + unsupportedProjectionOfDomNodes, + validateMatchingNode, + validateNodeExists, +} from './error_handling'; import {collectDomEventsInfo, convertHydrateTriggersToJsAction} from './event_replay'; import {setJSActionAttributes} from '../event_delegation_utils'; import { @@ -183,13 +189,7 @@ function annotateComponentLViewForHydration( // Root elements might also be annotated with the `ngSkipHydration` attribute, // check if it's present before starting the serialization process. if (hostElement && !(hostElement as HTMLElement).hasAttribute(SKIP_HYDRATION_ATTR_NAME)) { - return annotateHostElementForHydration( - hostElement as HTMLElement, - lView, - null, - context, - injector, - ); + return annotateHostElementForHydration(hostElement as HTMLElement, lView, null, context); } return null; } @@ -226,13 +226,7 @@ function annotateLContainerForHydration( // Serialize all views within this view container. const rootLView = lContainer[PARENT]; - const rootLViewNghIndex = annotateHostElementForHydration( - hostElement, - rootLView, - null, - context, - injector, - ); + const rootLViewNghIndex = annotateHostElementForHydration(hostElement, rootLView, null, context); const renderer = componentLView[RENDERER] as Renderer2; @@ -336,7 +330,6 @@ function serializeLContainer( lView: LView, parentDeferBlockId: string | null, context: HydrationContext, - injector: Injector, ): SerializedContainerView[] { const views: SerializedContainerView[] = []; let lastViewAsString = ''; @@ -364,7 +357,7 @@ function serializeLContainer( // The `+1` is to capture the `` element. numRootNodes = calcNumRootNodesInLContainer(childLView) + 1; - annotateLContainerForHydration(childLView, context, injector); + annotateLContainerForHydration(childLView, context, lView[INJECTOR]!); const componentLView = unwrapLView(childLView[HOST]) as LView; @@ -426,15 +419,17 @@ function serializeLContainer( if ((node as Node).nodeType === Node.COMMENT_NODE) { annotateDeferBlockAnchorForHydration(node as RComment, deferBlockId); } - } - // Add JSAction attributes for root nodes that use some hydration triggers - const actionList = convertHydrateTriggersToJsAction(tDetails.hydrateTriggers); - for (let et of actionList) { - context.eventTypesToReplay.regular.add(et); + } else { + ngDevMode && validateNodeExists(node, childLView, tNode); + ngDevMode && + validateMatchingNode(node, Node.COMMENT_NODE, null, childLView, tNode, true); + + annotateDeferBlockAnchorForHydration(node as RComment, deferBlockId); } if (!isHydrateNeverBlock) { - annotateDeferBlockRootNodesWithJsAction(actionList, rootNodes, deferBlockId); + // Add JSAction attributes for root nodes that use some hydration triggers + annotateDeferBlockRootNodesWithJsAction(tDetails, rootNodes, deferBlockId, context); } // Use current block id as parent for nested routes. @@ -445,6 +440,9 @@ function serializeLContainer( // (not at the view level). serializedView[DEFER_BLOCK_ID] = deferBlockId; } + // DEFER_BLOCK_STATE is used for reconciliation in hydration, both regular and incremental. + // We need to know which template is rendered when hydrating. So we serialize this state + // regardless of hydration type. serializedView[DEFER_BLOCK_STATE] = lDetails[CURRENT_DEFER_BLOCK_STATE]; } @@ -452,7 +450,7 @@ function serializeLContainer( // TODO(incremental-hydration): avoid copying of an object here serializedView = { ...serializedView, - ...serializeLView(lContainer[i] as LView, parentDeferBlockId, context, injector), + ...serializeLView(lContainer[i] as LView, parentDeferBlockId, context), }; } } @@ -545,7 +543,6 @@ function serializeLView( lView: LView, parentDeferBlockId: string | null = null, context: HydrationContext, - injector: Injector, ): SerializedView { const ngh: SerializedView = {}; const tView = lView[TVIEW]; @@ -670,7 +667,6 @@ function serializeLView( hostNode as LView, parentDeferBlockId, context, - injector, ); } } @@ -682,7 +678,6 @@ function serializeLView( lView, parentDeferBlockId, context, - injector, ); } else if (Array.isArray(lView[i]) && !isLetDeclaration(tNode)) { // This is a component, annotate the host node with an `ngh` attribute. @@ -695,7 +690,6 @@ function serializeLView( lView[i], parentDeferBlockId, context, - injector, ); } } else { @@ -820,7 +814,6 @@ function annotateHostElementForHydration( lView: LView, parentDeferBlockId: string | null, context: HydrationContext, - injector: Injector, ): number | null { const renderer = lView[RENDERER]; if ( @@ -835,7 +828,7 @@ function annotateHostElementForHydration( renderer.setAttribute(element, SKIP_HYDRATION_ATTR_NAME, ''); return null; } else { - const ngh = serializeLView(lView, parentDeferBlockId, context, injector); + const ngh = serializeLView(lView, parentDeferBlockId, context); const index = context.serializedViewCollection.add(ngh); renderer.setAttribute(element, NGH_ATTR_NAME, index.toString()); return index; @@ -848,10 +841,7 @@ function annotateHostElementForHydration( * @param comment The Host element to be annotated * @param deferBlockId the id of the target defer block */ -function annotateDeferBlockAnchorForHydration( - comment: RComment, - deferBlockId: string | null, -): void { +function annotateDeferBlockAnchorForHydration(comment: RComment, deferBlockId: string): void { comment.textContent = `ngh=${deferBlockId}`; } @@ -890,11 +880,24 @@ function isContentProjectedNode(tNode: TNode): boolean { return false; } +/** + * Incremental hydration requires that any defer block root node + * with interaction or hover triggers have all of their root nodes + * trigger hydration with those events. So we need to make sure all + * the root nodes of that block have the proper jsaction attribute + * to ensure hydration is triggered, since the content is dehydrated + */ function annotateDeferBlockRootNodesWithJsAction( - actionList: string[], + tDetails: TDeferBlockDetails, rootNodes: any[], parentDeferBlockId: string, + context: HydrationContext, ) { + const actionList = convertHydrateTriggersToJsAction(tDetails.hydrateTriggers); + for (let et of actionList) { + context.eventTypesToReplay.regular.add(et); + } + if (actionList.length > 0) { const elementNodes = (rootNodes as HTMLElement[]).filter( (rn) => rn.nodeType === Node.ELEMENT_NODE, diff --git a/packages/core/src/hydration/api.ts b/packages/core/src/hydration/api.ts index 860dd3bb050..e3140d67ac7 100644 --- a/packages/core/src/hydration/api.ts +++ b/packages/core/src/hydration/api.ts @@ -308,6 +308,7 @@ export function withI18nSupport(): Provider[] { /** * Returns a set of providers required to setup support for incremental hydration. * Requires hydration to be enabled separately. + * Enabling incremental hydration also enables event replay for the entire app. * * @developerPreview */ @@ -330,9 +331,10 @@ export function withIncrementalHydration(): Provider[] { useFactory: () => { if (isPlatformBrowser()) { const injector = inject(Injector); + const doc = getDocument(); return () => { - bootstrapIncrementalHydration(getDocument(), injector); - appendDeferBlocksToJSActionMap(getDocument(), injector); + bootstrapIncrementalHydration(doc, injector); + appendDeferBlocksToJSActionMap(doc, injector); }; } return () => {}; // noop for the server code diff --git a/packages/core/src/hydration/blocks.ts b/packages/core/src/hydration/blocks.ts index 2a42b420f48..841911f214b 100644 --- a/packages/core/src/hydration/blocks.ts +++ b/packages/core/src/hydration/blocks.ts @@ -24,7 +24,7 @@ import {whenStable, ApplicationRef} from '../application/application_ref'; * If there are any dehydrated `@defer` blocks found along the way, * they are also stored and returned from the function (as a list of ids). */ -export function findFirstKnownParentDeferBlock(deferBlockId: string, injector: Injector) { +export function findFirstHydratedParentDeferBlock(deferBlockId: string, injector: Injector) { const deferBlockRegistry = injector.get(DeferBlockRegistry); const transferState = injector.get(TransferState); const deferBlockParents = transferState.get(NGH_DEFER_BLOCKS_KEY, {}); @@ -69,7 +69,7 @@ async function hydrateFromBlockNameImpl( // Make sure we don't hydrate/trigger the same thing multiple times if (deferBlockRegistry.hydrating.has(blockName)) return {deferBlock: null, hydratedBlocks}; - const {blockId, deferBlock, dehydratedBlocks} = findFirstKnownParentDeferBlock( + const {blockId, deferBlock, dehydratedBlocks} = findFirstHydratedParentDeferBlock( blockName, injector, ); diff --git a/packages/core/src/hydration/event_replay.ts b/packages/core/src/hydration/event_replay.ts index fb61e789e0a..3cf1846dd43 100644 --- a/packages/core/src/hydration/event_replay.ts +++ b/packages/core/src/hydration/event_replay.ts @@ -32,14 +32,14 @@ import {BLOCK_ELEMENT_MAP, EVENT_REPLAY_ENABLED_DEFAULT, IS_EVENT_REPLAY_ENABLED import { sharedStashFunction, sharedMapFunction, - BLOCKNAME_ATTRIBUTE, + DEFER_BLOCK_SSR_ID_ATTRIBUTE, EventContractDetails, JSACTION_EVENT_CONTRACT, removeListenersFromBlocks, } from '../event_delegation_utils'; import {APP_ID} from '../application/application_tokens'; import {performanceMarkFeature} from '../util/performance'; -import {hydrateFromBlockName, findFirstKnownParentDeferBlock} from './blocks'; +import {hydrateFromBlockName, findFirstHydratedParentDeferBlock} from './blocks'; import {DeferBlock, DeferBlockTrigger, HydrateTriggerDetails} from '../defer/interfaces'; import {triggerAndWaitForCompletion} from '../defer/instructions'; import {cleanupDehydratedViews, cleanupLContainer} from './cleanup'; @@ -226,7 +226,8 @@ export function invokeRegisteredReplayListeners( event: Event, currentTarget: Element | null, ) { - const blockName = (currentTarget && currentTarget.getAttribute(BLOCKNAME_ATTRIBUTE)) ?? ''; + const blockName = + (currentTarget && currentTarget.getAttribute(DEFER_BLOCK_SSR_ID_ATTRIBUTE)) ?? ''; if (/d\d+/.test(blockName)) { hydrateAndInvokeBlockListeners(blockName, injector, event, currentTarget!); } else if (event.eventPhase === EventPhase.REPLAY) { @@ -259,7 +260,7 @@ async function triggerBlockHydration( onTriggerFn: (deferBlock: any) => void, ) { // grab the list of dehydrated blocks and queue them up - const {dehydratedBlocks} = findFirstKnownParentDeferBlock(blockName, injector); + const {dehydratedBlocks} = findFirstHydratedParentDeferBlock(blockName, injector); for (let block of dehydratedBlocks) { hydratingBlocks.add(block); } @@ -279,7 +280,7 @@ function replayQueuedBlockEvents(hydratedBlocks: Set, injector: Injector // empty it blockEventQueue = []; for (let {event, currentTarget} of queue) { - const blockName = currentTarget.getAttribute(BLOCKNAME_ATTRIBUTE)!; + const blockName = currentTarget.getAttribute(DEFER_BLOCK_SSR_ID_ATTRIBUTE)!; if (hydratedBlocks.has(blockName)) { invokeListeners(event, currentTarget); } else { diff --git a/packages/core/test/bundling/defer/bundle.golden_symbols.json b/packages/core/test/bundling/defer/bundle.golden_symbols.json index d9a9d120926..941ae367e06 100644 --- a/packages/core/test/bundling/defer/bundle.golden_symbols.json +++ b/packages/core/test/bundling/defer/bundle.golden_symbols.json @@ -459,7 +459,10 @@ "name": "SOURCE" }, { - "name": "SSR_STATE" + "name": "SSR_BLOCK_STATE" + }, + { + "name": "SSR_UNIQUE_ID" }, { "name": "SVG_NAMESPACE" @@ -509,9 +512,6 @@ { "name": "TYPE" }, - { - "name": "UNIQUE_SSR_ID" - }, { "name": "USE_VALUE" },