From a02466253a083a8f1759db543654eaa9c9de3fcc Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Wed, 10 Jan 2024 06:55:03 -0800 Subject: [PATCH 1/2] [skip ci] BridgelessUIManager: Align platform-only methods w/ PaperUIManager (#41997) Summary: Many methods on PaperUIMangaer are iOS only. Many methods on PaperUIManager are Android only. This diff makes sure that BridgelessUIManager only exports Android methods on Android, and iOS methods on iOS. Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D52012876 --- .../legacySendAccessibilityEvent.android.js | 5 +- .../ReactNative/BridgelessUIManager.js | 85 ++++++++++--------- .../Libraries/ReactNative/NativeUIManager.js | 20 +++-- .../Libraries/ReactNative/PaperUIManager.js | 6 +- .../Libraries/ReactNative/UIManager.d.ts | 18 ++-- .../getNativeComponentAttributes.js | 6 +- 6 files changed, 80 insertions(+), 60 deletions(-) diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.android.js b/packages/react-native/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.android.js index 09556be26a46..fdbabb475c7f 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.android.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.android.js @@ -9,6 +9,7 @@ */ import UIManager from '../../ReactNative/UIManager'; +import nullthrows from 'nullthrows'; /** * This is a function exposed to the React Renderer that can be used by the @@ -19,13 +20,13 @@ function legacySendAccessibilityEvent( eventType: string, ): void { if (eventType === 'focus') { - UIManager.sendAccessibilityEvent( + nullthrows(UIManager.sendAccessibilityEvent)( reactTag, UIManager.getConstants().AccessibilityEventTypes.typeViewFocused, ); } if (eventType === 'click') { - UIManager.sendAccessibilityEvent( + nullthrows(UIManager.sendAccessibilityEvent)( reactTag, UIManager.getConstants().AccessibilityEventTypes.typeViewClicked, ); diff --git a/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js b/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js index 95870984605c..e1bf88f40933 100644 --- a/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js +++ b/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js @@ -14,6 +14,7 @@ import type {RootTag} from '../Types/RootTagTypes'; import type {UIManagerJSInterface} from '../Types/UIManagerJSInterface'; import {unstable_hasComponent} from '../NativeComponent/NativeComponentRegistryUnstable'; +import Platform from '../Utilities/Platform'; import nullthrows from 'nullthrows'; function raiseSoftError(methodName: string, details?: string): void { @@ -96,8 +97,53 @@ const UIManagerJSOverridenAPIs = { }, }; +const UIManagerJSPlatformAPIs = Platform.select({ + android: { + getConstantsForViewManager: (viewManagerName: string): Object => { + raiseSoftError('getConstantsForViewManager'); + return {}; + }, + getDefaultEventTypes: (): Array => { + raiseSoftError('getDefaultEventTypes'); + return []; + }, + setLayoutAnimationEnabledExperimental: (enabled: boolean): void => { + raiseSoftError('setLayoutAnimationEnabledExperimental'); + }, + // Please use AccessibilityInfo.sendAccessibilityEvent instead. + // See SetAccessibilityFocusExample in AccessibilityExample.js for a migration example. + sendAccessibilityEvent: (reactTag: ?number, eventType: number): void => { + raiseSoftError('sendAccessibilityEvent'); + }, + showPopupMenu: ( + reactTag: ?number, + items: Array, + error: (error: Object) => void, + success: (event: string, selected?: number) => void, + ): void => { + raiseSoftError('showPopupMenu'); + }, + dismissPopupMenu: (): void => { + raiseSoftError('dismissPopupMenu'); + }, + }, + ios: { + lazilyLoadView: (name: string): Object => { + raiseSoftError('lazilyLoadView'); + return {}; + }, + focus: (reactTag: ?number): void => { + raiseSoftError('focus'); + }, + blur: (reactTag: ?number): void => { + raiseSoftError('blur'); + }, + }, +}); + const UIManagerJS: UIManagerJSInterface & {[string]: any} = { ...UIManagerJSOverridenAPIs, + ...UIManagerJSPlatformAPIs, getViewManagerConfig: (viewManagerName: string): mixed => { if (getUIManagerConstants) { return getUIManagerConstantsCache()[viewManagerName]; @@ -120,18 +166,6 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { return null; } }, - getConstantsForViewManager: (viewManagerName: string): Object => { - raiseSoftError('getConstantsForViewManager'); - return {}; - }, - getDefaultEventTypes: (): Array => { - raiseSoftError('getDefaultEventTypes'); - return []; - }, - lazilyLoadView: (name: string): Object => { - raiseSoftError('lazilyLoadView'); - return {}; - }, createView: ( reactTag: ?number, viewName: string, @@ -143,12 +177,6 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { updateView: (reactTag: number, viewName: string, props: Object): void => { raiseSoftError('updateView'); }, - focus: (reactTag: ?number): void => { - raiseSoftError('focus'); - }, - blur: (reactTag: ?number): void => { - raiseSoftError('blur'); - }, findSubviewIn: ( reactTag: ?number, point: Array, @@ -204,27 +232,6 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { ): void => { raiseSoftError('manageChildren'); }, - - // Android only - setLayoutAnimationEnabledExperimental: (enabled: boolean): void => { - raiseSoftError('setLayoutAnimationEnabledExperimental'); - }, - // Please use AccessibilityInfo.sendAccessibilityEvent instead. - // See SetAccessibilityFocusExample in AccessibilityExample.js for a migration example. - sendAccessibilityEvent: (reactTag: ?number, eventType: number): void => { - raiseSoftError('sendAccessibilityEvent'); - }, - showPopupMenu: ( - reactTag: ?number, - items: Array, - error: (error: Object) => void, - success: (event: string, selected?: number) => void, - ): void => { - raiseSoftError('showPopupMenu'); - }, - dismissPopupMenu: (): void => { - raiseSoftError('dismissPopupMenu'); - }, }; if (getUIManagerConstants) { diff --git a/packages/react-native/Libraries/ReactNative/NativeUIManager.js b/packages/react-native/Libraries/ReactNative/NativeUIManager.js index a9586ee74df0..e84ab25be84e 100644 --- a/packages/react-native/Libraries/ReactNative/NativeUIManager.js +++ b/packages/react-native/Libraries/ReactNative/NativeUIManager.js @@ -15,9 +15,6 @@ import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; export interface Spec extends TurboModule { +getConstants: () => Object; - +getConstantsForViewManager: (viewManagerName: string) => Object; - +getDefaultEventTypes: () => Array; - +lazilyLoadView: (name: string) => Object; // revisit return +createView: ( reactTag: ?number, viewName: string, @@ -25,8 +22,6 @@ export interface Spec extends TurboModule { props: Object, ) => void; +updateView: (reactTag: number, viewName: string, props: Object) => void; - +focus: (reactTag: ?number) => void; - +blur: (reactTag: ?number) => void; +findSubviewIn: ( reactTag: ?number, point: Array, @@ -107,15 +102,22 @@ export interface Spec extends TurboModule { ) => void; // Android only - +setLayoutAnimationEnabledExperimental: (enabled: boolean) => void; - +sendAccessibilityEvent: (reactTag: ?number, eventType: number) => void; - +showPopupMenu: ( + +getConstantsForViewManager?: (viewManagerName: string) => Object; + +getDefaultEventTypes?: () => Array; + +setLayoutAnimationEnabledExperimental?: (enabled: boolean) => void; + +sendAccessibilityEvent?: (reactTag: ?number, eventType: number) => void; + +showPopupMenu?: ( reactTag: ?number, items: Array, error: (error: Object) => void, success: (event: string, selected?: number) => void, ) => void; - +dismissPopupMenu: () => void; + +dismissPopupMenu?: () => void; + + // ios only + +lazilyLoadView?: (name: string) => Object; // revisit return + +focus?: (reactTag: ?number) => void; + +blur?: (reactTag: ?number) => void; } export default (TurboModuleRegistry.getEnforcing('UIManager'): Spec); diff --git a/packages/react-native/Libraries/ReactNative/PaperUIManager.js b/packages/react-native/Libraries/ReactNative/PaperUIManager.js index a2e14cc159f0..e5ad5a9aeb22 100644 --- a/packages/react-native/Libraries/ReactNative/PaperUIManager.js +++ b/packages/react-native/Libraries/ReactNative/PaperUIManager.js @@ -12,6 +12,7 @@ import type {RootTag} from '../Types/RootTagTypes'; import type {UIManagerJSInterface} from '../Types/UIManagerJSInterface'; import NativeUIManager from './NativeUIManager'; +import nullthrows from 'nullthrows'; const NativeModules = require('../BatchedBridge/NativeModules'); const defineLazyObjectProperty = require('../Utilities/defineLazyObjectProperty'); @@ -67,7 +68,7 @@ function getViewManagerConfig(viewManagerName: string): any { NativeUIManager.lazilyLoadView && !triedLoadingConfig.has(viewManagerName) ) { - const result = NativeUIManager.lazilyLoadView(viewManagerName); + const result = nullthrows(NativeUIManager.lazilyLoadView)(viewManagerName); triedLoadingConfig.add(viewManagerName); if (result != null && result.viewConfig != null) { getConstants()[viewManagerName] = result.viewConfig; @@ -161,7 +162,8 @@ if (Platform.OS === 'ios') { } else if (getConstants().ViewManagerNames) { NativeUIManager.getConstants().ViewManagerNames.forEach(viewManagerName => { defineLazyObjectProperty(NativeUIManager, viewManagerName, { - get: () => NativeUIManager.getConstantsForViewManager(viewManagerName), + get: () => + nullthrows(NativeUIManager.getConstantsForViewManager)(viewManagerName), }); }); } diff --git a/packages/react-native/Libraries/ReactNative/UIManager.d.ts b/packages/react-native/Libraries/ReactNative/UIManager.d.ts index 1f0b346802d7..4757f03201c6 100644 --- a/packages/react-native/Libraries/ReactNative/UIManager.d.ts +++ b/packages/react-native/Libraries/ReactNative/UIManager.d.ts @@ -112,7 +112,9 @@ export interface UIManagerStatic { * * UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true); */ - setLayoutAnimationEnabledExperimental(value: boolean): void; + setLayoutAnimationEnabledExperimental?: + | ((value: boolean) => void) + | undefined; /** * Used to display an Android PopupMenu. If a menu item is pressed, the success callback will @@ -126,12 +128,14 @@ export interface UIManagerStatic { * * Note that this works only on Android */ - showPopupMenu( - node: number, - items: string[], - error: () => void /* currently unused */, - success: (item: string, index: number | undefined) => void, - ): void; + showPopupMenu?: + | (( + node: number, + items: string[], + error: () => void /* currently unused */, + success: (item: string, index: number | undefined) => void, + ) => void) + | undefined; getViewManagerConfig: (name: string) => { Commands: {[key: string]: number}; diff --git a/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js b/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js index 6c9f11f06882..318a2d18a4e1 100644 --- a/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js +++ b/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js @@ -20,6 +20,7 @@ const pointsDiffer = require('../Utilities/differ/pointsDiffer'); const sizesDiffer = require('../Utilities/differ/sizesDiffer'); const UIManager = require('./UIManager'); const invariant = require('invariant'); +const nullthrows = require('nullthrows'); function getNativeComponentAttributes(uiViewClassName: string): any { const viewConfig = UIManager.getViewManagerConfig(uiViewClassName); @@ -105,7 +106,10 @@ function attachDefaultEventTypes(viewConfig: any) { const constants = UIManager.getConstants(); if (constants.ViewManagerNames || constants.LazyViewManagersEnabled) { // Lazy view managers enabled. - viewConfig = merge(viewConfig, UIManager.getDefaultEventTypes()); + viewConfig = merge( + viewConfig, + nullthrows(UIManager.getDefaultEventTypes)(), + ); } else { viewConfig.bubblingEventTypes = merge( viewConfig.bubblingEventTypes, From 8b7c93cb17993f684aa41e2bfea65b79d343b970 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Wed, 10 Jan 2024 06:55:03 -0800 Subject: [PATCH 2/2] BridgelessUIManager: Finish createView, updateView, setChildren, manageChildren (#42067) Summary: These methods should not be implemented in the new architecture. The **only** code that called these UIManagerModule methods was the paper renderer. And the New Architecture should instead use the Fabric renderer. Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D52345416 --- .../ReactNative/BridgelessUIManager.js | 57 +++++++++++-------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js b/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js index e1bf88f40933..eb226f017026 100644 --- a/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js +++ b/packages/react-native/Libraries/ReactNative/BridgelessUIManager.js @@ -97,6 +97,38 @@ const UIManagerJSOverridenAPIs = { }, }; +/** + * Leave Unimplemented: The only thing that called these methods was the paper renderer. + * In OSS, the New Architecture will just use the Fabric renderer, which uses + * different APIs. + */ +const UIManagerJSUnusedAPIs = { + createView: ( + reactTag: ?number, + viewName: string, + rootTag: RootTag, + props: Object, + ): void => { + raiseSoftError('createView'); + }, + updateView: (reactTag: number, viewName: string, props: Object): void => { + raiseSoftError('updateView'); + }, + setChildren: (containerTag: ?number, reactTags: Array): void => { + raiseSoftError('setChildren'); + }, + manageChildren: ( + containerTag: ?number, + moveFromIndices: Array, + moveToIndices: Array, + addChildReactTags: Array, + addAtIndices: Array, + removeAtIndices: Array, + ): void => { + raiseSoftError('manageChildren'); + }, +}; + const UIManagerJSPlatformAPIs = Platform.select({ android: { getConstantsForViewManager: (viewManagerName: string): Object => { @@ -144,6 +176,7 @@ const UIManagerJSPlatformAPIs = Platform.select({ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { ...UIManagerJSOverridenAPIs, ...UIManagerJSPlatformAPIs, + ...UIManagerJSUnusedAPIs, getViewManagerConfig: (viewManagerName: string): mixed => { if (getUIManagerConstants) { return getUIManagerConstantsCache()[viewManagerName]; @@ -166,17 +199,6 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { return null; } }, - createView: ( - reactTag: ?number, - viewName: string, - rootTag: RootTag, - props: Object, - ): void => { - raiseSoftError('createView'); - }, - updateView: (reactTag: number, viewName: string, props: Object): void => { - raiseSoftError('updateView'); - }, findSubviewIn: ( reactTag: ?number, point: Array, @@ -219,19 +241,6 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { ): void => { raiseSoftError('replaceExistingNonRootView'); }, - setChildren: (containerTag: ?number, reactTags: Array): void => { - raiseSoftError('setChildren'); - }, - manageChildren: ( - containerTag: ?number, - moveFromIndices: Array, - moveToIndices: Array, - addChildReactTags: Array, - addAtIndices: Array, - removeAtIndices: Array, - ): void => { - raiseSoftError('manageChildren'); - }, }; if (getUIManagerConstants) {