fabric: send events via JS thread
Summary: Calling the event emitters on the main thread seems to be problematic, so let's dispatch it via the JS thread. This requires some changes to make "eventTarget" single-use because otherwise the binding would need to synchronize the actual JS call with the act of releasing the target. Reviewed By: shergin Differential Revision: D8375291 fbshipit-source-id: bd2b42731176ae209f4a19c232309c163fb1c01b
This commit is contained in:
parent
0883e52c74
commit
2ca4770011
|
@ -188,6 +188,11 @@ struct RCTInstanceCallback : public InstanceCallback {
|
||||||
return (JSGlobalContextRef)(_reactInstance ? _reactInstance->getJavaScriptContext() : nullptr);
|
return (JSGlobalContextRef)(_reactInstance ? _reactInstance->getJavaScriptContext() : nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (std::shared_ptr<MessageQueueThread>)jsMessageThread
|
||||||
|
{
|
||||||
|
return _jsMessageThread;
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)isInspectable
|
- (BOOL)isInspectable
|
||||||
{
|
{
|
||||||
return _reactInstance ? _reactInstance->isInspectable() : NO;
|
return _reactInstance ? _reactInstance->isInspectable() : NO;
|
||||||
|
|
|
@ -30,8 +30,6 @@ public:
|
||||||
|
|
||||||
virtual EventTarget createEventTarget(const InstanceHandle &instanceHandle) const = 0;
|
virtual EventTarget createEventTarget(const InstanceHandle &instanceHandle) const = 0;
|
||||||
|
|
||||||
virtual void releaseEventTarget(const EventTarget &eventTarget) const = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dispatches "raw" event using some event-delivery infrastructure.
|
* Dispatches "raw" event using some event-delivery infrastructure.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -17,9 +17,7 @@ EventEmitter::EventEmitter(const InstanceHandle &instanceHandle, const Tag &tag,
|
||||||
tag_(tag),
|
tag_(tag),
|
||||||
eventDispatcher_(eventDispatcher) {}
|
eventDispatcher_(eventDispatcher) {}
|
||||||
|
|
||||||
EventEmitter::~EventEmitter() {
|
EventEmitter::~EventEmitter() {}
|
||||||
releaseEventTargetIfNeeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventEmitter::dispatchEvent(
|
void EventEmitter::dispatchEvent(
|
||||||
const std::string &type,
|
const std::string &type,
|
||||||
|
@ -31,7 +29,7 @@ void EventEmitter::dispatchEvent(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
createEventTargetIfNeeded();
|
EventTarget eventTarget = createEventTarget();
|
||||||
|
|
||||||
// Mixing `target` into `payload`.
|
// Mixing `target` into `payload`.
|
||||||
assert(payload.isObject());
|
assert(payload.isObject());
|
||||||
|
@ -39,31 +37,13 @@ void EventEmitter::dispatchEvent(
|
||||||
extendedPayload.merge_patch(payload);
|
extendedPayload.merge_patch(payload);
|
||||||
|
|
||||||
// TODO(T29610783): Reconsider using dynamic dispatch here.
|
// TODO(T29610783): Reconsider using dynamic dispatch here.
|
||||||
eventDispatcher->dispatchEvent(eventTarget_, type, extendedPayload, priority);
|
eventDispatcher->dispatchEvent(eventTarget, type, extendedPayload, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventEmitter::createEventTargetIfNeeded() const {
|
EventTarget EventEmitter::createEventTarget() const {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
|
||||||
|
|
||||||
if (eventTarget_) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &&eventDispatcher = eventDispatcher_.lock();
|
auto &&eventDispatcher = eventDispatcher_.lock();
|
||||||
assert(eventDispatcher);
|
assert(eventDispatcher);
|
||||||
eventTarget_ = eventDispatcher->createEventTarget(instanceHandle_);
|
return eventDispatcher->createEventTarget(instanceHandle_);
|
||||||
}
|
|
||||||
|
|
||||||
void EventEmitter::releaseEventTargetIfNeeded() const {
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
|
||||||
|
|
||||||
if (!eventTarget_) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &&eventDispatcher = eventDispatcher_.lock();
|
|
||||||
assert(eventDispatcher);
|
|
||||||
eventDispatcher->releaseEventTarget(eventTarget_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace react
|
} // namespace react
|
||||||
|
|
|
@ -48,14 +48,11 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void createEventTargetIfNeeded() const;
|
EventTarget createEventTarget() const;
|
||||||
void releaseEventTargetIfNeeded() const;
|
|
||||||
|
|
||||||
InstanceHandle instanceHandle_;
|
InstanceHandle instanceHandle_;
|
||||||
Tag tag_;
|
Tag tag_;
|
||||||
std::weak_ptr<const EventDispatcher> eventDispatcher_;
|
std::weak_ptr<const EventDispatcher> eventDispatcher_;
|
||||||
mutable EventTarget eventTarget_ {nullptr};
|
|
||||||
mutable std::mutex mutex_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace react
|
} // namespace react
|
||||||
|
|
|
@ -98,10 +98,6 @@ void FabricUIManager::setDispatchEventFunction(std::function<DispatchEventFuncti
|
||||||
dispatchEventFunction_ = dispatchEventFunction;
|
dispatchEventFunction_ = dispatchEventFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FabricUIManager::setReleaseEventTargetFunction(std::function<ReleaseEventTargetFunction> releaseEventTargetFunction) {
|
|
||||||
releaseEventTargetFunction_ = releaseEventTargetFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FabricUIManager::setReleaseEventHandlerFunction(std::function<ReleaseEventHandlerFunction> releaseEventHandlerFunction) {
|
void FabricUIManager::setReleaseEventHandlerFunction(std::function<ReleaseEventHandlerFunction> releaseEventHandlerFunction) {
|
||||||
releaseEventHandlerFunction_ = releaseEventHandlerFunction;
|
releaseEventHandlerFunction_ = releaseEventHandlerFunction;
|
||||||
}
|
}
|
||||||
|
@ -119,10 +115,6 @@ void FabricUIManager::dispatchEvent(const EventTarget &eventTarget, const std::s
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FabricUIManager::releaseEventTarget(const EventTarget &eventTarget) const {
|
|
||||||
releaseEventTargetFunction_(eventTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int rootTag, folly::dynamic props, InstanceHandle instanceHandle) {
|
SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int rootTag, folly::dynamic props, InstanceHandle instanceHandle) {
|
||||||
isLoggingEnabled && LOG(INFO) << "FabricUIManager::createNode(tag: " << tag << ", name: " << viewName << ", rootTag: " << rootTag << ", props: " << props << ")";
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::createNode(tag: " << tag << ", name: " << viewName << ", rootTag: " << rootTag << ", props: " << props << ")";
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ namespace react {
|
||||||
|
|
||||||
using CreateEventTargetFunction = EventTarget (InstanceHandle instanceHandle);
|
using CreateEventTargetFunction = EventTarget (InstanceHandle instanceHandle);
|
||||||
using DispatchEventFunction = void (EventHandler eventHandler, EventTarget eventTarget, std::string type, folly::dynamic payload);
|
using DispatchEventFunction = void (EventHandler eventHandler, EventTarget eventTarget, std::string type, folly::dynamic payload);
|
||||||
using ReleaseEventTargetFunction = void (EventTarget eventTarget);
|
|
||||||
using ReleaseEventHandlerFunction = void (EventHandler eventHandler);
|
using ReleaseEventHandlerFunction = void (EventHandler eventHandler);
|
||||||
|
|
||||||
class FabricUIManager {
|
class FabricUIManager {
|
||||||
|
@ -46,14 +45,12 @@ public:
|
||||||
*/
|
*/
|
||||||
void setCreateEventTargetFunction(std::function<CreateEventTargetFunction> createEventTargetFunction);
|
void setCreateEventTargetFunction(std::function<CreateEventTargetFunction> createEventTargetFunction);
|
||||||
void setDispatchEventFunction(std::function<DispatchEventFunction> dispatchEventFunction);
|
void setDispatchEventFunction(std::function<DispatchEventFunction> dispatchEventFunction);
|
||||||
void setReleaseEventTargetFunction(std::function<ReleaseEventTargetFunction> releaseEventTargetFunction);
|
|
||||||
void setReleaseEventHandlerFunction(std::function<ReleaseEventHandlerFunction> releaseEventHandlerFunction);
|
void setReleaseEventHandlerFunction(std::function<ReleaseEventHandlerFunction> releaseEventHandlerFunction);
|
||||||
|
|
||||||
#pragma mark - Native-facing Interface
|
#pragma mark - Native-facing Interface
|
||||||
|
|
||||||
EventTarget createEventTarget(const InstanceHandle &instanceHandle) const;
|
EventTarget createEventTarget(const InstanceHandle &instanceHandle) const;
|
||||||
void dispatchEvent(const EventTarget &eventTarget, const std::string &type, const folly::dynamic &payload) const;
|
void dispatchEvent(const EventTarget &eventTarget, const std::string &type, const folly::dynamic &payload) const;
|
||||||
void releaseEventTarget(const EventTarget &eventTarget) const;
|
|
||||||
|
|
||||||
#pragma mark - JavaScript/React-facing Interface
|
#pragma mark - JavaScript/React-facing Interface
|
||||||
|
|
||||||
|
@ -75,7 +72,6 @@ private:
|
||||||
EventHandler eventHandler_;
|
EventHandler eventHandler_;
|
||||||
std::function<CreateEventTargetFunction> createEventTargetFunction_;
|
std::function<CreateEventTargetFunction> createEventTargetFunction_;
|
||||||
std::function<DispatchEventFunction> dispatchEventFunction_;
|
std::function<DispatchEventFunction> dispatchEventFunction_;
|
||||||
std::function<ReleaseEventTargetFunction> releaseEventTargetFunction_;
|
|
||||||
std::function<ReleaseEventHandlerFunction> releaseEventHandlerFunction_;
|
std::function<ReleaseEventHandlerFunction> releaseEventHandlerFunction_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,16 +30,13 @@ EventTarget SchedulerEventDispatcher::createEventTarget(const InstanceHandle &in
|
||||||
return uiManager_->createEventTarget(instanceHandle);
|
return uiManager_->createEventTarget(instanceHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SchedulerEventDispatcher::releaseEventTarget(const EventTarget &eventTarget) const {
|
|
||||||
uiManager_->releaseEventTarget(eventTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SchedulerEventDispatcher::dispatchEvent(
|
void SchedulerEventDispatcher::dispatchEvent(
|
||||||
const EventTarget &eventTarget,
|
const EventTarget &eventTarget,
|
||||||
const std::string &type,
|
const std::string &type,
|
||||||
const folly::dynamic &payload,
|
const folly::dynamic &payload,
|
||||||
const EventPriority &priority
|
const EventPriority &priority
|
||||||
) const {
|
) const {
|
||||||
|
// TODO: Schedule the event based on priority.
|
||||||
uiManager_->dispatchEvent(eventTarget, normalizeEventType(type), payload);
|
uiManager_->dispatchEvent(eventTarget, normalizeEventType(type), payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,6 @@ public:
|
||||||
|
|
||||||
EventTarget createEventTarget(const InstanceHandle &instanceHandle) const override;
|
EventTarget createEventTarget(const InstanceHandle &instanceHandle) const override;
|
||||||
|
|
||||||
void releaseEventTarget(const EventTarget &eventTarget) const override;
|
|
||||||
|
|
||||||
void dispatchEvent(
|
void dispatchEvent(
|
||||||
const EventTarget &eventTarget,
|
const EventTarget &eventTarget,
|
||||||
const std::string &type,
|
const std::string &type,
|
||||||
|
|
Loading…
Reference in New Issue