mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Remove pending records when unobserving a target in IntersectionObserver (#41450)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41450 `IntersectionObserver` shouldn't report entries for targets that are no longer being observed by the observer. This wasn't the case before because it was possible to create an intersection observer entry, then unobserve the target and then dispatch the pending entries (including the unobserved target). This fixes that issue to align with Web browsers. Changelog: [internal] Reviewed By: rshest Differential Revision: D51256827 fbshipit-source-id: 28035f00bcb05a8ca53140719019032b3399436c
This commit is contained in:
committed by
Facebook GitHub Bot
parent
fc0c084df0
commit
a493ea43ff
Vendored
+10
@@ -96,6 +96,16 @@ const NativeIntersectionObserverMock = {
|
||||
'unexpected duplicate call to unobserve',
|
||||
);
|
||||
observations.splice(observationIndex, 1);
|
||||
|
||||
pendingRecords = pendingRecords.filter(
|
||||
record =>
|
||||
record.intersectionObserverId !== intersectionObserverId ||
|
||||
record.targetInstanceHandle !==
|
||||
FabricUIManagerMock.__getInstanceHandleFromNode(
|
||||
// $FlowExpectedError[incompatible-call]
|
||||
targetShadowNode,
|
||||
),
|
||||
);
|
||||
},
|
||||
connect: (notifyIntersectionObserversCallback: () => void): void => {
|
||||
invariant(callback == null, 'unexpected call to connect');
|
||||
|
||||
+36
-20
@@ -70,31 +70,47 @@ void IntersectionObserverManager::unobserve(
|
||||
const ShadowNode& shadowNode) {
|
||||
SystraceSection s("IntersectionObserverManager::unobserve");
|
||||
|
||||
std::unique_lock lock(observersMutex_);
|
||||
{
|
||||
std::unique_lock lock(observersMutex_);
|
||||
|
||||
auto surfaceId = shadowNode.getSurfaceId();
|
||||
auto surfaceId = shadowNode.getSurfaceId();
|
||||
|
||||
auto observersIt = observersBySurfaceId_.find(surfaceId);
|
||||
if (observersIt == observersBySurfaceId_.end()) {
|
||||
return;
|
||||
auto observersIt = observersBySurfaceId_.find(surfaceId);
|
||||
if (observersIt == observersBySurfaceId_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& observers = observersIt->second;
|
||||
|
||||
observers.erase(
|
||||
std::remove_if(
|
||||
observers.begin(),
|
||||
observers.end(),
|
||||
[intersectionObserverId, &shadowNode](const auto& observer) {
|
||||
return observer.getIntersectionObserverId() ==
|
||||
intersectionObserverId &&
|
||||
ShadowNode::sameFamily(
|
||||
observer.getTargetShadowNode(), shadowNode);
|
||||
}),
|
||||
observers.end());
|
||||
|
||||
if (observers.empty()) {
|
||||
observersBySurfaceId_.erase(surfaceId);
|
||||
}
|
||||
}
|
||||
|
||||
auto& observers = observersIt->second;
|
||||
{
|
||||
std::unique_lock lock(pendingEntriesMutex_);
|
||||
|
||||
observers.erase(
|
||||
std::remove_if(
|
||||
observers.begin(),
|
||||
observers.end(),
|
||||
[intersectionObserverId, &shadowNode](const auto& observer) {
|
||||
return observer.getIntersectionObserverId() ==
|
||||
intersectionObserverId &&
|
||||
ShadowNode::sameFamily(
|
||||
observer.getTargetShadowNode(), shadowNode);
|
||||
}),
|
||||
observers.end());
|
||||
|
||||
if (observers.empty()) {
|
||||
observersBySurfaceId_.erase(surfaceId);
|
||||
pendingEntries_.erase(
|
||||
std::remove_if(
|
||||
pendingEntries_.begin(),
|
||||
pendingEntries_.end(),
|
||||
[intersectionObserverId, &shadowNode](const auto& entry) {
|
||||
return entry.intersectionObserverId == intersectionObserverId &&
|
||||
ShadowNode::sameFamily(*entry.shadowNode, shadowNode);
|
||||
}),
|
||||
pendingEntries_.end());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user