mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fix bug in IntersectionObserver (#44439)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44439 Changelog: [internal] (IntersectionObserver isn't enabled yet in OSS). This fixes a bug in `IntersectionObserver` when observing the same target in multiple observers. In that case, the first time we `unobserve` we clean up some metadata that's shared across observers, and other observers observing the target have problems with the missing data. This fixes the problem by removing the clean up, as the data structure backing this information is a `WeakMap` anyway, so it'll be cleaned up automatically eventually, and the stored data is very small. Reviewed By: twobassdrum Differential Revision: D57046864 fbshipit-source-id: b001cf1ae4f4c91b74b1ad487e01691d5f3be1ce
This commit is contained in:
committed by
Facebook GitHub Bot
parent
a23ae9c7f2
commit
024f3357bb
+6
-26
@@ -67,19 +67,11 @@ function setTargetForInstanceHandle(
|
||||
instanceHandleToTargetMap.set(key, target);
|
||||
}
|
||||
|
||||
function unsetTargetForInstanceHandle(instanceHandle: mixed): void {
|
||||
// $FlowExpectedError[incompatible-type] instanceHandle is typed as mixed but we know it's an object and we need it to be to use it as a key in a WeakMap.
|
||||
const key: interface {} = instanceHandle;
|
||||
instanceHandleToTargetMap.delete(key);
|
||||
}
|
||||
|
||||
// The mapping between ReactNativeElement and their corresponding shadow node
|
||||
// also needs to be kept here because React removes the link when unmounting.
|
||||
// We also keep the instance handle so we don't have to retrieve it again
|
||||
// from the target to unobserve.
|
||||
const targetToShadowNodeAndInstanceHandleMap: WeakMap<
|
||||
const targetToShadowNodeMap: WeakMap<
|
||||
ReactNativeElement,
|
||||
[ReturnType<typeof getShadowNode>, mixed],
|
||||
ReturnType<typeof getShadowNode>,
|
||||
> = new WeakMap();
|
||||
|
||||
/**
|
||||
@@ -163,12 +155,8 @@ export function observe({
|
||||
// access it even after the instance handle has been unmounted.
|
||||
setTargetForInstanceHandle(instanceHandle, target);
|
||||
|
||||
// Same for the mapping between the target and its shadow node
|
||||
// and instance handle.
|
||||
targetToShadowNodeAndInstanceHandleMap.set(target, [
|
||||
targetShadowNode,
|
||||
instanceHandle,
|
||||
]);
|
||||
// Same for the mapping between the target and its shadow node.
|
||||
targetToShadowNodeMap.set(target, targetShadowNode);
|
||||
|
||||
if (!isConnected) {
|
||||
NativeIntersectionObserver.connect(notifyIntersectionObservers);
|
||||
@@ -201,26 +189,18 @@ export function unobserve(
|
||||
return;
|
||||
}
|
||||
|
||||
const targetShadowNodeAndInstanceHandle =
|
||||
targetToShadowNodeAndInstanceHandleMap.get(target);
|
||||
if (targetShadowNodeAndInstanceHandle == null) {
|
||||
const targetShadowNode = targetToShadowNodeMap.get(target);
|
||||
if (targetShadowNode == null) {
|
||||
console.error(
|
||||
'IntersectionObserverManager: could not find registration data for target',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const [targetShadowNode, instanceHandle] = targetShadowNodeAndInstanceHandle;
|
||||
|
||||
NativeIntersectionObserver.unobserve(
|
||||
intersectionObserverId,
|
||||
targetShadowNode,
|
||||
);
|
||||
|
||||
// We can guarantee we won't receive any more entries for this target,
|
||||
// so we don't need to keep the mappings anymore.
|
||||
unsetTargetForInstanceHandle(instanceHandle);
|
||||
targetToShadowNodeAndInstanceHandleMap.delete(target);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user