diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.cpp b/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.cpp index 22a12a2ffb43fe..4ac066f55fd51e 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.cpp @@ -84,7 +84,7 @@ void EventEmitter::dispatchEvent( eventDispatcher->dispatchEvent( RawEvent( normalizeEventType(std::move(type)), - payloadFactory, + std::make_unique(payloadFactory), eventTarget_, category), priority); @@ -102,7 +102,7 @@ void EventEmitter::dispatchUniqueEvent( eventDispatcher->dispatchUniqueEvent(RawEvent( normalizeEventType(std::move(type)), - payloadFactory, + std::make_unique(payloadFactory), eventTarget_, RawEvent::Category::Continuous)); } diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.h b/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.h index c02d605b43b77d..df0c12c93a4f76 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.h +++ b/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.h @@ -12,9 +12,11 @@ #include #include +#include #include #include #include +#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventPayload.h b/packages/react-native/ReactCommon/react/renderer/core/EventPayload.h new file mode 100644 index 00000000000000..4d30cf5ec5f952 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/core/EventPayload.h @@ -0,0 +1,29 @@ +/* + * 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 + +namespace facebook::react { + +/** + * Abstract base class for all event payload types. + */ +struct EventPayload { + virtual ~EventPayload() = default; + + EventPayload() = default; + EventPayload(const EventPayload &) = default; + EventPayload &operator=(const EventPayload &) = default; + EventPayload(EventPayload &&) = default; + EventPayload &operator=(EventPayload &&) = default; + + virtual jsi::Value asJSIValue(jsi::Runtime &runtime) const = 0; +}; + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventPipe.h b/packages/react-native/ReactCommon/react/renderer/core/EventPipe.h index 53d41488418d3e..a31bc54d5ad5c5 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventPipe.h +++ b/packages/react-native/ReactCommon/react/renderer/core/EventPipe.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -22,6 +23,6 @@ using EventPipe = std::function; + const EventPayload &payload)>; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventQueueProcessor.cpp b/packages/react-native/ReactCommon/react/renderer/core/EventQueueProcessor.cpp index 4ff9406f60bbe1..78d47132154ee4 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventQueueProcessor.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/EventQueueProcessor.cpp @@ -53,12 +53,17 @@ void EventQueueProcessor::flushEvents( eventLogger->onEventDispatch(event.loggingTag); } + if (event.eventPayload == nullptr) { + // Something has gone terribly wrong + continue; + } + eventPipe_( runtime, event.eventTarget.get(), event.type, reactPriority, - event.payloadFactory); + *event.eventPayload); if (eventLogger != nullptr) { eventLogger->onEventEnd(event.loggingTag); diff --git a/packages/react-native/ReactCommon/react/renderer/core/RawEvent.cpp b/packages/react-native/ReactCommon/react/renderer/core/RawEvent.cpp index 646ce4aea3ad86..5fcdba1f1d0342 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/RawEvent.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/RawEvent.cpp @@ -11,11 +11,11 @@ namespace facebook::react { RawEvent::RawEvent( std::string type, - ValueFactory payloadFactory, + std::unique_ptr eventPayload, SharedEventTarget eventTarget, Category category) : type(std::move(type)), - payloadFactory(std::move(payloadFactory)), + eventPayload(std::move(eventPayload)), eventTarget(std::move(eventTarget)), category(category) {} diff --git a/packages/react-native/ReactCommon/react/renderer/core/RawEvent.h b/packages/react-native/ReactCommon/react/renderer/core/RawEvent.h index d9ec02c796e79a..4023d831f7d5a1 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/RawEvent.h +++ b/packages/react-native/ReactCommon/react/renderer/core/RawEvent.h @@ -11,8 +11,8 @@ #include #include +#include #include -#include namespace facebook::react { @@ -60,12 +60,12 @@ struct RawEvent { RawEvent( std::string type, - ValueFactory payloadFactory, + std::unique_ptr eventPayload, SharedEventTarget eventTarget, Category category = Category::Unspecified); std::string type; - ValueFactory payloadFactory; + std::unique_ptr eventPayload; SharedEventTarget eventTarget; Category category; EventTag loggingTag{0}; diff --git a/packages/react-native/ReactCommon/react/renderer/core/ValueFactoryEventPayload.cpp b/packages/react-native/ReactCommon/react/renderer/core/ValueFactoryEventPayload.cpp new file mode 100644 index 00000000000000..fc5e81d3646f76 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/core/ValueFactoryEventPayload.cpp @@ -0,0 +1,19 @@ +/* + * 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 "ValueFactoryEventPayload.h" + +namespace facebook::react { + +ValueFactoryEventPayload::ValueFactoryEventPayload(ValueFactory factory) + : valueFactory_(std::move(factory)) {} + +jsi::Value ValueFactoryEventPayload::asJSIValue(jsi::Runtime &runtime) const { + return valueFactory_(runtime); +} + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/ValueFactoryEventPayload.h b/packages/react-native/ReactCommon/react/renderer/core/ValueFactoryEventPayload.h new file mode 100644 index 00000000000000..08486966dd5905 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/core/ValueFactoryEventPayload.h @@ -0,0 +1,24 @@ +/* + * 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 +#include + +namespace facebook::react { + +class ValueFactoryEventPayload : public EventPayload { + public: + explicit ValueFactoryEventPayload(ValueFactory factory); + jsi::Value asJSIValue(jsi::Runtime &runtime) const override; + + private: + ValueFactory valueFactory_; +}; + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/EventQueueProcessorTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/EventQueueProcessorTest.cpp index e88013b9e555b6..1a4f9dfc409f91 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/EventQueueProcessorTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/EventQueueProcessorTest.cpp @@ -41,7 +41,7 @@ class EventQueueProcessorTest : public testing::Test { std::unique_ptr eventProcessor_; std::vector eventTypes_; std::vector eventPriorities_; - ValueFactory dummyValueFactory_; + std::unique_ptr dummyEventPayload_; }; TEST_F(EventQueueProcessorTest, singleUnspecifiedEvent) { @@ -49,7 +49,7 @@ TEST_F(EventQueueProcessorTest, singleUnspecifiedEvent) { *runtime_, {RawEvent( "my type", - dummyValueFactory_, + dummyEventPayload_, nullptr, RawEvent::Category::Unspecified)}); @@ -63,22 +63,22 @@ TEST_F(EventQueueProcessorTest, continuousEvent) { *runtime_, {RawEvent( "touchStart", - dummyValueFactory_, + dummyEventPayload_, nullptr, RawEvent::Category::ContinuousStart), RawEvent( "touchMove", - dummyValueFactory_, + dummyEventPayload_, nullptr, RawEvent::Category::Unspecified), RawEvent( "touchEnd", - dummyValueFactory_, + dummyEventPayload_, nullptr, RawEvent::Category::ContinuousEnd), RawEvent( "custom event", - dummyValueFactory_, + dummyEventPayload_, nullptr, RawEvent::Category::Unspecified)}); @@ -103,7 +103,7 @@ TEST_F(EventQueueProcessorTest, alwaysContinuousEvent) { { RawEvent( "onScroll", - dummyValueFactory_, + dummyEventPayload_, nullptr, RawEvent::Category::Continuous), }); @@ -120,7 +120,7 @@ TEST_F(EventQueueProcessorTest, alwaysDiscreteEvent) { { RawEvent( "onChange", - dummyValueFactory_, + dummyEventPayload_, nullptr, RawEvent::Category::Discrete), }); diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp index 1d812fcccf845a..990912be9cbe77 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp @@ -60,11 +60,11 @@ Scheduler::Scheduler( const EventTarget *eventTarget, const std::string &type, ReactEventPriority priority, - const ValueFactory &payloadFactory) { + const EventPayload &payload) { uiManager->visitBinding( [&](UIManagerBinding const &uiManagerBinding) { uiManagerBinding.dispatchEvent( - runtime, eventTarget, type, priority, payloadFactory); + runtime, eventTarget, type, priority, payload); }, runtime); if (runtimeScheduler != nullptr) { diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp index ef4100ef6c4df9..e56132e02c226f 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp @@ -93,10 +93,10 @@ void UIManagerBinding::dispatchEvent( EventTarget const *eventTarget, std::string const &type, ReactEventPriority priority, - ValueFactory const &payloadFactory) const { + const EventPayload &eventPayload) const { SystraceSection s("UIManagerBinding::dispatchEvent", "type", type); - auto payload = payloadFactory(runtime); + auto payload = eventPayload.asJSIValue(runtime); // If a payload is null, the factory has decided to cancel the event if (payload.isNull()) { diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.h b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.h index b2180ea4ede328..7f5adc03f4c122 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.h +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.h @@ -52,7 +52,7 @@ class UIManagerBinding : public jsi::HostObject { EventTarget const *eventTarget, std::string const &type, ReactEventPriority priority, - ValueFactory const &payloadFactory) const; + const EventPayload &payload) const; /* * Invalidates the binding and underlying UIManager.