@samitouri / QOS-React-1 / commits / 0418c8a8b6

[RN] Move new event dispatching pipeline to RN (#36266)

## Summary We found a bug in the logic in https://github.com/facebook/react/pull/36253 and we realized it's very inconvenient to iterate on the implementation when it's in this repository, as we're forced to then synchronize it to RN to test changes. This moves the entire implementation to RN for simplicity and also to simplify some clean ups in the future (like removing `top` prefixes from native event types). ## How did you test this change? The changes are gated. Will test e2e in RN.

Rubén Norte committed Apr 14, 2026 at 18:10 UTC 0418c8a8b61a2328fd8e9105a6f49093ee91b436
5 files changed +6 -642
packages/react-native-renderer/src/ReactFabricEventEmitter.js
+2 -40
@@ -30,21 +30,13 @@ import {runEventsInBatch} from './legacy-events/EventBatching';
30
31 import {
32 RawEventEmitter,
33 - ReactNativeViewConfigRegistry,
34 - dispatchTrustedEvent,
35 - setEventInitTimeStamp,
33 + dispatchNativeEvent,
34 } from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
35 import {getPublicInstance} from './ReactFiberConfigFabric';
38 -import LegacySyntheticEvent from './LegacySyntheticEvent';
39 -import {topLevelTypeToEventName} from './ReactNativeEventTypeMapping';
40 -import {processResponderEvent} from './ReactNativeResponder';
36 import {enableNativeEventTargetEventDispatching} from './ReactNativeFeatureFlags';
37
38 export {getListener, registrationNameModules as registrationNames};
39
45 -const {customBubblingEventTypes, customDirectEventTypes} =
46 - ReactNativeViewConfigRegistry;
47 -
40 /**
41 * Allows registered plugins an opportunity to extract events from top-level
42 * native browser events.
@@ -143,38 +135,8 @@ export function dispatchEvent(
135 RawEventEmitter.emit('*', event);
136
137 if (enableNativeEventTargetEventDispatching()) {
146 - // Process responder events before normal event dispatch.
147 - // This handles touch negotiation (onStartShouldSetResponder, etc.)
148 - processResponderEvent(topLevelType, targetFiber, nativeEvent);
149 -
150 - // New EventTarget-based dispatch path
138 if (eventTarget != null) {
152 - const bubbleDispatchConfig = customBubblingEventTypes[topLevelType];
153 - const directDispatchConfig = customDirectEventTypes[topLevelType];
154 - const bubbles = bubbleDispatchConfig != null;
155 -
156 - // Skip events that are not registered in the view config
157 - if (bubbles || directDispatchConfig != null) {
158 - const eventName = topLevelTypeToEventName(topLevelType);
159 - const options = {
160 - bubbles,
161 - cancelable: true,
162 - };
163 - // Preserve the native event timestamp for backwards compatibility.
164 - // The legacy SyntheticEvent system used nativeEvent.timeStamp || nativeEvent.timestamp.
165 - const nativeTimestamp =
166 - nativeEvent.timeStamp ?? nativeEvent.timestamp;
167 - if (typeof nativeTimestamp === 'number') {
168 - setEventInitTimeStamp(options, nativeTimestamp);
169 - }
170 - const syntheticEvent = new LegacySyntheticEvent(
171 - eventName,
172 - options,
173 - nativeEvent,
174 - );
175 - // $FlowFixMe[incompatible-call]
176 - dispatchTrustedEvent(eventTarget, syntheticEvent);
177 - }
139 + dispatchNativeEvent(eventTarget, topLevelType, nativeEvent);
140 }
141 } else {
142 // Heritage plugin event system
packages/react-native-renderer/src/ReactNativeEventTypeMapping.js deleted
-24
@@ -1,24 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -/**
11 - * Converts a topLevelType (e.g., "topPress") to a DOM event name (e.g., "press").
12 - * Strips the "top" prefix and lowercases the result.
13 - */
14 -export function topLevelTypeToEventName(topLevelType: string): string {
15 - const fourthChar = topLevelType.charCodeAt(3);
16 - if (
17 - topLevelType.startsWith('top') &&
18 - fourthChar >= 65 /* A */ &&
19 - fourthChar <= 90 /* Z */
20 - ) {
21 - return topLevelType.slice(3).toLowerCase();
22 - }
23 - return topLevelType;
24 -}
packages/react-native-renderer/src/ReactNativeResponder.js deleted
-572
@@ -1,572 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -/**
11 - * Responder System:
12 - * -----------------
13 - *
14 - * - A global, solitary "interaction lock" on a view.
15 - * - If a node becomes the responder, it should convey visual feedback
16 - * immediately to indicate so, either by highlighting or moving accordingly.
17 - * - To be the responder means that touches are exclusively important to that
18 - * responder view, and no other view.
19 - * - While touches are still occurring, the responder lock can be transferred to
20 - * a new view, but only to increasingly "higher" views (meaning ancestors of
21 - * the current responder).
22 - *
23 - * Responder being granted:
24 - * ------------------------
25 - *
26 - * - Touch starts, moves, and scrolls can cause a view to become the responder.
27 - * - We dispatch `startShouldSetResponder`/`moveShouldSetResponder` as bubbling
28 - * EventTarget events to the "appropriate place".
29 - * - If nothing is currently the responder, the "appropriate place" is the
30 - * initiating event's target.
31 - * - If something *is* already the responder, the "appropriate place" is the
32 - * first common ancestor of the event target and the current responder.
33 - * - Some negotiation happens: See the timing diagram below.
34 - * - Scrolled views automatically become responder. The reasoning is that a
35 - * platform scroll view that isn't built on top of the responder system has
36 - * begun scrolling, and the active responder must now be notified that the
37 - * interaction is no longer locked to it — the system has taken over.
38 - *
39 - * Responder being released:
40 - * -------------------------
41 - *
42 - * As soon as no more touches that *started* inside of descendants of the
43 - * *current* responder remain active, an `onResponderRelease` event is
44 - * dispatched to the current responder, and the responder lock is released.
45 - *
46 - * Direct dispatch (no EventTarget):
47 - * ----------------------------------
48 - *
49 - * Responder events bypass EventTarget entirely. Handlers are read directly
50 - * from `canonical.currentProps` at dispatch time — no commit-time registration,
51 - * no wrappers, no addEventListener.
52 - *
53 - * Negotiation walks the fiber tree manually (capture then bubble phase) using
54 - * `getParent()`. The first handler returning `true` wins.
55 - *
56 - * Lifecycle events call the handler directly and inspect return values:
57 - * - `onResponderGrant` returning `true` → block native responder
58 - * - `onResponderTerminationRequest` returning `false` → refuse termination
59 - *
60 - *
61 - * Negotiation Performed
62 - * +-----------------------+
63 - * / \
64 - * Process low level events to + Current Responder + wantsResponder
65 - * determine who to perform negot-| (if any exists at all) |
66 - * iation/transition | Otherwise just pass through|
67 - * -------------------------------+----------------------------+------------------+
68 - * Bubble to find first ID | |
69 - * to return true:wantsResponder | |
70 - * | |
71 - * +-------------+ | |
72 - * | onTouchStart| | |
73 - * +------+------+ none | |
74 - * | return| |
75 - * +-----------v-------------+true| +------------------------+ |
76 - * |onStartShouldSetResponder|----->|onResponderStart (cur) |<-----------+
77 - * +-----------+-------------+ | +------------------------+ | |
78 - * | | | +--------+-------+
79 - * | returned true for| false:REJECT +-------->|onResponderReject
80 - * | wantsResponder | | | +----------------+
81 - * | (now attempt | +------------------+-----+ |
82 - * | handoff) | | onResponder | |
83 - * +------------------->| TerminationRequest| |
84 - * | +------------------+-----+ |
85 - * | | | +----------------+
86 - * | true:GRANT +-------->|onResponderGrant|
87 - * | | +--------+-------+
88 - * | +------------------------+ | |
89 - * | | onResponderTerminate |<-----------+
90 - * | +------------------+-----+ |
91 - * | | | +----------------+
92 - * | +-------->|onResponderStart|
93 - * | | +----------------+
94 - * Bubble to find first ID | |
95 - * to return true:wantsResponder | |
96 - * | |
97 - * +-------------+ | |
98 - * | onTouchMove | | |
99 - * +------+------+ none | |
100 - * | return| |
101 - * +-----------v-------------+true| +------------------------+ |
102 - * |onMoveShouldSetResponder |----->|onResponderMove (cur) |<-----------+
103 - * +-----------+-------------+ | +------------------------+ | |
104 - * | | | +--------+-------+
105 - * | returned true for| false:REJECT +-------->|onResponderReject
106 - * | wantsResponder | | | +----------------+
107 - * | (now attempt | +------------------+-----+ |
108 - * | handoff) | | onResponder | |
109 - * +------------------->| TerminationRequest| |
110 - * | +------------------+-----+ |
111 - * | | | +----------------+
112 - * | true:GRANT +-------->|onResponderGrant|
113 - * | | +--------+-------+
114 - * | +------------------------+ | |
115 - * | | onResponderTerminate |<-----------+
116 - * | +------------------+-----+ |
117 - * | | | +----------------+
118 - * | +-------->|onResponderMove |
119 - * | | +----------------+
120 - * | |
121 - * | |
122 - * Some active touch started| |
123 - * inside current responder | +------------------------+ |
124 - * +------------------------->| onResponderEnd | |
125 - * | | +------------------------+ |
126 - * +---+---------+ | |
127 - * | onTouchEnd | | |
128 - * +---+---------+ | |
129 - * | | +------------------------+ |
130 - * +------------------------->| onResponderEnd | |
131 - * No active touches started| +-----------+------------+ |
132 - * inside current responder | | |
133 - * | v |
134 - * | +------------------------+ |
135 - * | | onResponderRelease | |
136 - * | +------------------------+ |
137 - * | |
138 - * + +
139 - */
140 -
141 -import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
142 -
143 -import LegacySyntheticEvent from './LegacySyntheticEvent';
144 -import ResponderTouchHistoryStore from './legacy-events/ResponderTouchHistoryStore';
145 -import {HostComponent} from 'react-reconciler/src/ReactWorkTags';
146 -import {getInstanceFromNode} from './ReactFabricComponentTree';
147 -
148 -// The currently active responder (tracked as a fiber)
149 -let responderFiber: Fiber | null = null;
150 -
151 -/**
152 - * Count of current touches. A textInput should become responder iff the
153 - * selection changes while there is a touch on the screen.
154 - */
155 -let trackedTouchCount = 0;
156 -
157 -function isStartish(topLevelType: string): boolean {
158 - return topLevelType === 'topTouchStart';
159 -}
160 -
161 -function isMoveish(topLevelType: string): boolean {
162 - return topLevelType === 'topTouchMove';
163 -}
164 -
165 -function isEndish(topLevelType: string): boolean {
166 - return topLevelType === 'topTouchEnd' || topLevelType === 'topTouchCancel';
167 -}
168 -
169 -/**
170 - * Walk up the fiber tree, skipping non-HostComponent fibers.
171 - */
172 -function getParent(inst: Fiber): Fiber | null {
173 - let fiber = inst.return;
174 - while (fiber != null) {
175 - if (fiber.tag === HostComponent) {
176 - return fiber;
177 - }
178 - fiber = fiber.return;
179 - }
180 - return null;
181 -}
182 -
183 -/**
184 - * Return the lowest common ancestor of A and B, or null if they are in
185 - * different trees.
186 - */
187 -function getLowestCommonAncestor(instA: Fiber, instB: Fiber): Fiber | null {
188 - let depthA = 0;
189 - for (let tempA: Fiber | null = instA; tempA; tempA = getParent(tempA)) {
190 - depthA++;
191 - }
192 - let depthB = 0;
193 - for (let tempB: Fiber | null = instB; tempB; tempB = getParent(tempB)) {
194 - depthB++;
195 - }
196 -
197 - let a = instA;
198 - let b = instB;
199 -
200 - // If A is deeper, crawl up.
201 - while (depthA - depthB > 0) {
202 - a = (getParent(a): any);
203 - depthA--;
204 - }
205 -
206 - // If B is deeper, crawl up.
207 - while (depthB - depthA > 0) {
208 - b = (getParent(b): any);
209 - depthB--;
210 - }
211 -
212 - // Walk in lockstep until we find a match.
213 - let depth = depthA;
214 - while (depth--) {
215 - if (a === b || a === b.alternate) {
216 - return a;
217 - }
218 - a = (getParent(a): any);
219 - b = (getParent(b): any);
220 - }
221 - return null;
222 -}
223 -
224 -/**
225 - * Return true if A is an ancestor of B.
226 - */
227 -function isAncestor(instA: Fiber, instB: Fiber | null): boolean {
228 - let current = instB;
229 - while (current != null) {
230 - if (instA === current || instA === current.alternate) {
231 - return true;
232 - }
233 - current = getParent(current);
234 - }
235 - return false;
236 -}
237 -
238 -function changeResponder(
239 - nextResponderFiber: Fiber | null,
240 - blockNativeResponder: boolean,
241 -): void {
242 - const oldResponderFiber = responderFiber;
243 - responderFiber = nextResponderFiber;
244 -
245 - // Notify the native side about responder changes so native gestures
246 - // (e.g. ScrollView scroll) can defer to JS.
247 - if (oldResponderFiber != null && oldResponderFiber.stateNode != null) {
248 - nativeFabricUIManager.setIsJSResponder(
249 - oldResponderFiber.stateNode.node,
250 - false,
251 - blockNativeResponder,
252 - );
253 - }
254 - if (nextResponderFiber != null && nextResponderFiber.stateNode != null) {
255 - nativeFabricUIManager.setIsJSResponder(
256 - nextResponderFiber.stateNode.node,
257 - true,
258 - blockNativeResponder,
259 - );
260 - }
261 -}
262 -
263 -/**
264 - * Determine the negotiation event name for a given topLevelType.
265 - */
266 -function getShouldSetEventName(topLevelType: string): string {
267 - if (isStartish(topLevelType)) {
268 - return 'startShouldSetResponder';
269 - } else if (isMoveish(topLevelType)) {
270 - return 'moveShouldSetResponder';
271 - } else if (topLevelType === 'topSelectionChange') {
272 - return 'selectionChangeShouldSetResponder';
273 - } else {
274 - return 'scrollShouldSetResponder';
275 - }
276 -}
277 -
278 -/**
279 - * Run negotiation by walking the fiber tree directly. Performs capture phase
280 - * (root→target) then bubble phase (target→root), calling handlers from
281 - * `canonical.currentProps`. The first handler that returns `true` wins.
282 - *
283 - * The dispatch target is determined as follows:
284 - * - If no responder exists, dispatch from the event target (full tree).
285 - * - If a responder exists, dispatch from the lowest common ancestor (LCA)
286 - * of the responder and the target — only ancestors can claim.
287 - * - If the LCA is the current responder itself, skip it (don't re-negotiate
288 - * with yourself) and dispatch from the parent.
289 - *
290 - * @return {Fiber | null} The fiber that claimed the responder, or null.
291 - */
292 -function negotiateResponder(
293 - targetFiber: Fiber,
294 - topLevelType: string,
295 - nativeEvent: {[string]: mixed},
296 -): Fiber | null {
297 - const shouldSetEventName = getShouldSetEventName(topLevelType);
298 -
299 - // Determine the negotiation dispatch target
300 - let negotiationFiber;
301 - let skipSelf = false;
302 - if (responderFiber == null) {
303 - negotiationFiber = targetFiber;
304 - } else {
305 - negotiationFiber = getLowestCommonAncestor(responderFiber, targetFiber);
306 - if (negotiationFiber == null) {
307 - return null;
308 - }
309 - if (negotiationFiber === responderFiber) {
310 - skipSelf = true;
311 - }
312 - }
313 -
314 - const dispatchFiber = skipSelf
315 - ? getParent(negotiationFiber)
316 - : negotiationFiber;
317 - if (dispatchFiber == null) {
318 - return null;
319 - }
320 -
321 - // Build ancestor path (root to dispatch fiber)
322 - const path: Array<Fiber> = [];
323 - let fiber: Fiber | null = dispatchFiber;
324 - while (fiber != null) {
325 - path.unshift(fiber);
326 - fiber = getParent(fiber);
327 - }
328 -
329 - const event = new LegacySyntheticEvent(
330 - shouldSetEventName,
331 - {bubbles: true, cancelable: true},
332 - nativeEvent,
333 - );
334 - // $FlowFixMe[prop-missing] touchHistory is a responder-specific extension not in the Event type
335 - event.touchHistory = ResponderTouchHistoryStore.touchHistory;
336 -
337 - // Derive prop names from event name
338 - const bubblePropName =
339 - 'on' +
340 - shouldSetEventName.charAt(0).toUpperCase() +
341 - shouldSetEventName.slice(1);
342 - const capturePropName = bubblePropName + 'Capture';
343 -
344 - // Capture phase: root → target
345 - for (let i = 0; i < path.length; i++) {
346 - const stateNode = path[i].stateNode;
347 - if (stateNode == null) {
348 - continue;
349 - }
350 - const handler = stateNode.canonical.currentProps[capturePropName];
351 - if (typeof handler === 'function' && handler(event) === true) {
352 - return path[i];
353 - }
354 - }
355 -
356 - // Bubble phase: target → root
357 - for (let i = path.length - 1; i >= 0; i--) {
358 - const stateNode = path[i].stateNode;
359 - if (stateNode == null) {
360 - continue;
361 - }
362 - const handler = stateNode.canonical.currentProps[bubblePropName];
363 - if (typeof handler === 'function' && handler(event) === true) {
364 - return path[i];
365 - }
366 - }
367 -
368 - return null;
369 -}
370 -
371 -/**
372 - * Dispatch a lifecycle responder event by calling the handler directly from
373 - * `canonical.currentProps`. Returns the handler's return value so callers can
374 - * inspect it (e.g. `onResponderGrant` returning `true` to block native).
375 - */
376 -function dispatchResponderEvent(
377 - fiber: Fiber,
378 - eventName: string,
379 - nativeEvent: {[string]: mixed},
380 -): mixed {
381 - const stateNode = fiber.stateNode;
382 - if (stateNode == null) {
383 - return undefined;
384 - }
385 -
386 - const propName =
387 - 'on' + eventName.charAt(0).toUpperCase() + eventName.slice(1);
388 - const handler = stateNode.canonical.currentProps[propName];
389 - if (typeof handler !== 'function') {
390 - return undefined;
391 - }
392 -
393 - const event = new LegacySyntheticEvent(
394 - eventName,
395 - {bubbles: false, cancelable: true},
396 - nativeEvent,
397 - );
398 - // $FlowFixMe[prop-missing] touchHistory is a responder-specific extension not in the Event type
399 - event.touchHistory = ResponderTouchHistoryStore.touchHistory;
400 -
401 - return handler(event);
402 -}
403 -
404 -/**
405 - * A transfer is a negotiation between a currently set responder and the next
406 - * element to claim responder status. Any start event could trigger a transfer
407 - * of responderFiber. Any move event could trigger a transfer.
408 - *
409 - * @return {boolean} True if a transfer of responder could possibly occur.
410 - */
411 -function canTriggerTransfer(
412 - topLevelType: string,
413 - targetFiber: Fiber | null,
414 - nativeEvent: {[string]: mixed},
415 -): boolean {
416 - return (
417 - targetFiber != null &&
418 - ((topLevelType === 'topScroll' && !nativeEvent.responderIgnoreScroll) ||
419 - (trackedTouchCount > 0 && topLevelType === 'topSelectionChange') ||
420 - isStartish(topLevelType) ||
421 - isMoveish(topLevelType))
422 - );
423 -}
424 -
425 -/**
426 - * Returns whether or not this touch end event makes it such that there are no
427 - * longer any touches that started inside of the current `responderFiber`.
428 - *
429 - * @param {NativeEvent} nativeEvent Native touch end event.
430 - * @return {boolean} Whether or not this touch end event ends the responder.
431 - */
432 -function noResponderTouches(nativeEvent: {[string]: mixed}): boolean {
433 - const touches = (nativeEvent.touches: any);
434 - if (!touches || touches.length === 0) {
435 - return true;
436 - }
437 - for (let i = 0; i < touches.length; i++) {
438 - const activeTouch = touches[i];
439 - const target = activeTouch.target;
440 - if (target !== null && target !== undefined && target !== 0) {
441 - // Is the original touch location inside of the current responder?
442 - const targetInst = getInstanceFromNode(target);
443 - if (
444 - responderFiber != null &&
445 - targetInst != null &&
446 - isAncestor(responderFiber, targetInst)
447 - ) {
448 - return false;
449 - }
450 - }
451 - }
452 - return true;
453 -}
454 -
455 -/**
456 - * Process a native event through the responder system.
457 - * Called from ReactFabricEventEmitter when the flag is enabled.
458 - */
459 -export function processResponderEvent(
460 - topLevelType: string,
461 - targetFiber: Fiber | null,
462 - nativeEvent: {[string]: mixed},
463 -): void {
464 - // Track touch count
465 - if (isStartish(topLevelType)) {
466 - trackedTouchCount += 1;
467 - } else if (isEndish(topLevelType)) {
468 - if (trackedTouchCount >= 0) {
469 - trackedTouchCount -= 1;
470 - } else {
471 - if (__DEV__) {
472 - console.warn(
473 - 'Ended a touch event which was not counted in `trackedTouchCount`.',
474 - );
475 - }
476 - return;
477 - }
478 - }
479 -
480 - ResponderTouchHistoryStore.recordTouchTrack(topLevelType, (nativeEvent: any));
481 -
482 - // Negotiation: determine if a new responder should be set
483 - if (
484 - canTriggerTransfer(topLevelType, targetFiber, nativeEvent) &&
485 - targetFiber != null
486 - ) {
487 - const wantsResponderFiber = negotiateResponder(
488 - targetFiber,
489 - topLevelType,
490 - nativeEvent,
491 - );
492 -
493 - if (wantsResponderFiber != null && wantsResponderFiber !== responderFiber) {
494 - // A new view wants to become responder.
495 - // onResponderGrant returning true means block native responder.
496 - const grantResult = dispatchResponderEvent(
497 - wantsResponderFiber,
498 - 'responderGrant',
499 - nativeEvent,
500 - );
501 - const blockNativeResponder = grantResult === true;
502 -
503 - if (responderFiber != null) {
504 - // Capture in a local to preserve Flow narrowing across function calls.
505 - const currentResponder = responderFiber;
506 - // Ask current responder if it will terminate.
507 - // onResponderTerminationRequest returning false means refuse.
508 - const terminationResult = dispatchResponderEvent(
509 - currentResponder,
510 - 'responderTerminationRequest',
511 - nativeEvent,
512 - );
513 - const shouldSwitch = terminationResult !== false;
514 -
515 - if (shouldSwitch) {
516 - dispatchResponderEvent(
517 - currentResponder,
518 - 'responderTerminate',
519 - nativeEvent,
520 - );
521 - changeResponder(wantsResponderFiber, blockNativeResponder);
522 - } else {
523 - dispatchResponderEvent(
524 - wantsResponderFiber,
525 - 'responderReject',
526 - nativeEvent,
527 - );
528 - }
529 - } else {
530 - changeResponder(wantsResponderFiber, blockNativeResponder);
531 - }
532 - }
533 - }
534 -
535 - // Responder may or may not have transferred on a new touch start/move.
536 - // Regardless, whoever is the responder after any potential transfer, we
537 - // direct all touch start/move/ends to them in the form of
538 - // `onResponderMove/Start/End`. These will be called for *every* additional
539 - // finger that move/start/end, dispatched directly to whoever is the
540 - // current responder at that moment, until the responder is "released".
541 - //
542 - // These multiple individual change touch events are always bookended
543 - // by `onResponderGrant`, and one of
544 - // (`onResponderRelease/onResponderTerminate`).
545 - if (responderFiber != null) {
546 - // Capture in a local to preserve Flow narrowing across function calls.
547 - const activeResponder = responderFiber;
548 - if (isStartish(topLevelType)) {
549 - dispatchResponderEvent(activeResponder, 'responderStart', nativeEvent);
550 - } else if (isMoveish(topLevelType)) {
551 - dispatchResponderEvent(activeResponder, 'responderMove', nativeEvent);
552 - } else if (isEndish(topLevelType)) {
553 - dispatchResponderEvent(activeResponder, 'responderEnd', nativeEvent);
554 -
555 - if (topLevelType === 'topTouchCancel') {
556 - dispatchResponderEvent(
557 - activeResponder,
558 - 'responderTerminate',
559 - nativeEvent,
560 - );
561 - changeResponder(null, false);
562 - } else if (noResponderTouches(nativeEvent)) {
563 - dispatchResponderEvent(
564 - activeResponder,
565 - 'responderRelease',
566 - nativeEvent,
567 - );
568 - changeResponder(null, false);
569 - }
570 - }
571 - }
572 -}
packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativePrivateInterface.js
+1
@@ -65,4 +65,5 @@ module.exports = {
65 get diffAttributePayloads() {
66 return require('./diffAttributePayloads').default;
67 },
68 + dispatchNativeEvent() {},
69 };
scripts/flow/react-native-host-hooks.js
+3 -6
@@ -204,13 +204,10 @@ declare module 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface'
204 declare export function getInternalInstanceHandleFromPublicInstance(
205 publicInstance: PublicInstance,
206 ): ?Object;
207 - declare export function dispatchTrustedEvent(
207 + declare export function dispatchNativeEvent(
208 target: EventTarget,
209 - event: Event,
210 - ): void;
211 - declare export function setEventInitTimeStamp(
212 - eventInit: {[string]: mixed},
213 - timeStamp: number,
209 + type: string,
210 + eventData: {[string]: mixed},
211 ): void;
212 declare export function createAttributePayload(
213 props: Object,