diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.kt index 39eb047a5a5..5c79d382a79 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.kt @@ -7,6 +7,7 @@ package com.facebook.react +import android.annotation.SuppressLint import android.app.Activity import android.content.Intent import android.content.res.Configuration @@ -420,21 +421,27 @@ public open class ReactDelegate { } /** - * Get the current [ReactContext] from [ReactHost] or [ReactInstanceManager] + * Get the current [ReactContext] from the host captured when this delegate was constructed. + * + * A [ReactHost] always takes precedence, regardless of the process-wide architecture flag. When + * only a [ReactNativeHost] is present, its context is returned if the host is already + * initialized; otherwise this returns `null` without creating a [ReactInstanceManager]. * * Do not store a reference to this, if the React instance is reloaded or destroyed, this context * will no longer be valid. */ + @get:SuppressLint("DeprecatedClass") public val currentReactContext: ReactContext? get() { - return if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) { - if (reactHost != null) { - reactHost?.currentReactContext - } else { - null - } + reactHost?.let { + return it.currentReactContext + } + + val reactNativeHost = reactNativeHost ?: return null + return if (reactNativeHost.hasInstance()) { + reactNativeHost.reactInstanceManager.currentReactContext } else { - getReactInstanceManager().currentReactContext + null } } } diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/ReactDelegateTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/ReactDelegateTest.kt new file mode 100644 index 00000000000..e06e50c1c17 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/ReactDelegateTest.kt @@ -0,0 +1,141 @@ +/* + * 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 + +import android.annotation.SuppressLint +import android.app.Activity +import android.app.Application +import com.facebook.react.bridge.ReactContext +import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags +import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsDefaults +import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsForTests +import org.assertj.core.api.Assertions.assertThat +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.robolectric.Robolectric +import org.robolectric.RobolectricTestRunner + +@SuppressLint( + "ActivityStoredInField", + "DeprecatedClass", + "DeprecatedMethod", + "DeprecatedSuperclass", +) +@RunWith(RobolectricTestRunner::class) +class ReactDelegateTest { + + private lateinit var activity: Activity + + @Before + fun setUp() { + ReactNativeFeatureFlagsForTests.setUp() + activity = Robolectric.buildActivity(Activity::class.java).create().get() + } + + @After + fun tearDown() { + ReactNativeFeatureFlags.dangerouslyReset() + } + + @Test + fun currentReactContext_withReactHost_returnsContext() { + overrideBridgelessArchitecture(true) + val reactContext = mock() + val reactHost = mock { on { currentReactContext } doReturn reactContext } + val delegate = ReactDelegate(activity, reactHost, "test-app", null) + + assertThat(delegate.currentReactContext).isSameAs(reactContext) + } + + @Test + fun currentReactContext_withReactHost_ignoresArchitectureFlag() { + overrideBridgelessArchitecture(false) + val reactContext = mock() + val reactHost = mock { on { currentReactContext } doReturn reactContext } + val delegate = ReactDelegate(activity, reactHost, "test-app", null) + + assertThat(delegate.currentReactContext).isSameAs(reactContext) + } + + @Suppress("DEPRECATION") + @Test + fun currentReactContext_withoutReactNativeHost_returnsNull() { + overrideBridgelessArchitecture(false) + val delegate = ReactDelegate(activity, null as ReactNativeHost?, "test-app", null) + + assertThat(delegate.currentReactContext).isNull() + } + + @Suppress("DEPRECATION") + @Test + fun currentReactContext_withUninitializedReactNativeHost_doesNotCreateInstance() { + overrideBridgelessArchitecture(false) + val reactNativeHost = + object : ReactNativeHost(activity.application as Application) { + override fun getUseDeveloperSupport(): Boolean = false + + override fun getPackages(): List = emptyList() + } + val delegate = ReactDelegate(activity, reactNativeHost, "test-app", null) + + assertThat(delegate.currentReactContext).isNull() + assertThat(reactNativeHost.hasInstance()).isFalse() + } + + @Suppress("DEPRECATION") + @Test + fun currentReactContext_withInitializedReactNativeHost_returnsContext() { + overrideBridgelessArchitecture(false) + val reactContext = mock() + val instanceManager = + mock { on { currentReactContext } doReturn reactContext } + val reactNativeHost = createInitializedReactNativeHost(instanceManager) + val delegate = ReactDelegate(activity, reactNativeHost, "test-app", null) + + assertThat(delegate.currentReactContext).isSameAs(reactContext) + } + + @Suppress("DEPRECATION") + @Test + fun currentReactContext_withReactNativeHost_ignoresArchitectureFlag() { + overrideBridgelessArchitecture(true) + val reactContext = mock() + val instanceManager = + mock { on { currentReactContext } doReturn reactContext } + val reactNativeHost = createInitializedReactNativeHost(instanceManager) + val delegate = ReactDelegate(activity, reactNativeHost, "test-app", null) + + assertThat(delegate.currentReactContext).isSameAs(reactContext) + } + + @Suppress("DEPRECATION") + private fun createInitializedReactNativeHost( + instanceManager: ReactInstanceManager, + ): ReactNativeHost = + object : ReactNativeHost(activity.application as Application) { + override val reactInstanceManager: ReactInstanceManager = instanceManager + + override fun hasInstance(): Boolean = true + + override fun getUseDeveloperSupport(): Boolean = false + + override fun getPackages(): List = emptyList() + } + + private fun overrideBridgelessArchitecture(enabled: Boolean) { + ReactNativeFeatureFlags.override( + object : ReactNativeFeatureFlagsDefaults() { + override fun enableBridgelessArchitecture(): Boolean = enabled + }, + ) + } +}

AltStyle によって変換されたページ (->オリジナル) /