-
Notifications
You must be signed in to change notification settings - Fork 47.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fabric HostComponent as EventEmitter: support add/removeEventListener (unstable only) #23386
Changes from 16 commits
434adcc
fc44017
b852035
cbe9457
a85bdf5
4dbbf5a
f5c518d
f4b835a
4ce290c
a1cd472
c135e37
ea15053
39a0451
7d5ecac
dd47e87
9f22e9c
5045281
15fc32a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,13 +10,15 @@ | |
import type {AnyNativeEvent} from './legacy-events/PluginModuleType'; | ||
import type {TopLevelType} from './legacy-events/TopLevelEventTypes'; | ||
import SyntheticEvent from './legacy-events/SyntheticEvent'; | ||
import type {PropagationPhases} from './legacy-events/PropagationPhases'; | ||
|
||
// Module provided by RN: | ||
import {ReactNativeViewConfigRegistry} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface'; | ||
import accumulateInto from './legacy-events/accumulateInto'; | ||
import getListener from './ReactNativeGetListener'; | ||
import getListeners from './ReactNativeGetListeners'; | ||
import forEachAccumulated from './legacy-events/forEachAccumulated'; | ||
import {HostComponent} from 'react-reconciler/src/ReactWorkTags'; | ||
import isArray from 'shared/isArray'; | ||
|
||
const { | ||
customBubblingEventTypes, | ||
|
@@ -26,10 +28,37 @@ const { | |
// Start of inline: the below functions were inlined from | ||
// EventPropagator.js, as they deviated from ReactDOM's newer | ||
// implementations. | ||
function listenerAtPhase(inst, event, propagationPhase: PropagationPhases) { | ||
function listenersAtPhase(inst, event, propagationPhase: PropagationPhases) { | ||
const registrationName = | ||
event.dispatchConfig.phasedRegistrationNames[propagationPhase]; | ||
return getListener(inst, registrationName); | ||
return getListeners(inst, registrationName, propagationPhase, true); | ||
} | ||
|
||
function accumulateListenersAndInstances(inst, event, listeners) { | ||
const listenersLength = listeners | ||
? isArray(listeners) | ||
? listeners.length | ||
: 1 | ||
: 0; | ||
if (listenersLength > 0) { | ||
event._dispatchListeners = accumulateInto( | ||
event._dispatchListeners, | ||
listeners, | ||
); | ||
|
||
// Avoid allocating additional arrays here | ||
if (event._dispatchInstances == null && listenersLength === 1) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this stuff seems a bit convoluted: the goal is to avoid array allocation at all costs since this is a very hot path. See |
||
event._dispatchInstances = inst; | ||
} else { | ||
event._dispatchInstances = event._dispatchInstances || []; | ||
if (!isArray(event._dispatchInstances)) { | ||
event._dispatchInstances = [event._dispatchInstances]; | ||
} | ||
for (let i = 0; i < listenersLength; i++) { | ||
event._dispatchInstances.push(inst); | ||
} | ||
} | ||
} | ||
} | ||
|
||
function accumulateDirectionalDispatches(inst, phase, event) { | ||
|
@@ -38,14 +67,8 @@ function accumulateDirectionalDispatches(inst, phase, event) { | |
console.error('Dispatching inst must not be null'); | ||
} | ||
} | ||
const listener = listenerAtPhase(inst, event, phase); | ||
if (listener) { | ||
event._dispatchListeners = accumulateInto( | ||
event._dispatchListeners, | ||
listener, | ||
); | ||
event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); | ||
} | ||
const listeners = listenersAtPhase(inst, event, phase); | ||
accumulateListenersAndInstances(inst, event, listeners); | ||
} | ||
|
||
function getParent(inst) { | ||
|
@@ -103,14 +126,8 @@ function accumulateDispatches( | |
): void { | ||
if (inst && event && event.dispatchConfig.registrationName) { | ||
const registrationName = event.dispatchConfig.registrationName; | ||
const listener = getListener(inst, registrationName); | ||
if (listener) { | ||
event._dispatchListeners = accumulateInto( | ||
event._dispatchListeners, | ||
listener, | ||
); | ||
event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); | ||
} | ||
const listeners = getListeners(inst, registrationName, 'bubbled', false); | ||
accumulateListenersAndInstances(inst, event, listeners); | ||
} | ||
} | ||
|
||
|
@@ -130,7 +147,6 @@ function accumulateDirectDispatches(events: ?(Array<Object> | Object)) { | |
} | ||
|
||
// End of inline | ||
type PropagationPhases = 'bubbled' | 'captured'; | ||
|
||
const ReactNativeBridgeEventPlugin = { | ||
eventTypes: {}, | ||
|
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be optimized, but (since the API is unstable, not used at all, and this change is primarily for prototyping) I would prefer not spending too much time on this atm until we we've validated the usefulness of these APIs