From b49c8add15d181240be43e02f97330b979a0e72d Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Mon, 27 Aug 2018 07:21:24 -0700 Subject: [PATCH] Fabric: Rethinking of EventEmitter's role Summary: @public Now, one of the main purposes of `EventEmitter`s is to create RawEvent instances for all specific event invocations. Reviewed By: mdvacca Differential Revision: D8886226 fbshipit-source-id: 82a489174efcda097887e70650a2038dc986d149 --- ReactCommon/fabric/events/EventEmitter.cpp | 59 +++++++++++++++++----- ReactCommon/fabric/events/EventEmitter.h | 23 ++++++--- 2 files changed, 61 insertions(+), 21 deletions(-) diff --git a/ReactCommon/fabric/events/EventEmitter.cpp b/ReactCommon/fabric/events/EventEmitter.cpp index 2e99199ee..46d6cb064 100644 --- a/ReactCommon/fabric/events/EventEmitter.cpp +++ b/ReactCommon/fabric/events/EventEmitter.cpp @@ -9,22 +9,33 @@ #include +#include "RawEvent.h" + namespace facebook { namespace react { -EventEmitter::EventEmitter(const EventTarget &eventTarget, const Tag &tag, const SharedEventDispatcher &eventDispatcher): - eventTarget_(eventTarget), - tag_(tag), - eventDispatcher_(eventDispatcher) { +// TODO(T29874519): Get rid of "top" prefix once and for all. +/* + * Capitalizes the first letter of the event type and adds "top" prefix + * (e.g. "layout" becames "topLayout"). + */ +static std::string normalizeEventType(const std::string &type) { + std::string prefixedType = type; + prefixedType[0] = toupper(prefixedType[0]); + prefixedType.insert(0, "top"); + return prefixedType; } -EventEmitter::~EventEmitter() { - auto &&eventDispatcher = eventDispatcher_.lock(); - if (eventDispatcher && eventTarget_) { - eventDispatcher->releaseEventTarget(eventTarget_); - } +std::recursive_mutex &EventEmitter::DispatchMutex() { + static std::recursive_mutex mutex; + return mutex; } +EventEmitter::EventEmitter(const EventTarget &eventTarget, const Tag &tag, const std::shared_ptr &eventDispatcher): + eventTarget_(eventTarget), + tag_(tag), + eventDispatcher_(eventDispatcher) {} + void EventEmitter::dispatchEvent( const std::string &type, const folly::dynamic &payload, @@ -35,15 +46,37 @@ void EventEmitter::dispatchEvent( return; } - assert(eventTarget_ && "Attempted to dispatch an event without an eventTarget."); - // Mixing `target` into `payload`. assert(payload.isObject()); folly::dynamic extendedPayload = folly::dynamic::object("target", tag_); extendedPayload.merge_patch(payload); - // TODO(T29610783): Reconsider using dynamic dispatch here. - eventDispatcher->dispatchEvent(eventTarget_, type, extendedPayload, priority); + std::weak_ptr weakEventEmitter = shared_from_this(); + + eventDispatcher->dispatchEvent( + RawEvent( + normalizeEventType(type), + extendedPayload, + eventTarget_, + [weakEventEmitter]() { + auto eventEmitter = weakEventEmitter.lock(); + if (!eventEmitter) { + return false; + } + + return eventEmitter->getEnabled(); + } + ), + priority + ); +} + +void EventEmitter::setEnabled(bool enabled) const { + enabled_ = enabled; +} + +bool EventEmitter::getEnabled() const { + return enabled_; } } // namespace react diff --git a/ReactCommon/fabric/events/EventEmitter.h b/ReactCommon/fabric/events/EventEmitter.h index f2f41732e..01694e520 100644 --- a/ReactCommon/fabric/events/EventEmitter.h +++ b/ReactCommon/fabric/events/EventEmitter.h @@ -24,10 +24,9 @@ using SharedEventEmitter = std::shared_ptr; * Base class for all particular typed event handlers. * Stores `InstanceHandle` identifying a particular component and the pointer * to `EventDispatcher` which is responsible for delivering the event. - * - * TODO: Reconsider naming of all event-related things. */ -class EventEmitter { +class EventEmitter: + public std::enable_shared_from_this { /* * We have to repeat `Tag` type definition here because `events` module does @@ -36,11 +35,19 @@ class EventEmitter { using Tag = int32_t; public: - EventEmitter(const EventTarget &eventTarget, const Tag &tag, const SharedEventDispatcher &eventDispatcher); - virtual ~EventEmitter(); + static std::recursive_mutex &DispatchMutex(); + + EventEmitter(const EventTarget &eventTarget, const Tag &tag, const std::shared_ptr &eventDispatcher); + virtual ~EventEmitter() = default; + + /* + * Indicates that an event can be delivered to `eventTarget`. + * Callsite must acquire `DispatchMutex` to access those methods. + */ + void setEnabled(bool enabled) const; + bool getEnabled() const; protected: - /* * Initates an event delivery process. * Is used by particular subclasses only. @@ -52,10 +59,10 @@ protected: ) const; private: - - mutable EventTarget eventTarget_ {nullptr}; + EventTarget eventTarget_; Tag tag_; std::weak_ptr eventDispatcher_; + mutable bool enabled_; // Protected by `DispatchMutex`. }; } // namespace react