From 0b14a19ea6f0bfd97fc8d3e3663615feab875d66 Mon Sep 17 00:00:00 2001 From: Devan Buggay Date: Mon, 29 Sep 2025 12:28:02 -0700 Subject: [PATCH] Migrate ReactRoot to Kotlin (#53238) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53238 Changelog: [Android][Changed] - Migrated ReactRoot to Kotlin Reviewed By: cortinico Differential Revision: D80074359 fbshipit-source-id: 273f5bfc2826f59f2bb1521b8dbd95c48e5eb0c4 --- .../ReactAndroid/api/ReactAndroid.api | 6 ++ .../facebook/react/uimanager/ReactRoot.java | 76 ------------------- .../com/facebook/react/uimanager/ReactRoot.kt | 66 ++++++++++++++++ .../react/uimanager/UIManagerHelper.kt | 3 +- .../java/com/facebook/react/RootViewTest.kt | 2 +- 5 files changed, 75 insertions(+), 78 deletions(-) delete mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.kt diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 87d9afd5774..eac51277424 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -3806,6 +3806,7 @@ public abstract interface class com/facebook/react/uimanager/ReactPointerEventsV } public abstract interface class com/facebook/react/uimanager/ReactRoot { + public static final field Companion Lcom/facebook/react/uimanager/ReactRoot$Companion; public static final field STATE_STARTED I public static final field STATE_STOPPED I public abstract fun getAppProperties ()Landroid/os/Bundle; @@ -3823,6 +3824,11 @@ public abstract interface class com/facebook/react/uimanager/ReactRoot { public abstract fun setShouldLogContentAppeared (Z)V } +public final class com/facebook/react/uimanager/ReactRoot$Companion { + public static final field STATE_STARTED I + public static final field STATE_STOPPED I +} + public abstract interface class com/facebook/react/uimanager/ReactShadowNode { public abstract fun addChildAt (Lcom/facebook/react/uimanager/ReactShadowNode;I)V public abstract fun addNativeChildAt (Lcom/facebook/react/uimanager/ReactShadowNode;I)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java deleted file mode 100644 index 5db5a41da2c..00000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.uimanager; - -import android.os.Bundle; -import android.view.ViewGroup; -import androidx.annotation.Nullable; -import com.facebook.infer.annotation.Nullsafe; -import com.facebook.react.uimanager.common.UIManagerType; -import java.util.concurrent.atomic.AtomicInteger; - -/** Interface for the root native view of a React native application */ -@Nullsafe(Nullsafe.Mode.LOCAL) -public interface ReactRoot { - - /** This constant represents that ReactRoot hasn't started yet or it has been destroyed. */ - int STATE_STOPPED = 0; - - /** This constant represents that ReactRoot has started. */ - int STATE_STARTED = 1; - - /** Return cached launch properties for app */ - @Nullable - Bundle getAppProperties(); - - String getJSModuleName(); - - /** Fabric or Default UI Manager, see {@link UIManagerType} */ - @UIManagerType - int getUIManagerType(); - - int getRootViewTag(); - - void setRootViewTag(int rootViewTag); - - /** Calls into JS to start the React application. */ - void runApplication(); - - /** Handler for stages {@link com.facebook.react.surface.ReactStage} */ - void onStage(@ReactStage int stage); - - /** Return native view for root */ - ViewGroup getRootViewGroup(); - - /** - * @return Cached values for widthMeasureSpec. - */ - int getWidthMeasureSpec(); - - /** - * @return Cached values for and heightMeasureSpec. - */ - int getHeightMeasureSpec(); - - /** Sets a flag that determines whether to log that content appeared on next view added. */ - void setShouldLogContentAppeared(boolean shouldLogContentAppeared); - - /** - * @return a {@link String} that represents the root js application that is being rendered with - * this {@link ReactRoot} - * @deprecated We recommend to not use this method as it is will be replaced in the near future. - */ - @Deprecated - @Nullable - String getSurfaceID(); - - /** - * @return an {@link AtomicInteger} that represents the state of the ReactRoot object. - */ - AtomicInteger getState(); -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.kt new file mode 100644 index 00000000000..b51c11c5f47 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.kt @@ -0,0 +1,66 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.uimanager + +import android.os.Bundle +import android.view.ViewGroup +import com.facebook.react.uimanager.common.UIManagerType +import java.util.concurrent.atomic.AtomicInteger + +/** Interface for the root native view of a React native application */ +public interface ReactRoot { + + public companion object { + /** This constant represents that ReactRoot hasn't started yet or it has been destroyed. */ + public const val STATE_STOPPED: Int = 0 + + /** This constant represents that ReactRoot has started. */ + public const val STATE_STARTED: Int = 1 + } + + /** Return cached launch properties for app */ + public fun getAppProperties(): Bundle? + + public fun getJSModuleName(): String + + /** Fabric or Default UI Manager, see [UIManagerType] */ + @UIManagerType public fun getUIManagerType(): Int + + public fun getRootViewTag(): Int + + public fun setRootViewTag(rootViewTag: Int) + + /** Calls into JS to start the React application. */ + public fun runApplication() + + /** Handler for stages [com.facebook.react.surface.ReactStage] */ + public fun onStage(@ReactStage stage: Int) + + /** Return native view for root */ + public fun getRootViewGroup(): ViewGroup + + /** @return Cached values for widthMeasureSpec. */ + public fun getWidthMeasureSpec(): Int + + /** @return Cached values for and heightMeasureSpec. */ + public fun getHeightMeasureSpec(): Int + + /** Sets a flag that determines whether to log that content appeared on next view added. */ + public fun setShouldLogContentAppeared(shouldLogContentAppeared: Boolean) + + /** + * @return a [String] that represents the root js application that is being rendered with this + * [ReactRoot] + * @deprecated We recommend to not use this method as it is will be replaced in the near future. + */ + @Deprecated("We recommend to not use this method as it is will be replaced in the near future.") + public fun getSurfaceID(): String? + + /** @return an [AtomicInteger] that represents the state of the ReactRoot object. */ + public fun getState(): AtomicInteger +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.kt index 87288fcc61d..758f3f069d7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.kt @@ -194,7 +194,8 @@ public object UIManagerHelper { public fun getSurfaceId(view: View): Int { if (view is ReactRoot) { val rootView = view as ReactRoot - return if (rootView.uiManagerType == UIManagerType.FABRIC) rootView.rootViewTag else -1 + return if (rootView.getUIManagerType() == UIManagerType.FABRIC) rootView.getRootViewTag() + else -1 } val reactTag = view.id diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.kt index 820e184b2df..3411c37d697 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.kt @@ -98,7 +98,7 @@ class RootViewTest { val rootViewId = 11 val rootView = ReactRootView(reactContext) rootView.id = rootViewId - rootView.rootViewTag = rootViewId + rootView.setRootViewTag(rootViewId) rootView.startReactApplication(instanceManager, "") rootView.simulateAttachForTesting() val ts = SystemClock.currentTimeMillis()