diff --git a/packages/react-native/ReactCommon/react/renderer/dom/DOM.cpp b/packages/react-native/ReactCommon/react/renderer/dom/DOM.cpp index 811e59cdb1f..29412339e8a 100644 --- a/packages/react-native/ReactCommon/react/renderer/dom/DOM.cpp +++ b/packages/react-native/ReactCommon/react/renderer/dom/DOM.cpp @@ -72,9 +72,15 @@ ShadowNode::Shared getPositionedAncestorOfShadowNodeInRevision( auto ancestors = shadowNode.getFamily().getAncestors(*currentRevision); if (ancestors.empty()) { + // The node is no longer part of an active shadow tree, or is the root. return nullptr; } + if (ancestors.size() == 1) { + // The parent is the root + return currentRevision; + } + for (auto it = ancestors.rbegin(); it != ancestors.rend(); it++) { const auto layoutableAncestorShadowNode = dynamic_cast(&(it->first.get())); @@ -86,11 +92,9 @@ ShadowNode::Shared getPositionedAncestorOfShadowNodeInRevision( // We have found our nearest positioned ancestor, now to get a shared // pointer of it it++; - if (it != ancestors.rend()) { - return it->first.get().getChildren().at(it->second); - } - // else the positioned ancestor is the root which we return outside of the - // loop + return it == ancestors.rend() + ? currentRevision + : it->first.get().getChildren().at(it->second); } } diff --git a/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeDocument-itest.js b/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeDocument-itest.js index d6af1dafbe7..11aeacfa63d 100644 --- a/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeDocument-itest.js +++ b/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeDocument-itest.js @@ -122,6 +122,10 @@ describe('ReactNativeDocument', () => { expect(y).toBe(0); expect(width).toBe(200); expect(height).toBe(100); + + expect(document.documentElement.offsetParent).toBe(null); + expect(document.documentElement.offsetTop).toBe(0); + expect(document.documentElement.offsetLeft).toBe(0); }); it('implements compareDocumentPosition correctly', () => { diff --git a/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeElement-itest.js b/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeElement-itest.js index 1803022c8b4..dccd3d38895 100644 --- a/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeElement-itest.js +++ b/packages/react-native/src/private/webapis/dom/nodes/__tests__/ReactNativeElement-itest.js @@ -1064,7 +1064,7 @@ describe('ReactNativeElement', () => { }); describe('offsetParent / offsetTop / offsetLeft', () => { - it('retun the rounded offset values and the parent, or null and zeros when disconnected or hidden', () => { + it('return the rounded offset values and the parent, or null and zeros when disconnected or hidden', () => { const parentRef = createRef(); const elementRef = createRef(); @@ -1089,6 +1089,8 @@ describe('ReactNativeElement', () => { expect(element.offsetLeft).toBe(5); expect(element.offsetParent).toBe(parentElement); + expect(parentElement.offsetParent).toBe(root.document.documentElement); + Fantom.runTask(() => { root.render(