Skip to content

Commit 089621e

Browse files
generatedunixname89002005232357facebook-github-bot
authored andcommitted
Revert D65085733 (#51520)
Summary: Pull Request resolved: #51520 Changelog: [Internal] - revert Intersection Observer `root` due to bug Reviewed By: lunaleaps Differential Revision: D75186289 fbshipit-source-id: d644b1ef3261996596af6a243076f7172d500167
1 parent 50ca7e5 commit 089621e

12 files changed

Lines changed: 48 additions & 758 deletions

File tree

packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9607,7 +9607,6 @@ exports[`public API should not change unintentionally src/private/webapis/inters
96079607
observer: IntersectionObserver
96089608
) => mixed;
96099609
export interface IntersectionObserverInit {
9610-
root?: ?ReactNativeElement;
96119610
threshold?: number | $ReadOnlyArray<number>;
96129611
rnRootThreshold?: number | $ReadOnlyArray<number>;
96139612
}

packages/react-native/ReactCommon/react/nativemodule/intersectionobserver/NativeIntersectionObserver.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,12 @@ jsi::Object NativeIntersectionObserver::observeV2(
7070
auto shadowNode =
7171
shadowNodeFromValue(runtime, std::move(options.targetShadowNode));
7272
auto shadowNodeFamily = shadowNode->getFamilyShared();
73-
74-
std::optional<ShadowNodeFamily::Shared> observationRootShadowNodeFamily;
75-
if (options.rootShadowNode.isObject()) {
76-
observationRootShadowNodeFamily =
77-
shadowNodeFromValue(runtime, options.rootShadowNode)->getFamilyShared();
78-
}
79-
8073
auto thresholds = options.thresholds;
8174
auto rootThresholds = options.rootThresholds;
8275
auto& uiManager = getUIManagerFromRuntime(runtime);
8376

8477
intersectionObserverManager_.observe(
8578
intersectionObserverId,
86-
observationRootShadowNodeFamily,
8779
shadowNodeFamily,
8880
thresholds,
8981
rootThresholds,

packages/react-native/ReactCommon/react/nativemodule/intersectionobserver/NativeIntersectionObserver.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ using NativeIntersectionObserverObserveOptions =
2222
NativeIntersectionObserverNativeIntersectionObserverObserveOptions<
2323
// intersectionObserverId
2424
NativeIntersectionObserverIntersectionObserverId,
25-
// rootShadowNode
26-
jsi::Value,
2725
// targetShadowNode
2826
jsi::Object,
2927
// thresholds

packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserver.cpp

Lines changed: 22 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,17 @@ namespace facebook::react {
1616

1717
IntersectionObserver::IntersectionObserver(
1818
IntersectionObserverObserverId intersectionObserverId,
19-
std::optional<ShadowNodeFamily::Shared> observationRootShadowNodeFamily,
2019
ShadowNodeFamily::Shared targetShadowNodeFamily,
2120
std::vector<Float> thresholds,
2221
std::optional<std::vector<Float>> rootThresholds)
2322
: intersectionObserverId_(intersectionObserverId),
24-
observationRootShadowNodeFamily_(
25-
std::move(observationRootShadowNodeFamily)),
2623
targetShadowNodeFamily_(std::move(targetShadowNodeFamily)),
2724
thresholds_(std::move(thresholds)),
2825
rootThresholds_(std::move(rootThresholds)) {}
2926

30-
static std::shared_ptr<const ShadowNode> getShadowNode(
31-
const ShadowNodeFamily::AncestorList& ancestors) {
32-
if (ancestors.empty()) {
33-
return nullptr;
34-
}
35-
36-
const auto& lastAncestor = ancestors.back();
37-
const ShadowNode& parentNode = lastAncestor.first.get();
38-
int childIndex = lastAncestor.second;
39-
40-
const std::shared_ptr<const ShadowNode>& childNode =
41-
parentNode.getChildren().at(childIndex);
42-
return childNode;
43-
}
44-
45-
static Rect getRootNodeBoundingRect(const RootShadowNode& rootShadowNode) {
46-
const auto layoutableRootShadowNode =
47-
dynamic_cast<const LayoutableShadowNode*>(&rootShadowNode);
48-
49-
react_native_assert(
50-
layoutableRootShadowNode != nullptr &&
51-
"RootShadowNode instances must always inherit from LayoutableShadowNode.");
52-
53-
auto layoutMetrics = layoutableRootShadowNode->getLayoutMetrics();
27+
static Rect getRootBoundingRect(
28+
const LayoutableShadowNode& layoutableRootShadowNode) {
29+
auto layoutMetrics = layoutableRootShadowNode.getLayoutMetrics();
5430

5531
if (layoutMetrics == EmptyLayoutMetrics ||
5632
layoutMetrics.displayType == DisplayType::None) {
@@ -59,12 +35,13 @@ static Rect getRootNodeBoundingRect(const RootShadowNode& rootShadowNode) {
5935

6036
// Apply the transform to translate the root view to its location in the
6137
// viewport.
62-
return layoutMetrics.frame * layoutableRootShadowNode->getTransform();
38+
return layoutMetrics.frame * layoutableRootShadowNode.getTransform();
6339
}
6440

65-
static Rect getBoundingRect(const ShadowNodeFamily::AncestorList& ancestors) {
41+
static Rect getTargetBoundingRect(
42+
const ShadowNodeFamily::AncestorList& targetAncestors) {
6643
auto layoutMetrics = LayoutableShadowNode::computeRelativeLayoutMetrics(
67-
ancestors,
44+
targetAncestors,
6845
{/* .includeTransform = */ true,
6946
/* .includeViewportOffset = */ true});
7047
return layoutMetrics == EmptyLayoutMetrics ? Rect{} : layoutMetrics.frame;
@@ -86,7 +63,7 @@ static Rect getClippedTargetBoundingRect(
8663
static Rect computeIntersection(
8764
const Rect& rootBoundingRect,
8865
const Rect& targetBoundingRect,
89-
const ShadowNodeFamily::AncestorList& targetToRootAncestors) {
66+
const ShadowNodeFamily::AncestorList& targetAncestors) {
9067
auto absoluteIntersectionRect =
9168
Rect::intersect(rootBoundingRect, targetBoundingRect);
9269

@@ -102,15 +79,10 @@ static Rect computeIntersection(
10279
return {};
10380
}
10481

105-
// Coordinates of the target after clipping the parts hidden by a parent,
106-
// until till the root (e.g.: in scroll views, or in views with a parent with
107-
// overflow: hidden)
108-
auto clippedTargetFromRoot =
109-
getClippedTargetBoundingRect(targetToRootAncestors);
110-
111-
auto clippedTargetBoundingRect = Rect{
112-
rootBoundingRect.origin + clippedTargetFromRoot.origin,
113-
clippedTargetFromRoot.size};
82+
// Coordinates of the target after clipping the parts hidden by a parent
83+
// (e.g.: in scroll views, or in views with a parent with overflow: hidden)
84+
auto clippedTargetBoundingRect =
85+
getClippedTargetBoundingRect(targetAncestors);
11486

11587
return Rect::intersect(rootBoundingRect, clippedTargetBoundingRect);
11688
}
@@ -133,34 +105,23 @@ std::optional<IntersectionObserverEntry>
133105
IntersectionObserver::updateIntersectionObservation(
134106
const RootShadowNode& rootShadowNode,
135107
double time) {
136-
bool hasCustomRoot = observationRootShadowNodeFamily_.has_value();
137-
138-
auto rootAncestors = hasCustomRoot
139-
? observationRootShadowNodeFamily_.value()->getAncestors(rootShadowNode)
140-
: ShadowNodeFamily::AncestorList{};
108+
const auto layoutableRootShadowNode =
109+
dynamic_cast<const LayoutableShadowNode*>(&rootShadowNode);
141110

142-
// Absolute coordinates of the root
143-
auto rootBoundingRect = hasCustomRoot
144-
? getBoundingRect(rootAncestors)
145-
: getRootNodeBoundingRect(rootShadowNode);
111+
react_native_assert(
112+
layoutableRootShadowNode != nullptr &&
113+
"RootShadowNode instances must always inherit from LayoutableShadowNode.");
146114

147115
auto targetAncestors = targetShadowNodeFamily_->getAncestors(rootShadowNode);
148116

149-
// Absolute coordinates of the target
150-
auto targetBoundingRect = getBoundingRect(targetAncestors);
151-
152-
if ((hasCustomRoot && rootAncestors.empty()) || targetAncestors.empty()) {
153-
// If observation root or target is not a descendant of `rootShadowNode`
154-
return setNotIntersectingState(
155-
rootBoundingRect, targetBoundingRect, {}, time);
156-
}
117+
// Absolute coordinates of the root
118+
auto rootBoundingRect = getRootBoundingRect(*layoutableRootShadowNode);
157119

158-
auto targetToRootAncestors = hasCustomRoot
159-
? targetShadowNodeFamily_->getAncestors(*getShadowNode(rootAncestors))
160-
: targetAncestors;
120+
// Absolute coordinates of the target
121+
auto targetBoundingRect = getTargetBoundingRect(targetAncestors);
161122

162123
auto intersectionRect = computeIntersection(
163-
rootBoundingRect, targetBoundingRect, targetToRootAncestors);
124+
rootBoundingRect, targetBoundingRect, targetAncestors);
164125

165126
Float targetBoundingRectArea =
166127
targetBoundingRect.size.width * targetBoundingRect.size.height;

packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserver.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ class IntersectionObserver {
4040
public:
4141
IntersectionObserver(
4242
IntersectionObserverObserverId intersectionObserverId,
43-
std::optional<ShadowNodeFamily::Shared> observationRootShadowNodeFamily,
4443
ShadowNodeFamily::Shared targetShadowNodeFamily,
4544
std::vector<Float> thresholds,
4645
std::optional<std::vector<Float>> rootThresholds = std::nullopt);
@@ -82,7 +81,6 @@ class IntersectionObserver {
8281
double time);
8382

8483
IntersectionObserverObserverId intersectionObserverId_;
85-
std::optional<ShadowNodeFamily::Shared> observationRootShadowNodeFamily_;
8684
ShadowNodeFamily::Shared targetShadowNodeFamily_;
8785
std::vector<Float> thresholds_;
8886
std::optional<std::vector<Float>> rootThresholds_;

packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserverManager.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ IntersectionObserverManager::IntersectionObserverManager() = default;
3939

4040
void IntersectionObserverManager::observe(
4141
IntersectionObserverObserverId intersectionObserverId,
42-
const std::optional<ShadowNodeFamily::Shared>&
43-
observationRootShadowNodeFamily,
4442
const ShadowNodeFamily::Shared& shadowNodeFamily,
4543
std::vector<Float> thresholds,
4644
std::optional<std::vector<Float>> rootThresholds,
@@ -60,7 +58,6 @@ void IntersectionObserverManager::observe(
6058
auto& observers = observersBySurfaceId_[surfaceId];
6159
observers.emplace_back(std::make_unique<IntersectionObserver>(
6260
intersectionObserverId,
63-
observationRootShadowNodeFamily,
6461
shadowNodeFamily,
6562
std::move(thresholds),
6663
std::move(rootThresholds)));

packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserverManager.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ class IntersectionObserverManager final
2727

2828
void observe(
2929
IntersectionObserverObserverId intersectionObserverId,
30-
const std::optional<ShadowNodeFamily::Shared>& observationRootShadowNode,
3130
const ShadowNodeFamily::Shared& shadowNode,
3231
std::vector<Float> thresholds,
3332
std::optional<std::vector<Float>> rootThresholds,

packages/react-native/src/private/webapis/intersectionobserver/IntersectionObserver.js

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export type IntersectionObserverCallback = (
2323
) => mixed;
2424

2525
export interface IntersectionObserverInit {
26-
root?: ?ReactNativeElement;
26+
// root?: ReactNativeElement, // This option exists on the Web but it's not currently supported in React Native.
2727
// rootMargin?: string, // This option exists on the Web but it's not currently supported in React Native.
2828
threshold?: number | $ReadOnlyArray<number>;
2929

@@ -67,7 +67,6 @@ export default class IntersectionObserver {
6767
_observationTargets: Set<ReactNativeElement> = new Set();
6868
_intersectionObserverId: ?IntersectionObserverId;
6969
_rootThresholds: $ReadOnlyArray<number> | null;
70-
_root: ReactNativeElement | null;
7170

7271
constructor(
7372
callback: IntersectionObserverCallback,
@@ -86,18 +85,16 @@ export default class IntersectionObserver {
8685
}
8786

8887
// $FlowExpectedError[prop-missing] it's not typed in React Native but exists on Web.
89-
if (options?.rootMargin != null) {
88+
if (options?.root != null) {
9089
throw new TypeError(
91-
"Failed to construct 'IntersectionObserver': rootMargin is not supported",
90+
"Failed to construct 'IntersectionObserver': root is not supported",
9291
);
9392
}
9493

95-
if (
96-
options?.root != null &&
97-
!(options?.root instanceof ReactNativeElement)
98-
) {
94+
// $FlowExpectedError[prop-missing] it's not typed in React Native but exists on Web.
95+
if (options?.rootMargin != null) {
9996
throw new TypeError(
100-
"Failed to construct 'IntersectionObserver': Failed to read the 'root' property from 'IntersectionObserverInit': The provided value is not of type '(null or ReactNativeElement)",
97+
"Failed to construct 'IntersectionObserver': rootMargin is not supported",
10198
);
10299
}
103100

@@ -108,7 +105,6 @@ export default class IntersectionObserver {
108105
options?.threshold,
109106
this._rootThresholds != null, // only provide default if no rootThreshold
110107
);
111-
this._root = options?.root ?? null;
112108
}
113109

114110
/**
@@ -120,7 +116,7 @@ export default class IntersectionObserver {
120116
* NOTE: This cannot currently be configured and `root` is always `null`.
121117
*/
122118
get root(): ReactNativeElement | null {
123-
return this._root;
119+
return null;
124120
}
125121

126122
/**
@@ -187,7 +183,6 @@ export default class IntersectionObserver {
187183

188184
const didStartObserving = IntersectionObserverManager.observe({
189185
intersectionObserverId: this._getOrCreateIntersectionObserverId(),
190-
root: this._root,
191186
target,
192187
});
193188

0 commit comments

Comments
 (0)