Skip to content

Commit 6389334

Browse files
rubennortefacebook-github-bot
authored andcommitted
Fix crash when accessing offsetParent from documentElement (#51773)
Summary: Pull Request resolved: #51773 Changelog: [internal] (This isn't a public API yet so not marking it as a bugfix). This fixes a crash in the `offsetParent` DOM API when called on a node whose parent is the `documentElement`. Reviewed By: andrewdacenko Differential Revision: D75876349 fbshipit-source-id: d90fcc3cb98f592c396cb0f5ee6ec80c9570745a
1 parent b4ae5c1 commit 6389334

3 files changed

Lines changed: 16 additions & 6 deletions

File tree

packages/react-native/ReactCommon/react/renderer/dom/DOM.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,15 @@ ShadowNode::Shared getPositionedAncestorOfShadowNodeInRevision(
7272
auto ancestors = shadowNode.getFamily().getAncestors(*currentRevision);
7373

7474
if (ancestors.empty()) {
75+
// The node is no longer part of an active shadow tree, or is the root.
7576
return nullptr;
7677
}
7778

79+
if (ancestors.size() == 1) {
80+
// The parent is the root
81+
return currentRevision;
82+
}
83+
7884
for (auto it = ancestors.rbegin(); it != ancestors.rend(); it++) {
7985
const auto layoutableAncestorShadowNode =
8086
dynamic_cast<const LayoutableShadowNode*>(&(it->first.get()));
@@ -86,11 +92,9 @@ ShadowNode::Shared getPositionedAncestorOfShadowNodeInRevision(
8692
// We have found our nearest positioned ancestor, now to get a shared
8793
// pointer of it
8894
it++;
89-
if (it != ancestors.rend()) {
90-
return it->first.get().getChildren().at(it->second);
91-
}
92-
// else the positioned ancestor is the root which we return outside of the
93-
// loop
95+
return it == ancestors.rend()
96+
? currentRevision
97+
: it->first.get().getChildren().at(it->second);
9498
}
9599
}
96100

packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeDocument-itest.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ describe('ReactNativeDocument', () => {
122122
expect(y).toBe(0);
123123
expect(width).toBe(200);
124124
expect(height).toBe(100);
125+
126+
expect(document.documentElement.offsetParent).toBe(null);
127+
expect(document.documentElement.offsetTop).toBe(0);
128+
expect(document.documentElement.offsetLeft).toBe(0);
125129
});
126130

127131
it('implements compareDocumentPosition correctly', () => {

packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeElement-itest.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1064,7 +1064,7 @@ describe('ReactNativeElement', () => {
10641064
});
10651065

10661066
describe('offsetParent / offsetTop / offsetLeft', () => {
1067-
it('retun the rounded offset values and the parent, or null and zeros when disconnected or hidden', () => {
1067+
it('return the rounded offset values and the parent, or null and zeros when disconnected or hidden', () => {
10681068
const parentRef = createRef<HostInstance>();
10691069
const elementRef = createRef<HostInstance>();
10701070

@@ -1089,6 +1089,8 @@ describe('ReactNativeElement', () => {
10891089
expect(element.offsetLeft).toBe(5);
10901090
expect(element.offsetParent).toBe(parentElement);
10911091

1092+
expect(parentElement.offsetParent).toBe(root.document.documentElement);
1093+
10921094
Fantom.runTask(() => {
10931095
root.render(
10941096
<View key="parent" style={{display: 'none'}}>

0 commit comments

Comments
 (0)