Skip to content

Commit

Permalink
Remove pending records when unobserving a target in IntersectionObser…
Browse files Browse the repository at this point in the history
…ver (facebook#41450)

Summary:

`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]

Differential Revision: D51256827
  • Loading branch information
rubennorte authored and facebook-github-bot committed Nov 14, 2023
1 parent ca04723 commit b9b4379
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

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);
{
std::unique_lock lock(pendingEntriesMutex_);

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());
}
}

Expand Down

0 comments on commit b9b4379

Please sign in to comment.