From 46ffe84453aaf3836da6abfe4c0b078ca0ac4f21 Mon Sep 17 00:00:00 2001 From: Nadiia D Date: Mon, 26 Apr 2021 22:56:28 -0700 Subject: [PATCH] Make RootTag an opaque type Summary: Changelog: [General][Changed] Make the RootTag an opaque type Reviewed By: yungsters Differential Revision: D27992320 fbshipit-source-id: 2901f0e59f573106295b986fe04db227134235da --- Libraries/Image/Image.android.js | 3 ++- Libraries/Image/Image.ios.js | 5 ++++- Libraries/Image/NativeImageLoaderIOS.js | 3 ++- Libraries/ReactNative/AppContainer.js | 3 ++- Libraries/ReactNative/AppRegistry.js | 5 ++++- Libraries/ReactNative/DummyUIManager.js | 4 +++- Libraries/ReactNative/FabricUIManager.js | 7 ++++--- Libraries/ReactNative/NativeUIManager.js | 3 ++- Libraries/ReactNative/PaperUIManager.js | 3 ++- Libraries/ReactNative/RootTag.js | 4 ++-- Libraries/ReactNative/UIManager.js | 3 ++- Libraries/TurboModule/RCTExport.js | 2 +- Libraries/Types/RootTagTypes.js | 11 +++++++++++ .../src/androidTest/js/UIManagerTestModule.js | 13 +++++++------ 14 files changed, 48 insertions(+), 21 deletions(-) create mode 100644 Libraries/Types/RootTagTypes.js diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index 08f81303528..2f9aec0d666 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -27,6 +27,7 @@ import NativeImageLoaderAndroid from './NativeImageLoaderAndroid'; const TextInlineImageNativeComponent = require('./TextInlineImageNativeComponent'); import type {ImageProps as ImagePropsType} from './ImageProps'; +import type {RootTag} from '../Types/RootTagTypes'; let _requestId = 1; function generateRequestId() { @@ -195,7 +196,7 @@ function getSizeWithHeaders( function prefetchWithMetadata( url: string, queryRootName: string, - rootTag?: ?number, + rootTag?: ?RootTag, callback: ?Function, ): any { // TODO: T79192300 Log queryRootName and rootTag diff --git a/Libraries/Image/Image.ios.js b/Libraries/Image/Image.ios.js index 850ccfa7067..45905817540 100644 --- a/Libraries/Image/Image.ios.js +++ b/Libraries/Image/Image.ios.js @@ -23,6 +23,7 @@ import type {ImageStyleProp} from '../StyleSheet/StyleSheet'; import NativeImageLoaderIOS from './NativeImageLoaderIOS'; import ImageViewNativeComponent from './ImageViewNativeComponent'; +import type {RootTag} from 'react-native/Libraries/Types/RootTagTypes'; function getSize( uri: string, @@ -60,13 +61,15 @@ function getSizeWithHeaders( function prefetchWithMetadata( url: string, queryRootName: string, - rootTag?: ?number, + rootTag?: ?RootTag, ): any { if (NativeImageLoaderIOS.prefetchImageWithMetadata) { // number params like rootTag cannot be nullable before TurboModules is available return NativeImageLoaderIOS.prefetchImageWithMetadata( url, queryRootName, + // NOTE: RootTag type + // $FlowFixMe[incompatible-call] RootTag: number is incompatible with RootTag rootTag ? rootTag : 0, ); } else { diff --git a/Libraries/Image/NativeImageLoaderIOS.js b/Libraries/Image/NativeImageLoaderIOS.js index cbebf34e2d1..91c65a6e245 100644 --- a/Libraries/Image/NativeImageLoaderIOS.js +++ b/Libraries/Image/NativeImageLoaderIOS.js @@ -8,6 +8,7 @@ * @format */ +import type {RootTag} from '../TurboModule/RCTExport'; import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; @@ -27,7 +28,7 @@ export interface Spec extends TurboModule { +prefetchImageWithMetadata?: ( uri: string, queryRootName: string, - rootTag: number, + rootTag: RootTag, ) => Promise; +queryCache: (uris: Array) => Promise; } diff --git a/Libraries/ReactNative/AppContainer.js b/Libraries/ReactNative/AppContainer.js index 7740178689d..5d96cc739b9 100644 --- a/Libraries/ReactNative/AppContainer.js +++ b/Libraries/ReactNative/AppContainer.js @@ -13,12 +13,13 @@ import RCTDeviceEventEmitter from '../EventEmitter/RCTDeviceEventEmitter'; import StyleSheet from '../StyleSheet/StyleSheet'; import {type EventSubscription} from '../vendor/emitter/EventEmitter'; import {RootTagContext, createRootTag} from './RootTag'; +import type {RootTag} from './RootTag'; import * as React from 'react'; type Props = $ReadOnly<{| children?: React.Node, fabric?: boolean, - rootTag: number, + rootTag: number | RootTag, initialProps?: {...}, showArchitectureIndicator?: boolean, WrapperComponent?: ?React.ComponentType, diff --git a/Libraries/ReactNative/AppRegistry.js b/Libraries/ReactNative/AppRegistry.js index 96edccc1096..0bb8a8658f7 100644 --- a/Libraries/ReactNative/AppRegistry.js +++ b/Libraries/ReactNative/AppRegistry.js @@ -22,6 +22,7 @@ import {coerceDisplayMode} from './DisplayMode'; import createPerformanceLogger from '../Utilities/createPerformanceLogger'; import NativeHeadlessJsTaskSupport from './NativeHeadlessJsTaskSupport'; import HeadlessJsTaskError from './HeadlessJsTaskError'; +import type {RootTag} from 'react-native/Libraries/Types/RootTagTypes'; type Task = (taskData: any) => Promise; export type TaskProvider = () => Task; @@ -243,7 +244,9 @@ const AppRegistry = { * * See https://reactnative.dev/docs/appregistry.html#unmountapplicationcomponentatroottag */ - unmountApplicationComponentAtRootTag(rootTag: number): void { + unmountApplicationComponentAtRootTag(rootTag: RootTag): void { + // NOTE: RootTag type + // $FlowFixMe[incompatible-call] RootTag: RootTag is incompatible with number, needs an updated synced version of the ReactNativeTypes.js file ReactNative.unmountComponentAtNodeAndRemoveContainer(rootTag); }, diff --git a/Libraries/ReactNative/DummyUIManager.js b/Libraries/ReactNative/DummyUIManager.js index 0d380f0a276..fd66374dc08 100644 --- a/Libraries/ReactNative/DummyUIManager.js +++ b/Libraries/ReactNative/DummyUIManager.js @@ -10,6 +10,8 @@ 'use strict'; +import type {RootTag} from 'react-native/Libraries/Types/RootTagTypes'; + module.exports = { getViewManagerConfig: (viewManagerName: string): mixed => { console.warn( @@ -30,7 +32,7 @@ module.exports = { createView: ( reactTag: ?number, viewName: string, - rootTag: number, + rootTag: RootTag, props: Object, ) => {}, updateView: (reactTag: number, viewName: string, props: Object) => {}, diff --git a/Libraries/ReactNative/FabricUIManager.js b/Libraries/ReactNative/FabricUIManager.js index 62c17e8e4ad..987ef84f381 100644 --- a/Libraries/ReactNative/FabricUIManager.js +++ b/Libraries/ReactNative/FabricUIManager.js @@ -16,6 +16,7 @@ import type { MeasureLayoutOnSuccessCallback, LayoutAnimationConfig, } from '../Renderer/shims/ReactNativeTypes'; +import type {RootTag} from 'react-native/Libraries/Types/RootTagTypes'; // TODO: type these properly. type Node = {...}; @@ -26,7 +27,7 @@ export type Spec = {| +createNode: ( reactTag: number, viewName: string, - rootTag: number, + rootTag: RootTag, props: NodeProps, instanceHandle: InstanceHandle, ) => Node, @@ -34,10 +35,10 @@ export type Spec = {| +cloneNodeWithNewChildren: (node: Node) => Node, +cloneNodeWithNewProps: (node: Node, newProps: NodeProps) => Node, +cloneNodeWithNewChildrenAndProps: (node: Node, newProps: NodeProps) => Node, - +createChildSet: (rootTag: number) => NodeSet, + +createChildSet: (rootTag: RootTag) => NodeSet, +appendChild: (parentNode: Node, child: Node) => Node, +appendChildToSet: (childSet: NodeSet, child: Node) => void, - +completeRoot: (rootTag: number, childSet: NodeSet) => void, + +completeRoot: (rootTag: RootTag, childSet: NodeSet) => void, +measure: (node: Node, callback: MeasureOnSuccessCallback) => void, +measureInWindow: ( node: Node, diff --git a/Libraries/ReactNative/NativeUIManager.js b/Libraries/ReactNative/NativeUIManager.js index 53fa251eed9..ce77d2d4db3 100644 --- a/Libraries/ReactNative/NativeUIManager.js +++ b/Libraries/ReactNative/NativeUIManager.js @@ -8,6 +8,7 @@ * @format */ +import type {RootTag} from '../TurboModule/RCTExport'; import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; @@ -19,7 +20,7 @@ export interface Spec extends TurboModule { +createView: ( reactTag: ?number, viewName: string, - rootTag: number, + rootTag: RootTag, props: Object, ) => void; +updateView: (reactTag: number, viewName: string, props: Object) => void; diff --git a/Libraries/ReactNative/PaperUIManager.js b/Libraries/ReactNative/PaperUIManager.js index fe9cc014cc6..c468958e566 100644 --- a/Libraries/ReactNative/PaperUIManager.js +++ b/Libraries/ReactNative/PaperUIManager.js @@ -15,6 +15,7 @@ const UIManagerProperties = require('./UIManagerProperties'); const defineLazyObjectProperty = require('../Utilities/defineLazyObjectProperty'); import NativeUIManager from './NativeUIManager'; +import type {RootTag} from 'react-native/Libraries/Types/RootTagTypes'; const viewManagerConfigs = {}; @@ -84,7 +85,7 @@ const UIManagerJS = { createView( reactTag: ?number, viewName: string, - rootTag: number, + rootTag: RootTag, props: Object, ): void { if (Platform.OS === 'ios' && viewManagerConfigs[viewName] === undefined) { diff --git a/Libraries/ReactNative/RootTag.js b/Libraries/ReactNative/RootTag.js index 0470e42487e..03c83a86af9 100644 --- a/Libraries/ReactNative/RootTag.js +++ b/Libraries/ReactNative/RootTag.js @@ -11,7 +11,7 @@ import * as React from 'react'; // TODO: Make this into an opaque type. -export type RootTag = number; +export opaque type RootTag = number; export const RootTagContext: React$Context = React.createContext( 0, @@ -24,6 +24,6 @@ if (__DEV__) { /** * Intended to only be used by `AppContainer`. */ -export function createRootTag(rootTag: number): RootTag { +export function createRootTag(rootTag: number | RootTag): RootTag { return rootTag; } diff --git a/Libraries/ReactNative/UIManager.js b/Libraries/ReactNative/UIManager.js index 668961338d2..ac916e66a24 100644 --- a/Libraries/ReactNative/UIManager.js +++ b/Libraries/ReactNative/UIManager.js @@ -10,6 +10,7 @@ import UIManagerInjection from './UIManagerInjection'; import type {Spec} from './NativeUIManager'; +import type {RootTag} from 'react-native/Libraries/Types/RootTagTypes'; interface UIManagerJSInterface extends Spec { +getViewManagerConfig: (viewManagerName: string) => Object; @@ -17,7 +18,7 @@ interface UIManagerJSInterface extends Spec { +createView: ( reactTag: ?number, viewName: string, - rootTag: number, + rootTag: RootTag, props: Object, ) => void; +updateView: (reactTag: number, viewName: string, props: Object) => void; diff --git a/Libraries/TurboModule/RCTExport.js b/Libraries/TurboModule/RCTExport.js index bbf236ed452..d68194adb36 100644 --- a/Libraries/TurboModule/RCTExport.js +++ b/Libraries/TurboModule/RCTExport.js @@ -35,4 +35,4 @@ export interface DEPRECATED_RCTExport { export interface TurboModule extends DEPRECATED_RCTExport {} -export type {RootTag} from '../ReactNative/RootTag.js'; +export type {RootTag} from '../Types/RootTagTypes.js'; diff --git a/Libraries/Types/RootTagTypes.js b/Libraries/Types/RootTagTypes.js new file mode 100644 index 00000000000..4fde211e5f0 --- /dev/null +++ b/Libraries/Types/RootTagTypes.js @@ -0,0 +1,11 @@ +/** + * Copyright (c) Facebook, Inc. and its 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 + * @format + */ + +export type {RootTag} from '../ReactNative/RootTag'; diff --git a/ReactAndroid/src/androidTest/js/UIManagerTestModule.js b/ReactAndroid/src/androidTest/js/UIManagerTestModule.js index 61b0d0b2f38..25c7c5e0cc7 100644 --- a/ReactAndroid/src/androidTest/js/UIManagerTestModule.js +++ b/ReactAndroid/src/androidTest/js/UIManagerTestModule.js @@ -16,6 +16,7 @@ const React = require('react'); const renderApplication = require('react-native/Libraries/ReactNative/renderApplication'); const {StyleSheet, Text, View} = require('react-native'); +import type {RootTag} from 'react-native/Libraries/Types/RootTagTypes'; type FlexTestAppProps = $ReadOnly<{||}>; class FlexTestApp extends React.Component { @@ -234,26 +235,26 @@ const UpdatePositionInListTestAppStyles = StyleSheet.create({ const emptyExactProps = Object.freeze({}); const UIManagerTestModule = { - renderFlexTestApplication(rootTag: number) { + renderFlexTestApplication(rootTag: RootTag) { renderApplication(FlexTestApp, emptyExactProps, rootTag); }, - renderFlexWithTextApplication(rootTag: number) { + renderFlexWithTextApplication(rootTag: RootTag) { renderApplication(FlexWithText, emptyExactProps, rootTag); }, - renderAbsolutePositionBottomRightTestApplication(rootTag: number) { + renderAbsolutePositionBottomRightTestApplication(rootTag: RootTag) { renderApplication( AbsolutePositionBottomRightTestApp, emptyExactProps, rootTag, ); }, - renderAbsolutePositionTestApplication(rootTag: number) { + renderAbsolutePositionTestApplication(rootTag: RootTag) { renderApplication(AbsolutePositionTestApp, emptyExactProps, rootTag); }, - renderCenteredTextViewTestApplication(rootTag: number, text: string) { + renderCenteredTextViewTestApplication(rootTag: RootTag, text: string) { renderApplication(CenteredTextView, {text: text}, rootTag); }, - renderUpdatePositionInListTestApplication(rootTag: number) { + renderUpdatePositionInListTestApplication(rootTag: RootTag) { renderApplication(UpdatePositionInListTestApp, emptyExactProps, rootTag); }, flushUpdatePositionInList,