From aac7c4d5d24787f46ad1745204748c533554489e Mon Sep 17 00:00:00 2001 From: "Andrew Chen (Eng)" Date: Thu, 27 Sep 2018 15:55:31 -0700 Subject: [PATCH] Refactor UIManager view manager accesses Summary: Replaced each view manager access with a getViewManager() function call. This will later be used to lazily load view manager classes by allowing java to avoid sending the entire list of view managers to JS. Reviewed By: QueryConnectionException Differential Revision: D9695788 fbshipit-source-id: 949858aa2f0b0b00b68e260461ba8f1d085cf07f --- .../DrawerAndroid/DrawerLayoutAndroid.android.js | 8 +++++--- .../Components/RefreshControl/RefreshControl.js | 5 +++-- Libraries/Components/ScrollResponder.js | 7 ++++--- Libraries/Components/TextInput/TextInput.js | 9 ++++----- Libraries/Components/TextInput/TextInputState.js | 6 ++++-- .../ToolbarAndroid/ToolbarAndroid.android.js | 5 +++-- .../Touchable/TouchableNativeFeedback.android.js | 4 ++-- .../Components/ViewPager/ViewPagerAndroid.android.js | 5 +++-- Libraries/Components/WebView/WebView.android.js | 12 ++++++------ Libraries/Components/WebView/WebView.ios.js | 4 ++-- Libraries/RCTTest/SnapshotViewIOS.ios.js | 2 +- Libraries/ReactNative/UIManager.js | 3 +++ .../ReactNative/getNativeComponentAttributes.js | 4 ++-- Libraries/Text/Text.js | 2 +- Libraries/Utilities/deprecatedPropType.js | 5 ++++- .../uimanager/UIManagerModuleConstantsHelper.java | 6 +++--- jest/setup.js | 1 + 17 files changed, 51 insertions(+), 37 deletions(-) diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index 66e54b4943..2133888428 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -21,7 +21,8 @@ const StyleSheet = require('StyleSheet'); const UIManager = require('UIManager'); const View = require('View'); -const DrawerConsts = UIManager.AndroidDrawerLayout.Constants; +const DrawerConsts = UIManager.getViewManagerConfig('AndroidDrawerLayout') + .Constants; const createReactClass = require('create-react-class'); const dismissKeyboard = require('dismissKeyboard'); @@ -254,7 +255,7 @@ const DrawerLayoutAndroid = createReactClass({ openDrawer: function() { UIManager.dispatchViewManagerCommand( this._getDrawerLayoutHandle(), - UIManager.AndroidDrawerLayout.Commands.openDrawer, + UIManager.getViewManagerConfig('AndroidDrawerLayout').Commands.openDrawer, null, ); }, @@ -265,7 +266,8 @@ const DrawerLayoutAndroid = createReactClass({ closeDrawer: function() { UIManager.dispatchViewManagerCommand( this._getDrawerLayoutHandle(), - UIManager.AndroidDrawerLayout.Commands.closeDrawer, + UIManager.getViewManagerConfig('AndroidDrawerLayout').Commands + .closeDrawer, null, ); }, diff --git a/Libraries/Components/RefreshControl/RefreshControl.js b/Libraries/Components/RefreshControl/RefreshControl.js index 1b53849ee5..1ebd30dbd4 100644 --- a/Libraries/Components/RefreshControl/RefreshControl.js +++ b/Libraries/Components/RefreshControl/RefreshControl.js @@ -21,8 +21,9 @@ import type {ColorValue} from 'StyleSheetTypes'; import type {ViewProps} from 'ViewPropTypes'; if (Platform.OS === 'android') { - const AndroidSwipeRefreshLayout = require('UIManager') - .AndroidSwipeRefreshLayout; + const AndroidSwipeRefreshLayout = require('UIManager').getViewManagerConfig( + 'AndroidSwipeRefreshLayout', + ); var RefreshLayoutConsts = AndroidSwipeRefreshLayout ? AndroidSwipeRefreshLayout.Constants : {SIZE: {}}; diff --git a/Libraries/Components/ScrollResponder.js b/Libraries/Components/ScrollResponder.js index 99e34f4119..dc55a74100 100644 --- a/Libraries/Components/ScrollResponder.js +++ b/Libraries/Components/ScrollResponder.js @@ -436,7 +436,7 @@ const ScrollResponderMixin = { } UIManager.dispatchViewManagerCommand( nullthrows(this.scrollResponderGetScrollableNode()), - UIManager.RCTScrollView.Commands.scrollTo, + UIManager.getViewManagerConfig('RCTScrollView').Commands.scrollTo, [x || 0, y || 0, animated !== false], ); }, @@ -454,7 +454,7 @@ const ScrollResponderMixin = { const animated = (options && options.animated) !== false; UIManager.dispatchViewManagerCommand( this.scrollResponderGetScrollableNode(), - UIManager.RCTScrollView.Commands.scrollToEnd, + UIManager.getViewManagerConfig('RCTScrollView').Commands.scrollToEnd, [animated], ); }, @@ -513,7 +513,8 @@ const ScrollResponderMixin = { scrollResponderFlashScrollIndicators: function() { UIManager.dispatchViewManagerCommand( this.scrollResponderGetScrollableNode(), - UIManager.RCTScrollView.Commands.flashScrollIndicators, + UIManager.getViewManagerConfig('RCTScrollView').Commands + .flashScrollIndicators, [], ); }, diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 97590c9ab4..7d69abc2b6 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -875,7 +875,7 @@ const TextInput = createReactClass({ render: function() { let textInput; if (Platform.OS === 'ios') { - textInput = UIManager.RCTVirtualText + textInput = UIManager.getViewManagerConfig('RCTVirtualText') ? this._renderIOS() : this._renderIOSLegacy(); } else if (Platform.OS === 'android') { @@ -1048,10 +1048,9 @@ const TextInput = createReactClass({ _renderAndroid: function() { const props = Object.assign({}, this.props); props.style = [this.props.style]; - props.autoCapitalize = - UIManager.AndroidTextInput.Constants.AutoCapitalizationType[ - props.autoCapitalize || 'sentences' - ]; + props.autoCapitalize = UIManager.getViewManagerConfig( + 'AndroidTextInput', + ).Constants.AutoCapitalizationType[props.autoCapitalize || 'sentences']; /* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This comment * suppresses an error when upgrading Flow's support for React. To see the * error delete this comment and run Flow. */ diff --git a/Libraries/Components/TextInput/TextInputState.js b/Libraries/Components/TextInput/TextInputState.js index d53456677b..19acafe264 100644 --- a/Libraries/Components/TextInput/TextInputState.js +++ b/Libraries/Components/TextInput/TextInputState.js @@ -42,7 +42,8 @@ function focusTextInput(textFieldID: ?number) { } else if (Platform.OS === 'android') { UIManager.dispatchViewManagerCommand( textFieldID, - UIManager.AndroidTextInput.Commands.focusTextInput, + UIManager.getViewManagerConfig('AndroidTextInput').Commands + .focusTextInput, null, ); } @@ -62,7 +63,8 @@ function blurTextInput(textFieldID: ?number) { } else if (Platform.OS === 'android') { UIManager.dispatchViewManagerCommand( textFieldID, - UIManager.AndroidTextInput.Commands.blurTextInput, + UIManager.getViewManagerConfig('AndroidTextInput').Commands + .blurTextInput, null, ); } diff --git a/Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js b/Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js index eb6da14628..b7295bd1b1 100644 --- a/Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js +++ b/Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js @@ -185,8 +185,9 @@ const ToolbarAndroid = createReactClass({ action.icon = resolveAssetSource(action.icon); } if (action.show) { - action.show = - UIManager.ToolbarAndroid.Constants.ShowAsAction[action.show]; + action.show = UIManager.getViewManagerConfig( + 'ToolbarAndroid', + ).Constants.ShowAsAction[action.show]; } nativeActions.push(action); } diff --git a/Libraries/Components/Touchable/TouchableNativeFeedback.android.js b/Libraries/Components/Touchable/TouchableNativeFeedback.android.js index bd9fdfce16..77e5434792 100644 --- a/Libraries/Components/Touchable/TouchableNativeFeedback.android.js +++ b/Libraries/Components/Touchable/TouchableNativeFeedback.android.js @@ -223,7 +223,7 @@ const TouchableNativeFeedback = createReactClass({ _dispatchHotspotUpdate: function(destX, destY) { UIManager.dispatchViewManagerCommand( ReactNative.findNodeHandle(this), - UIManager.RCTView.Commands.hotspotUpdate, + UIManager.getViewManagerConfig('RCTView').Commands.hotspotUpdate, [destX || 0, destY || 0], ); }, @@ -231,7 +231,7 @@ const TouchableNativeFeedback = createReactClass({ _dispatchPressedStateChange: function(pressed) { UIManager.dispatchViewManagerCommand( ReactNative.findNodeHandle(this), - UIManager.RCTView.Commands.setPressed, + UIManager.getViewManagerConfig('RCTView').Commands.setPressed, [pressed], ); }, diff --git a/Libraries/Components/ViewPager/ViewPagerAndroid.android.js b/Libraries/Components/ViewPager/ViewPagerAndroid.android.js index d77c081429..dda5c0d862 100644 --- a/Libraries/Components/ViewPager/ViewPagerAndroid.android.js +++ b/Libraries/Components/ViewPager/ViewPagerAndroid.android.js @@ -233,7 +233,7 @@ class ViewPagerAndroid extends React.Component<{ setPage = (selectedPage: number) => { UIManager.dispatchViewManagerCommand( ReactNative.findNodeHandle(this), - UIManager.AndroidViewPager.Commands.setPage, + UIManager.getViewManagerConfig('AndroidViewPager').Commands.setPage, [selectedPage], ); }; @@ -245,7 +245,8 @@ class ViewPagerAndroid extends React.Component<{ setPageWithoutAnimation = (selectedPage: number) => { UIManager.dispatchViewManagerCommand( ReactNative.findNodeHandle(this), - UIManager.AndroidViewPager.Commands.setPageWithoutAnimation, + UIManager.getViewManagerConfig('AndroidViewPager').Commands + .setPageWithoutAnimation, [selectedPage], ); }; diff --git a/Libraries/Components/WebView/WebView.android.js b/Libraries/Components/WebView/WebView.android.js index 6c85f0f642..83991432b5 100644 --- a/Libraries/Components/WebView/WebView.android.js +++ b/Libraries/Components/WebView/WebView.android.js @@ -366,7 +366,7 @@ class WebView extends React.Component { goForward = () => { UIManager.dispatchViewManagerCommand( this.getWebViewHandle(), - UIManager.RCTWebView.Commands.goForward, + UIManager.getViewManagerConfig('RCTWebView').Commands.goForward, null, ); }; @@ -374,7 +374,7 @@ class WebView extends React.Component { goBack = () => { UIManager.dispatchViewManagerCommand( this.getWebViewHandle(), - UIManager.RCTWebView.Commands.goBack, + UIManager.getViewManagerConfig('RCTWebView').Commands.goBack, null, ); }; @@ -385,7 +385,7 @@ class WebView extends React.Component { }); UIManager.dispatchViewManagerCommand( this.getWebViewHandle(), - UIManager.RCTWebView.Commands.reload, + UIManager.getViewManagerConfig('RCTWebView').Commands.reload, null, ); }; @@ -393,7 +393,7 @@ class WebView extends React.Component { stopLoading = () => { UIManager.dispatchViewManagerCommand( this.getWebViewHandle(), - UIManager.RCTWebView.Commands.stopLoading, + UIManager.getViewManagerConfig('RCTWebView').Commands.stopLoading, null, ); }; @@ -401,7 +401,7 @@ class WebView extends React.Component { postMessage = data => { UIManager.dispatchViewManagerCommand( this.getWebViewHandle(), - UIManager.RCTWebView.Commands.postMessage, + UIManager.getViewManagerConfig('RCTWebView').Commands.postMessage, [String(data)], ); }; @@ -415,7 +415,7 @@ class WebView extends React.Component { injectJavaScript = data => { UIManager.dispatchViewManagerCommand( this.getWebViewHandle(), - UIManager.RCTWebView.Commands.injectJavaScript, + UIManager.getViewManagerConfig('RCTWebView').Commands.injectJavaScript, [data], ); }; diff --git a/Libraries/Components/WebView/WebView.ios.js b/Libraries/Components/WebView/WebView.ios.js index 290db85eb8..f6c9295bab 100644 --- a/Libraries/Components/WebView/WebView.ios.js +++ b/Libraries/Components/WebView/WebView.ios.js @@ -561,10 +561,10 @@ class WebView extends React.Component { _getCommands() { if (!this.props.useWebKit) { - return UIManager.RCTWebView.Commands; + return UIManager.getViewManagerConfig('RCTWebView').Commands; } - return UIManager.RCTWKWebView.Commands; + return UIManager.getViewManagerConfig('RCTWKWebView').Commands; } /** diff --git a/Libraries/RCTTest/SnapshotViewIOS.ios.js b/Libraries/RCTTest/SnapshotViewIOS.ios.js index 1f77eecdab..ef2bbdb687 100644 --- a/Libraries/RCTTest/SnapshotViewIOS.ios.js +++ b/Libraries/RCTTest/SnapshotViewIOS.ios.js @@ -25,7 +25,7 @@ import type {ViewProps} from 'ViewPropTypes'; // Verify that RCTSnapshot is part of the UIManager since it is only loaded // if you have linked against RCTTest like in tests, otherwise we will have // a warning printed out -const RCTSnapshot = UIManager.RCTSnapshot +const RCTSnapshot = UIManager.getViewManagerConfig('RCTSnapshot') ? requireNativeComponent('RCTSnapshot') : View; diff --git a/Libraries/ReactNative/UIManager.js b/Libraries/ReactNative/UIManager.js index 534663b963..c935630119 100644 --- a/Libraries/ReactNative/UIManager.js +++ b/Libraries/ReactNative/UIManager.js @@ -35,6 +35,9 @@ UIManager.takeSnapshot = function() { 'Use ReactNative.takeSnapshot instead.', ); }; +UIManager.getViewManagerConfig = function(viewManagerName: string) { + return UIManager[viewManagerName]; +}; /** * Copies the ViewManager constants and commands into UIManager. This is diff --git a/Libraries/ReactNative/getNativeComponentAttributes.js b/Libraries/ReactNative/getNativeComponentAttributes.js index 6868fec538..64771945f9 100644 --- a/Libraries/ReactNative/getNativeComponentAttributes.js +++ b/Libraries/ReactNative/getNativeComponentAttributes.js @@ -23,7 +23,7 @@ const invariant = require('fbjs/lib/invariant'); const warning = require('fbjs/lib/warning'); function getNativeComponentAttributes(uiViewClassName: string) { - const viewConfig = UIManager[uiViewClassName]; + const viewConfig = UIManager.getViewManagerConfig(uiViewClassName); invariant( viewConfig != null && viewConfig.NativeProps != null, @@ -36,7 +36,7 @@ function getNativeComponentAttributes(uiViewClassName: string) { let {baseModuleName, bubblingEventTypes, directEventTypes} = viewConfig; let nativeProps = viewConfig.NativeProps; while (baseModuleName) { - const baseModule = UIManager[baseModuleName]; + const baseModule = UIManager.getViewManagerConfig(baseModuleName); if (!baseModule) { warning(false, 'Base module "%s" does not exist', baseModuleName); baseModuleName = null; diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 9be5d1fc93..0fabe24e9a 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -258,7 +258,7 @@ const RCTText = createReactNativeComponentClass( ); const RCTVirtualText = - UIManager.RCTVirtualText == null + UIManager.getViewManagerConfig('RCTVirtualText') == null ? RCTText : createReactNativeComponentClass('RCTVirtualText', () => ({ validAttributes: { diff --git a/Libraries/Utilities/deprecatedPropType.js b/Libraries/Utilities/deprecatedPropType.js index fefa12bd90..59619fb50b 100644 --- a/Libraries/Utilities/deprecatedPropType.js +++ b/Libraries/Utilities/deprecatedPropType.js @@ -21,7 +21,10 @@ function deprecatedPropType( ): ReactPropsCheckType { return function validate(props, propName, componentName, ...rest) { // Don't warn for native components. - if (!UIManager[componentName] && props[propName] !== undefined) { + if ( + !UIManager.getViewManagerConfig(componentName) && + props[propName] !== undefined + ) { console.warn( `\`${propName}\` supplied to \`${componentName}\` has been deprecated. ${explanation}`, ); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java index 20517e05ae..a6aed93436 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java @@ -28,9 +28,9 @@ import javax.annotation.Nullable; /** * Generates a lazy discovery enabled version of {@link UIManagerModule} constants. It only * contains a list of view manager names, so that JS side is aware of the managers there are. - * Actual ViewManager instantiation happens when {@code UIManager.SpecificViewManager} call happens. - * The View Manager is then registered on the JS side with the help of - * {@code UIManagerModule.getConstantsForViewManager}. + * Actual ViewManager instantiation happens when + * {@code UIManager.getViewManagerConfig('SpecificViewManager')} call happens. The View Manager is then + * registered on the JS side with the help of {@code UIManagerModule.getConstantsForViewManager}. */ /* package */ static Map createConstants( UIManagerModule.ViewManagerResolver resolver) { diff --git a/jest/setup.js b/jest/setup.js index 9aef617dd4..1e3cef4142 100644 --- a/jest/setup.js +++ b/jest/setup.js @@ -253,6 +253,7 @@ const mockNativeModules = { createView: jest.fn(), dispatchViewManagerCommand: jest.fn(), focus: jest.fn(), + getViewManagerConfig: jest.fn(), setChildren: jest.fn(), manageChildren: jest.fn(), updateView: jest.fn(),