Skip to content

Commit 0a52770

Browse files
authored
Event Replaying (#16725)
* Add Event Replaying Infra * Wire up Roots and Suspense boundaries, to retry events, after they commit * Replay discrete events in order in a separate scheduler callback * Add continuous events These events only replay their last target if the target is not yet hydrated. That way we don't have to wait for a previously hovered boundary before invoking the current target. * Enable tests from before These tests were written with replaying in mind and now we can properly enable them. * Unify replaying and dispatching * Mark system flags as a replay and pass to legacy events That way we can check if this is a replay and therefore needs a special case. One such special case is "mouseover" where we check the relatedTarget. * Eagerly listen to all replayable events To minimize breakages in a minor, I only do this for the new root APIs since replaying only matters there anyway. Only if hydrating. For Flare, I have to attach all active listeners since the current system has one DOM listener for each. In a follow up I plan on optimizing that by only attaching one if there's at least one active listener which would allow us to start with only passive and then upgrade. * Desperate attempt to save bytese * Add test for mouseover replaying We need to check if the "relatedTarget" is mounted due to how the old event system dispatches from the "out" event. * Fix for nested boundaries and suspense in root container This is a follow up to #16673 which didn't have a test because it wasn't observable yet. This shows that it had a bug. * Rename RESPONDER_EVENT_SYSTEM to PLUGIN_EVENT_SYSTEM
1 parent a87d245 commit 0a52770

25 files changed

+1270
-131
lines changed

packages/legacy-events/EventPluginHub.js

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import type {ReactSyntheticEvent} from './ReactSyntheticEventType';
2222
import type {Fiber} from 'react-reconciler/src/ReactFiber';
2323
import type {AnyNativeEvent} from './PluginModuleType';
2424
import type {TopLevelType} from './TopLevelEventTypes';
25+
import type {EventSystemFlags} from 'legacy-events/EventSystemFlags';
2526

2627
function isInteractive(tag) {
2728
return (
@@ -131,6 +132,7 @@ export function getListener(inst: Fiber, registrationName: string) {
131132
*/
132133
function extractPluginEvents(
133134
topLevelType: TopLevelType,
135+
eventSystemFlags: EventSystemFlags,
134136
targetInst: null | Fiber,
135137
nativeEvent: AnyNativeEvent,
136138
nativeEventTarget: EventTarget,
@@ -142,6 +144,7 @@ function extractPluginEvents(
142144
if (possiblePlugin) {
143145
const extractedEvents = possiblePlugin.extractEvents(
144146
topLevelType,
147+
eventSystemFlags,
145148
targetInst,
146149
nativeEvent,
147150
nativeEventTarget,
@@ -156,12 +159,14 @@ function extractPluginEvents(
156159

157160
export function runExtractedPluginEventsInBatch(
158161
topLevelType: TopLevelType,
162+
eventSystemFlags: EventSystemFlags,
159163
targetInst: null | Fiber,
160164
nativeEvent: AnyNativeEvent,
161165
nativeEventTarget: EventTarget,
162166
) {
163167
const events = extractPluginEvents(
164168
topLevelType,
169+
eventSystemFlags,
165170
targetInst,
166171
nativeEvent,
167172
nativeEventTarget,

packages/legacy-events/EventSystemFlags.js

+1
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ export const RESPONDER_EVENT_SYSTEM = 1 << 1;
1414
export const IS_PASSIVE = 1 << 2;
1515
export const IS_ACTIVE = 1 << 3;
1616
export const PASSIVE_NOT_SUPPORTED = 1 << 4;
17+
export const IS_REPLAYED = 1 << 5;

packages/legacy-events/PluginModuleType.js

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {
1313
ReactSyntheticEvent,
1414
} from './ReactSyntheticEventType';
1515
import type {TopLevelType} from './TopLevelEventTypes';
16+
import type {EventSystemFlags} from 'legacy-events/EventSystemFlags';
1617

1718
export type EventTypes = {[key: string]: DispatchConfig};
1819

@@ -24,6 +25,7 @@ export type PluginModule<NativeEvent> = {
2425
eventTypes: EventTypes,
2526
extractEvents: (
2627
topLevelType: TopLevelType,
28+
eventSystemFlags: EventSystemFlags,
2729
targetInst: null | Fiber,
2830
nativeTarget: NativeEvent,
2931
nativeEventTarget: EventTarget,

packages/legacy-events/ResponderEventPlugin.js

+1
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@ const ResponderEventPlugin = {
504504
*/
505505
extractEvents: function(
506506
topLevelType,
507+
eventSystemFlags,
507508
targetInst,
508509
nativeEvent,
509510
nativeEventTarget,

packages/legacy-events/__tests__/ResponderEventPlugin-test.internal.js

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
'use strict';
1111

1212
const {HostComponent} = require('shared/ReactWorkTags');
13+
const {PLUGIN_EVENT_SYSTEM} = require('legacy-events/EventSystemFlags');
1314

1415
let EventBatching;
1516
let EventPluginUtils;
@@ -313,6 +314,7 @@ const run = function(config, hierarchyConfig, nativeEventConfig) {
313314
// Trigger the event
314315
const extractedEvents = ResponderEventPlugin.extractEvents(
315316
nativeEventConfig.topLevelType,
317+
PLUGIN_EVENT_SYSTEM,
316318
nativeEventConfig.targetInst,
317319
nativeEventConfig.nativeEvent,
318320
nativeEventConfig.target,

0 commit comments

Comments
 (0)