[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.
This commit is contained in:
Rubén Norte
2025-02-24 13:46:06 +00:00
committed by GitHub
parent e03c384bcb
commit 986696032b
6 changed files with 66 additions and 100 deletions
@@ -7,14 +7,13 @@
* @flow
*/
import type {ViewConfig} from './ReactNativeTypes';
import type {
HostInstance,
LegacyPublicInstance,
MeasureOnSuccessCallback,
MeasureInWindowOnSuccessCallback,
MeasureLayoutOnSuccessCallback,
MeasureOnSuccessCallback,
INativeMethods,
ViewConfig,
} from './ReactNativeTypes';
} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
import type {Instance} from './ReactFiberConfigNative';
// Modules provided by RN:
@@ -29,7 +28,7 @@ import {
warnForStyleProps,
} from './NativeMethodsMixinUtils';
class ReactNativeFiberHostComponent implements INativeMethods {
class ReactNativeFiberHostComponent implements LegacyPublicInstance {
_children: Array<Instance | number>;
_nativeTag: number;
_internalFiberInstanceHandleDEV: Object;
@@ -71,7 +70,7 @@ class ReactNativeFiberHostComponent implements INativeMethods {
}
measureLayout(
relativeToNativeNode: number | HostInstance,
relativeToNativeNode: number | LegacyPublicInstance,
onSuccess: MeasureLayoutOnSuccessCallback,
onFail?: () => void /* currently unused */,
) {
@@ -236,6 +236,7 @@ function getInspectorDataForViewAtPoint(
pointerY: locationY,
frame: {left, top, width, height},
touchedViewTag: nativeViewTag,
// $FlowExpectedError[incompatible-call]
closestPublicInstance: nativeViewTag,
});
},
@@ -7,8 +7,9 @@
* @flow
*/
import type {Node, HostComponent} from './ReactNativeTypes';
import type {Node} from './ReactNativeTypes';
import type {ElementRef, ElementType} from 'react';
import type {PublicInstance} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
// Modules provided by RN:
import {
@@ -32,7 +33,7 @@ import {
export function findHostInstance_DEPRECATED<TElementType: ElementType>(
componentOrHandle: ?(ElementRef<TElementType> | number),
): ?ElementRef<HostComponent<{...}>> {
): ?PublicInstance {
if (__DEV__) {
const owner = currentOwner;
if (owner !== null && isRendering && owner.stateNode !== null) {
@@ -222,15 +223,10 @@ export function getNodeFromInternalInstanceHandle(
);
}
// Should have been PublicInstance from ReactFiberConfigFabric
type FabricPublicInstance = mixed;
// Should have been PublicInstance from ReactFiberConfigNative
type PaperPublicInstance = HostComponent<empty>;
// Remove this once Paper is no longer supported and DOM Node API are enabled by default in RN.
export function isChildPublicInstance(
parentInstance: FabricPublicInstance | PaperPublicInstance,
childInstance: FabricPublicInstance | PaperPublicInstance,
parentInstance: PublicInstance,
childInstance: PublicInstance,
): boolean {
if (__DEV__) {
// Paper
+17 -77
View File
@@ -14,33 +14,17 @@ import type {
ElementRef,
ElementType,
MixedElement,
RefSetter,
} from 'react';
// $FlowFixMe[nonstrict-import] TODO(@rubennorte)
import {type PublicRootInstance} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
export type MeasureOnSuccessCallback = (
x: number,
y: number,
width: number,
height: number,
pageX: number,
pageY: number,
) => void;
export type MeasureInWindowOnSuccessCallback = (
x: number,
y: number,
width: number,
height: number,
) => void;
export type MeasureLayoutOnSuccessCallback = (
left: number,
top: number,
width: number,
height: number,
) => void;
import type {
// $FlowFixMe[nonstrict-import] TODO(@rubennorte)
MeasureOnSuccessCallback,
// $FlowFixMe[nonstrict-import] TODO(@rubennorte)
PublicInstance,
// $FlowFixMe[nonstrict-import] TODO(@rubennorte)
PublicRootInstance,
// $FlowFixMe[nonstrict-import] TODO(@rubennorte)
PublicTextInstance,
} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
export type AttributeType<T, V> =
| true
@@ -106,45 +90,6 @@ export type PartialViewConfig = $ReadOnly<{
validAttributes?: PartialAttributeConfiguration,
}>;
/**
* Current usages should migrate to this definition
*/
export interface INativeMethods {
blur(): void;
focus(): void;
measure(callback: MeasureOnSuccessCallback): void;
measureInWindow(callback: MeasureInWindowOnSuccessCallback): void;
measureLayout(
relativeToNativeNode: number | HostInstance,
onSuccess: MeasureLayoutOnSuccessCallback,
onFail?: () => void,
): void;
setNativeProps(nativeProps: {...}): void;
}
export type NativeMethods = $ReadOnly<{
blur(): void,
focus(): void,
measure(callback: MeasureOnSuccessCallback): void,
measureInWindow(callback: MeasureInWindowOnSuccessCallback): void,
measureLayout(
relativeToNativeNode: number | HostInstance,
onSuccess: MeasureLayoutOnSuccessCallback,
onFail?: () => void,
): void,
setNativeProps(nativeProps: {...}): void,
}>;
// This validates that INativeMethods and NativeMethods stay in sync using Flow!
declare const ensureNativeMethodsAreSynced: NativeMethods;
(ensureNativeMethodsAreSynced: INativeMethods);
export type HostInstance = NativeMethods;
export type HostComponent<Config: {...}> = component(
ref: RefSetter<HostInstance>,
...Config
);
type InspectorDataProps = $ReadOnly<{
[propName: string]: string,
...
@@ -211,20 +156,17 @@ export type RenderRootOptions = {
export type ReactNativeType = {
findHostInstance_DEPRECATED<TElementType: ElementType>(
componentOrHandle: ?(ElementRef<TElementType> | number),
): ?HostInstance,
): ?PublicInstance,
findNodeHandle<TElementType: ElementType>(
componentOrHandle: ?(ElementRef<TElementType> | number),
): ?number,
isChildPublicInstance(
parent: PublicInstance | HostComponent<empty>,
child: PublicInstance | HostComponent<empty>,
): boolean,
isChildPublicInstance(parent: PublicInstance, child: PublicInstance): boolean,
dispatchCommand(
handle: HostInstance,
handle: PublicInstance,
command: string,
args: Array<mixed>,
): void,
sendAccessibilityEvent(handle: HostInstance, eventType: string): void,
sendAccessibilityEvent(handle: PublicInstance, eventType: string): void,
render(
element: MixedElement,
containerTag: number,
@@ -239,23 +181,21 @@ export type ReactNativeType = {
export opaque type Node = mixed;
export opaque type InternalInstanceHandle = mixed;
type PublicInstance = mixed;
type PublicTextInstance = mixed;
export type ReactFabricType = {
findHostInstance_DEPRECATED<TElementType: ElementType>(
componentOrHandle: ?(ElementRef<TElementType> | number),
): ?HostInstance,
): ?PublicInstance,
findNodeHandle<TElementType: ElementType>(
componentOrHandle: ?(ElementRef<TElementType> | number),
): ?number,
dispatchCommand(
handle: HostInstance,
handle: PublicInstance,
command: string,
args: Array<mixed>,
): void,
isChildPublicInstance(parent: PublicInstance, child: PublicInstance): boolean,
sendAccessibilityEvent(handle: HostInstance, eventType: string): void,
sendAccessibilityEvent(handle: PublicInstance, eventType: string): void,
render(
element: MixedElement,
containerTag: number,
@@ -7,10 +7,6 @@
* @flow strict-local
*/
export opaque type PublicInstance = mixed;
export opaque type PublicTextInstance = mixed;
export opaque type PublicRootInstance = mixed;
module.exports = {
get BatchedBridge() {
return require('./BatchedBridge.js');
+37 -3
View File
@@ -9,9 +9,26 @@
// libdefs cannot actually import. These are supposed to be the types imported
// from 'react-native-renderer/src/ReactNativeTypes'
type __MeasureOnSuccessCallback = any;
type __MeasureInWindowOnSuccessCallback = any;
type __MeasureLayoutOnSuccessCallback = any;
type __MeasureOnSuccessCallback = (
x: number,
y: number,
width: number,
height: number,
pageX: number,
pageY: number,
) => void;
type __MeasureInWindowOnSuccessCallback = (
x: number,
y: number,
width: number,
height: number,
) => void;
type __MeasureLayoutOnSuccessCallback = (
left: number,
top: number,
width: number,
height: number,
) => void;
type __ReactNativeBaseComponentViewConfig = any;
type __ViewConfigGetter = any;
type __ViewConfig = any;
@@ -144,6 +161,23 @@ declare module 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface'
declare export opaque type PublicInstance;
declare export opaque type PublicTextInstance;
declare export opaque type PublicRootInstance;
declare export type MeasureOnSuccessCallback = __MeasureOnSuccessCallback;
declare export type MeasureInWindowOnSuccessCallback =
__MeasureInWindowOnSuccessCallback;
declare export type MeasureLayoutOnSuccessCallback =
__MeasureLayoutOnSuccessCallback;
declare export interface LegacyPublicInstance {
blur(): void;
focus(): void;
measure(callback: __MeasureOnSuccessCallback): void;
measureInWindow(callback: __MeasureInWindowOnSuccessCallback): void;
measureLayout(
relativeToNativeNode: number | LegacyPublicInstance,
onSuccess: __MeasureLayoutOnSuccessCallback,
onFail?: () => void,
): void;
setNativeProps(nativeProps: {...}): void;
}
declare export function getNodeFromPublicInstance(
publicInstance: PublicInstance,
): Object;