From 9f039d8b0267cc84b60b36ae8296d195b50780ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Thu, 16 Mar 2023 17:00:56 +0000 Subject: [PATCH] Revert "Extracted definition and access to public instances to a separate module in Fabric (#26321)" This reverts commit f828bad387f573c462d2a58afb38aea8bdbe9cb5. --- .../react-native-renderer/src/ReactFabric.js | 5 - .../src/ReactFabricComponentTree.js | 8 +- .../src/ReactFabricHostConfig.js | 202 ++++++++++++++---- .../src/ReactFabricPublicInstance.js | 153 ------------- .../src/ReactFabricPublicInstanceUtils.js | 29 --- .../src/ReactNativeComponentTree.js | 5 +- .../src/ReactNativeFiberInspector.js | 34 +-- .../src/ReactNativeHostConfig.js | 4 +- .../src/ReactNativePublicCompat.js | 103 ++------- .../src/ReactNativeTypes.js | 3 - .../__tests__/ReactFabric-test.internal.js | 40 +--- .../ReactFabricAndNative-test.internal.js | 5 +- scripts/flow/react-native-host-hooks.js | 14 +- 13 files changed, 213 insertions(+), 392 deletions(-) delete mode 100644 packages/react-native-renderer/src/ReactFabricPublicInstance.js delete mode 100644 packages/react-native-renderer/src/ReactFabricPublicInstanceUtils.js diff --git a/packages/react-native-renderer/src/ReactFabric.js b/packages/react-native-renderer/src/ReactFabric.js index a6e2bd883b84f..84d5651f83be1 100644 --- a/packages/react-native-renderer/src/ReactFabric.js +++ b/packages/react-native-renderer/src/ReactFabric.js @@ -38,7 +38,6 @@ import { findNodeHandle, dispatchCommand, sendAccessibilityEvent, - getNodeFromInternalInstanceHandle, } from './ReactNativePublicCompat'; // $FlowFixMe[missing-local-annot] @@ -120,10 +119,6 @@ export { // This export is typically undefined in production builds. // See the "enableGetInspectorDataForInstanceInProduction" flag. getInspectorDataForInstance, - // The public instance has a reference to the internal instance handle. - // This method allows it to acess the most recent shadow node for - // the instance (it's only accessible through it). - getNodeFromInternalInstanceHandle, }; injectIntoDevTools({ diff --git a/packages/react-native-renderer/src/ReactFabricComponentTree.js b/packages/react-native-renderer/src/ReactFabricComponentTree.js index b1cc8642dee70..4cdb1ca81505c 100644 --- a/packages/react-native-renderer/src/ReactFabricComponentTree.js +++ b/packages/react-native-renderer/src/ReactFabricComponentTree.js @@ -20,12 +20,6 @@ import {getPublicInstance} from './ReactFabricHostConfig'; // This is ok in DOM because they types are interchangeable, but in React Native // they aren't. function getInstanceFromNode(node: Instance | TextInstance): Fiber | null { - const instance: Instance = (node: $FlowFixMe); // In React Native, node is never a text instance - - if (instance.internalInstanceHandle != null) { - return instance.internalInstanceHandle; - } - // $FlowFixMe[incompatible-return] DevTools incorrectly passes a fiber in React Native. return node; } @@ -41,7 +35,7 @@ function getNodeFromInstance(fiber: Fiber): PublicInstance { } function getFiberCurrentPropsFromNode(instance: Instance): Props { - return instance.currentProps; + return instance.canonical.currentProps; } export { diff --git a/packages/react-native-renderer/src/ReactFabricHostConfig.js b/packages/react-native-renderer/src/ReactFabricHostConfig.js index 0b2dfd0ffe91f..717a496453eda 100644 --- a/packages/react-native-renderer/src/ReactFabricHostConfig.js +++ b/packages/react-native-renderer/src/ReactFabricHostConfig.js @@ -7,13 +7,22 @@ * @flow */ -import type {TouchedViewDataAtPoint, ViewConfig} from './ReactNativeTypes'; -import { - createPublicInstance, - type ReactFabricHostComponent, -} from './ReactFabricPublicInstance'; +import type {ElementRef} from 'react'; +import type { + HostComponent, + MeasureInWindowOnSuccessCallback, + MeasureLayoutOnSuccessCallback, + MeasureOnSuccessCallback, + INativeMethods, + ViewConfig, + TouchedViewDataAtPoint, +} from './ReactNativeTypes'; + +import {warnForStyleProps} from './NativeMethodsMixinUtils'; import {create, diff} from './ReactNativeAttributePayload'; + import {dispatchEvent} from './ReactFabricEventEmitter'; + import { DefaultEventPriority, DiscreteEventPriority, @@ -22,6 +31,7 @@ import { // Modules provided by RN: import { ReactNativeViewConfigRegistry, + TextInputState, deepFreezeAndThrowOnMutationInDev, } from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface'; @@ -36,9 +46,14 @@ const { appendChildToSet: appendChildNodeToSet, completeRoot, registerEventHandler, + measure: fabricMeasure, + measureInWindow: fabricMeasureInWindow, + measureLayout: fabricMeasureLayout, unstable_DefaultEventPriority: FabricDefaultPriority, unstable_DiscreteEventPriority: FabricDiscretePriority, unstable_getCurrentEventPriority: fabricGetCurrentEventPriority, + setNativeProps, + getBoundingClientRect: fabricGetBoundingClientRect, } = nativeFabricUIManager; const {get: getViewConfigForType} = ReactNativeViewConfigRegistry; @@ -53,15 +68,9 @@ type Node = Object; export type Type = string; export type Props = Object; export type Instance = { - // Reference to the shadow node. node: Node, - nativeTag: number, - viewConfig: ViewConfig, - currentProps: Props, - // Reference to the React handle (the fiber) - internalInstanceHandle: Object, - // Exposed through refs. - publicInstance: ReactFabricHostComponent, + canonical: ReactFabricHostComponent, + ... }; export type TextInstance = {node: Node, ...}; export type HydratableInstance = Instance | TextInstance; @@ -95,6 +104,137 @@ if (registerEventHandler) { registerEventHandler(dispatchEvent); } +const noop = () => {}; + +/** + * This is used for refs on host components. + */ +class ReactFabricHostComponent implements INativeMethods { + _nativeTag: number; + viewConfig: ViewConfig; + currentProps: Props; + _internalInstanceHandle: Object; + + constructor( + tag: number, + viewConfig: ViewConfig, + props: Props, + internalInstanceHandle: Object, + ) { + this._nativeTag = tag; + this.viewConfig = viewConfig; + this.currentProps = props; + this._internalInstanceHandle = internalInstanceHandle; + } + + blur() { + TextInputState.blurTextInput(this); + } + + focus() { + TextInputState.focusTextInput(this); + } + + measure(callback: MeasureOnSuccessCallback) { + const node = getShadowNodeFromInternalInstanceHandle( + this._internalInstanceHandle, + ); + if (node != null) { + fabricMeasure(node, callback); + } + } + + measureInWindow(callback: MeasureInWindowOnSuccessCallback) { + const node = getShadowNodeFromInternalInstanceHandle( + this._internalInstanceHandle, + ); + if (node != null) { + fabricMeasureInWindow(node, callback); + } + } + + measureLayout( + relativeToNativeNode: number | ElementRef>, + onSuccess: MeasureLayoutOnSuccessCallback, + onFail?: () => void /* currently unused */, + ) { + if ( + typeof relativeToNativeNode === 'number' || + !(relativeToNativeNode instanceof ReactFabricHostComponent) + ) { + if (__DEV__) { + console.error( + 'Warning: ref.measureLayout must be called with a ref to a native component.', + ); + } + + return; + } + + const toStateNode = getShadowNodeFromInternalInstanceHandle( + this._internalInstanceHandle, + ); + const fromStateNode = getShadowNodeFromInternalInstanceHandle( + relativeToNativeNode._internalInstanceHandle, + ); + + if (toStateNode != null && fromStateNode != null) { + fabricMeasureLayout( + toStateNode, + fromStateNode, + onFail != null ? onFail : noop, + onSuccess != null ? onSuccess : noop, + ); + } + } + + unstable_getBoundingClientRect(): DOMRect { + const node = getShadowNodeFromInternalInstanceHandle( + this._internalInstanceHandle, + ); + if (node != null) { + const rect = fabricGetBoundingClientRect(node); + + if (rect) { + return new DOMRect(rect[0], rect[1], rect[2], rect[3]); + } + } + + // Empty rect if any of the above failed + return new DOMRect(0, 0, 0, 0); + } + + setNativeProps(nativeProps: Object) { + if (__DEV__) { + warnForStyleProps(nativeProps, this.viewConfig.validAttributes); + } + const updatePayload = create(nativeProps, this.viewConfig.validAttributes); + + const node = getShadowNodeFromInternalInstanceHandle( + this._internalInstanceHandle, + ); + if (node != null && updatePayload != null) { + setNativeProps(node, updatePayload); + } + } +} + +type ParamOf = $Call<((arg: T) => mixed) => T, Fn>; +type ShadowNode = ParamOf<(typeof nativeFabricUIManager)['measure']>; + +export function getShadowNodeFromInternalInstanceHandle( + internalInstanceHandle: mixed, +): ?ShadowNode { + return ( + // $FlowExpectedError[incompatible-return] internalInstanceHandle is opaque but we need to make an exception here. + internalInstanceHandle && + // $FlowExpectedError[incompatible-return] + internalInstanceHandle.stateNode && + // $FlowExpectedError[incompatible-use] + internalInstanceHandle.stateNode.node + ); +} + export * from 'react-reconciler/src/ReactFiberHostConfigWithNoMutation'; export * from 'react-reconciler/src/ReactFiberHostConfigWithNoHydration'; export * from 'react-reconciler/src/ReactFiberHostConfigWithNoScopes'; @@ -140,19 +280,16 @@ export function createInstance( internalInstanceHandle, // internalInstanceHandle ); - const component = createPublicInstance( + const component = new ReactFabricHostComponent( tag, viewConfig, + props, internalInstanceHandle, ); return { node: node, - nativeTag: tag, - viewConfig, - currentProps: props, - internalInstanceHandle, - publicInstance: component, + canonical: component, }; } @@ -222,15 +359,12 @@ export function getChildHostContext( } export function getPublicInstance(instance: Instance): null | PublicInstance { - if (instance.publicInstance != null) { - return instance.publicInstance; + if (instance.canonical) { + return instance.canonical; } - // For compatibility with the legacy renderer, in case it's used with Fabric - // in the same app. - // $FlowExpectedError[prop-missing] + // For compatibility with Paper if (instance._nativeTag != null) { - // $FlowExpectedError[incompatible-return] return instance; } @@ -249,12 +383,12 @@ export function prepareUpdate( newProps: Props, hostContext: HostContext, ): null | Object { - const viewConfig = instance.viewConfig; + const viewConfig = instance.canonical.viewConfig; const updatePayload = diff(oldProps, newProps, viewConfig.validAttributes); // TODO: If the event handlers have changed, we need to update the current props // in the commit phase but there is no host config hook to do it yet. // So instead we hack it by updating it in the render phase. - instance.currentProps = newProps; + instance.canonical.currentProps = newProps; return updatePayload; } @@ -333,11 +467,7 @@ export function cloneInstance( } return { node: clone, - nativeTag: instance.nativeTag, - viewConfig: instance.viewConfig, - currentProps: instance.currentProps, - internalInstanceHandle: instance.internalInstanceHandle, - publicInstance: instance.publicInstance, + canonical: instance.canonical, }; } @@ -347,7 +477,7 @@ export function cloneHiddenInstance( props: Props, internalInstanceHandle: Object, ): Instance { - const viewConfig = instance.viewConfig; + const viewConfig = instance.canonical.viewConfig; const node = instance.node; const updatePayload = create( {style: {display: 'none'}}, @@ -355,11 +485,7 @@ export function cloneHiddenInstance( ); return { node: cloneNodeWithNewProps(node, updatePayload), - nativeTag: instance.nativeTag, - viewConfig: instance.viewConfig, - currentProps: instance.currentProps, - internalInstanceHandle: instance.internalInstanceHandle, - publicInstance: instance.publicInstance, + canonical: instance.canonical, }; } diff --git a/packages/react-native-renderer/src/ReactFabricPublicInstance.js b/packages/react-native-renderer/src/ReactFabricPublicInstance.js deleted file mode 100644 index 282e5af7cde1e..0000000000000 --- a/packages/react-native-renderer/src/ReactFabricPublicInstance.js +++ /dev/null @@ -1,153 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - */ - -import type {ElementRef} from 'react'; -import type { - ViewConfig, - INativeMethods, - HostComponent, - MeasureInWindowOnSuccessCallback, - MeasureLayoutOnSuccessCallback, - MeasureOnSuccessCallback, -} from './ReactNativeTypes'; - -import {TextInputState} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface'; -import {create} from './ReactNativeAttributePayload'; -import {warnForStyleProps} from './NativeMethodsMixinUtils'; -import {getNodeFromInternalInstanceHandle} from './ReactNativePublicCompat'; - -const { - measure: fabricMeasure, - measureInWindow: fabricMeasureInWindow, - measureLayout: fabricMeasureLayout, - setNativeProps, - getBoundingClientRect: fabricGetBoundingClientRect, -} = nativeFabricUIManager; - -const noop = () => {}; - -/** - * This is used for refs on host components. - */ -export class ReactFabricHostComponent implements INativeMethods { - // These need to be accessible from `ReactFabricPublicInstanceUtils`. - __nativeTag: number; - __internalInstanceHandle: mixed; - - _viewConfig: ViewConfig; - - constructor( - tag: number, - viewConfig: ViewConfig, - internalInstanceHandle: mixed, - ) { - this.__nativeTag = tag; - this._viewConfig = viewConfig; - this.__internalInstanceHandle = internalInstanceHandle; - } - - blur() { - TextInputState.blurTextInput(this); - } - - focus() { - TextInputState.focusTextInput(this); - } - - measure(callback: MeasureOnSuccessCallback) { - const node = getNodeFromInternalInstanceHandle( - this.__internalInstanceHandle, - ); - if (node != null) { - fabricMeasure(node, callback); - } - } - - measureInWindow(callback: MeasureInWindowOnSuccessCallback) { - const node = getNodeFromInternalInstanceHandle( - this.__internalInstanceHandle, - ); - if (node != null) { - fabricMeasureInWindow(node, callback); - } - } - - measureLayout( - relativeToNativeNode: number | ElementRef>, - onSuccess: MeasureLayoutOnSuccessCallback, - onFail?: () => void /* currently unused */, - ) { - if ( - typeof relativeToNativeNode === 'number' || - !(relativeToNativeNode instanceof ReactFabricHostComponent) - ) { - if (__DEV__) { - console.error( - 'Warning: ref.measureLayout must be called with a ref to a native component.', - ); - } - - return; - } - - const toStateNode = getNodeFromInternalInstanceHandle( - this.__internalInstanceHandle, - ); - const fromStateNode = getNodeFromInternalInstanceHandle( - relativeToNativeNode.__internalInstanceHandle, - ); - - if (toStateNode != null && fromStateNode != null) { - fabricMeasureLayout( - toStateNode, - fromStateNode, - onFail != null ? onFail : noop, - onSuccess != null ? onSuccess : noop, - ); - } - } - - unstable_getBoundingClientRect(): DOMRect { - const node = getNodeFromInternalInstanceHandle( - this.__internalInstanceHandle, - ); - if (node != null) { - const rect = fabricGetBoundingClientRect(node); - - if (rect) { - return new DOMRect(rect[0], rect[1], rect[2], rect[3]); - } - } - - // Empty rect if any of the above failed - return new DOMRect(0, 0, 0, 0); - } - - setNativeProps(nativeProps: {...}): void { - if (__DEV__) { - warnForStyleProps(nativeProps, this._viewConfig.validAttributes); - } - const updatePayload = create(nativeProps, this._viewConfig.validAttributes); - - const node = getNodeFromInternalInstanceHandle( - this.__internalInstanceHandle, - ); - if (node != null && updatePayload != null) { - setNativeProps(node, updatePayload); - } - } -} - -export function createPublicInstance( - tag: number, - viewConfig: ViewConfig, - internalInstanceHandle: mixed, -): ReactFabricHostComponent { - return new ReactFabricHostComponent(tag, viewConfig, internalInstanceHandle); -} diff --git a/packages/react-native-renderer/src/ReactFabricPublicInstanceUtils.js b/packages/react-native-renderer/src/ReactFabricPublicInstanceUtils.js deleted file mode 100644 index a1d9fbea4dcc5..0000000000000 --- a/packages/react-native-renderer/src/ReactFabricPublicInstanceUtils.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - */ - -import type {ReactFabricHostComponent} from './ReactFabricPublicInstance'; - -/** - * IMPORTANT: This module is used in Paper and Fabric. It needs to be defined - * outside of `ReactFabricPublicInstance` because that module requires - * `nativeFabricUIManager` to be defined in the global scope (which does not - * happen in Paper). - */ - -export function getNativeTagFromPublicInstance( - publicInstance: ReactFabricHostComponent, -): number { - return publicInstance.__nativeTag; -} - -export function getInternalInstanceHandleFromPublicInstance( - publicInstance: ReactFabricHostComponent, -): mixed { - return publicInstance.__internalInstanceHandle; -} diff --git a/packages/react-native-renderer/src/ReactNativeComponentTree.js b/packages/react-native-renderer/src/ReactNativeComponentTree.js index 7021610daf20d..3af3fa5a443f5 100644 --- a/packages/react-native-renderer/src/ReactNativeComponentTree.js +++ b/packages/react-native-renderer/src/ReactNativeComponentTree.js @@ -25,9 +25,8 @@ function getTagFromInstance(inst) { let nativeInstance = inst.stateNode; let tag = nativeInstance._nativeTag; if (tag === undefined) { - // For compatibility with Fabric - tag = nativeInstance.nativeTag; - nativeInstance = nativeInstance.publicInstance; + nativeInstance = nativeInstance.canonical; + tag = nativeInstance._nativeTag; } if (!tag) { diff --git a/packages/react-native-renderer/src/ReactNativeFiberInspector.js b/packages/react-native-renderer/src/ReactNativeFiberInspector.js index 57d9b0542c37b..d977236a32558 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberInspector.js +++ b/packages/react-native-renderer/src/ReactNativeFiberInspector.js @@ -20,8 +20,6 @@ import {HostComponent} from 'react-reconciler/src/ReactWorkTags'; import {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface'; import {enableGetInspectorDataForInstanceInProduction} from 'shared/ReactFeatureFlags'; import {getClosestInstanceFromNode} from './ReactNativeComponentTree'; -import {getInternalInstanceHandleFromPublicInstance} from './ReactFabricPublicInstanceUtils'; -import {getNodeFromInternalInstanceHandle} from './ReactNativePublicCompat'; const emptyObject = {}; if (__DEV__) { @@ -37,15 +35,15 @@ function createHierarchy(fiberHierarchy) { props: getHostProps(fiber), source: fiber._debugSource, measure: callback => { - // If this is Fabric, we'll find a shadow node and use that to measure. + // If this is Fabric, we'll find a ShadowNode and use that to measure. const hostFiber = findCurrentHostFiber(fiber); - const node = + const shadowNode = hostFiber != null && hostFiber.stateNode !== null && hostFiber.stateNode.node; - if (node) { - nativeFabricUIManager.measure(node, callback); + if (shadowNode) { + nativeFabricUIManager.measure(shadowNode, callback); } else { return UIManager.measure( getHostNode(fiber, findNodeHandle), @@ -196,40 +194,30 @@ function getInspectorDataForViewAtPoint( if (__DEV__) { let closestInstance = null; - const fabricInstanceHandle = - getInternalInstanceHandleFromPublicInstance(inspectedView); - const fabricNode = - fabricInstanceHandle != null - ? getNodeFromInternalInstanceHandle(fabricInstanceHandle) - : null; - if (fabricNode) { + if (inspectedView._internalInstanceHandle != null) { // For Fabric we can look up the instance handle directly and measure it. nativeFabricUIManager.findNodeAtPoint( - fabricNode, + inspectedView._internalInstanceHandle.stateNode.node, locationX, locationY, internalInstanceHandle => { - const node = - internalInstanceHandle != null - ? getNodeFromInternalInstanceHandle(internalInstanceHandle) - : null; - if (internalInstanceHandle == null || node == null) { + if (internalInstanceHandle == null) { callback({ pointerY: locationY, frame: {left: 0, top: 0, width: 0, height: 0}, ...getInspectorDataForInstance(closestInstance), }); - return; } closestInstance = - internalInstanceHandle.stateNode.internalInstanceHandle; + internalInstanceHandle.stateNode.canonical._internalInstanceHandle; // Note: this is deprecated and we want to remove it ASAP. Keeping it here for React DevTools compatibility for now. - const nativeViewTag = internalInstanceHandle.stateNode.nativeTag; + const nativeViewTag = + internalInstanceHandle.stateNode.canonical._nativeTag; nativeFabricUIManager.measure( - node, + internalInstanceHandle.stateNode.node, (x, y, width, height, pageX, pageY) => { const inspectorData = getInspectorDataForInstance(closestInstance); diff --git a/packages/react-native-renderer/src/ReactNativeHostConfig.js b/packages/react-native-renderer/src/ReactNativeHostConfig.js index 330875debaefd..a3b58315205f3 100644 --- a/packages/react-native-renderer/src/ReactNativeHostConfig.js +++ b/packages/react-native-renderer/src/ReactNativeHostConfig.js @@ -218,8 +218,8 @@ export function getChildHostContext( export function getPublicInstance(instance: Instance): * { // $FlowExpectedError[prop-missing] For compatibility with Fabric - if (instance.publicInstance != null) { - return instance.publicInstance; + if (instance.canonical) { + return instance.canonical; } return instance; diff --git a/packages/react-native-renderer/src/ReactNativePublicCompat.js b/packages/react-native-renderer/src/ReactNativePublicCompat.js index 527983af6d593..a6be670d912cb 100644 --- a/packages/react-native-renderer/src/ReactNativePublicCompat.js +++ b/packages/react-native-renderer/src/ReactNativePublicCompat.js @@ -7,7 +7,7 @@ * @flow */ -import type {Node, HostComponent} from './ReactNativeTypes'; +import type {HostComponent} from './ReactNativeTypes'; import type {ElementRef, ElementType} from 'react'; // Modules provided by RN: @@ -23,11 +23,6 @@ import { import ReactSharedInternals from 'shared/ReactSharedInternals'; import getComponentNameFromType from 'shared/getComponentNameFromType'; -import { - getInternalInstanceHandleFromPublicInstance, - getNativeTagFromPublicInstance, -} from './ReactFabricPublicInstanceUtils'; - const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; export function findHostInstance_DEPRECATED( @@ -50,24 +45,19 @@ export function findHostInstance_DEPRECATED( owner.stateNode._warnedAboutRefsInRender = true; } } - if (componentOrHandle == null) { return null; } - - // For compatibility with Fabric instances - if (componentOrHandle.publicInstance) { - // $FlowExpectedError[incompatible-return] Can't refine componentOrHandle as a Fabric instance - return componentOrHandle.publicInstance; - } - - // For compatibility with legacy renderer instances + // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN if (componentOrHandle._nativeTag) { - // $FlowFixMe[incompatible-exact] Necessary when running Flow on Fabric - // $FlowFixMe[incompatible-return] + // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN return componentOrHandle; } - + // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN + if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { + // $FlowFixMe Flow has hardcoded values for React DOM that don't work with RN + return componentOrHandle.canonical; + } let hostInstance; if (__DEV__) { hostInstance = findHostInstanceWithWarning( @@ -78,7 +68,6 @@ export function findHostInstance_DEPRECATED( hostInstance = findHostInstance(componentOrHandle); } - // findHostInstance handles legacy vs. Fabric differences correctly // $FlowFixMe[incompatible-exact] we need to fix the definition of `HostComponent` to use NativeMethods as an interface, not as a type. return hostInstance; } @@ -101,32 +90,19 @@ export function findNodeHandle(componentOrHandle: any): ?number { owner.stateNode._warnedAboutRefsInRender = true; } } - if (componentOrHandle == null) { return null; } - if (typeof componentOrHandle === 'number') { // Already a node handle return componentOrHandle; } - - // For compatibility with legacy renderer instances if (componentOrHandle._nativeTag) { return componentOrHandle._nativeTag; } - - // For compatibility with Fabric instances - if (componentOrHandle.nativeTag != null) { - return componentOrHandle.nativeTag; + if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { + return componentOrHandle.canonical._nativeTag; } - - // For compatibility with Fabric public instances - const nativeTag = getNativeTagFromPublicInstance(componentOrHandle); - if (nativeTag) { - return nativeTag; - } - let hostInstance; if (__DEV__) { hostInstance = findHostInstanceWithWarning( @@ -141,14 +117,7 @@ export function findNodeHandle(componentOrHandle: any): ?number { return hostInstance; } - // $FlowFixMe[prop-missing] For compatibility with legacy renderer instances - if (hostInstance._nativeTag != null) { - // $FlowFixMe[incompatible-return] - return hostInstance._nativeTag; - } - - // $FlowFixMe[incompatible-call] Necessary when running Flow on the legacy renderer - return getNativeTagFromPublicInstance(hostInstance); + return hostInstance._nativeTag; } export function dispatchCommand( @@ -156,11 +125,7 @@ export function dispatchCommand( command: string, args: Array, ) { - const nativeTag = - handle._nativeTag != null - ? handle._nativeTag - : getNativeTagFromPublicInstance(handle); - if (nativeTag == null) { + if (handle._nativeTag == null) { if (__DEV__) { console.error( "dispatchCommand was called with a ref that isn't a " + @@ -170,25 +135,18 @@ export function dispatchCommand( return; } - const internalInstanceHandle = - getInternalInstanceHandleFromPublicInstance(handle); - - if (internalInstanceHandle != null) { - const node = getNodeFromInternalInstanceHandle(internalInstanceHandle); - if (node != null) { - nativeFabricUIManager.dispatchCommand(node, command, args); + if (handle._internalInstanceHandle != null) { + const {stateNode} = handle._internalInstanceHandle; + if (stateNode != null) { + nativeFabricUIManager.dispatchCommand(stateNode.node, command, args); } } else { - UIManager.dispatchViewManagerCommand(nativeTag, command, args); + UIManager.dispatchViewManagerCommand(handle._nativeTag, command, args); } } export function sendAccessibilityEvent(handle: any, eventType: string) { - const nativeTag = - handle._nativeTag != null - ? handle._nativeTag - : getNativeTagFromPublicInstance(handle); - if (nativeTag == null) { + if (handle._nativeTag == null) { if (__DEV__) { console.error( "sendAccessibilityEvent was called with a ref that isn't a " + @@ -198,27 +156,12 @@ export function sendAccessibilityEvent(handle: any, eventType: string) { return; } - const internalInstanceHandle = - getInternalInstanceHandleFromPublicInstance(handle); - if (internalInstanceHandle != null) { - const node = getNodeFromInternalInstanceHandle(internalInstanceHandle); - if (node != null) { - nativeFabricUIManager.sendAccessibilityEvent(node, eventType); + if (handle._internalInstanceHandle != null) { + const {stateNode} = handle._internalInstanceHandle; + if (stateNode != null) { + nativeFabricUIManager.sendAccessibilityEvent(stateNode.node, eventType); } } else { - legacySendAccessibilityEvent(nativeTag, eventType); + legacySendAccessibilityEvent(handle._nativeTag, eventType); } } - -export function getNodeFromInternalInstanceHandle( - internalInstanceHandle: mixed, -): ?Node { - return ( - // $FlowExpectedError[incompatible-return] internalInstanceHandle is opaque but we need to make an exception here. - internalInstanceHandle && - // $FlowExpectedError[incompatible-return] - internalInstanceHandle.stateNode && - // $FlowExpectedError[incompatible-use] - internalInstanceHandle.stateNode.node - ); -} diff --git a/packages/react-native-renderer/src/ReactNativeTypes.js b/packages/react-native-renderer/src/ReactNativeTypes.js index ca9a9dfc04d03..a524d4313866c 100644 --- a/packages/react-native-renderer/src/ReactNativeTypes.js +++ b/packages/react-native-renderer/src/ReactNativeTypes.js @@ -212,8 +212,6 @@ export type ReactNativeType = { ... }; -export opaque type Node = mixed; - export type ReactFabricType = { findHostInstance_DEPRECATED( componentOrHandle: ?(ElementRef | number), @@ -237,7 +235,6 @@ export type ReactFabricType = { concurrentRoot: ?boolean, ): ?ElementRef, unmountComponentAtNode(containerTag: number): void, - getNodeFromInternalInstanceHandle(internalInstanceHandle: mixed): ?Node, ... }; diff --git a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js index 42ed69a8c290c..935edb0335def 100644 --- a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js @@ -15,8 +15,6 @@ let ReactFabric; let createReactNativeComponentClass; let StrictMode; let act; -let getNativeTagFromPublicInstance; -let getInternalInstanceHandleFromPublicInstance; const DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT = "Warning: dispatchCommand was called with a ref that isn't a " + @@ -42,10 +40,6 @@ describe('ReactFabric', () => { createReactNativeComponentClass = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface') .ReactNativeViewConfigRegistry.register; - getNativeTagFromPublicInstance = - require('../ReactFabricPublicInstanceUtils').getNativeTagFromPublicInstance; - getInternalInstanceHandleFromPublicInstance = - require('../ReactFabricPublicInstanceUtils').getInternalInstanceHandleFromPublicInstance; act = require('internal-test-utils').act; }); @@ -937,7 +931,7 @@ describe('ReactFabric', () => { '\n in RCTView (at **)' + '\n in ContainsStrictModeChild (at **)', ]); - expect(match).toBe(getNativeTagFromPublicInstance(child)); + expect(match).toBe(child._nativeTag); }); it('findNodeHandle should warn if passed a component that is inside StrictMode', async () => { @@ -974,7 +968,7 @@ describe('ReactFabric', () => { '\n in RCTView (at **)' + '\n in IsInStrictMode (at **)', ]); - expect(match).toBe(getNativeTagFromPublicInstance(child)); + expect(match).toBe(child._nativeTag); }); it('should no-op if calling sendAccessibilityEvent on unmounted refs', async () => { @@ -1008,34 +1002,4 @@ describe('ReactFabric', () => { expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled(); }); - - it('getNodeFromInternalInstanceHandle should return the correct shadow node', async () => { - const View = createReactNativeComponentClass('RCTView', () => ({ - validAttributes: {foo: true}, - uiViewClassName: 'RCTView', - })); - - let viewRef; - await act(() => { - ReactFabric.render( - { - viewRef = ref; - }} - />, - 1, - ); - }); - - const expectedShadowNode = - nativeFabricUIManager.createNode.mock.results[0].value; - expect(expectedShadowNode).toEqual(expect.any(Object)); - - const internalInstanceHandle = - getInternalInstanceHandleFromPublicInstance(viewRef); - expect( - ReactFabric.getNodeFromInternalInstanceHandle(internalInstanceHandle), - ).toBe(expectedShadowNode); - }); }); diff --git a/packages/react-native-renderer/src/__tests__/ReactFabricAndNative-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactFabricAndNative-test.internal.js index fca6d00c72774..e494701dd0038 100644 --- a/packages/react-native-renderer/src/__tests__/ReactFabricAndNative-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactFabricAndNative-test.internal.js @@ -16,7 +16,6 @@ let ReactNative; let UIManager; let createReactNativeComponentClass; let ReactNativePrivateInterface; -let getNativeTagFromPublicInstance; describe('created with ReactFabric called with ReactNative', () => { beforeEach(() => { @@ -36,8 +35,6 @@ describe('created with ReactFabric called with ReactNative', () => { createReactNativeComponentClass = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface') .ReactNativeViewConfigRegistry.register; - getNativeTagFromPublicInstance = - require('../ReactFabricPublicInstanceUtils').getNativeTagFromPublicInstance; }); it('find Fabric instances with the RN renderer', () => { @@ -57,7 +54,7 @@ describe('created with ReactFabric called with ReactNative', () => { ReactFabric.render(, 11); const instance = ReactNative.findHostInstance_DEPRECATED(ref.current); - expect(getNativeTagFromPublicInstance(instance)).toBe(2); + expect(instance._nativeTag).toBe(2); }); it('find Fabric nodes with the RN renderer', () => { diff --git a/scripts/flow/react-native-host-hooks.js b/scripts/flow/react-native-host-hooks.js index 7cb3e389126c5..e3899db44528d 100644 --- a/scripts/flow/react-native-host-hooks.js +++ b/scripts/flow/react-native-host-hooks.js @@ -178,19 +178,19 @@ declare var nativeFabricUIManager: { dispatchCommand: (node: Object, command: string, args: Array) => void, sendAccessibilityEvent: (node: Object, eventTypeName: string) => void, - measure: (node: Object, callback: __MeasureOnSuccessCallback) => void, + measure: (node: Node, callback: __MeasureOnSuccessCallback) => void, measureInWindow: ( - node: Object, + node: Node, callback: __MeasureInWindowOnSuccessCallback, ) => void, measureLayout: ( - node: Object, - relativeNode: Object, + node: Node, + relativeNode: Node, onFail: () => void, onSuccess: __MeasureLayoutOnSuccessCallback, ) => void, getBoundingClientRect: ( - node: Object, + node: Node, ) => [ /* x:*/ number, /* y:*/ number, @@ -198,13 +198,13 @@ declare var nativeFabricUIManager: { /* height:*/ number, ], findNodeAtPoint: ( - node: Object, + node: Node, locationX: number, locationY: number, callback: (Object) => void, ) => void, setIsJSResponder: ( - node: Object, + node: Node, isJsResponder: boolean, blockNativeResponder: boolean, ) => void,