From 4b9e4fa1ef4a23abfd6df77ab645fdba6dd6bb8b Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Tue, 4 Jan 2022 16:02:51 -0800 Subject: [PATCH] Codemod: Make Android native ViewConfigs inherit parents' bubbling/direct events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: # Problem 1. Static ViewConfigs on **both platforms** contain their parent component's inherited bubbling/direct events (and props). 2. On Android, native ViewConfigs for child components **do not** inherit bubbling/direct events from their parent. (They do inherit the props, however). # Cause How child components inherit props from their parent component on Android: 1. A ViewManager's native props are calculated by [calling ViewManager.getNativeProps()](https://www.internalfb.com/code/fbsource/[5769b6d6ca123b2bed31dc2bc6bc8e4701581891]/xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java?lines=139) 2. Which [calls into ViewManagerPropertyUpdater.getNativeProps()](https://www.internalfb.com/code/fbsource/[11f0031c5e83d4d8903112d7d720b58981d3613f]/xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java?lines=278-280) 3. Which [calls into a code-generated $$PropsSetter object](https://www.internalfb.com/code/fbsource/[11f0031c5e83d4d8903112d7d720b58981d3613f]/xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerPropertyUpdater.java?lines=73-74%2C112) 4. The ReactProp annotation processor [code-generates a $$PropsSetter object](https://www.internalfb.com/code/fbsource/[cbc8ca6036219069ad52fb6aec66488b7a06a879]/xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/processing/ReactPropertyProcessor.java?lines=265) by [visiting the ViewManager’s *entire class hierarchy* in search of ReactProp annotations](https://www.internalfb.com/code/fbsource/[cbc8ca6036219069ad52fb6aec66488b7a06a879]/xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/processing/ReactPropertyProcessor.java?lines=203-230). Why child components don't inherit direct/bubbling events from their parents: 1. When we get the bubbling/direct events for a component on Android, we just call into the child ViewManager, which didn't forward its parent's props (until this diff): https://www.internalfb.com/code/fbsource/[5769b6d6ca123b2bed31dc2bc6bc8e4701581891]/xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java?lines=113%2C122 # Fix Codemod all components to manually forward the bubbling/direct events from their parents. Why Not: - Leads to a lot of boilerplate code. - Feels like a bandaid solution. - Doesn’t scale to open source. There’s more process when authoring new components. - Are thre more idiomatic alternative solutions? (See alternatives considered). Why: - It’s a bandaid solution, yes. And it doesn’t scale well to other components, true. But, we’re only bloating deprecated APIs. Long term, we’re going to kill off getExportedCustomBubblingEventTypeConstants() and getExportedCustomDirectEventTypeConstants(). - Our goal is to just unblock Static ViewConfigs. This is the simplest/safest/least intrusive way to accomplish our goal. # FAQ **If child components don't contain their parents bubbling/direct events, how can they can respond to their parent's bubbling/direct events?** - Bubbling/direct events are stored in a [global map](https://www.internalfb.com/code/fbsource/[2de1e1d59f6e0316868a6c4d9bca5fe673210106]/xplat/js/react-native-github/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js?lines=20-34). Once *one* component registers a bubbling/direct event, all components [can respond to that event](https://www.internalfb.com/code/fbsource/[2de1e1d59f6e0316868a6c4d9bca5fe673210106]/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.js?lines=2439-2440). **How does this component prop/event inheriting work on iOS?** 1. On iOS, ViewConfigs have a baseViewConfig property. 2. All components at least have baseViewConfig = RCTViewManager. 3. To create the native ViewConfig for the component, JavaScript runs this loop: https://www.internalfb.com/code/fbsource/[058bc6c4976d4cebb442dd2675a2a0570a214403]/xplat/js/react-native-github/Libraries/ReactNative/getNativeComponentAttributes.js?lines=42-61 # Alternative Solutions ***Solution 1:** Make Android components leverage baseViewConfig, like iOS.* Why Not: - baseViewConfig leads to unnecessary round trips from JS → Native (see [this TODO](https://www.internalfb.com/code/fbsource/[a88c9751494f1ee863a76238b532fca2b134032d]/xplat/js/react-native-github/Libraries/ReactNative/getNativeComponentAttributes.js?lines=34-35) that tells us we should avoid this on iOS). ***Solution 2:** In [UIManagerModuleConstantsHelper](https://www.internalfb.com/code/fbsource/[6717cba1e0db71777cf11dcf7b861b171bfd0c84]/xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java?lines=105-145), which generates the native ViewConfig for Android components, use Java reflection APIs to visit the class hierarchy of all ViewManagers when collecting bubbling/direct events.* Complications: - **Challenging to Implement**: Have to rely on advanced Java reflection APIs. You can’t just do getSuperclass().getDeclaredMethod(...).invoke(object) to invoke an overridden method. - **Challenging to Ship**: Would lead to a penalties when creating native view configs: either performance, or memory. This negatively impacts VR and legacy React Native android. ***Solution 3:** Create a deprecated ReactProp-like annotation (e.g: ReactEvent) but for declaring bubbling/direct events in Java ViewManagers for zero runtime cost event declaration.* Details: - Legacy React Native infra will be code-modded to newer ReactEvent annotation infra. - The ReactEvent annotation processor will navigate the ViewManager’s class hierarchy at build-time to generate a class that returns the ViewManager’s bubbling/direct events. - UIManagerModuleConstantsHelper will call into this class to get the bubbling/direct events. - **Aside:** The component codegen can also generate these annotations. This way, all you need to do is hook up your ViewManagers to codegen to guarantee that your native component exports the right bubbling/direct events to JavaScript. Why Not: - This is a lot of throwaway work for just making the SVC === NVC check pass, which we're only doing to unblock the SVC migration. Why is this throwaway work? - Java ViewManagers don’t do anything special in native with the Bubbling/Direct events. They declare the Bubbling/Direct events for JavaScript consumption. If JavaScript is the source of truth, then there’s no value in sending these Bubbling/Direct events to Java ViewManagers. Changelog: [Internal] Reviewed By: JoshuaGross Differential Revision: D33303418 fbshipit-source-id: 8d99fe80f83244443406bcfdc6cfea43b26f9c75 --- .../react/uimanager/BaseViewManager.java | 14 ++- .../drawer/ReactDrawerLayoutManager.java | 19 ++-- .../react/views/image/ReactImageManager.java | 29 +++--- .../views/modal/ReactModalHostManager.java | 15 +++- .../views/scroll/ReactScrollViewManager.java | 8 +- .../views/slider/ReactSliderManager.java | 13 ++- .../SwipeRefreshLayoutManager.java | 13 ++- .../views/text/ReactTextViewManager.java | 13 ++- .../textinput/ReactTextInputManager.java | 88 +++++++++++-------- 9 files changed, 141 insertions(+), 71 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java index 44596513318..1edee99465d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java @@ -429,9 +429,17 @@ public abstract class BaseViewManager getExportedCustomDirectEventTypeConstants() { - return MapBuilder.builder() - .put("topAccessibilityAction", MapBuilder.of("registrationName", "onAccessibilityAction")) - .build(); + @Nullable + Map baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants(); + Map eventTypeConstants = + baseEventTypeConstants == null ? new HashMap() : baseEventTypeConstants; + eventTypeConstants.putAll( + MapBuilder.builder() + .put( + "topAccessibilityAction", + MapBuilder.of("registrationName", "onAccessibilityAction")) + .build()); + return eventTypeConstants; } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java index 218cf10436f..67066aa5299 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java @@ -31,6 +31,7 @@ import com.facebook.react.views.drawer.events.DrawerClosedEvent; import com.facebook.react.views.drawer.events.DrawerOpenedEvent; import com.facebook.react.views.drawer.events.DrawerSlideEvent; import com.facebook.react.views.drawer.events.DrawerStateChangedEvent; +import java.util.HashMap; import java.util.Map; /** View Manager for {@link ReactDrawerLayout} components. */ @@ -210,12 +211,18 @@ public class ReactDrawerLayoutManager extends ViewGroupManager baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants(); + Map eventTypeConstants = + baseEventTypeConstants == null ? new HashMap() : baseEventTypeConstants; + eventTypeConstants.putAll( + MapBuilder.of( + DrawerSlideEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDrawerSlide"), + DrawerOpenedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDrawerOpen"), + DrawerClosedEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDrawerClose"), + DrawerStateChangedEvent.EVENT_NAME, + MapBuilder.of("registrationName", "onDrawerStateChanged"))); + return eventTypeConstants; } /** diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java index 3cef2275af8..187958c6ee4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java @@ -24,6 +24,7 @@ import com.facebook.react.uimanager.ViewProps; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactPropGroup; import com.facebook.yoga.YogaConstants; +import java.util.HashMap; import java.util.Map; @ReactModule(name = ReactImageManager.REACT_CLASS) @@ -245,17 +246,23 @@ public class ReactImageManager extends SimpleViewManager { @Override public @Nullable Map getExportedCustomDirectEventTypeConstants() { - return MapBuilder.of( - ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_LOAD_START), - MapBuilder.of("registrationName", "onLoadStart"), - ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_PROGRESS), - MapBuilder.of("registrationName", "onProgress"), - ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_LOAD), - MapBuilder.of("registrationName", "onLoad"), - ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_ERROR), - MapBuilder.of("registrationName", "onError"), - ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_LOAD_END), - MapBuilder.of("registrationName", "onLoadEnd")); + @Nullable + Map baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants(); + Map eventTypeConstants = + baseEventTypeConstants == null ? new HashMap() : baseEventTypeConstants; + eventTypeConstants.putAll( + MapBuilder.of( + ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_LOAD_START), + MapBuilder.of("registrationName", "onLoadStart"), + ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_PROGRESS), + MapBuilder.of("registrationName", "onProgress"), + ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_LOAD), + MapBuilder.of("registrationName", "onLoad"), + ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_ERROR), + MapBuilder.of("registrationName", "onError"), + ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_LOAD_END), + MapBuilder.of("registrationName", "onLoadEnd"))); + return eventTypeConstants; } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java index cff999c6a88..9a6e1c033c6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java @@ -24,6 +24,7 @@ import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.react.viewmanagers.ModalHostViewManagerDelegate; import com.facebook.react.viewmanagers.ModalHostViewManagerInterface; +import java.util.HashMap; import java.util.Map; /** View manager for {@link ReactModalHostView} components. */ @@ -137,10 +138,16 @@ public class ReactModalHostManager extends ViewGroupManager @Override public Map getExportedCustomDirectEventTypeConstants() { - return MapBuilder.builder() - .put(RequestCloseEvent.EVENT_NAME, MapBuilder.of("registrationName", "onRequestClose")) - .put(ShowEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShow")) - .build(); + @Nullable + Map baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants(); + Map eventTypeConstants = + baseEventTypeConstants == null ? new HashMap() : baseEventTypeConstants; + eventTypeConstants.putAll( + MapBuilder.builder() + .put(RequestCloseEvent.EVENT_NAME, MapBuilder.of("registrationName", "onRequestClose")) + .put(ShowEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShow")) + .build()); + return eventTypeConstants; } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java index 8e1a25e0d0e..3eb8aefafe7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java @@ -30,6 +30,7 @@ import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactPropGroup; import com.facebook.yoga.YogaConstants; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -335,7 +336,12 @@ public class ReactScrollViewManager extends ViewGroupManager @Override public @Nullable Map getExportedCustomDirectEventTypeConstants() { - return createExportedCustomDirectEventTypeConstants(); + @Nullable + Map baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants(); + Map eventTypeConstants = + baseEventTypeConstants == null ? new HashMap() : baseEventTypeConstants; + eventTypeConstants.putAll(createExportedCustomDirectEventTypeConstants()); + return eventTypeConstants; } public static Map createExportedCustomDirectEventTypeConstants() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java index 35ae1d3678d..f8040636a00 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java @@ -37,6 +37,7 @@ import com.facebook.yoga.YogaMeasureFunction; import com.facebook.yoga.YogaMeasureMode; import com.facebook.yoga.YogaMeasureOutput; import com.facebook.yoga.YogaNode; +import java.util.HashMap; import java.util.Map; /** @@ -246,9 +247,15 @@ public class ReactSliderManager extends SimpleViewManager @Override public Map getExportedCustomDirectEventTypeConstants() { - return MapBuilder.of( - ReactSlidingCompleteEvent.EVENT_NAME, - MapBuilder.of("registrationName", "onSlidingComplete")); + @Nullable + Map baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants(); + Map eventTypeConstants = + baseEventTypeConstants == null ? new HashMap() : baseEventTypeConstants; + eventTypeConstants.putAll( + MapBuilder.of( + ReactSlidingCompleteEvent.EVENT_NAME, + MapBuilder.of("registrationName", "onSlidingComplete"))); + return eventTypeConstants; } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/SwipeRefreshLayoutManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/SwipeRefreshLayoutManager.java index 0f2be380eaf..255855f3cab 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/SwipeRefreshLayoutManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/SwipeRefreshLayoutManager.java @@ -29,6 +29,7 @@ import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.react.viewmanagers.AndroidSwipeRefreshLayoutManagerDelegate; import com.facebook.react.viewmanagers.AndroidSwipeRefreshLayoutManagerInterface; +import java.util.HashMap; import java.util.Map; /** @@ -175,9 +176,15 @@ public class SwipeRefreshLayoutManager extends ViewGroupManager getExportedCustomDirectEventTypeConstants() { - return MapBuilder.builder() - .put("topRefresh", MapBuilder.of("registrationName", "onRefresh")) - .build(); + @Nullable + Map baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants(); + Map eventTypeConstants = + baseEventTypeConstants == null ? new HashMap() : baseEventTypeConstants; + eventTypeConstants.putAll( + MapBuilder.builder() + .put("topRefresh", MapBuilder.of("registrationName", "onRefresh")) + .build()); + return eventTypeConstants; } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java index eac8c312719..04af66144bb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java @@ -22,6 +22,7 @@ import com.facebook.react.uimanager.ReactStylesDiffMap; import com.facebook.react.uimanager.StateWrapper; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.yoga.YogaMeasureMode; +import java.util.HashMap; import java.util.Map; /** @@ -152,9 +153,15 @@ public class ReactTextViewManager @Override public @Nullable Map getExportedCustomDirectEventTypeConstants() { - return MapBuilder.of( - "topTextLayout", MapBuilder.of("registrationName", "onTextLayout"), - "topInlineViewLayout", MapBuilder.of("registrationName", "onInlineViewLayout")); + @Nullable + Map baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants(); + Map eventTypeConstants = + baseEventTypeConstants == null ? new HashMap() : baseEventTypeConstants; + eventTypeConstants.putAll( + MapBuilder.of( + "topTextLayout", MapBuilder.of("registrationName", "onTextLayout"), + "topInlineViewLayout", MapBuilder.of("registrationName", "onInlineViewLayout"))); + return eventTypeConstants; } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index 79e78e4db57..df6cc09407b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -202,48 +202,62 @@ public class ReactTextInputManager extends BaseViewManager getExportedCustomBubblingEventTypeConstants() { - return MapBuilder.builder() - .put( - "topSubmitEditing", - MapBuilder.of( - "phasedRegistrationNames", - MapBuilder.of("bubbled", "onSubmitEditing", "captured", "onSubmitEditingCapture"))) - .put( - "topEndEditing", - MapBuilder.of( - "phasedRegistrationNames", - MapBuilder.of("bubbled", "onEndEditing", "captured", "onEndEditingCapture"))) - .put( - "topTextInput", - MapBuilder.of( - "phasedRegistrationNames", - MapBuilder.of("bubbled", "onTextInput", "captured", "onTextInputCapture"))) - .put( - "topFocus", - MapBuilder.of( - "phasedRegistrationNames", - MapBuilder.of("bubbled", "onFocus", "captured", "onFocusCapture"))) - .put( - "topBlur", - MapBuilder.of( - "phasedRegistrationNames", - MapBuilder.of("bubbled", "onBlur", "captured", "onBlurCapture"))) - .put( - "topKeyPress", - MapBuilder.of( - "phasedRegistrationNames", - MapBuilder.of("bubbled", "onKeyPress", "captured", "onKeyPressCapture"))) - .build(); + @Nullable + Map baseEventTypeConstants = + super.getExportedCustomBubblingEventTypeConstants(); + Map eventTypeConstants = + baseEventTypeConstants == null ? new HashMap() : baseEventTypeConstants; + eventTypeConstants.putAll( + MapBuilder.builder() + .put( + "topSubmitEditing", + MapBuilder.of( + "phasedRegistrationNames", + MapBuilder.of( + "bubbled", "onSubmitEditing", "captured", "onSubmitEditingCapture"))) + .put( + "topEndEditing", + MapBuilder.of( + "phasedRegistrationNames", + MapBuilder.of("bubbled", "onEndEditing", "captured", "onEndEditingCapture"))) + .put( + "topTextInput", + MapBuilder.of( + "phasedRegistrationNames", + MapBuilder.of("bubbled", "onTextInput", "captured", "onTextInputCapture"))) + .put( + "topFocus", + MapBuilder.of( + "phasedRegistrationNames", + MapBuilder.of("bubbled", "onFocus", "captured", "onFocusCapture"))) + .put( + "topBlur", + MapBuilder.of( + "phasedRegistrationNames", + MapBuilder.of("bubbled", "onBlur", "captured", "onBlurCapture"))) + .put( + "topKeyPress", + MapBuilder.of( + "phasedRegistrationNames", + MapBuilder.of("bubbled", "onKeyPress", "captured", "onKeyPressCapture"))) + .build()); + return eventTypeConstants; } @Nullable @Override public Map getExportedCustomDirectEventTypeConstants() { - return MapBuilder.builder() - .put( - ScrollEventType.getJSEventName(ScrollEventType.SCROLL), - MapBuilder.of("registrationName", "onScroll")) - .build(); + @Nullable + Map baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants(); + Map eventTypeConstants = + baseEventTypeConstants == null ? new HashMap() : baseEventTypeConstants; + eventTypeConstants.putAll( + MapBuilder.builder() + .put( + ScrollEventType.getJSEventName(ScrollEventType.SCROLL), + MapBuilder.of("registrationName", "onScroll")) + .build()); + return eventTypeConstants; } @Override