Add isUnique option in RawEvent and refactor EventQueue to use it (#50987)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50987

Changelog: [internal]

This adds a new `isUnique` option in `RawEvent` to determine if it's unique (whether it should be coalesced with other unique events of the same type and target).

This effectively makes `dispatchUniqueEvent` redundant, as we can use `dispatchEvent` with a `RawEvent` marked as unique.

This will allow us to fix the bug we found in the new tests for event dispatching, where non-unique events of a given type where being coalesced with non-unique events of the same type.

Reviewed By: javache

Differential Revision: D73849220

fbshipit-source-id: ce89623aee509071ab6a86654ee25d9614863a8a
This commit is contained in:
Rubén Norte
2025-04-29 10:13:09 -07:00
committed by Facebook GitHub Bot
parent 41de764c83
commit ab543d1ab1
3 changed files with 35 additions and 31 deletions
@@ -29,40 +29,40 @@ EventQueue::EventQueue(
void EventQueue::enqueueEvent(RawEvent&& rawEvent) const {
{
std::scoped_lock lock(queueMutex_);
eventQueue_.push_back(std::move(rawEvent));
if (rawEvent.isUnique) {
auto repeatedEvent = eventQueue_.rend();
for (auto it = eventQueue_.rbegin(); it != eventQueue_.rend(); ++it) {
if (it->type == rawEvent.type &&
it->eventTarget == rawEvent.eventTarget) {
repeatedEvent = it;
break;
} else if (it->eventTarget == rawEvent.eventTarget) {
// It is necessary to maintain order of different event types
// for the same target. If the same target has event types A1, B1
// in the event queue and event A2 occurs. A1 has to stay in the
// queue.
break;
}
}
if (repeatedEvent == eventQueue_.rend()) {
eventQueue_.push_back(std::move(rawEvent));
} else {
*repeatedEvent = std::move(rawEvent);
}
} else {
eventQueue_.push_back(std::move(rawEvent));
}
}
onEnqueue();
}
void EventQueue::enqueueUniqueEvent(RawEvent&& rawEvent) const {
{
std::scoped_lock lock(queueMutex_);
auto repeatedEvent = eventQueue_.rend();
for (auto it = eventQueue_.rbegin(); it != eventQueue_.rend(); ++it) {
if (it->type == rawEvent.type &&
it->eventTarget == rawEvent.eventTarget) {
repeatedEvent = it;
break;
} else if (it->eventTarget == rawEvent.eventTarget) {
// It is necessary to maintain order of different event types
// for the same target. If the same target has event types A1, B1
// in the event queue and event A2 occurs. A1 has to stay in the
// queue.
break;
}
}
if (repeatedEvent == eventQueue_.rend()) {
eventQueue_.push_back(std::move(rawEvent));
} else {
*repeatedEvent = std::move(rawEvent);
}
}
onEnqueue();
rawEvent.isUnique = true;
enqueueEvent(std::move(rawEvent));
}
void EventQueue::enqueueStateUpdate(StateUpdate&& stateUpdate) const {
@@ -13,10 +13,12 @@ RawEvent::RawEvent(
std::string type,
SharedEventPayload eventPayload,
SharedEventTarget eventTarget,
Category category)
Category category,
bool isUnique)
: type(std::move(type)),
eventPayload(std::move(eventPayload)),
eventTarget(std::move(eventTarget)),
category(category) {}
category(category),
isUnique(isUnique) {}
} // namespace facebook::react
@@ -69,13 +69,15 @@ struct RawEvent {
std::string type,
SharedEventPayload eventPayload,
SharedEventTarget eventTarget,
Category category = Category::Unspecified);
Category category = Category::Unspecified,
bool isUnique = false);
std::string type;
SharedEventPayload eventPayload;
SharedEventTarget eventTarget;
Category category;
EventTag loggingTag{0};
bool isUnique{false};
// The client may specify a platform-specific timestamp for the event start
// time, for example when MotionEvent was triggered on the Android native