Fabric: ValueFactory and EventEmitter::dispatchEvent based on that

Summary:
Now the event delive pipeline supports `JSI::Value`-based payload. Instead of passing `folly::dynamic`, now we are passing `std::function<jsi::Value(jsi::Runtime &runtime)>` as factory that can build a `JSI::Value` with given `jsi::Runtime` and any captured data.
The old (now legacy) way of calling `EventEmitter::dispatchEvent(..., const folly::dynamic &payload, ...)` is also supported.

Reviewed By: sahrens

Differential Revision: D13123043

fbshipit-source-id: d65348bb215013042abb2fcfe5083a8c697333d0
This commit is contained in:
Valentin Shergin
2018-11-27 20:58:28 -08:00
committed by Facebook Github Bot
parent f4da8769a3
commit dea8773c19
10 changed files with 52 additions and 18 deletions

View File

@@ -56,6 +56,7 @@ rn_xplat_cxx_library(
"xplat//folly:memory",
"xplat//folly:molly",
"xplat//jsi:jsi",
"xplat//jsi:JSIDynamic",
"xplat//third-party/glog:glog",
react_native_xplat_target("fabric/debug:debug"),
],

View File

@@ -8,6 +8,8 @@
#include "EventEmitter.h"
#include <folly/dynamic.h>
#include <jsi/JSIDynamic.h>
#include <jsi/jsi.h>
#include <react/debug/SystraceSection.h>
#include "RawEvent.h"
@@ -34,6 +36,12 @@ std::recursive_mutex &EventEmitter::DispatchMutex() {
return mutex;
}
ValueFactory EventEmitter::defaultPayloadFactory() {
static auto payloadFactory =
ValueFactory{[](jsi::Runtime &runtime) { return jsi::Object(runtime); }};
return payloadFactory;
}
EventEmitter::EventEmitter(
SharedEventTarget eventTarget,
Tag tag,
@@ -46,6 +54,18 @@ void EventEmitter::dispatchEvent(
const std::string &type,
const folly::dynamic &payload,
const EventPriority &priority) const {
dispatchEvent(
type,
[payload](jsi::Runtime &runtime) {
return valueFromDynamic(runtime, payload);
},
priority);
}
void EventEmitter::dispatchEvent(
const std::string &type,
const ValueFactory &payloadFactory,
const EventPriority &priority) const {
SystraceSection s("EventEmitter::dispatchEvent");
auto eventDispatcher = eventDispatcher_.lock();
@@ -54,7 +74,8 @@ void EventEmitter::dispatchEvent(
}
eventDispatcher->dispatchEvent(
RawEvent(normalizeEventType(type), payload, eventTarget_), priority);
RawEvent(normalizeEventType(type), payloadFactory, eventTarget_),
priority);
}
void EventEmitter::enable() const {

View File

@@ -45,6 +45,8 @@ class EventEmitter {
public:
static std::recursive_mutex &DispatchMutex();
static ValueFactory defaultPayloadFactory();
EventEmitter(
SharedEventTarget eventTarget,
Tag tag,
@@ -76,7 +78,13 @@ class EventEmitter {
*/
void dispatchEvent(
const std::string &type,
const folly::dynamic &payload = folly::dynamic::object(),
const ValueFactory &payloadFactory =
EventEmitter::defaultPayloadFactory(),
const EventPriority &priority = EventPriority::AsynchronousBatched) const;
void dispatchEvent(
const std::string &type,
const folly::dynamic &payload,
const EventPriority &priority = EventPriority::AsynchronousBatched) const;
private:

View File

@@ -44,7 +44,10 @@ void EventQueue::onBeat(jsi::Runtime &runtime) const {
for (const auto &event : queue) {
eventPipe_(
runtime, event.eventTarget.lock().get(), event.type, event.payload);
runtime,
event.eventTarget.lock().get(),
event.type,
event.payloadFactory);
}
}
}

View File

@@ -12,10 +12,10 @@ namespace react {
RawEvent::RawEvent(
std::string type,
folly::dynamic payload,
ValueFactory payloadFactory,
WeakEventTarget eventTarget)
: type(std::move(type)),
payload(std::move(payload)),
payloadFactory(std::move(payloadFactory)),
eventTarget(std::move(eventTarget)) {}
} // namespace react

View File

@@ -9,6 +9,7 @@
#include <memory>
#include <folly/dynamic.h>
#include <jsi/jsi.h>
#include <react/events/primitives.h>
namespace facebook {
@@ -21,11 +22,11 @@ class RawEvent {
public:
RawEvent(
std::string type,
folly::dynamic payload,
ValueFactory payloadFactory,
WeakEventTarget eventTarget);
const std::string type;
const folly::dynamic payload;
const ValueFactory payloadFactory;
const WeakEventTarget eventTarget;
};

View File

@@ -47,11 +47,13 @@ struct EventTarget {};
using SharedEventTarget = std::shared_ptr<const EventTarget>;
using WeakEventTarget = std::weak_ptr<const EventTarget>;
using ValueFactory = std::function<jsi::Value(jsi::Runtime &runtime)>;
using EventPipe = std::function<void(
jsi::Runtime &runtime,
const EventTarget *eventTarget,
const std::string &type,
const folly::dynamic &payload)>;
const ValueFactory &payloadFactory)>;
} // namespace react
} // namespace facebook

View File

@@ -37,8 +37,8 @@ Scheduler::Scheduler(const SharedContextContainer &contextContainer)
jsi::Runtime &runtime,
const EventTarget *eventTarget,
const std::string &type,
const folly::dynamic &payload) {
uiManagerBinding->dispatchEvent(runtime, eventTarget, type, payload);
const ValueFactory &payloadFactory) {
uiManagerBinding->dispatchEvent(runtime, eventTarget, type, payloadFactory);
};
auto eventDispatcher = std::make_shared<EventDispatcher>(

View File

@@ -67,11 +67,11 @@ void UIManagerBinding::dispatchEvent(
jsi::Runtime &runtime,
const EventTarget *eventTarget,
const std::string &type,
const folly::dynamic &payload) const {
const ValueFactory &payloadFactory) const {
SystraceSection s("UIManagerBinding::dispatchEvent");
auto payload = payloadFactory(runtime);
auto eventTargetValue = jsi::Value::null();
folly::dynamic extendedPayload;
if (eventTarget) {
auto &eventTargetWrapper =
@@ -83,10 +83,8 @@ void UIManagerBinding::dispatchEvent(
// Mixing `target` into `payload`.
assert(payload.isObject());
extendedPayload = folly::dynamic::object("target", eventTargetWrapper.tag);
extendedPayload.merge_patch(payload);
} else {
extendedPayload = payload;
payload.asObject(runtime).setProperty(
runtime, "target", eventTargetWrapper.tag);
}
auto &eventHandlerWrapper =
@@ -95,7 +93,7 @@ void UIManagerBinding::dispatchEvent(
runtime,
{std::move(eventTargetValue),
jsi::String::createFromUtf8(runtime, type),
jsi::valueFromDynamic(runtime, extendedPayload)});
std::move(payload)});
}
void UIManagerBinding::invalidate() const {

View File

@@ -49,7 +49,7 @@ class UIManagerBinding : public jsi::HostObject {
jsi::Runtime &runtime,
const EventTarget *eventTarget,
const std::string &type,
const folly::dynamic &payload) const;
const ValueFactory &payloadFactory) const;
/*
* Invalidates the binding and underlying UIManager.