mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
0ee8e292a4
Summary: Changelog: [internal] There is a possibility of race between updating scrollview's state and virtualised list asking for layout of individual cells. To make sure the race doesn't happen, state must be updated before dispatching onScroll event. Android has implemented a different mechanism to tackle this issue in D28558380 (https://github.com/facebook/react-native/commit/b161241db2ef74d2e4bff36d4972f5f0312dcc44). Reviewed By: JoshuaGross Differential Revision: D28642737 fbshipit-source-id: 33874beac69fc5a66eeb7f459fd89cd0b00dafcf
120 lines
2.9 KiB
C++
120 lines
2.9 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#include "EventQueue.h"
|
|
|
|
#include "EventEmitter.h"
|
|
#include "ShadowNodeFamily.h"
|
|
|
|
namespace facebook {
|
|
namespace react {
|
|
|
|
EventQueue::EventQueue(
|
|
EventQueueProcessor eventProcessor,
|
|
std::unique_ptr<EventBeat> eventBeat)
|
|
: eventProcessor_(std::move(eventProcessor)),
|
|
eventBeat_(std::move(eventBeat)) {
|
|
eventBeat_->setBeatCallback(
|
|
std::bind(&EventQueue::onBeat, this, std::placeholders::_1));
|
|
}
|
|
|
|
void EventQueue::enqueueEvent(RawEvent &&rawEvent) const {
|
|
{
|
|
std::lock_guard<std::mutex> lock(queueMutex_);
|
|
eventQueue_.push_back(std::move(rawEvent));
|
|
}
|
|
|
|
onEnqueue();
|
|
}
|
|
|
|
void EventQueue::enqueueUniqueEvent(RawEvent &&rawEvent) const {
|
|
{
|
|
std::lock_guard<std::mutex> lock(queueMutex_);
|
|
|
|
auto repeatedEvent = eventQueue_.rend();
|
|
|
|
for (auto it = eventQueue_.rbegin(); it != eventQueue_.rend(); ++it) {
|
|
if (it->type == rawEvent.type &&
|
|
it->eventTarget == rawEvent.eventTarget) {
|
|
repeatedEvent = it;
|
|
break;
|
|
} else if (it->eventTarget == rawEvent.eventTarget) {
|
|
// It is necessary to maintain order of different event types
|
|
// for the same target. If the same target has event types A1, B1
|
|
// in the event queue and event A2 occurs. A1 has to stay in the
|
|
// queue.
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (repeatedEvent == eventQueue_.rend()) {
|
|
eventQueue_.push_back(std::move(rawEvent));
|
|
} else {
|
|
*repeatedEvent = std::move(rawEvent);
|
|
}
|
|
}
|
|
|
|
onEnqueue();
|
|
}
|
|
|
|
void EventQueue::enqueueStateUpdate(StateUpdate &&stateUpdate) const {
|
|
{
|
|
std::lock_guard<std::mutex> lock(queueMutex_);
|
|
if (!stateUpdateQueue_.empty()) {
|
|
auto const position = stateUpdateQueue_.back();
|
|
if (stateUpdate.family == position.family) {
|
|
stateUpdateQueue_.pop_back();
|
|
}
|
|
}
|
|
stateUpdateQueue_.push_back(std::move(stateUpdate));
|
|
}
|
|
|
|
onEnqueue();
|
|
}
|
|
|
|
void EventQueue::onBeat(jsi::Runtime &runtime) const {
|
|
flushStateUpdates();
|
|
flushEvents(runtime);
|
|
}
|
|
|
|
void EventQueue::flushEvents(jsi::Runtime &runtime) const {
|
|
std::vector<RawEvent> queue;
|
|
|
|
{
|
|
std::lock_guard<std::mutex> lock(queueMutex_);
|
|
|
|
if (eventQueue_.size() == 0) {
|
|
return;
|
|
}
|
|
|
|
queue = std::move(eventQueue_);
|
|
eventQueue_.clear();
|
|
}
|
|
|
|
eventProcessor_.flushEvents(runtime, std::move(queue));
|
|
}
|
|
|
|
void EventQueue::flushStateUpdates() const {
|
|
std::vector<StateUpdate> stateUpdateQueue;
|
|
|
|
{
|
|
std::lock_guard<std::mutex> lock(queueMutex_);
|
|
|
|
if (stateUpdateQueue_.empty()) {
|
|
return;
|
|
}
|
|
|
|
stateUpdateQueue = std::move(stateUpdateQueue_);
|
|
stateUpdateQueue_.clear();
|
|
}
|
|
|
|
eventProcessor_.flushStateUpdates(std::move(stateUpdateQueue));
|
|
}
|
|
|
|
} // namespace react
|
|
} // namespace facebook
|