Back out "Allow listeners in EventEmitter" (#50298)

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

Given EventDispatcher already synchronously calls EventListener, this convenience method for listening to events directly from EventEmitter was short-sighted. We will revisit how to handle JS vs. UI dispatched events for NativeAnimated purposes in future diffs. For now, this reverts https://github.com/facebook/react-native/pull/49998

This change is not being marked as breaking since the change that added this API has not yet been shipped to stable.

## Changelog

[General][Removed] - EventEmitter addListener and removeListener APIs

Reviewed By: zeyap

Differential Revision: D71909828

fbshipit-source-id: 9246de5c7a33368d182369a2d6eb57aa960b415b
This commit is contained in:
Eric Rozell
2025-03-26 20:42:10 -07:00
committed by Facebook GitHub Bot
parent d49ec1d79c
commit c12fdc0fcf
4 changed files with 51 additions and 87 deletions
@@ -94,16 +94,6 @@ void EventEmitter::dispatchEvent(
return;
}
// Allows the event listener to interrupt default event dispatch
if (payload != nullptr) {
if (eventListeners_.willDispatchEvent(
eventTarget_ != nullptr ? eventTarget_->getTag() : 0,
type,
*payload)) {
return;
}
}
eventDispatcher->dispatchEvent(RawEvent(
normalizeEventType(std::move(type)),
std::move(payload),
@@ -129,16 +119,6 @@ void EventEmitter::dispatchUniqueEvent(
return;
}
// Allows the event listener to interrupt default event dispatch
if (payload != nullptr) {
if (eventListeners_.willDispatchEvent(
eventTarget_ != nullptr ? eventTarget_->getTag() : 0,
type,
*payload)) {
return;
}
}
eventDispatcher->dispatchUniqueEvent(RawEvent(
normalizeEventType(std::move(type)),
std::move(payload),
@@ -173,17 +153,4 @@ const SharedEventTarget& EventEmitter::getEventTarget() const {
return eventTarget_;
}
void EventEmitter::addListener(
std::shared_ptr<const EventEmitterListener> listener) const {
eventListeners_.addListener(std::move(listener));
}
/*
* Removes provided event listener to the event dispatcher.
*/
void EventEmitter::removeListener(
const std::shared_ptr<const EventEmitterListener>& listener) const {
eventListeners_.removeListener(listener);
}
} // namespace facebook::react
@@ -12,7 +12,6 @@
#include <folly/dynamic.h>
#include <react/renderer/core/EventDispatcher.h>
#include <react/renderer/core/EventListener.h>
#include <react/renderer/core/EventPayload.h>
#include <react/renderer/core/EventTarget.h>
#include <react/renderer/core/ReactPrimitives.h>
@@ -103,25 +102,12 @@ class EventEmitter {
void dispatchUniqueEvent(std::string type, SharedEventPayload payload) const;
#pragma mark - Event listeners
/*
* Adds provided event listener to the event dispatcher.
*/
void addListener(std::shared_ptr<const EventEmitterListener> listener) const;
/*
* Removes provided event listener to the event dispatcher.
*/
void removeListener(
const std::shared_ptr<const EventEmitterListener>& listener) const;
private:
friend class UIManagerBinding;
mutable SharedEventTarget eventTarget_;
EventDispatcher::Weak eventDispatcher_;
mutable EventEmitterListenerContainer eventListeners_{};
mutable int enableCounter_{0};
mutable bool isEnabled_{false};
};
@@ -0,0 +1,44 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "EventListener.h"
#include <mutex>
namespace facebook::react {
bool EventListenerContainer::willDispatchEvent(const RawEvent& event) {
std::shared_lock lock(mutex_);
bool handled = false;
for (const auto& listener : eventListeners_) {
handled = (*listener)(event);
if (handled) {
break;
}
}
return handled;
}
void EventListenerContainer::addListener(
std::shared_ptr<const EventListener> listener) {
std::unique_lock lock(mutex_);
eventListeners_.push_back(std::move(listener));
}
void EventListenerContainer::removeListener(
const std::shared_ptr<const EventListener>& listener) {
std::unique_lock lock(mutex_);
auto it = std::find(eventListeners_.begin(), eventListeners_.end(), listener);
if (it != eventListeners_.end()) {
eventListeners_.erase(it);
}
}
} // namespace facebook::react
@@ -7,10 +7,9 @@
#pragma once
#include <mutex>
#include <shared_mutex>
#include <string>
#include <react/renderer/core/EventPayload.h>
#include <react/renderer/core/RawEvent.h>
namespace facebook::react {
@@ -20,55 +19,23 @@ namespace facebook::react {
* Return `true` to interrupt default dispatch to JS event emitter, `false` to
* pass through to default handlers.
*/
using EventListener = std::function<bool(const RawEvent& event)>;
template <typename... TArgs>
using EventListenerT = std::function<bool(TArgs...)>;
template <typename... TArgs>
class EventListenerContainerT {
class EventListenerContainer {
public:
/*
* Invoke listeners in this container with the event.
* Returns true if event was handled by the listener, false to continue
* default dispatch.
*/
bool willDispatchEvent(TArgs... args) {
std::shared_lock lock(mutex_);
bool handled = false;
for (const auto& listener : eventListeners_) {
handled = (*listener)(args...);
if (handled) {
break;
}
}
return handled;
}
bool willDispatchEvent(const RawEvent& event);
void addListener(std::shared_ptr<const EventListenerT<TArgs...>> listener) {
std::unique_lock lock(mutex_);
eventListeners_.push_back(std::move(listener));
}
void removeListener(
const std::shared_ptr<const EventListenerT<TArgs...>>& listener) {
std::unique_lock lock(mutex_);
auto it =
std::find(eventListeners_.begin(), eventListeners_.end(), listener);
if (it != eventListeners_.end()) {
eventListeners_.erase(it);
}
}
void addListener(std::shared_ptr<const EventListener> listener);
void removeListener(const std::shared_ptr<const EventListener>& listener);
private:
std::shared_mutex mutex_;
std::vector<std::shared_ptr<const EventListenerT<TArgs...>>> eventListeners_;
std::vector<std::shared_ptr<const EventListener>> eventListeners_;
};
using EventListener = EventListenerT<const RawEvent&>;
using EventListenerContainer = EventListenerContainerT<const RawEvent&>;
using EventEmitterListener =
EventListenerT<Tag, const std::string&, const EventPayload&>;
using EventEmitterListenerContainer =
EventListenerContainerT<Tag, const std::string&, const EventPayload&>;
} // namespace facebook::react