{
  "version": 3,
  "sources": ["../../../src/providers/http-polling/polling-manager.ts"],
  "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { applyFilters } from '@wordpress/hooks';\n\n/**\n * External dependencies\n */\nimport * as Y from 'yjs';\nimport * as encoding from 'lib0/encoding';\nimport * as decoding from 'lib0/decoding';\nimport type { Awareness } from 'y-protocols/awareness';\nimport { removeAwarenessStates } from 'y-protocols/awareness';\nimport * as syncProtocol from 'y-protocols/sync';\n\n/**\n * Internal dependencies\n */\nimport {\n\tDEFAULT_CLIENT_LIMIT_PER_ROOM,\n\tERROR_RETRY_DELAYS_SOLO_MS,\n\tERROR_RETRY_DELAYS_WITH_COLLABORATORS_MS,\n\tMAX_UPDATE_SIZE_IN_BYTES,\n\tPOLLING_INTERVAL_IN_MS,\n\tPOLLING_INTERVAL_WITH_COLLABORATORS_IN_MS,\n\tPOLLING_INTERVAL_BACKGROUND_TAB_IN_MS,\n\tDISCONNECT_DIALOG_RETRY_MS,\n\tMANUAL_RETRY_INTERVAL_MS,\n} from './config';\nimport { ConnectionError, ConnectionErrorCode } from '../../errors';\nimport type { ConnectionStatus } from '../../types';\nimport {\n\ttype AwarenessState,\n\ttype LocalAwarenessState,\n\ttype SyncPayload,\n\ttype SyncUpdate,\n\tSyncUpdateType,\n\ttype UpdateQueue,\n} from './types';\nimport {\n\tbase64ToUint8Array,\n\tcreateSyncUpdate,\n\tcreateUpdateQueue,\n\tintValueOrDefault,\n\tpostSyncUpdate,\n\tpostSyncUpdateNonBlocking,\n} from './utils';\n\nconst POLLING_MANAGER_ORIGIN = 'polling-manager';\n\ntype LogFunction = (\n\tmessage: string,\n\tdebug?: object,\n\terrorLevel?: 'error' | 'log' | 'warn',\n\tforce?: boolean\n) => void;\n\ninterface PollingManager {\n\tregisterRoom: ( options: RegisterRoomOptions ) => void;\n\tretryNow: () => void;\n\tunregisterRoom: (\n\t\troom: string,\n\t\toptions?: { sendDisconnectSignal?: boolean }\n\t) => void;\n}\n\ninterface RegisterRoomOptions {\n\troom: string;\n\tdoc: Y.Doc;\n\tawareness: Awareness;\n\tlog: LogFunction;\n\tonStatusChange: ( status: ConnectionStatus ) => void;\n\tonSync: () => void;\n}\n\ninterface RoomState {\n\tclientId: number;\n\tcreateCompactionUpdate: () => SyncUpdate;\n\tendCursor: number;\n\tisPrimaryRoom: boolean;\n\tlocalAwarenessState: LocalAwarenessState;\n\tlog: LogFunction;\n\tonStatusChange: ( status: ConnectionStatus ) => void;\n\tprocessAwarenessUpdate: ( state: AwarenessState ) => void;\n\tprocessDocUpdate: ( update: SyncUpdate ) => SyncUpdate | void;\n\troom: string;\n\tunregister: () => void;\n\tupdateQueue: UpdateQueue;\n}\n\n/**\n * Minimal shape of a WordPress REST API error as it arrives on the client\n * via apiFetch. WP_Error is serialized to JSON with a `data.status` field\n * containing the HTTP status code; `code` and `message` are best-effort.\n */\ninterface WPRestError {\n\tcode?: string;\n\tmessage?: string;\n\tdata: { status: number };\n}\n\n/**\n * Check if an error is a forbidden (403) response from the WordPress REST\n * API. These errors have a `data.status` property set by WP_Error.\n *\n * @param error The caught error to inspect.\n */\nfunction isForbiddenError( error: unknown ): error is WPRestError {\n\treturn ( error as WPRestError | undefined )?.data?.status === 403;\n}\n\n/**\n * Try to identify which room caused a forbidden error by checking if any\n * room name from the request appears in the error message. The WordPress\n * REST API includes the room name in per-entity permission errors (e.g.\n * \"You do not have permission to sync this entity: postType/post:123.\").\n * Room names are never translated, so substring matching is reliable.\n *\n * Returns the room name if found, or null for generic auth failures\n * (e.g. \"not logged in\") where no specific room is identified.\n *\n * @param error The forbidden error, narrowed via isForbiddenError.\n * @param rooms The room names from the request payload.\n */\nfunction identifyForbiddenRoom(\n\terror: WPRestError,\n\trooms: string[]\n): string | null {\n\tconst message = typeof error.message === 'string' ? error.message : '';\n\n\t// Sort rooms by length descending so the longest match wins. Room names\n\t// embed numeric IDs (e.g. \"postType/post:1\", \"postType/post:10\"), and a\n\t// shorter name can be a substring of a longer one. Without sorting, the\n\t// iteration order is the room registration order, so a 403 referencing\n\t// \"postType/post:10\" could incorrectly match \"postType/post:1\" first.\n\tconst sortedRooms = [ ...rooms ].sort( ( a, b ) => b.length - a.length );\n\n\tfor ( const room of sortedRooms ) {\n\t\tif ( message.includes( room ) ) {\n\t\t\treturn room;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Handle a 403 from the sync endpoint. Silently unregisters the affected\n * rooms, and restores pending updates for the remaining rooms so they retry on\n * the next poll cycle.\n *\n * @param error          The forbidden error, narrowed via isForbiddenError.\n * @param requestedRooms The rooms that were in the failing request.\n */\nfunction handleForbiddenError(\n\terror: WPRestError,\n\trequestedRooms: SyncPayload[ 'rooms' ]\n): void {\n\tconst forbiddenRoom = identifyForbiddenRoom(\n\t\terror,\n\t\trequestedRooms.map( ( r ) => r.room )\n\t);\n\n\tif ( forbiddenRoom ) {\n\t\t// A specific room was denied \u2014 unregister only that room.\n\t\tconst state = roomStates.get( forbiddenRoom );\n\t\tif ( state ) {\n\t\t\tstate.log(\n\t\t\t\t'Permission denied, unregistering room',\n\t\t\t\t{ error },\n\t\t\t\t'error',\n\t\t\t\ttrue // force\n\t\t\t);\n\t\t\tunregisterRoom( forbiddenRoom, { sendDisconnectSignal: false } );\n\t\t}\n\n\t\t// Restore updates for remaining rooms so they can be retried on\n\t\t// the next poll cycle.\n\t\tfor ( const room of requestedRooms ) {\n\t\t\tif (\n\t\t\t\troom.room === forbiddenRoom ||\n\t\t\t\t! roomStates.has( room.room )\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst remainingState = roomStates.get( room.room )!;\n\t\t\tif ( room.updates.length > 0 ) {\n\t\t\t\tremainingState.updateQueue.restore( room.updates );\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// Generic auth failure (e.g. not logged in) \u2014 unregister all rooms.\n\t\tconst rooms = [ ...roomStates.keys() ];\n\t\tfor ( const room of rooms ) {\n\t\t\tconst state = roomStates.get( room );\n\t\t\tif ( state ) {\n\t\t\t\tstate.log(\n\t\t\t\t\t'Permission denied, unregistering room',\n\t\t\t\t\t{ error },\n\t\t\t\t\t'error',\n\t\t\t\t\ttrue // force\n\t\t\t\t);\n\t\t\t\tunregisterRoom( room, { sendDisconnectSignal: false } );\n\t\t\t}\n\t\t}\n\t}\n}\n\nconst roomStates: Map< string, RoomState > = new Map();\n\n/**\n * Create a compaction update by merging existing updates. This preserves\n * the original operation metadata (client IDs, logical clocks) so that\n * Yjs deduplication works correctly when the compaction is applied.\n *\n * Deprecated: The server is moving towards full state updates for compaction.\n *\n * @param updates The updates to merge\n */\nfunction createDeprecatedCompactionUpdate( updates: SyncUpdate[] ): SyncUpdate {\n\t// Extract only compaction and update types for merging (skip sync-step updates).\n\t// Decode base64 updates to Uint8Array for merging.\n\tconst mergeable = updates\n\t\t.filter( ( u ) =>\n\t\t\t[ SyncUpdateType.COMPACTION, SyncUpdateType.UPDATE ].includes(\n\t\t\t\tu.type\n\t\t\t)\n\t\t)\n\t\t.map( ( u ) => base64ToUint8Array( u.data ) );\n\n\t// Merge all updates while preserving operation metadata.\n\treturn createSyncUpdate(\n\t\tY.mergeUpdatesV2( mergeable ),\n\t\tSyncUpdateType.COMPACTION\n\t);\n}\n\n/**\n * Create sync step 1 update (announce our state vector).\n *\n * @param doc The Yjs document\n */\nfunction createSyncStep1Update( doc: Y.Doc ): SyncUpdate {\n\tconst encoder = encoding.createEncoder();\n\tsyncProtocol.writeSyncStep1( encoder, doc );\n\treturn createSyncUpdate(\n\t\tencoding.toUint8Array( encoder ),\n\t\tSyncUpdateType.SYNC_STEP_1\n\t);\n}\n\n/**\n * Create sync step 2 update (acknowledge sync step 1).\n *\n * @param doc   The Yjs document\n * @param step1 The sync step 1 update received\n */\nfunction createSyncStep2Update( doc: Y.Doc, step1: Uint8Array ): SyncUpdate {\n\tconst decoder = decoding.createDecoder( step1 );\n\tconst encoder = encoding.createEncoder();\n\tsyncProtocol.readSyncMessage(\n\t\tdecoder,\n\t\tencoder,\n\t\tdoc,\n\t\tPOLLING_MANAGER_ORIGIN\n\t);\n\treturn createSyncUpdate(\n\t\tencoding.toUint8Array( encoder ),\n\t\tSyncUpdateType.SYNC_STEP_2\n\t);\n}\n\n/**\n * Process an incoming awareness update from the server.\n *\n * @param state     The awareness state received\n * @param awareness The local Awareness instance\n */\nfunction processAwarenessUpdate(\n\tstate: AwarenessState,\n\tawareness: Awareness\n): void {\n\tconst currentStates = awareness.getStates();\n\tconst added = new Set< number >();\n\tconst updated = new Set< number >();\n\n\t// Removed clients are missing from the server state.\n\tconst removed = new Set< number >(\n\t\tArray.from( currentStates.keys() ).filter(\n\t\t\t( clientId ) => ! state[ clientId ]\n\t\t)\n\t);\n\n\tObject.entries( state ).forEach( ( [ clientIdString, awarenessState ] ) => {\n\t\tconst clientId = Number( clientIdString );\n\n\t\t// Skip our own state (we already have it locally).\n\t\tif ( clientId === awareness.clientID ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// A null state should be removed by the server, but handle it here just in case.\n\t\tif ( null === awarenessState ) {\n\t\t\tcurrentStates.delete( clientId );\n\t\t\tremoved.add( clientId );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( ! currentStates.has( clientId ) ) {\n\t\t\tcurrentStates.set( clientId, awarenessState );\n\t\t\tadded.add( clientId );\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentState = currentStates.get( clientId );\n\n\t\tif (\n\t\t\tJSON.stringify( currentState ) !== JSON.stringify( awarenessState )\n\t\t) {\n\t\t\tcurrentStates.set( clientId, awarenessState );\n\t\t\tupdated.add( clientId );\n\t\t}\n\t} );\n\n\tif ( added.size + updated.size > 0 ) {\n\t\tawareness.emit( 'change', [\n\t\t\t{\n\t\t\t\tadded: Array.from( added ),\n\t\t\t\tupdated: Array.from( updated ),\n\t\t\t\t// Left blank on purpose, as the removal of clients is handled in the if condition below.\n\t\t\t\tremoved: [],\n\t\t\t},\n\t\t] );\n\t}\n\n\tif ( removed.size > 0 ) {\n\t\tremoveAwarenessStates(\n\t\t\tawareness,\n\t\t\tArray.from( removed ),\n\t\t\tPOLLING_MANAGER_ORIGIN\n\t\t);\n\t}\n}\n\n/**\n * Process an incoming sync / document update based on its type.\n *\n * @param update The typed update received\n * @param doc    The Yjs document\n * @param onSync Callback when sync is complete\n * @return A response update if needed (e.g., sync_step2 in response to sync_step1)\n */\nfunction processDocUpdate(\n\tupdate: SyncUpdate,\n\tdoc: Y.Doc,\n\tonSync: () => void\n): SyncUpdate | void {\n\tconst data = base64ToUint8Array( update.data );\n\n\tswitch ( update.type ) {\n\t\tcase SyncUpdateType.SYNC_STEP_1: {\n\t\t\t// Respond to sync step 1 with sync step 2.\n\t\t\treturn createSyncStep2Update( doc, data );\n\t\t}\n\n\t\tcase SyncUpdateType.SYNC_STEP_2: {\n\t\t\t// Apply sync step 2 (potentially contains missing updates).\n\t\t\tconst decoder = decoding.createDecoder( data );\n\t\t\tconst encoder = encoding.createEncoder();\n\t\t\tsyncProtocol.readSyncMessage(\n\t\t\t\tdecoder,\n\t\t\t\tencoder,\n\t\t\t\tdoc,\n\t\t\t\tPOLLING_MANAGER_ORIGIN\n\t\t\t);\n\t\t\tonSync();\n\t\t\treturn;\n\t\t}\n\n\t\tcase SyncUpdateType.COMPACTION:\n\t\tcase SyncUpdateType.UPDATE: {\n\t\t\t// Apply document update directly.\n\t\t\tY.applyUpdateV2( doc, data, POLLING_MANAGER_ORIGIN );\n\t\t}\n\t}\n}\n\n/**\n * Check whether the awareness state exceeds the configured connection limit.\n *\n * @param awareness The awareness state from the server response.\n * @param roomState The room state corresponding to the awareness state\n * @return True if a peer limit has been exceeded.\n */\nfunction checkConnectionLimit(\n\tawareness: AwarenessState,\n\troomState: RoomState\n): boolean {\n\tif ( ! roomState.isPrimaryRoom || hasCheckedConnectionLimit ) {\n\t\treturn false;\n\t}\n\n\t// Limits are only enforced on the initial connection.\n\thasCheckedConnectionLimit = true;\n\n\tconst maxClientsPerRoom = applyFilters(\n\t\t'sync.pollingProvider.maxClientsPerRoom',\n\t\tDEFAULT_CLIENT_LIMIT_PER_ROOM,\n\t\troomState.room\n\t);\n\n\tconst clientCount = Object.keys( awareness ).length;\n\tconst validatedLimit = intValueOrDefault(\n\t\tmaxClientsPerRoom,\n\t\tDEFAULT_CLIENT_LIMIT_PER_ROOM\n\t);\n\n\tif ( clientCount > validatedLimit ) {\n\t\troomState.log( 'Connection limit exceeded', {\n\t\t\tclientCount,\n\t\t\tmaxClientsPerRoom: validatedLimit,\n\t\t\troom: roomState.room,\n\t\t} );\n\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nlet areListenersRegistered = false;\nlet consecutiveFailures = 0;\nlet hasCheckedConnectionLimit = false;\nlet isManualRetry = false;\nlet hasCollaborators = false;\nlet isActiveBrowser = 'visible' === document.visibilityState;\nlet isPolling = false;\nlet isUnloadPending = false;\nlet pollInterval = POLLING_INTERVAL_IN_MS;\nlet pollingTimeoutId: ReturnType< typeof setTimeout > | null = null;\n\n/**\n * Mark that a page unload has been requested. This fires on\n * `beforeunload` which happens before the browser aborts in-flight\n * fetches, allowing us to distinguish poll failures caused by\n * navigation from genuine server errors in the catch block.\n *\n * If the user cancels the unload (e.g. by dismissing a \"Save Changes?\" dialog),\n * the flag is reset at the start of the next poll cycle so that polling can\n * resume.\n */\nfunction handleBeforeUnload(): void {\n\tisUnloadPending = true;\n}\n\n/**\n * Send a disconnect signal for all registered rooms when the page is\n * being unloaded. Uses `sendBeacon` so the request survives navigation.\n */\nfunction handlePageHide(): void {\n\tconst rooms = Array.from( roomStates.entries() ).map(\n\t\t( [ room, state ] ) => ( {\n\t\t\tafter: 0,\n\t\t\tawareness: null,\n\t\t\tclient_id: state.clientId,\n\t\t\troom,\n\t\t\tupdates: [],\n\t\t} )\n\t);\n\n\tpostSyncUpdateNonBlocking( { rooms } );\n}\n\n/**\n * Hangle change in visibility state of browser tab.\n *\n * Used to trigger a slow down of the collaboration syncs when the\n * browser tab becomes inactive (either the user switches tabs or the\n * screen saver comes on).\n *\n * Fires on the document's visibilitychange event.\n */\nfunction handleVisibilityChange() {\n\tconst wasActive = isActiveBrowser;\n\tisActiveBrowser = document.visibilityState === 'visible';\n\n\tif ( isActiveBrowser && ! wasActive ) {\n\t\t/*\n\t\t * Remove scheduled polling and repoll immediately when reactivated.\n\t\t *\n\t\t * This ensures that any updates by collaborators are immediately\n\t\t * reflected in the document once the browser tab becomes active.\n\t\t * Otherwise there would be a delay of up to 30 seconds before the\n\t\t * updates came through.\n\t\t *\n\t\t * Only repoll if we cleared a pending timeout, meaning the poll loop\n\t\t * was idle between cycles. If no timeout is pending, a poll request\n\t\t * is already in-flight and will pick up the updated isActiveBrowser\n\t\t * value when it schedules the next cycle.\n\t\t */\n\t\tif ( pollingTimeoutId ) {\n\t\t\tclearTimeout( pollingTimeoutId );\n\t\t\tpollingTimeoutId = null;\n\t\t\tpoll();\n\t\t}\n\t}\n}\n\nfunction poll(): void {\n\tisPolling = true;\n\tpollingTimeoutId = null;\n\n\tasync function start(): Promise< void > {\n\t\tif ( 0 === roomStates.size ) {\n\t\t\tisPolling = false;\n\t\t\treturn;\n\t\t}\n\n\t\t// Reset the unloading flag at the start of each poll cycle so\n\t\t// it doesn't permanently suppress disconnect after the user\n\t\t// cancels a beforeunload dialog.\n\t\tisUnloadPending = false;\n\n\t\t// Emit 'connecting' status.\n\t\troomStates.forEach( ( state ) => {\n\t\t\tstate.onStatusChange( { status: 'connecting' } );\n\t\t} );\n\n\t\t// Create a payload with all queued updates. We include rooms even if they\n\t\t// have no updates to ensure we receive any incoming updates. Note that we\n\t\t// withhold our own updates until we detect another collaborator using the\n\t\t// queue's pause / resume mechanism.\n\t\tconst payload: SyncPayload = {\n\t\t\trooms: Array.from( roomStates.entries() ).map(\n\t\t\t\t( [ room, state ] ) => ( {\n\t\t\t\t\tafter: state.endCursor ?? 0,\n\t\t\t\t\tawareness: state.localAwarenessState,\n\t\t\t\t\tclient_id: state.clientId,\n\t\t\t\t\troom,\n\t\t\t\t\tupdates: state.updateQueue.get(),\n\t\t\t\t} )\n\t\t\t),\n\t\t};\n\n\t\ttry {\n\t\t\tconst { rooms } = await postSyncUpdate( payload );\n\n\t\t\t// Emit 'connected' status.\n\t\t\tconsecutiveFailures = 0;\n\t\t\tisManualRetry = false;\n\t\t\troomStates.forEach( ( state ) => {\n\t\t\t\tstate.onStatusChange( { status: 'connected' } );\n\t\t\t} );\n\n\t\t\t// Reset before checking each room\n\t\t\thasCollaborators = false;\n\n\t\t\trooms.forEach( ( room ) => {\n\t\t\t\tif ( ! roomStates.has( room.room ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst roomState = roomStates.get( room.room )!;\n\t\t\t\troomState.endCursor = room.end_cursor;\n\n\t\t\t\t// If a limit is exceeded, disconnect immediately without processing updates.\n\t\t\t\tif ( checkConnectionLimit( room.awareness, roomState ) ) {\n\t\t\t\t\troomState.onStatusChange( {\n\t\t\t\t\t\tstatus: 'disconnected',\n\t\t\t\t\t\terror: new ConnectionError(\n\t\t\t\t\t\t\tConnectionErrorCode.CONNECTION_LIMIT_EXCEEDED,\n\t\t\t\t\t\t\t'Connection limit exceeded'\n\t\t\t\t\t\t),\n\t\t\t\t\t} );\n\t\t\t\t\tunregisterRoom( room.room );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Process awareness update.\n\t\t\t\troomState.processAwarenessUpdate( room.awareness );\n\n\t\t\t\t// If there is another collaborator on the primary entity,\n\t\t\t\t// resume all room queues for the next poll and increase\n\t\t\t\t// polling frequency. We only check the primary room to\n\t\t\t\t// avoid false positives from shared collection rooms\n\t\t\t\t// (e.g. taxonomy/category), but resume all queues so\n\t\t\t\t// collection rooms (e.g. root/comment) can also sync.\n\t\t\t\tif (\n\t\t\t\t\troomState.isPrimaryRoom &&\n\t\t\t\t\tObject.keys( room.awareness ).length > 1\n\t\t\t\t) {\n\t\t\t\t\thasCollaborators = true;\n\t\t\t\t\troomStates.forEach( ( state ) => {\n\t\t\t\t\t\tstate.updateQueue.resume();\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t\t// Process each incoming update and collect any responses.\n\t\t\t\tconst responseUpdates: SyncUpdate[] = [];\n\t\t\t\tfor ( const update of room.updates ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst response = roomState.processDocUpdate( update );\n\t\t\t\t\t\tif ( response ) {\n\t\t\t\t\t\t\tresponseUpdates.push( response );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch ( error ) {\n\t\t\t\t\t\troomState.log(\n\t\t\t\t\t\t\t'Failed to apply sync update',\n\t\t\t\t\t\t\t{ error, update },\n\t\t\t\t\t\t\t'error',\n\t\t\t\t\t\t\ttrue // force\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\troomState.updateQueue.addBulk( responseUpdates );\n\n\t\t\t\t// Respond to compaction requests from server. The server asks only one\n\t\t\t\t// client at a time to compact (lowest active client ID). We encode our\n\t\t\t\t// full document state to replace all prior updates on the server.\n\t\t\t\tif ( room.should_compact ) {\n\t\t\t\t\troomState.log( 'Server requested compaction update' );\n\t\t\t\t\troomState.updateQueue.clear();\n\t\t\t\t\troomState.updateQueue.add(\n\t\t\t\t\t\troomState.createCompactionUpdate()\n\t\t\t\t\t);\n\t\t\t\t} else if ( room.compaction_request ) {\n\t\t\t\t\t// Deprecated\n\t\t\t\t\troomState.log( 'Server requested (old) compaction update' );\n\t\t\t\t\troomState.updateQueue.add(\n\t\t\t\t\t\tcreateDeprecatedCompactionUpdate(\n\t\t\t\t\t\t\troom.compaction_request\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// Recalculate polling interval.\n\t\t\tif ( isActiveBrowser && hasCollaborators ) {\n\t\t\t\tpollInterval = POLLING_INTERVAL_WITH_COLLABORATORS_IN_MS;\n\t\t\t} else if ( isActiveBrowser ) {\n\t\t\t\tpollInterval = POLLING_INTERVAL_IN_MS;\n\t\t\t} else {\n\t\t\t\tpollInterval = POLLING_INTERVAL_BACKGROUND_TAB_IN_MS;\n\t\t\t}\n\t\t} catch ( error ) {\n\t\t\t// A 403 response means the user does not have permission to\n\t\t\t// sync a specific entity. Silently unregister the affected\n\t\t\t// room(s) and let polling continue for the rest.\n\t\t\tif ( isForbiddenError( error ) ) {\n\t\t\t\thandleForbiddenError( error, payload.rooms );\n\n\t\t\t\t// If every room was unregistered, stop the poll loop\n\t\t\t\t// instead of scheduling another tick. Reset isPolling\n\t\t\t\t// so a future registerRoom() call can restart it.\n\t\t\t\tif ( roomStates.size === 0 ) {\n\t\t\t\t\tisPolling = false;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Use the explicit retry delay schedule for backoff.\n\t\t\t\tconsecutiveFailures++;\n\t\t\t\tconst retrySchedule = hasCollaborators\n\t\t\t\t\t? ERROR_RETRY_DELAYS_WITH_COLLABORATORS_MS\n\t\t\t\t\t: ERROR_RETRY_DELAYS_SOLO_MS;\n\t\t\t\tif ( consecutiveFailures <= retrySchedule.length ) {\n\t\t\t\t\tpollInterval = retrySchedule[ consecutiveFailures - 1 ];\n\t\t\t\t} else {\n\t\t\t\t\tpollInterval = DISCONNECT_DIALOG_RETRY_MS;\n\t\t\t\t}\n\n\t\t\t\t// After a manual retry, use a shorter interval for one cycle.\n\t\t\t\tif ( isManualRetry ) {\n\t\t\t\t\tpollInterval = MANUAL_RETRY_INTERVAL_MS;\n\t\t\t\t\tisManualRetry = false;\n\t\t\t\t}\n\n\t\t\t\t// Recover from the failed request. We don't know whether the server stored\n\t\t\t\t// our updates before the error occurred (e.g. a network timeout after a\n\t\t\t\t// successful write). Re-sending the same updates via restore() would\n\t\t\t\t// duplicate them on the server and cause unbounded storage growth.\n\t\t\t\t//\n\t\t\t\t// Instead, for rooms that had outgoing updates, replace the queue with a\n\t\t\t\t// single compaction (full document state). This is idempotent: if the\n\t\t\t\t// server already stored the updates, the compaction safely supersedes\n\t\t\t\t// them; if it didn't, the compaction includes them. Updates not seen by\n\t\t\t\t// this client are preserved in both cases.\n\t\t\t\tfor ( const room of payload.rooms ) {\n\t\t\t\t\tif ( ! roomStates.has( room.room ) ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst state = roomStates.get( room.room )!;\n\n\t\t\t\t\tif ( room.updates.length > 0 && state.endCursor > 0 ) {\n\t\t\t\t\t\tstate.updateQueue.clear();\n\t\t\t\t\t\tstate.updateQueue.add( state.createCompactionUpdate() );\n\t\t\t\t\t} else if ( room.updates.length > 0 ) {\n\t\t\t\t\t\tstate.updateQueue.restore( room.updates );\n\t\t\t\t\t}\n\n\t\t\t\t\tstate.log(\n\t\t\t\t\t\t'Error posting sync update, will retry with backoff',\n\t\t\t\t\t\t{ error, nextPoll: pollInterval },\n\t\t\t\t\t\t'error',\n\t\t\t\t\t\ttrue // force\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Don't report disconnected status when the request was aborted\n\t\t\t\t// due to page unload (e.g. during a refresh) to avoid briefly\n\t\t\t\t// flashing the disconnect dialog before the new page loads.\n\t\t\t\tif ( ! isUnloadPending ) {\n\t\t\t\t\tconst backgroundRetriesFailed =\n\t\t\t\t\t\tconsecutiveFailures > retrySchedule.length;\n\n\t\t\t\t\troomStates.forEach( ( state ) => {\n\t\t\t\t\t\tstate.onStatusChange( {\n\t\t\t\t\t\t\tstatus: 'disconnected',\n\t\t\t\t\t\t\tcanManuallyRetry: true,\n\t\t\t\t\t\t\tconsecutiveFailures,\n\t\t\t\t\t\t\tbackgroundRetriesFailed,\n\t\t\t\t\t\t\twillAutoRetryInMs: pollInterval,\n\t\t\t\t\t\t} );\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpollingTimeoutId = setTimeout( poll, pollInterval );\n\t}\n\n\t// Start polling.\n\tvoid start();\n}\n\nfunction registerRoom( {\n\troom,\n\tdoc,\n\tawareness,\n\tlog,\n\tonSync,\n\tonStatusChange,\n}: RegisterRoomOptions ): void {\n\tif ( roomStates.has( room ) ) {\n\t\treturn;\n\t}\n\n\t// Note: Queue is initially paused. Call .resume() to unpause.\n\tconst updateQueue = createUpdateQueue( [ createSyncStep1Update( doc ) ] );\n\n\t/**\n\t * Connection limits are enforced on the first entity to be loaded for sync.\n\t * This is an inelegant solution to a hard problem: This sync provider and the\n\t * sync package in general intentionally have no knowledge of the individual\n\t * entities being synced.\n\t *\n\t * Let's say a user opens a document (Entity A) for editing. If you asked the\n\t * user what they are doing, they would reply \"I'm editing Entity A.\" You might\n\t * say that Entity A is \"primary.\"\n\t *\n\t * However, the action of editing Entity A also triggers the loading of a\n\t * collection of document categories (Entity B) and another document (Entity C)\n\t * that is embedded in Entity A. You might therefore say that Entity B and\n\t * Entity C are \"secondary\" in this session.\n\t *\n\t * Meanwhile, a different user opens Entity C for editing, which also triggers\n\t * the loading of Entity B. In this session, Entity C is \"primary\" and Entity B\n\t * is \"secondary.\"\n\t *\n\t * How do we enforce limits? The intuitive answer is that we only want to count\n\t * connections when the entity is \"primary.\" However, we have no ability to\n\t * detect this. A document might be loaded as a primary entity in one session\n\t * and a secondary entity in another.\n\t *\n\t * In practice, we can consider the first-loaded entity as \"primary\" and use it\n\t * to enforce our connection limit. This is an imperfect assumption of consumer\n\t * behavior.\n\t *\n\t * How might this approach be improved? We could develop some way to annotate\n\t * entity loading so that the consumer can indicate which entity is primary.\n\t */\n\tconst isPrimaryRoom = 0 === roomStates.size;\n\n\tfunction onAwarenessUpdate(): void {\n\t\troomState.localAwarenessState = awareness.getLocalState() ?? {};\n\t}\n\n\tfunction onDocUpdate( update: Uint8Array, origin: unknown ): void {\n\t\tif ( POLLING_MANAGER_ORIGIN === origin ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( update.byteLength > MAX_UPDATE_SIZE_IN_BYTES ) {\n\t\t\tconst state = roomStates.get( room );\n\t\t\tif ( ! state ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tstate.log( 'Document size limit exceeded', {\n\t\t\t\tmaxUpdateSizeInBytes: MAX_UPDATE_SIZE_IN_BYTES,\n\t\t\t\tupdateSizeInBytes: update.byteLength,\n\t\t\t} );\n\n\t\t\tstate.onStatusChange( {\n\t\t\t\tstatus: 'disconnected',\n\t\t\t\terror: new ConnectionError(\n\t\t\t\t\tConnectionErrorCode.DOCUMENT_SIZE_LIMIT_EXCEEDED,\n\t\t\t\t\t'Document size limit exceeded'\n\t\t\t\t),\n\t\t\t} );\n\n\t\t\t// This is an unrecoverable error. Unregister the room to prevent syncing.\n\t\t\tunregisterRoom( room );\n\t\t}\n\n\t\t// Tag local document changes as 'update' type.\n\t\tupdateQueue.add( createSyncUpdate( update, SyncUpdateType.UPDATE ) );\n\t}\n\n\tfunction unregister(): void {\n\t\tdoc.off( 'updateV2', onDocUpdate );\n\t\tawareness.off( 'change', onAwarenessUpdate );\n\t\tupdateQueue.clear();\n\t}\n\n\tconst roomState: RoomState = {\n\t\tclientId: doc.clientID,\n\t\tcreateCompactionUpdate: () =>\n\t\t\tcreateSyncUpdate(\n\t\t\t\tY.encodeStateAsUpdateV2( doc ),\n\t\t\t\tSyncUpdateType.COMPACTION\n\t\t\t),\n\t\tendCursor: 0,\n\t\tisPrimaryRoom,\n\t\tlocalAwarenessState: awareness.getLocalState() ?? {},\n\t\tlog,\n\t\tonStatusChange,\n\t\tprocessAwarenessUpdate: ( state: AwarenessState ) =>\n\t\t\tprocessAwarenessUpdate( state, awareness ),\n\t\tprocessDocUpdate: ( update: SyncUpdate ) =>\n\t\t\tprocessDocUpdate( update, doc, onSync ),\n\t\troom,\n\t\tunregister,\n\t\tupdateQueue,\n\t};\n\n\tdoc.on( 'updateV2', onDocUpdate );\n\tawareness.on( 'change', onAwarenessUpdate );\n\troomStates.set( room, roomState );\n\n\tif ( ! areListenersRegistered ) {\n\t\twindow.addEventListener( 'beforeunload', handleBeforeUnload );\n\t\twindow.addEventListener( 'pagehide', handlePageHide );\n\t\tdocument.addEventListener( 'visibilitychange', handleVisibilityChange );\n\t\tareListenersRegistered = true;\n\t}\n\n\tif ( ! isPolling ) {\n\t\tpoll();\n\t}\n}\n\nfunction unregisterRoom(\n\troom: string,\n\t{ sendDisconnectSignal = true }: { sendDisconnectSignal?: boolean } = {}\n): void {\n\tconst state = roomStates.get( room );\n\tif ( state ) {\n\t\tif ( sendDisconnectSignal ) {\n\t\t\t// Send a disconnect signal so the server removes this client's\n\t\t\t// awareness entry immediately instead of waiting for the timeout.\n\t\t\tconst rooms = [\n\t\t\t\t{\n\t\t\t\t\tafter: 0,\n\t\t\t\t\tawareness: null,\n\t\t\t\t\tclient_id: state.clientId,\n\t\t\t\t\troom,\n\t\t\t\t\tupdates: [],\n\t\t\t\t},\n\t\t\t];\n\n\t\t\tpostSyncUpdateNonBlocking( { rooms } );\n\t\t}\n\n\t\tstate.unregister();\n\t\troomStates.delete( room );\n\t}\n\n\tif ( 0 === roomStates.size && areListenersRegistered ) {\n\t\twindow.removeEventListener( 'beforeunload', handleBeforeUnload );\n\t\twindow.removeEventListener( 'pagehide', handlePageHide );\n\t\tdocument.removeEventListener(\n\t\t\t'visibilitychange',\n\t\t\thandleVisibilityChange\n\t\t);\n\t\tareListenersRegistered = false;\n\t\thasCheckedConnectionLimit = false;\n\t\tconsecutiveFailures = 0;\n\t}\n}\n\n/**\n * Immediately retry the sync connection by cancelling any pending\n * timeout and triggering a new poll. If the retry fails, the next\n * auto-retry waits 15s (MANUAL_RETRY_INTERVAL_MS) instead of the\n * usual 30s, then falls back to 30s for subsequent auto-retries.\n */\nfunction retryNow(): void {\n\tisManualRetry = true;\n\n\tif ( pollingTimeoutId ) {\n\t\tclearTimeout( pollingTimeoutId );\n\t\tpollingTimeoutId = null;\n\t\tpoll();\n\t}\n}\n\nexport const pollingManager: PollingManager = {\n\tregisterRoom,\n\tretryNow,\n\tunregisterRoom,\n};\n"],
  "mappings": "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",
  "names": []
}
