diff --git a/packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js b/packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js index 2ac6cb0a4b60..26de45076f35 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js @@ -1613,6 +1613,116 @@ describe('FragmentRefs', () => { ); }); + // @gate enableFragmentRefs + it('compares a root-level Fragment', async () => { + const fragmentRef = React.createRef(); + const emptyFragmentRef = React.createRef(); + const childRef = React.createRef(); + const siblingPrecedingRef = React.createRef(); + const siblingFollowingRef = React.createRef(); + const root = ReactDOMClient.createRoot(container); + + function Test() { + return ( + +
+ +
+ + +
+ + ); + } + + await act(() => root.render()); + + const fragmentInstance = fragmentRef.current; + if (fragmentInstance == null) { + throw new Error('Expected fragment instance to be non-null'); + } + const emptyFragmentInstance = emptyFragmentRef.current; + if (emptyFragmentInstance == null) { + throw new Error('Expected empty fragment instance to be non-null'); + } + + expectPosition( + fragmentInstance.compareDocumentPosition(childRef.current), + { + preceding: false, + following: false, + contains: false, + containedBy: true, + disconnected: false, + implementationSpecific: false, + }, + ); + + expectPosition( + fragmentInstance.compareDocumentPosition(siblingPrecedingRef.current), + { + preceding: true, + following: false, + contains: false, + containedBy: false, + disconnected: false, + implementationSpecific: false, + }, + ); + + expectPosition( + fragmentInstance.compareDocumentPosition(siblingFollowingRef.current), + { + preceding: false, + following: true, + contains: false, + containedBy: false, + disconnected: false, + implementationSpecific: false, + }, + ); + + expectPosition( + emptyFragmentInstance.compareDocumentPosition(childRef.current), + { + preceding: true, + following: false, + contains: false, + containedBy: false, + disconnected: false, + implementationSpecific: true, + }, + ); + + expectPosition( + emptyFragmentInstance.compareDocumentPosition( + siblingPrecedingRef.current, + ), + { + preceding: true, + following: false, + contains: false, + containedBy: false, + disconnected: false, + implementationSpecific: true, + }, + ); + + expectPosition( + emptyFragmentInstance.compareDocumentPosition( + siblingFollowingRef.current, + ), + { + preceding: false, + following: true, + contains: false, + containedBy: false, + disconnected: false, + implementationSpecific: true, + }, + ); + }); + describe('with portals', () => { // @gate enableFragmentRefs it('handles portaled elements', async () => { diff --git a/packages/react-native-renderer/src/ReactFiberConfigFabric.js b/packages/react-native-renderer/src/ReactFiberConfigFabric.js index 233c267a1d6a..19dd8af1b5ac 100644 --- a/packages/react-native-renderer/src/ReactFiberConfigFabric.js +++ b/packages/react-native-renderer/src/ReactFiberConfigFabric.js @@ -25,7 +25,6 @@ import type {Fiber} from 'react-reconciler/src/ReactInternalTypes'; import {HostText} from 'react-reconciler/src/ReactWorkTags'; import { getFragmentParentHostFiber, - getInstanceFromHostFiber, traverseFragmentInstance, } from 'react-reconciler/src/ReactFiberTreeReflection'; @@ -303,6 +302,13 @@ export function getPublicInstance(instance: Instance): null | PublicInstance { return instance.canonical.publicInstance; } + // Handle root containers + if (instance.containerInfo != null) { + if (instance.containerInfo.publicInstance != null) { + return instance.containerInfo.publicInstance; + } + } + // For compatibility with the legacy renderer, in case it's used with Fabric // in the same app. // $FlowExpectedError[prop-missing] @@ -347,9 +353,8 @@ export function getPublicInstanceFromInternalInstanceHandle( } function getPublicInstanceFromHostFiber(fiber: Fiber): PublicInstance { - const instance = getInstanceFromHostFiber(fiber); - const publicInstance = getPublicInstance(instance); - if (publicInstance == null) { + const publicInstance = getPublicInstance(fiber.stateNode); + if (publicInstance === null) { throw new Error('Expected to find a host node. This is a bug in React.'); } return publicInstance; @@ -691,11 +696,11 @@ FragmentInstance.prototype.compareDocumentPosition = function ( if (parentHostFiber === null) { return Node.DOCUMENT_POSITION_DISCONNECTED; } - const parentHostInstance = getPublicInstanceFromHostFiber(parentHostFiber); const children: Array = []; traverseFragmentInstance(this._fragmentFiber, collectChildren, children); if (children.length === 0) { - return compareDocumentPositionForEmptyFragment( + const parentHostInstance = getPublicInstanceFromHostFiber(parentHostFiber); + return compareDocumentPositionForEmptyFragment( this._fragmentFiber, parentHostInstance, otherNode,