@samitouri / QOS-React / commits / 9dd378ff12

[RN] Move definition of public instances to ReactNativePrivateInterface (#32446)

## Summary > [!NOTE] > This only modifies types, so shouldn't have an impact at runtime. Some time ago we moved some type definitions from React to React Native in #26437. This continues making progress on that so values that are created by React Native and passed to the React renderer (in this case public instances) are actually defined in React Native and not in React. This will allow us to modify the definition of some of these types without having to make changes in the React repository (in the short term, we want to refactor PublicInstance from an object to an interface, and then modify that interface to add all the new DOM methods). ## How did you test this change? Manually synced `ReactNativeTypes` on top of https://github.com/facebook/react-native/pull/49602 and verified Flow passes.

Rubén Norte committed Feb 24, 2025 at 13:46 UTC 9dd378ff1222335ff133bab2d61001fcc84a1c56
6 files changed +66 -100
packages/react-native-renderer/src/ReactNativeFiberHostComponent.js
+6 -7
@@ -7,14 +7,13 @@
7 * @flow
8 */
9
10 +import type {ViewConfig} from './ReactNativeTypes';
11 import type {
11 - HostInstance,
12 + LegacyPublicInstance,
13 + MeasureOnSuccessCallback,
14 MeasureInWindowOnSuccessCallback,
15 MeasureLayoutOnSuccessCallback,
14 - MeasureOnSuccessCallback,
15 - INativeMethods,
16 - ViewConfig,
17 -} from './ReactNativeTypes';
16 +} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
17 import type {Instance} from './ReactFiberConfigNative';
18
19 // Modules provided by RN:
@@ -29,7 +28,7 @@ import {
28 warnForStyleProps,
29 } from './NativeMethodsMixinUtils';
30
32 -class ReactNativeFiberHostComponent implements INativeMethods {
31 +class ReactNativeFiberHostComponent implements LegacyPublicInstance {
32 _children: Array<Instance | number>;
33 _nativeTag: number;
34 _internalFiberInstanceHandleDEV: Object;
@@ -71,7 +70,7 @@ class ReactNativeFiberHostComponent implements INativeMethods {
70 }
71
72 measureLayout(
74 - relativeToNativeNode: number | HostInstance,
73 + relativeToNativeNode: number | LegacyPublicInstance,
74 onSuccess: MeasureLayoutOnSuccessCallback,
75 onFail?: () => void /* currently unused */,
76 ) {
packages/react-native-renderer/src/ReactNativeFiberInspector.js
+1
@@ -236,6 +236,7 @@ function getInspectorDataForViewAtPoint(
236 pointerY: locationY,
237 frame: {left, top, width, height},
238 touchedViewTag: nativeViewTag,
239 + // $FlowExpectedError[incompatible-call]
240 closestPublicInstance: nativeViewTag,
241 });
242 },
packages/react-native-renderer/src/ReactNativePublicCompat.js
+5 -9
@@ -7,8 +7,9 @@
7 * @flow
8 */
9
10 -import type {Node, HostComponent} from './ReactNativeTypes';
10 +import type {Node} from './ReactNativeTypes';
11 import type {ElementRef, ElementType} from 'react';
12 +import type {PublicInstance} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
13
14 // Modules provided by RN:
15 import {
@@ -32,7 +33,7 @@ import {
33
34 export function findHostInstance_DEPRECATED<TElementType: ElementType>(
35 componentOrHandle: ?(ElementRef<TElementType> | number),
35 -): ?ElementRef<HostComponent<{...}>> {
36 +): ?PublicInstance {
37 if (__DEV__) {
38 const owner = currentOwner;
39 if (owner !== null && isRendering && owner.stateNode !== null) {
@@ -222,15 +223,10 @@ export function getNodeFromInternalInstanceHandle(
223 );
224 }
225
225 -// Should have been PublicInstance from ReactFiberConfigFabric
226 -type FabricPublicInstance = mixed;
227 -// Should have been PublicInstance from ReactFiberConfigNative
228 -type PaperPublicInstance = HostComponent<empty>;
229 -
226 // Remove this once Paper is no longer supported and DOM Node API are enabled by default in RN.
227 export function isChildPublicInstance(
232 - parentInstance: FabricPublicInstance | PaperPublicInstance,
233 - childInstance: FabricPublicInstance | PaperPublicInstance,
228 + parentInstance: PublicInstance,
229 + childInstance: PublicInstance,
230 ): boolean {
231 if (__DEV__) {
232 // Paper
packages/react-native-renderer/src/ReactNativeTypes.js
+17 -77
@@ -14,33 +14,17 @@ import type {
14 ElementRef,
15 ElementType,
16 MixedElement,
17 - RefSetter,
17 } from 'react';
19 -// $FlowFixMe[nonstrict-import] TODO(@rubennorte)
20 -import {type PublicRootInstance} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
21 -
22 -export type MeasureOnSuccessCallback = (
23 - x: number,
24 - y: number,
25 - width: number,
26 - height: number,
27 - pageX: number,
28 - pageY: number,
29 -) => void;
30 -
31 -export type MeasureInWindowOnSuccessCallback = (
32 - x: number,
33 - y: number,
34 - width: number,
35 - height: number,
36 -) => void;
37 -
38 -export type MeasureLayoutOnSuccessCallback = (
39 - left: number,
40 - top: number,
41 - width: number,
42 - height: number,
43 -) => void;
18 +import type {
19 + // $FlowFixMe[nonstrict-import] TODO(@rubennorte)
20 + MeasureOnSuccessCallback,
21 + // $FlowFixMe[nonstrict-import] TODO(@rubennorte)
22 + PublicInstance,
23 + // $FlowFixMe[nonstrict-import] TODO(@rubennorte)
24 + PublicRootInstance,
25 + // $FlowFixMe[nonstrict-import] TODO(@rubennorte)
26 + PublicTextInstance,
27 +} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
28
29 export type AttributeType<T, V> =
30 | true
@@ -106,45 +90,6 @@ export type PartialViewConfig = $ReadOnly<{
90 validAttributes?: PartialAttributeConfiguration,
91 }>;
92
109 -/**
110 - * Current usages should migrate to this definition
111 - */
112 -export interface INativeMethods {
113 - blur(): void;
114 - focus(): void;
115 - measure(callback: MeasureOnSuccessCallback): void;
116 - measureInWindow(callback: MeasureInWindowOnSuccessCallback): void;
117 - measureLayout(
118 - relativeToNativeNode: number | HostInstance,
119 - onSuccess: MeasureLayoutOnSuccessCallback,
120 - onFail?: () => void,
121 - ): void;
122 - setNativeProps(nativeProps: {...}): void;
123 -}
124 -
125 -export type NativeMethods = $ReadOnly<{
126 - blur(): void,
127 - focus(): void,
128 - measure(callback: MeasureOnSuccessCallback): void,
129 - measureInWindow(callback: MeasureInWindowOnSuccessCallback): void,
130 - measureLayout(
131 - relativeToNativeNode: number | HostInstance,
132 - onSuccess: MeasureLayoutOnSuccessCallback,
133 - onFail?: () => void,
134 - ): void,
135 - setNativeProps(nativeProps: {...}): void,
136 -}>;
137 -
138 -// This validates that INativeMethods and NativeMethods stay in sync using Flow!
139 -declare const ensureNativeMethodsAreSynced: NativeMethods;
140 -(ensureNativeMethodsAreSynced: INativeMethods);
141 -
142 -export type HostInstance = NativeMethods;
143 -export type HostComponent<Config: {...}> = component(
144 - ref: RefSetter<HostInstance>,
145 - ...Config
146 -);
147 -
93 type InspectorDataProps = $ReadOnly<{
94 [propName: string]: string,
95 ...
@@ -211,20 +156,17 @@ export type RenderRootOptions = {
156 export type ReactNativeType = {
157 findHostInstance_DEPRECATED<TElementType: ElementType>(
158 componentOrHandle: ?(ElementRef<TElementType> | number),
214 - ): ?HostInstance,
159 + ): ?PublicInstance,
160 findNodeHandle<TElementType: ElementType>(
161 componentOrHandle: ?(ElementRef<TElementType> | number),
162 ): ?number,
218 - isChildPublicInstance(
219 - parent: PublicInstance | HostComponent<empty>,
220 - child: PublicInstance | HostComponent<empty>,
221 - ): boolean,
163 + isChildPublicInstance(parent: PublicInstance, child: PublicInstance): boolean,
164 dispatchCommand(
223 - handle: HostInstance,
165 + handle: PublicInstance,
166 command: string,
167 args: Array<mixed>,
168 ): void,
227 - sendAccessibilityEvent(handle: HostInstance, eventType: string): void,
169 + sendAccessibilityEvent(handle: PublicInstance, eventType: string): void,
170 render(
171 element: MixedElement,
172 containerTag: number,
@@ -239,23 +181,21 @@ export type ReactNativeType = {
181
182 export opaque type Node = mixed;
183 export opaque type InternalInstanceHandle = mixed;
242 -type PublicInstance = mixed;
243 -type PublicTextInstance = mixed;
184
185 export type ReactFabricType = {
186 findHostInstance_DEPRECATED<TElementType: ElementType>(
187 componentOrHandle: ?(ElementRef<TElementType> | number),
248 - ): ?HostInstance,
188 + ): ?PublicInstance,
189 findNodeHandle<TElementType: ElementType>(
190 componentOrHandle: ?(ElementRef<TElementType> | number),
191 ): ?number,
192 dispatchCommand(
253 - handle: HostInstance,
193 + handle: PublicInstance,
194 command: string,
195 args: Array<mixed>,
196 ): void,
197 isChildPublicInstance(parent: PublicInstance, child: PublicInstance): boolean,
258 - sendAccessibilityEvent(handle: HostInstance, eventType: string): void,
198 + sendAccessibilityEvent(handle: PublicInstance, eventType: string): void,
199 render(
200 element: MixedElement,
201 containerTag: number,
packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativePrivateInterface.js
-4
@@ -7,10 +7,6 @@
7 * @flow strict-local
8 */
9
10 -export opaque type PublicInstance = mixed;
11 -export opaque type PublicTextInstance = mixed;
12 -export opaque type PublicRootInstance = mixed;
13 -
10 module.exports = {
11 get BatchedBridge() {
12 return require('./BatchedBridge.js');
scripts/flow/react-native-host-hooks.js
+37 -3
@@ -9,9 +9,26 @@
9
10 // libdefs cannot actually import. These are supposed to be the types imported
11 // from 'react-native-renderer/src/ReactNativeTypes'
12 -type __MeasureOnSuccessCallback = any;
13 -type __MeasureInWindowOnSuccessCallback = any;
14 -type __MeasureLayoutOnSuccessCallback = any;
12 +type __MeasureOnSuccessCallback = (
13 + x: number,
14 + y: number,
15 + width: number,
16 + height: number,
17 + pageX: number,
18 + pageY: number,
19 +) => void;
20 +type __MeasureInWindowOnSuccessCallback = (
21 + x: number,
22 + y: number,
23 + width: number,
24 + height: number,
25 +) => void;
26 +type __MeasureLayoutOnSuccessCallback = (
27 + left: number,
28 + top: number,
29 + width: number,
30 + height: number,
31 +) => void;
32 type __ReactNativeBaseComponentViewConfig = any;
33 type __ViewConfigGetter = any;
34 type __ViewConfig = any;
@@ -144,6 +161,23 @@ declare module 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface'
161 declare export opaque type PublicInstance;
162 declare export opaque type PublicTextInstance;
163 declare export opaque type PublicRootInstance;
164 + declare export type MeasureOnSuccessCallback = __MeasureOnSuccessCallback;
165 + declare export type MeasureInWindowOnSuccessCallback =
166 + __MeasureInWindowOnSuccessCallback;
167 + declare export type MeasureLayoutOnSuccessCallback =
168 + __MeasureLayoutOnSuccessCallback;
169 + declare export interface LegacyPublicInstance {
170 + blur(): void;
171 + focus(): void;
172 + measure(callback: __MeasureOnSuccessCallback): void;
173 + measureInWindow(callback: __MeasureInWindowOnSuccessCallback): void;
174 + measureLayout(
175 + relativeToNativeNode: number | LegacyPublicInstance,
176 + onSuccess: __MeasureLayoutOnSuccessCallback,
177 + onFail?: () => void,
178 + ): void;
179 + setNativeProps(nativeProps: {...}): void;
180 + }
181 declare export function getNodeFromPublicInstance(
182 publicInstance: PublicInstance,
183 ): Object;