diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 36a789a6de05..470216875444 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -4805,6 +4805,8 @@ public abstract interface class com/facebook/react/uimanager/UIManagerModule$Cus public class com/facebook/react/uimanager/UIManagerModuleConstantsHelper { public fun ()V + public static fun createConstants (Ljava/util/List;Ljava/util/Map;Ljava/util/Map;)Ljava/util/Map; + public static fun createConstantsForViewManager (Lcom/facebook/react/uimanager/ViewManager;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)Ljava/util/Map; public static fun getDefaultExportableEventTypes ()Ljava/util/Map; } @@ -5167,11 +5169,13 @@ public abstract interface annotation class com/facebook/react/uimanager/common/U public static final field Companion Lcom/facebook/react/uimanager/common/UIManagerType$Companion; public static final field DEFAULT I public static final field FABRIC I + public static final field LEGACY I } public final class com/facebook/react/uimanager/common/UIManagerType$Companion { public static final field DEFAULT I public static final field FABRIC I + public static final field LEGACY I } public final class com/facebook/react/uimanager/common/ViewUtil { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java index 03f05f53a040..41d926719083 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java @@ -12,10 +12,10 @@ import com.facebook.react.bridge.ModuleSpec; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.UIManager; import com.facebook.react.module.annotations.ReactModuleList; import com.facebook.react.module.model.ReactModuleInfo; import com.facebook.react.module.model.ReactModuleInfoProvider; -import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.ViewManager; import com.facebook.react.views.debuggingoverlay.DebuggingOverlayManager; import java.util.ArrayList; @@ -54,7 +54,7 @@ public Map getReactModuleInfos() { } /** - * @return a map of view managers that should be registered with {@link UIManagerModule} + * @return a map of view managers that should be registered with {@link UIManager} */ private Map getViewManagersMap() { if (mViewManagers == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackage.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackage.kt index 3541d31fb023..2ccc7a0edd43 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackage.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackage.kt @@ -9,9 +9,9 @@ package com.facebook.react import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.UIManager import com.facebook.react.common.annotations.DeprecatedInNewArchitecture import com.facebook.react.common.annotations.StableReactNativeAPI -import com.facebook.react.uimanager.UIManagerModule import com.facebook.react.uimanager.ViewManager /** @@ -37,7 +37,7 @@ public interface ReactPackage { @DeprecatedInNewArchitecture(message = "Migrate to BaseReactPackage and implement getModule") public fun createNativeModules(reactContext: ReactApplicationContext): List - /** @return a list of view managers that should be registered with [UIManagerModule] */ + /** @return a list of view managers that should be registered with [UIManager] */ public fun createViewManagers( reactContext: ReactApplicationContext ): List> diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java index a42933c8a5af..8c41b589ac27 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java @@ -9,8 +9,8 @@ import static com.facebook.infer.annotation.ThreadConfined.UI; import static com.facebook.react.uimanager.BlendModeHelper.needsIsolatedLayer; -import static com.facebook.react.uimanager.common.UIManagerType.DEFAULT; import static com.facebook.react.uimanager.common.UIManagerType.FABRIC; +import static com.facebook.react.uimanager.common.UIManagerType.LEGACY; import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE; import android.content.Context; @@ -114,7 +114,7 @@ public interface ReactRootViewEventListener { private int mLastHeight = 0; private int mLastOffsetX = Integer.MIN_VALUE; private int mLastOffsetY = Integer.MIN_VALUE; - private @UIManagerType int mUIManagerType = DEFAULT; + private @UIManagerType int mUIManagerType = LEGACY; private final AtomicInteger mState = new AtomicInteger(STATE_STOPPED); public ReactRootView(Context context) { @@ -817,7 +817,7 @@ public void handleException(final Throwable t) { } public void setIsFabric(boolean isFabric) { - mUIManagerType = isFabric ? FABRIC : DEFAULT; + mUIManagerType = isFabric ? FABRIC : LEGACY; } @Override diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java index cf14e51cf5f5..408b5bd4927e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java @@ -27,6 +27,7 @@ import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.common.annotations.VisibleForTesting; +import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.modules.core.ReactChoreographer; @@ -232,7 +233,7 @@ void executeBatch(long maxBatchNumber, NativeAnimatedNodesManager nodesManager) private boolean mInitializedForFabric = false; private boolean mInitializedForNonFabric = false; private boolean mEnqueuedAnimationOnFrame = false; - private @UIManagerType int mUIManagerType = UIManagerType.DEFAULT; + private @UIManagerType int mUIManagerType = UIManagerType.LEGACY; private int mNumFabricAnimations = 0; private int mNumNonFabricAnimations = 0; @@ -387,9 +388,13 @@ public void willDispatchViewUpdates(final UIManager uiManager) { if (mOperations.isEmpty() && mPreOperations.isEmpty()) { return; } - if (mUIManagerType == UIManagerType.FABRIC) { + if (mUIManagerType == UIManagerType.FABRIC + || ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) { return; } + // The following code ONLY executes for non-fabric + // When ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE is true, the folowing code + // might be stripped out. final long frameNo = mCurrentBatchNumber++; @@ -542,8 +547,8 @@ private void decrementInFlightAnimationsForViewTag(final int viewTag) { mUIManagerType = UIManagerType.FABRIC; } else if (mNumFabricAnimations == 0 && mNumNonFabricAnimations > 0 - && mUIManagerType != UIManagerType.DEFAULT) { - mUIManagerType = UIManagerType.DEFAULT; + && mUIManagerType != UIManagerType.LEGACY) { + mUIManagerType = UIManagerType.LEGACY; } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModuleRegistry.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModuleRegistry.java index d4ad9fafa614..144757d070fe 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModuleRegistry.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModuleRegistry.java @@ -8,6 +8,8 @@ package com.facebook.react.bridge; import com.facebook.infer.annotation.Assertions; +import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel; +import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger; import com.facebook.react.module.annotations.ReactModule; import com.facebook.systrace.Systrace; import java.util.ArrayList; @@ -113,6 +115,8 @@ public void onBatchComplete() { // short-circuit // the search, and simply call OnBatchComplete on the UI Manager. // With Fabric, UIManager would no longer be a NativeModule, so this call would simply go away + LegacyArchitectureLogger.assertWhenLegacyArchitectureMinifyingEnabled( + "NativeModuleRegistry.onBatchComplete()", LegacyArchitectureLogLevel.ERROR); ModuleHolder moduleHolder = mModules.get("UIManager"); if (moduleHolder != null && moduleHolder.hasInstance()) { ((OnBatchCompleteListener) moduleHolder.getModule()).onBatchComplete(); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/ReactChoreographer.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/ReactChoreographer.kt index 7e1922e7d595..4ab9524557b2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/ReactChoreographer.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/ReactChoreographer.kt @@ -26,7 +26,7 @@ public class ReactChoreographer private constructor(choreographerProvider: Chore public enum class CallbackType(internal val order: Int) { /** For use by perf markers that need to happen immediately after draw */ PERF_MARKERS(0), - /** For use by [com.facebook.react.uimanager.UIManagerModule] */ + /** For use by [com.facebook.react.bridge.UIManager] */ DISPATCH_UI(1), /** For use by [com.facebook.react.animated.NativeAnimatedModule] */ NATIVE_ANIMATED_MODULE(2), diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/debug/DidJSUpdateUiDuringFrameDetector.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/debug/DidJSUpdateUiDuringFrameDetector.kt index 2b8537b62bdd..91d9bb222890 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/debug/DidJSUpdateUiDuringFrameDetector.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/debug/DidJSUpdateUiDuringFrameDetector.kt @@ -4,6 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ + @file:Suppress( "DEPRECATION") // Suppressing deprecation of NotThreadSafeViewHierarchyUpdateDebugListener diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.kt index b36322f37543..d4254083092f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.kt @@ -11,6 +11,7 @@ import android.view.Choreographer import com.facebook.infer.annotation.Assertions import com.facebook.react.bridge.ReactContext import com.facebook.react.bridge.UiThreadUtil +import com.facebook.react.common.build.ReactBuildConfig import com.facebook.react.uimanager.UIManagerModule import java.util.TreeMap @@ -37,8 +38,6 @@ public class FpsDebugFrameCallback(private val reactContext: ReactContext) : ) private var choreographer: Choreographer? = null - private val uiManagerModule: UIManagerModule? = - reactContext.getNativeModule(UIManagerModule::class.java) private val didJSUpdateUiDuringFrameDetector: DidJSUpdateUiDuringFrameDetector = DidJSUpdateUiDuringFrameDetector() private var firstFrameTime: Long = -1 @@ -88,10 +87,13 @@ public class FpsDebugFrameCallback(private val reactContext: ReactContext) : // T172641976: re-think if we need to implement addBridgeIdleDebugListener and // removeBridgeIdleDebugListener for Bridgeless @Suppress("DEPRECATION") - if (!reactContext.isBridgeless) { - reactContext.catalystInstance.addBridgeIdleDebugListener(didJSUpdateUiDuringFrameDetector) + if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) { + val uiManagerModule = reactContext.getNativeModule(UIManagerModule::class.java) + if (!reactContext.isBridgeless) { + reactContext.catalystInstance.addBridgeIdleDebugListener(didJSUpdateUiDuringFrameDetector) + } + uiManagerModule?.setViewHierarchyUpdateDebugListener(didJSUpdateUiDuringFrameDetector) } - uiManagerModule?.setViewHierarchyUpdateDebugListener(didJSUpdateUiDuringFrameDetector) this.targetFps = targetFps UiThreadUtil.runOnUiThread { choreographer = Choreographer.getInstance() @@ -107,10 +109,14 @@ public class FpsDebugFrameCallback(private val reactContext: ReactContext) : public fun stop() { @Suppress("DEPRECATION") - if (!reactContext.isBridgeless) { - reactContext.catalystInstance.removeBridgeIdleDebugListener(didJSUpdateUiDuringFrameDetector) + if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) { + val uiManagerModule = reactContext.getNativeModule(UIManagerModule::class.java) + if (!reactContext.isBridgeless) { + reactContext.catalystInstance.removeBridgeIdleDebugListener( + didJSUpdateUiDuringFrameDetector) + } + uiManagerModule?.setViewHierarchyUpdateDebugListener(null) } - uiManagerModule?.setViewHierarchyUpdateDebugListener(null) UiThreadUtil.runOnUiThread { choreographer = Choreographer.getInstance() choreographer?.removeFrameCallback(this) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index deb791ebbbb1..d2334db7e3ec 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -699,7 +699,9 @@ FabricUIManager getUIManager() { /* package */ @Nullable T getNativeModule(Class nativeModuleInterface) { - if (nativeModuleInterface == UIManagerModule.class) { + if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE + && nativeModuleInterface == UIManagerModule.class) { + ReactSoftExceptionLogger.logSoftExceptionVerbose( TAG, new ReactNoCrashBridgeNotAllowedSoftException( diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java index a5f1686ff858..51f8db33b0f6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java @@ -7,6 +7,9 @@ package com.facebook.react.runtime; +import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_CONSTANTS_END; +import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_CONSTANTS_START; + import android.content.res.AssetManager; import android.view.View; import com.facebook.common.logging.FLog; @@ -29,6 +32,7 @@ import com.facebook.react.bridge.NativeArray; import com.facebook.react.bridge.NativeMap; import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactMarker; import com.facebook.react.bridge.ReactNoCrashSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; import com.facebook.react.bridge.RuntimeExecutor; @@ -60,7 +64,6 @@ import com.facebook.react.uimanager.DisplayMetricsHolder; import com.facebook.react.uimanager.IllegalViewOperationException; import com.facebook.react.uimanager.UIConstantsProviderBinding; -import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.UIManagerModuleConstantsHelper; import com.facebook.react.uimanager.ViewManager; import com.facebook.react.uimanager.ViewManagerRegistry; @@ -68,6 +71,7 @@ import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.soloader.SoLoader; import com.facebook.systrace.Systrace; +import com.facebook.systrace.SystraceMessage; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -242,15 +246,13 @@ final class ReactInstance { if (viewManager == null) { return null; } - return (NativeMap) - UIManagerModule.getConstantsForViewManager(viewManager, customDirectEvents); + return getConstantsForViewManager(viewManager, customDirectEvents); }, () -> { List viewManagers = new ArrayList<>(mViewManagerResolver.getEagerViewManagerMap().values()); - Map constants = - UIManagerModule.createConstants(viewManagers, null, customDirectEvents); + Map constants = createConstants(viewManagers, null, customDirectEvents); Collection lazyViewManagers = mViewManagerResolver.getLazyViewManagerNames(); if (lazyViewManagers.size() > 0) { @@ -287,6 +289,40 @@ final class ReactInstance { Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); } + private static Map createConstants( + List viewManagers, + @Nullable Map customBubblingEvents, + @Nullable Map customDirectEvents) { + ReactMarker.logMarker(CREATE_UI_MANAGER_MODULE_CONSTANTS_START); + SystraceMessage.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "CreateUIManagerConstants") + .arg("Lazy", false) + .flush(); + try { + return UIManagerModuleConstantsHelper.createConstants( + viewManagers, customBubblingEvents, customDirectEvents); + } finally { + Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); + ReactMarker.logMarker(CREATE_UI_MANAGER_MODULE_CONSTANTS_END); + } + } + + private static NativeMap getConstantsForViewManager( + ViewManager viewManager, Map customDirectEvents) { + SystraceMessage.beginSection( + Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstance.getConstantsForViewManager") + .arg("ViewManager", viewManager.getName()) + .arg("Lazy", true) + .flush(); + try { + Map viewManagerConstants = + UIManagerModuleConstantsHelper.createConstantsForViewManager( + viewManager, null, null, null, customDirectEvents); + return Arguments.makeNativeMap(viewManagerConstants); + } finally { + SystraceMessage.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE).flush(); + } + } + void initializeEagerTurboModules() { mQueueConfiguration .getNativeModulesQueueThread() diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/touch/JSResponderHandler.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/touch/JSResponderHandler.kt index 8dddd3d4e9e0..7e45e24b1571 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/touch/JSResponderHandler.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/touch/JSResponderHandler.kt @@ -12,7 +12,7 @@ import android.view.ViewGroup import android.view.ViewParent /** - * This class coordinates JSResponder commands for [UIManagerModule]. It should be set as + * This class coordinates JSResponder commands for [UIManager]. It should be set as * OnInterceptTouchEventListener for all newly created native views that implements [ ] and thanks * to the information whether JSResponder is set and to which view it will correctly coordinate the * return values of [OnInterceptTouchEventListener] such that touch events will be dispatched to the diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java index 6ce016f91303..156ce4b9cdbc 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java @@ -22,6 +22,9 @@ import com.facebook.react.bridge.ReactNoCrashSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; import com.facebook.react.bridge.UIManager; +import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel; +import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger; +import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.uimanager.common.UIManagerType; import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.react.uimanager.events.EventDispatcherProvider; @@ -57,7 +60,7 @@ private static UIManager getUIManager( ReactContext context, @UIManagerType int uiManagerType, boolean returnNullIfCatalystIsInactive) { - if (context.isBridgeless()) { + if (ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE || context.isBridgeless()) { @Nullable UIManager uiManager = context.getFabricUIManager(); if (uiManager == null) { ReactSoftExceptionLogger.logSoftException( @@ -69,6 +72,14 @@ private static UIManager getUIManager( return uiManager; } + // The following code is compiled-out when `context.isBridgeless() == true && + // ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE == true ` because: + // - BridgelessReactContext.isBridgeless() is set to true statically + // - BridgeReactContext is compiled-out when UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE == true + // + // To detect a potential regression we add the following assertion ERROR + LegacyArchitectureLogger.assertWhenLegacyArchitectureMinifyingEnabled( + "UIManagerHelper.getUIManager(context, uiManagerType)", LegacyArchitectureLogLevel.ERROR); if (!context.hasCatalystInstance()) { ReactSoftExceptionLogger.logSoftException( TAG, @@ -181,7 +192,7 @@ public static int getSurfaceId(View view) { int reactTag = view.getId(); // In non-Fabric we don't have (or use) SurfaceId - if (getUIManagerType(reactTag) == UIManagerType.DEFAULT) { + if (getUIManagerType(reactTag) == UIManagerType.LEGACY) { return -1; } 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 512212d17ae4..4a06bb35f557 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 @@ -9,8 +9,8 @@ import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_CONSTANTS_END; import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_CONSTANTS_START; -import static com.facebook.react.uimanager.common.UIManagerType.DEFAULT; import static com.facebook.react.uimanager.common.UIManagerType.FABRIC; +import static com.facebook.react.uimanager.common.UIManagerType.LEGACY; import android.content.ComponentCallbacks2; import android.content.res.Configuration; @@ -185,7 +185,7 @@ public void initialize() { getReactApplicationContext().registerComponentCallbacks(mMemoryTrimCallback); getReactApplicationContext().registerComponentCallbacks(mViewManagerRegistry); mEventDispatcher.registerEventEmitter( - DEFAULT, getReactApplicationContext().getJSModule(RCTEventEmitter.class)); + LEGACY, getReactApplicationContext().getJSModule(RCTEventEmitter.class)); } @Override @@ -851,7 +851,7 @@ public void receiveEvent(int reactTag, String eventName, @Nullable WritableMap e @Override public void receiveEvent( int surfaceId, int reactTag, String eventName, @Nullable WritableMap event) { - assert ViewUtil.getUIManagerType(reactTag) == DEFAULT; + assert ViewUtil.getUIManagerType(reactTag) == LEGACY; getReactApplicationContext() .getJSModule(RCTEventEmitter.class) .receiveEvent(reactTag, eventName, event); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java index ed637a61ca98..82592f6a3042 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java @@ -86,7 +86,9 @@ private static void validateDirectEventNames( * into the map of {@link UIManagerModule} base constants that is stored in {@link * UIManagerModuleConstants}. TODO(6845124): Create a test for this */ - /* package */ static Map createConstants( + // NOTE: When converted to Kotlin this method should be `internal` due to + // visibility restriction for `ReactInstance` + public static Map createConstants( List viewManagers, @Nullable Map allBubblingEventTypes, @Nullable Map allDirectEventTypes) { @@ -124,7 +126,9 @@ private static void validateDirectEventNames( return constants; } - /* package */ static Map createConstantsForViewManager( + // NOTE: When converted to Kotlin this method should be `internal` due to + // visibility restriction for `ReactInstance` + public static Map createConstantsForViewManager( ViewManager viewManager, @Nullable Map defaultBubblingEvents, @Nullable Map defaultDirectEvents, diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/UIManagerType.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/UIManagerType.kt index 9a0a31f221f0..f0c97b732222 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/UIManagerType.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/UIManagerType.kt @@ -11,11 +11,15 @@ import androidx.annotation.IntDef import com.facebook.react.common.annotations.DeprecatedInNewArchitecture @Retention(AnnotationRetention.SOURCE) -@IntDef(UIManagerType.DEFAULT, UIManagerType.FABRIC) +@Suppress("DEPRECATION") +@IntDef(UIManagerType.DEFAULT, UIManagerType.LEGACY, UIManagerType.FABRIC) @DeprecatedInNewArchitecture public annotation class UIManagerType { public companion object { + @Deprecated( + "UIManagerType.DEFAULT will be deleted in the next release of React Native. Use [LEGACY] instead.") public const val DEFAULT: Int = 1 + public const val LEGACY: Int = 1 public const val FABRIC: Int = 2 } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/ViewUtil.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/ViewUtil.kt index d0367c83d0a3..16952d8c7b55 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/ViewUtil.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/ViewUtil.kt @@ -25,7 +25,7 @@ public object ViewUtil { if (viewTag % 2 == 0) { UIManagerType.FABRIC } else { - UIManagerType.DEFAULT + UIManagerType.LEGACY } /** @@ -55,8 +55,8 @@ public object ViewUtil { // by RN and is essentially a random number. // At some point it would be great to pass the SurfaceContext here instead. @UIManagerType - val uiManagerType = if (surfaceId == -1) UIManagerType.DEFAULT else UIManagerType.FABRIC - if (uiManagerType == UIManagerType.DEFAULT && !isRootTag(viewTag)) { + val uiManagerType = if (surfaceId == -1) UIManagerType.LEGACY else UIManagerType.FABRIC + if (uiManagerType == UIManagerType.LEGACY && !isRootTag(viewTag)) { // TODO (T123064648): Some events for Fabric still didn't have the surfaceId set, so if it's // not a React RootView, double check if the tag belongs to Fabric. if (viewTag % 2 == 0) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ReactEventEmitter.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ReactEventEmitter.kt index 39362ac9db46..2234c0f113b8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ReactEventEmitter.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ReactEventEmitter.kt @@ -32,12 +32,12 @@ internal class ReactEventEmitter(private val reactContext: ReactApplicationConte } fun register(@UIManagerType uiManagerType: Int, eventEmitter: RCTEventEmitter?) { - check(uiManagerType == UIManagerType.DEFAULT) + check(uiManagerType == UIManagerType.LEGACY) defaultEventEmitter = eventEmitter } fun unregister(@UIManagerType uiManagerType: Int) { - if (uiManagerType == UIManagerType.DEFAULT) { + if (uiManagerType == UIManagerType.LEGACY) { defaultEventEmitter = null } else { fabricEventEmitter = null @@ -73,7 +73,7 @@ internal class ReactEventEmitter(private val reactContext: ReactApplicationConte val reactTag = touches.getMap(0)?.getInt(TouchesHelper.TARGET_KEY) ?: 0 @UIManagerType val uiManagerType = getUIManagerType(reactTag) - if (uiManagerType == UIManagerType.DEFAULT) { + if (uiManagerType == UIManagerType.LEGACY) { ensureDefaultEventEmitter()?.receiveTouches(eventName, touches, changedIndices) } } @@ -83,7 +83,7 @@ internal class ReactEventEmitter(private val reactContext: ReactApplicationConte @UIManagerType val uiManagerType = getUIManagerType(event.viewTag, event.surfaceId) if (uiManagerType == UIManagerType.FABRIC) { fabricEventEmitter?.let { TouchesHelper.sendTouchEvent(it, event) } - } else if (uiManagerType == UIManagerType.DEFAULT) { + } else if (uiManagerType == UIManagerType.LEGACY) { ensureDefaultEventEmitter()?.let { TouchesHelper.sendTouchesLegacy(it, event) } } } @@ -119,7 +119,7 @@ internal class ReactEventEmitter(private val reactContext: ReactApplicationConte if (uiManagerType == UIManagerType.FABRIC) { fabricEventEmitter?.receiveEvent( surfaceId, targetTag, eventName, canCoalesceEvent, customCoalesceKey, params, category) - } else if (uiManagerType == UIManagerType.DEFAULT) { + } else if (uiManagerType == UIManagerType.LEGACY) { ensureDefaultEventEmitter()?.receiveEvent(targetTag, eventName, params) } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt index 139a1c1a8cb9..2245b09ce00f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt @@ -38,6 +38,7 @@ import com.facebook.react.bridge.WritableMap import com.facebook.react.bridge.WritableNativeMap import com.facebook.react.common.ReactConstants import com.facebook.react.common.annotations.VisibleForTesting +import com.facebook.react.common.build.ReactBuildConfig import com.facebook.react.config.ReactFeatureFlags import com.facebook.react.uimanager.JSPointerDispatcher import com.facebook.react.uimanager.JSTouchDispatcher @@ -502,25 +503,30 @@ public class ReactModalHostView(context: ThemedReactContext) : val realWidth: Float = width.toFloat().pxToDp() val realHeight: Float = height.toFloat().pxToDp() - stateWrapper?.let { sw -> + val sw = stateWrapper + if (sw != null) { // new architecture val newStateData: WritableMap = WritableNativeMap() newStateData.putDouble("screenWidth", realWidth.toDouble()) newStateData.putDouble("screenHeight", realHeight.toDouble()) sw.updateState(newStateData) + } else if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) { + // When UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE = true, means the Legacy Architecture is + // fully disabled and can be minified. + // The goal is to compile-out UIManagerModule from the following code block: + run { + // old architecture + // TODO: T44725185 remove after full migration to Fabric + reactContext.runOnNativeModulesQueueThread( + object : GuardedRunnable(reactContext) { + override fun runGuarded() { + reactContext.reactApplicationContext + .getNativeModule(UIManagerModule::class.java) + ?.updateNodeSize(id, viewWidth, viewHeight) + } + }) + } } - ?: run { - // old architecture - // TODO: T44725185 remove after full migration to Fabric - reactContext.runOnNativeModulesQueueThread( - object : GuardedRunnable(reactContext) { - override fun runGuarded() { - reactContext.reactApplicationContext - .getNativeModule(UIManagerModule::class.java) - ?.updateNodeSize(id, viewWidth, viewHeight) - } - }) - } } override fun handleException(t: Throwable) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/safeareaview/ReactSafeAreaView.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/safeareaview/ReactSafeAreaView.kt index 10ce2e124d04..5ebcca8d66f4 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/safeareaview/ReactSafeAreaView.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/safeareaview/ReactSafeAreaView.kt @@ -15,6 +15,7 @@ import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat.CONSUMED import com.facebook.react.bridge.GuardedRunnable import com.facebook.react.bridge.WritableNativeMap +import com.facebook.react.common.build.ReactBuildConfig import com.facebook.react.uimanager.PixelUtil.pxToDp import com.facebook.react.uimanager.StateWrapper import com.facebook.react.uimanager.ThemedReactContext @@ -40,25 +41,26 @@ internal class ReactSafeAreaView(val reactContext: ThemedReactContext) : ViewGro @UiThread private fun updateState(insets: Insets) { - stateWrapper?.let { stateWrapper -> - // fabric + val sw = stateWrapper + if (sw != null) { WritableNativeMap().apply { putDouble("left", insets.left.toFloat().pxToDp().toDouble()) putDouble("top", insets.top.toFloat().pxToDp().toDouble()) putDouble("bottom", insets.bottom.toFloat().pxToDp().toDouble()) putDouble("right", insets.right.toFloat().pxToDp().toDouble()) - stateWrapper.updateState(this) + sw.updateState(this) } + } else if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) { + // paper + reactContext.runOnNativeModulesQueueThread( + object : GuardedRunnable(reactContext) { + override fun runGuarded() { + this@ReactSafeAreaView.reactContext.reactApplicationContext + .getNativeModule(UIManagerModule::class.java) + ?.updateInsetsPadding(id, insets.top, insets.left, insets.bottom, insets.right) + } + }) } - // paper - ?: reactContext.runOnNativeModulesQueueThread( - object : GuardedRunnable(reactContext) { - override fun runGuarded() { - this@ReactSafeAreaView.reactContext.reactApplicationContext - .getNativeModule(UIManagerModule::class.java) - ?.updateInsetsPadding(id, insets.top, insets.left, insets.bottom, insets.right) - } - }) } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java index 26c9aebc8388..a8eb94f940f7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java @@ -77,7 +77,7 @@ public void start() { return; } mListening = true; - getUIManagerModule().addUIManagerEventListener(this); + getUIManager().addUIManagerEventListener(this); } /** Stop listening to view hierarchy updates. Should be called before this is destroyed. */ @@ -86,7 +86,7 @@ public void stop() { return; } mListening = false; - getUIManagerModule().removeUIManagerEventListener(this); + getUIManager().removeUIManagerEventListener(this); } /** @@ -143,7 +143,7 @@ private void updateScrollPositionInternal() { return (ReactViewGroup) mScrollView.getChildAt(0); } - private UIManager getUIManagerModule() { + private UIManager getUIManager() { return Assertions.assertNotNull( UIManagerHelper.getUIManager( (ReactContext) mScrollView.getContext(), diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt index 5b3f661c6344..1e920bc36c10 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt @@ -312,7 +312,7 @@ public object ReactScrollViewHelper { FLog.i( TAG, "updateFabricScrollState[%d] scrollX %d scrollY %d", scrollView.id, scrollX, scrollY) } - if (ViewUtil.getUIManagerType(scrollView.id) == UIManagerType.DEFAULT) { + if (ViewUtil.getUIManagerType(scrollView.id) == UIManagerType.LEGACY) { return } // NOTE: if the state wrapper is null, we shouldn't even update diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java index d1e4b4eb10e4..0d3aaf8c4c36 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java @@ -34,16 +34,18 @@ import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.UIManager; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.common.ReactConstants; +import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.internal.SystraceSection; import com.facebook.react.uimanager.BackgroundStyleApplicator; import com.facebook.react.uimanager.LengthPercentage; import com.facebook.react.uimanager.LengthPercentageType; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.ReactCompoundView; -import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.uimanager.UIManagerHelper; import com.facebook.react.uimanager.ViewDefaults; import com.facebook.react.uimanager.common.UIManagerType; import com.facebook.react.uimanager.common.ViewUtil; @@ -195,7 +197,8 @@ protected void onLayout( // TODO T62882314: Delete this method when Fabric is fully released in OSS int reactTag = getId(); if (!(getText() instanceof Spanned) - || ViewUtil.getUIManagerType(reactTag) == UIManagerType.FABRIC) { + || ViewUtil.getUIManagerType(reactTag) == UIManagerType.FABRIC + || ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) { /** * In general, {@link #setText} is called via {@link ReactTextViewManager#updateExtraData} * before we are laid out. This ordering is a requirement because we utilize the data from @@ -213,8 +216,8 @@ protected void onLayout( } ReactContext reactContext = getReactContext(); - UIManagerModule uiManager = - Assertions.assertNotNull(reactContext.getNativeModule(UIManagerModule.class)); + UIManager uiManager = + Assertions.assertNotNull(UIManagerHelper.getUIManager(reactContext, UIManagerType.LEGACY)); Spanned text = (Spanned) getText(); Layout layout = getLayout(); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 42f238363e81..6b654bdf449a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -961,12 +961,14 @@ private void setIntrinsicContentSize() { // view, we don't need to construct one or apply it at all - it provides no use in Fabric. ReactContext reactContext = getReactContext(this); - if (mStateWrapper == null && !reactContext.isBridgeless()) { + if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) { + if (mStateWrapper == null && !reactContext.isBridgeless()) { - final ReactTextInputLocalData localData = new ReactTextInputLocalData(this); - UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); - if (uiManager != null) { - uiManager.setViewLocalData(getId(), localData); + final ReactTextInputLocalData localData = new ReactTextInputLocalData(this); + UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); + if (uiManager != null) { + uiManager.setViewLocalData(getId(), localData); + } } } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index d6583d9ae3a6..2d7563395e6a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -222,13 +222,13 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - // No-op since UIManagerModule handles actually laying out children. + // No-op since UIManager handles actually laying out children. } @Override @SuppressLint("MissingSuperCall") public void requestLayout() { - // No-op, terminate `requestLayout` here, UIManagerModule handles laying out children and + // No-op, terminate `requestLayout` here, UIManager handles laying out children and // `layout` is called on all RN-managed views by `NativeViewHierarchyManager` }