From 4caceedcffeb44d1e637fe64ce9a509e9a0db5b8 Mon Sep 17 00:00:00 2001 From: Jan Kassens Date: Mon, 17 Apr 2023 16:24:33 -0400 Subject: [PATCH] Revert "Clean up discrete event replaying (#26558)" This reverts commit 9cfba0f6ecc15a342ef184552742c5db6c7f2d3e. --- .../src/events/ReactDOMEventListener.js | 2 +- .../src/events/ReactDOMEventReplaying.js | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/packages/react-dom-bindings/src/events/ReactDOMEventListener.js b/packages/react-dom-bindings/src/events/ReactDOMEventListener.js index 70cec7fa0e608..eef07fddf39ee 100644 --- a/packages/react-dom-bindings/src/events/ReactDOMEventListener.js +++ b/packages/react-dom-bindings/src/events/ReactDOMEventListener.js @@ -57,7 +57,7 @@ import {isRootDehydrated} from 'react-reconciler/src/ReactFiberShellHydration'; const {ReactCurrentBatchConfig} = ReactSharedInternals; // TODO: can we stop exporting these? -let _enabled: boolean = true; +export let _enabled: boolean = true; // This is exported in FB builds for use by legacy FB layer infra. // We'd like to remove this but it's not clear if this is safe. diff --git a/packages/react-dom-bindings/src/events/ReactDOMEventReplaying.js b/packages/react-dom-bindings/src/events/ReactDOMEventReplaying.js index 59fc3a8a61811..3e91e174c4fd5 100644 --- a/packages/react-dom-bindings/src/events/ReactDOMEventReplaying.js +++ b/packages/react-dom-bindings/src/events/ReactDOMEventReplaying.js @@ -60,6 +60,11 @@ type QueuedReplayableEvent = { let hasScheduledReplayAttempt = false; +// The queue of discrete events to be replayed. +const queuedDiscreteEvents: Array = []; + +// Indicates if any continuous event targets are non-null for early bailout. +const hasAnyQueuedContinuousEvents: boolean = false; // The last of each continuous event type. We only need to replay the last one // if the last target was dehydrated. let queuedFocus: null | QueuedReplayableEvent = null; @@ -77,6 +82,14 @@ type QueuedHydrationTarget = { }; const queuedExplicitHydrationTargets: Array = []; +export function hasQueuedDiscreteEvents(): boolean { + return queuedDiscreteEvents.length > 0; +} + +export function hasQueuedContinuousEvents(): boolean { + return hasAnyQueuedContinuousEvents; +} + const discreteReplayableEvents: Array = [ 'mousedown', 'mouseup', @@ -433,6 +446,21 @@ function scheduleCallbackIfUnblocked( export function retryIfBlockedOn( unblocked: Container | SuspenseInstance, ): void { + // Mark anything that was blocked on this as no longer blocked + // and eligible for a replay. + if (queuedDiscreteEvents.length > 0) { + scheduleCallbackIfUnblocked(queuedDiscreteEvents[0], unblocked); + // This is a exponential search for each boundary that commits. I think it's + // worth it because we expect very few discrete events to queue up and once + // we are actually fully unblocked it will be fast to replay them. + for (let i = 1; i < queuedDiscreteEvents.length; i++) { + const queuedEvent = queuedDiscreteEvents[i]; + if (queuedEvent.blockedOn === unblocked) { + queuedEvent.blockedOn = null; + } + } + } + if (queuedFocus !== null) { scheduleCallbackIfUnblocked(queuedFocus, unblocked); }