diff --git a/Libraries/ReactNative/requireNativeComponent.js b/Libraries/ReactNative/requireNativeComponent.js index 7a638afa8..7034d871a 100644 --- a/Libraries/ReactNative/requireNativeComponent.js +++ b/Libraries/ReactNative/requireNativeComponent.js @@ -12,7 +12,6 @@ */ 'use strict'; -const Platform = require('Platform'); const ReactNativeBridgeEventPlugin = require('ReactNativeBridgeEventPlugin'); const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes'); const UIManager = require('UIManager'); @@ -48,18 +47,35 @@ const warning = require('fbjs/lib/warning'); */ import type {ComponentInterface} from 'verifyPropTypes'; -let hasAttachedDefaultEventTypes: boolean = false; - function requireNativeComponent( viewName: string, componentInterface?: ?ComponentInterface, extraConfig?: ?{nativeOnly?: Object}, ): React$ComponentType | string { - function attachDefaultEventTypes(viewConfig) { - if (Platform.OS === 'android') { - // This is supported on Android platform only, - // as lazy view managers discovery is Android-specific. - viewConfig = merge(viewConfig, UIManager.getDefaultEventTypes()); + function attachBubblingEventTypes(viewConfig) { + if (UIManager.genericBubblingEventTypes) { + viewConfig.bubblingEventTypes = merge( + viewConfig.bubblingEventTypes, + UIManager.genericBubblingEventTypes, + ); + // As genericBubblingEventTypes do not change over time, and there's + // merge of all the events happening in Fiber, we need to pass + // genericBubblingEventTypes to Fiber only once. Therefore, we can delete + // it and forget about it. + delete UIManager.genericBubblingEventTypes; + } + } + + function attachDirectEventTypes(viewConfig) { + if (UIManager.genericDirectEventTypes) { + viewConfig.directEventTypes = merge( + viewConfig.directEventTypes, + UIManager.genericDirectEventTypes, + ); + // As genericDirectEventTypes do not change over time, and there's merge + // of all the events happening in Fiber, we need to pass genericDirectEventTypes + // to Fiber only once. Therefore, we can delete it and forget about it. + delete UIManager.genericDirectEventTypes; } } @@ -168,10 +184,8 @@ function requireNativeComponent( ); } - if (!hasAttachedDefaultEventTypes) { - attachDefaultEventTypes(viewConfig); - hasAttachedDefaultEventTypes = true; - } + attachBubblingEventTypes(viewConfig); + attachDirectEventTypes(viewConfig); // Register this view's event types with the ReactNative renderer. // This enables view managers to be initialized lazily, improving perf, diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java index 54e19763a..1cfef61ae 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -17,6 +17,7 @@ import android.content.res.Configuration; import com.facebook.common.logging.FLog; import com.facebook.debug.holder.PrinterHolder; import com.facebook.debug.tags.ReactDebugOverlayTags; +import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.animation.Animation; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Callback; @@ -116,6 +117,11 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements private int mBatchId = 0; + // Defines if events were already exported to JS. We do not send them more + // than once as they are stored and mixed in with Fiber for every ViewManager + // on JS side. + private boolean mEventsWereSentToJS = false; + public UIManagerModule( ReactApplicationContext reactContext, ViewManagerResolver viewManagerResolver, @@ -229,6 +235,7 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements } } + @DoNotStrip @ReactMethod(isBlockingSynchronousMethod = true) public @Nullable WritableMap getConstantsForViewManager(final String viewManagerName) { ViewManager targetView = @@ -245,8 +252,13 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements try { Map viewManagerConstants = UIManagerModuleConstantsHelper.createConstantsForViewManager( - targetView, null, mCustomDirectEvents); + targetView, + mEventsWereSentToJS ? null : UIManagerModuleConstants.getBubblingEventTypeConstants(), + mEventsWereSentToJS ? null : UIManagerModuleConstants.getDirectEventTypeConstants(), + null, + mCustomDirectEvents); if (viewManagerConstants != null) { + mEventsWereSentToJS = true; return Arguments.makeNativeMap(viewManagerConstants); } return null; @@ -255,12 +267,9 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements } } - @ReactMethod(isBlockingSynchronousMethod = true) - public WritableMap getDefaultEventTypes() { - return Arguments.makeNativeMap(UIManagerModuleConstantsHelper.getDefaultExportableEventTypes()); - } - - /** Resolves Direct Event name exposed to JS from the one known to the Native side. */ + /** + * Resolves Direct Event name exposed to JS from the one known to the Native side. + */ public CustomEventNamesResolver getDirectEventNamesResolver() { return new CustomEventNamesResolver() { @Override 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 f9062e935..28b108a2a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java @@ -24,9 +24,6 @@ import javax.annotation.Nullable; */ /* package */ class UIManagerModuleConstantsHelper { - private static final String BUBBLING_EVENTS_KEY = "bubblingEventTypes"; - private static final String DIRECT_EVENTS_KEY = "directEventTypes"; - /** * 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. @@ -41,12 +38,6 @@ import javax.annotation.Nullable; return constants; } - /* package */ static Map getDefaultExportableEventTypes() { - return MapBuilder.of( - BUBBLING_EVENTS_KEY, UIManagerModuleConstants.getBubblingEventTypeConstants(), - DIRECT_EVENTS_KEY, UIManagerModuleConstants.getDirectEventTypeConstants()); - } - /** * Generates map of constants that is then exposed by {@link UIManagerModule}. * Provided list of {@param viewManagers} is then used to populate content of @@ -93,6 +84,8 @@ import javax.annotation.Nullable; try { Map viewManagerConstants = createConstantsForViewManager( viewManager, + null, + null, allBubblingEventTypes, allDirectEventTypes); if (!viewManagerConstants.isEmpty()) { @@ -110,20 +103,31 @@ import javax.annotation.Nullable; /* package */ static Map createConstantsForViewManager( ViewManager viewManager, + @Nullable Map defaultBubblingEvents, + @Nullable Map defaultDirectEvents, @Nullable Map cumulativeBubblingEventTypes, @Nullable Map cumulativeDirectEventTypes) { + final String BUBBLING_EVENTS_KEY = "bubblingEventTypes"; + final String DIRECT_EVENTS_KEY = "directEventTypes"; + Map viewManagerConstants = MapBuilder.newHashMap(); Map viewManagerBubblingEvents = viewManager.getExportedCustomBubblingEventTypeConstants(); if (viewManagerBubblingEvents != null) { recursiveMerge(cumulativeBubblingEventTypes, viewManagerBubblingEvents); + recursiveMerge(viewManagerBubblingEvents, defaultBubblingEvents); viewManagerConstants.put(BUBBLING_EVENTS_KEY, viewManagerBubblingEvents); + } else if (defaultBubblingEvents != null) { + viewManagerConstants.put(BUBBLING_EVENTS_KEY, defaultBubblingEvents); } Map viewManagerDirectEvents = viewManager.getExportedCustomDirectEventTypeConstants(); if (viewManagerDirectEvents != null) { recursiveMerge(cumulativeDirectEventTypes, viewManagerDirectEvents); + recursiveMerge(viewManagerDirectEvents, defaultDirectEvents); viewManagerConstants.put(DIRECT_EVENTS_KEY, viewManagerDirectEvents); + } else if (defaultDirectEvents != null) { + viewManagerConstants.put(DIRECT_EVENTS_KEY, defaultDirectEvents); } Map customViewConstants = viewManager.getExportedViewConstants();