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..e08cc860965f 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,15 +97,93 @@ 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 => { + 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, + ...UIManagerJSUnusedAPIs, getViewManagerConfig: (viewManagerName: string): mixed => { if (getUIManagerConstants) { return getUIManagerConstantsCache()[viewManagerName]; } else { raiseSoftError( - 'getViewManagerConfig', - `Use hasViewManagerConfig instead. viewManagerName: ${viewManagerName}`, + `getViewManagerConfig('${viewManagerName}')`, + `If '${viewManagerName}' has a ViewManager and you want to retrieve its native ViewConfig, please turn on the native ViewConfig interop layer. If you want to see if this component is registered with React Native, please call hasViewManagerConfig('${viewManagerName}') instead.`, ); return null; } @@ -120,35 +199,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, - rootTag: RootTag, - props: Object, - ): void => { - raiseSoftError('createView'); - }, - 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, @@ -182,49 +232,12 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = { ): void => { raiseSoftError('configureNextLayoutAnimation'); }, - removeSubviewsFromContainerWithID: (containerID: number): void => { - raiseSoftError('removeSubviewsFromContainerWithID'); - }, replaceExistingNonRootView: ( reactTag: ?number, newReactTag: ?number, ): 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'); - }, - - // 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..160ee4f912d3 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, @@ -91,7 +86,6 @@ export interface Spec extends TurboModule { callback: () => void, // check what is returned here errorCallback: (error: Object) => void, ) => void; - +removeSubviewsFromContainerWithID: (containerID: number) => void; +replaceExistingNonRootView: ( reactTag: ?number, newReactTag: ?number, @@ -107,15 +101,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/UIManagerProperties.js b/packages/react-native/Libraries/ReactNative/UIManagerProperties.js index c332897730a6..b8b709e0c76b 100644 --- a/packages/react-native/Libraries/ReactNative/UIManagerProperties.js +++ b/packages/react-native/Libraries/ReactNative/UIManagerProperties.js @@ -41,7 +41,6 @@ module.exports = [ 'measureLayout', 'measureLayoutRelativeToParent', 'removeRootView', - 'removeSubviewsFromContainerWithID', 'replaceExistingNonRootView', 'sendAccessibilityEvent', 'setChildren', 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, diff --git a/packages/react-native/React/Modules/RCTUIManager.m b/packages/react-native/React/Modules/RCTUIManager.m index a646f95079db..fb9c5bc00869 100644 --- a/packages/react-native/React/Modules/RCTUIManager.m +++ b/packages/react-native/React/Modules/RCTUIManager.m @@ -700,31 +700,6 @@ - (RCTViewManagerUIBlock)uiBlockWithLayoutUpdateForRootView:(RCTRootShadowView * }; } -/** - * A method to be called from JS, which takes a container ID and then releases - * all subviews for that container upon receipt. - */ -RCT_EXPORT_METHOD(removeSubviewsFromContainerWithID : (nonnull NSNumber *)containerID) -{ - RCTLogWarn( - @"RCTUIManager.removeSubviewsFromContainerWithID method is deprecated and it will not be implemented in newer versions of RN (Fabric) - T47686450"); - id container = _shadowViewRegistry[containerID]; - RCTAssert(container != nil, @"container view (for ID %@) not found", containerID); - - NSUInteger subviewsCount = [container reactSubviews].count; - NSMutableArray *indices = [[NSMutableArray alloc] initWithCapacity:subviewsCount]; - for (NSUInteger childIndex = 0; childIndex < subviewsCount; childIndex++) { - [indices addObject:@(childIndex)]; - } - - [self manageChildren:containerID - moveFromIndices:nil - moveToIndices:nil - addChildReactTags:nil - addAtIndices:nil - removeAtIndices:indices]; -} - /** * Disassociates children from container. Doesn't remove from registries. * TODO: use [NSArray getObjects:buffer] to reuse same fast buffer each time. diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 440ff3e2b8f8..637c935cd063 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -4861,7 +4861,6 @@ public class com/facebook/react/uimanager/UIImplementation { public fun removeRootShadowNode (I)V public fun removeRootView (I)V protected final fun removeShadowNode (Lcom/facebook/react/uimanager/ReactShadowNode;)V - public fun removeSubviewsFromContainerWithID (I)V public fun replaceExistingNonRootView (II)V public fun resolveRootTagFromReactTag (I)I public final fun resolveShadowNode (I)Lcom/facebook/react/uimanager/ReactShadowNode; @@ -4949,7 +4948,6 @@ public class com/facebook/react/uimanager/UIManagerModule : com/facebook/react/b public fun receiveEvent (IILjava/lang/String;Lcom/facebook/react/bridge/WritableMap;)V public fun receiveEvent (ILjava/lang/String;Lcom/facebook/react/bridge/WritableMap;)V public fun removeRootView (I)V - public fun removeSubviewsFromContainerWithID (I)V public fun removeUIManagerEventListener (Lcom/facebook/react/bridge/UIManagerListener;)V public fun removeUIManagerListener (Lcom/facebook/react/uimanager/UIManagerModuleListener;)V public fun replaceExistingNonRootView (II)V @@ -7739,4 +7737,3 @@ public class com/facebook/react/views/view/ViewGroupClickEvent : com/facebook/re protected fun getEventData ()Lcom/facebook/react/bridge/WritableMap; public fun getEventName ()Ljava/lang/String; } - diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java index 894f32380bda..1f527f574b7c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java @@ -480,27 +480,6 @@ public void replaceExistingNonRootView(int oldTag, int newTag) { manageChildren(parent.getReactTag(), null, null, tagsToAdd, addAtIndices, indicesToRemove); } - /** - * Method which takes a container tag and then releases all subviews for that container upon - * receipt. TODO: The method name is incorrect and will be renamed, #6033872 - * - * @param containerTag the tag of the container for which the subviews must be removed - */ - public void removeSubviewsFromContainerWithID(int containerTag) { - ReactShadowNode containerNode = mShadowNodeRegistry.getNode(containerTag); - if (containerNode == null) { - throw new IllegalViewOperationException( - "Trying to remove subviews of an unknown view tag: " + containerTag); - } - - WritableArray indicesToRemove = Arguments.createArray(); - for (int childIndex = 0; childIndex < containerNode.getChildCount(); childIndex++) { - indicesToRemove.pushInt(childIndex); - } - - manageChildren(containerTag, null, null, null, null, indicesToRemove); - } - /** * Find the touch target child native view in the supplied root view hierarchy, given a react * target location. diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java index 964a22204f05..c5bbd85f0479 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -499,19 +499,6 @@ public void replaceExistingNonRootView(int oldTag, int newTag) { mUIImplementation.replaceExistingNonRootView(oldTag, newTag); } - /** - * Method which takes a container tag and then releases all subviews for that container upon - * receipt. - * - * @param containerTag the tag of the container for which the subviews must be removed - * @deprecated This method will not be available in Fabric UIManager class. - */ - @ReactMethod - @Deprecated - public void removeSubviewsFromContainerWithID(int containerTag) { - mUIImplementation.removeSubviewsFromContainerWithID(containerTag); - } - /** * Determines the location on screen, width, and height of the given view and returns the values * via an async callback. diff --git a/packages/react-native/jest/setup.js b/packages/react-native/jest/setup.js index 84aa60d57702..89931ad3377d 100644 --- a/packages/react-native/jest/setup.js +++ b/packages/react-native/jest/setup.js @@ -93,7 +93,6 @@ jest }), measure: jest.fn(), manageChildren: jest.fn(), - removeSubviewsFromContainerWithID: jest.fn(), replaceExistingNonRootView: jest.fn(), setChildren: jest.fn(), updateView: jest.fn(),