/
githubmr
/
facebook-react-native
Обзор
Документация
Войти
/
githubmr
/
facebook-react-native
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
main
packages/react-native/ReactCommon/react/bridging/EventEmitter.h
147 строк
4 KB
Christoph Purrer
Add GTest utility methods to test C++ Turbo Module EventEmitters (#54060)
14 окт 2025, 06:21
14 окт 2025, 06:21
6d7a93f
Код
Авторство
О чём код?
/* * 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. */ #pragma once #include <react/bridging/Function.h> #include <functional> #include <memory> #include <mutex> #include <unordered_map> #define FRIEND_TEST(test_case_name, test_name) \ friend class test_case_name##_##test_name##_Test namespace facebook::react { class EventSubscription { public: explicit EventSubscription(std::function<void()> remove) : remove_(std::move(remove)) {} ~EventSubscription() = default; EventSubscription(EventSubscription&&) noexcept = default; EventSubscription& operator=(EventSubscription&&) noexcept = default; EventSubscription(const EventSubscription&) = delete; EventSubscription& operator=(const EventSubscription&) = delete; void remove() { remove_(); } private: friend Bridging<EventSubscription>; std::function<void()> remove_; }; template <> struct Bridging<EventSubscription> { static EventSubscription fromJs( jsi::Runtime& rt, const jsi::Object& value, const std::shared_ptr<CallInvoker>& jsInvoker) { auto listener = bridging::fromJs<AsyncCallback<>>( rt, value.getProperty(rt, "remove"), jsInvoker); return EventSubscription( [listener = std::move(listener)]() mutable { listener(); }); } static jsi::Object toJs( jsi::Runtime& rt, const EventSubscription& eventSubscription, const std::shared_ptr<CallInvoker>& jsInvoker) { auto result = jsi::Object(rt); result.setProperty( rt, "remove", bridging::toJs(rt, eventSubscription.remove_, jsInvoker)); return result; } }; class IAsyncEventEmitter { public: IAsyncEventEmitter() noexcept = default; virtual ~IAsyncEventEmitter() noexcept = default; IAsyncEventEmitter(IAsyncEventEmitter&&) noexcept = default; IAsyncEventEmitter& operator=(IAsyncEventEmitter&&) noexcept = default; IAsyncEventEmitter(const IAsyncEventEmitter&) = delete; IAsyncEventEmitter& operator=(const IAsyncEventEmitter&) = delete; virtual jsi::Object get( jsi::Runtime& rt, const std::shared_ptr<CallInvoker>& jsInvoker) const = 0; }; template <typename... Args> class AsyncEventEmitter : public IAsyncEventEmitter { static_assert( sizeof...(Args) <= 1, "AsyncEventEmitter must have at most one argument"); public: AsyncEventEmitter() : state_(std::make_shared<SharedState>()) { listen_ = [state = state_](AsyncCallback<Args...> listener) { std::lock_guard<std::mutex> lock(state->mutex); auto listenerId = state->listenerId++; state->listeners.emplace(listenerId, std::move(listener)); return EventSubscription([state, listenerId]() { std::lock_guard<std::mutex> innerLock(state->mutex); state->listeners.erase(listenerId); }); }; } ~AsyncEventEmitter() override = default; AsyncEventEmitter(AsyncEventEmitter&&) noexcept = default; AsyncEventEmitter& operator=(AsyncEventEmitter&&) noexcept = default; AsyncEventEmitter(const AsyncEventEmitter&) = delete; AsyncEventEmitter& operator=(const AsyncEventEmitter&) = delete; void emit(std::function<jsi::Value(jsi::Runtime&)>&& converter) { std::lock_guard<std::mutex> lock(state_->mutex); for (auto& [_, listener] : state_->listeners) { listener.call([converter](jsi::Runtime& rt, jsi::Function& jsFunction) { jsFunction.call(rt, converter(rt)); }); } } void emit(Args... value) { std::lock_guard<std::mutex> lock(state_->mutex); for (const auto& [_, listener] : state_->listeners) { listener.call(static_cast<Args>(value)...); } } jsi::Object get( jsi::Runtime& rt, const std::shared_ptr<CallInvoker>& jsInvoker) const override { return bridging::toJs(rt, listen_, jsInvoker); } private: friend Bridging<AsyncEventEmitter>; FRIEND_TEST(BridgingTest, eventEmitterTest); struct SharedState { std::mutex mutex; std::unordered_map<size_t, AsyncCallback<Args...>> listeners; size_t listenerId{}; }; std::function<EventSubscription(AsyncCallback<Args...>)> listen_; std::shared_ptr<SharedState> state_; }; template <typename... Args> struct Bridging<AsyncEventEmitter<Args...>> { static jsi::Object toJs( jsi::Runtime& rt, const AsyncEventEmitter<Args...>& eventEmitter, const std::shared_ptr<CallInvoker>& jsInvoker) { return eventEmitter.get(rt, jsInvoker); } }; } // namespace facebook::react