From fa4bfde630121195271c7a0dfcd560799bf7d464 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Sun, 31 Mar 2024 06:10:45 -0700 Subject: [PATCH] Revert D55505416: Pull react instance method impls out of ReactContext Differential Revision: D55505416 Original commit changeset: ce1e3ab379eb Original Phabricator Diff: D55505416 fbshipit-source-id: ae988ae3464f40923521922d4c3ac4a57846a3ef --- .../ReactAndroid/api/ReactAndroid.api | 66 ++----- .../react/bridge/BridgeReactContext.kt | 185 +----------------- .../facebook/react/bridge/ReactContext.java | 162 +++++++++++++-- .../react/runtime/BridgelessReactContext.java | 14 -- .../react/uimanager/ThemedReactContext.java | 95 ++------- 5 files changed, 181 insertions(+), 341 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 888350fcf09..bde06d29131 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -543,22 +543,6 @@ public abstract class com/facebook/react/bridge/BaseJavaModule : com/facebook/re public final class com/facebook/react/bridge/BridgeReactContext : com/facebook/react/bridge/ReactApplicationContext { public fun (Landroid/content/Context;)V - public fun destroy ()V - public fun getCatalystInstance ()Lcom/facebook/react/bridge/CatalystInstance; - public fun getFabricUIManager ()Lcom/facebook/react/bridge/UIManager; - public fun getJSModule (Ljava/lang/Class;)Lcom/facebook/react/bridge/JavaScriptModule; - public fun getJavaScriptContextHolder ()Lcom/facebook/react/bridge/JavaScriptContextHolder; - public fun getNativeModule (Ljava/lang/Class;)Lcom/facebook/react/bridge/NativeModule; - public fun getNativeModules ()Ljava/util/Collection; - public fun getSourceURL ()Ljava/lang/String; - public fun handleException (Ljava/lang/Exception;)V - public fun hasActiveCatalystInstance ()Z - public fun hasActiveReactInstance ()Z - public fun hasCatalystInstance ()Z - public fun hasNativeModule (Ljava/lang/Class;)Z - public final fun initializeWithInstance (Lcom/facebook/react/bridge/CatalystInstance;)V - public fun isBridgeless ()Z - public fun registerSegment (ILjava/lang/String;Lcom/facebook/react/bridge/Callback;)V } public abstract interface class com/facebook/react/bridge/Callback { @@ -1104,35 +1088,36 @@ public abstract class com/facebook/react/bridge/ReactContext : android/content/C public fun assertOnNativeModulesQueueThread ()V public fun assertOnNativeModulesQueueThread (Ljava/lang/String;)V public fun assertOnUiQueueThread ()V - public abstract fun destroy ()V + public fun destroy ()V public fun emitDeviceEvent (Ljava/lang/String;)V public fun emitDeviceEvent (Ljava/lang/String;Ljava/lang/Object;)V - public abstract fun getCatalystInstance ()Lcom/facebook/react/bridge/CatalystInstance; + public fun getCatalystInstance ()Lcom/facebook/react/bridge/CatalystInstance; public fun getCurrentActivity ()Landroid/app/Activity; public fun getExceptionHandler ()Lcom/facebook/react/bridge/JSExceptionHandler; - public abstract fun getFabricUIManager ()Lcom/facebook/react/bridge/UIManager; + public fun getFabricUIManager ()Lcom/facebook/react/bridge/UIManager; public fun getJSExceptionHandler ()Lcom/facebook/react/bridge/JSExceptionHandler; public fun getJSMessageQueueThread ()Lcom/facebook/react/bridge/queue/MessageQueueThread; - public abstract fun getJSModule (Ljava/lang/Class;)Lcom/facebook/react/bridge/JavaScriptModule; - public abstract fun getJavaScriptContextHolder ()Lcom/facebook/react/bridge/JavaScriptContextHolder; + public fun getJSModule (Ljava/lang/Class;)Lcom/facebook/react/bridge/JavaScriptModule; + public fun getJavaScriptContextHolder ()Lcom/facebook/react/bridge/JavaScriptContextHolder; public fun getLifecycleState ()Lcom/facebook/react/common/LifecycleState; - public abstract fun getNativeModule (Ljava/lang/Class;)Lcom/facebook/react/bridge/NativeModule; - public abstract fun getNativeModules ()Ljava/util/Collection; + public fun getNativeModule (Ljava/lang/Class;)Lcom/facebook/react/bridge/NativeModule; + public fun getNativeModules ()Ljava/util/Collection; public fun getNativeModulesMessageQueueThread ()Lcom/facebook/react/bridge/queue/MessageQueueThread; - public abstract fun getSourceURL ()Ljava/lang/String; + public fun getSourceURL ()Ljava/lang/String; public fun getSystemService (Ljava/lang/String;)Ljava/lang/Object; public fun getUiMessageQueueThread ()Lcom/facebook/react/bridge/queue/MessageQueueThread; - public abstract fun handleException (Ljava/lang/Exception;)V - public abstract fun hasActiveCatalystInstance ()Z - public abstract fun hasActiveReactInstance ()Z - public abstract fun hasCatalystInstance ()Z + public fun handleException (Ljava/lang/Exception;)V + public fun hasActiveCatalystInstance ()Z + public fun hasActiveReactInstance ()Z + public fun hasCatalystInstance ()Z public fun hasCurrentActivity ()Z - public abstract fun hasNativeModule (Ljava/lang/Class;)Z - protected fun initializeFromOther (Lcom/facebook/react/bridge/ReactContext;)V + public fun hasNativeModule (Ljava/lang/Class;)Z protected fun initializeInteropModules ()V + protected fun initializeInteropModules (Lcom/facebook/react/bridge/ReactContext;)V public fun initializeMessageQueueThreads (Lcom/facebook/react/bridge/queue/ReactQueueConfiguration;)V + public fun initializeWithInstance (Lcom/facebook/react/bridge/CatalystInstance;)V public fun internal_registerInteropModule (Ljava/lang/Class;Ljava/lang/Object;)V - public abstract fun isBridgeless ()Z + public fun isBridgeless ()Z public fun isOnJSQueueThread ()Z public fun isOnNativeModulesQueueThread ()Z public fun isOnUiQueueThread ()Z @@ -1142,7 +1127,7 @@ public abstract class com/facebook/react/bridge/ReactContext : android/content/C public fun onHostResume (Landroid/app/Activity;)V public fun onNewIntent (Landroid/app/Activity;Landroid/content/Intent;)V public fun onWindowFocusChange (Z)V - public abstract fun registerSegment (ILjava/lang/String;Lcom/facebook/react/bridge/Callback;)V + public fun registerSegment (ILjava/lang/String;Lcom/facebook/react/bridge/Callback;)V public fun removeActivityEventListener (Lcom/facebook/react/bridge/ActivityEventListener;)V public fun removeLifecycleEventListener (Lcom/facebook/react/bridge/LifecycleEventListener;)V public fun removeWindowFocusChangeListener (Lcom/facebook/react/bridge/WindowFocusChangeListener;)V @@ -4837,25 +4822,16 @@ public class com/facebook/react/uimanager/ThemedReactContext : com/facebook/reac public fun (Lcom/facebook/react/bridge/ReactApplicationContext;Landroid/content/Context;)V public fun (Lcom/facebook/react/bridge/ReactApplicationContext;Landroid/content/Context;Ljava/lang/String;)V public fun (Lcom/facebook/react/bridge/ReactApplicationContext;Landroid/content/Context;Ljava/lang/String;I)V - public fun destroy ()V - public fun getCatalystInstance ()Lcom/facebook/react/bridge/CatalystInstance; + public fun addLifecycleEventListener (Lcom/facebook/react/bridge/LifecycleEventListener;)V + public fun getCurrentActivity ()Landroid/app/Activity; public fun getFabricUIManager ()Lcom/facebook/react/bridge/UIManager; - public fun getJSModule (Ljava/lang/Class;)Lcom/facebook/react/bridge/JavaScriptModule; - public fun getJavaScriptContextHolder ()Lcom/facebook/react/bridge/JavaScriptContextHolder; public fun getModuleName ()Ljava/lang/String; - public fun getNativeModule (Ljava/lang/Class;)Lcom/facebook/react/bridge/NativeModule; - public fun getNativeModules ()Ljava/util/Collection; public fun getReactApplicationContext ()Lcom/facebook/react/bridge/ReactApplicationContext; - public fun getSourceURL ()Ljava/lang/String; public fun getSurfaceID ()Ljava/lang/String; public fun getSurfaceId ()I - public fun handleException (Ljava/lang/Exception;)V - public fun hasActiveCatalystInstance ()Z - public fun hasActiveReactInstance ()Z - public fun hasCatalystInstance ()Z - public fun hasNativeModule (Ljava/lang/Class;)Z + public fun hasCurrentActivity ()Z public fun isBridgeless ()Z - public fun registerSegment (ILjava/lang/String;Lcom/facebook/react/bridge/Callback;)V + public fun removeLifecycleEventListener (Lcom/facebook/react/bridge/LifecycleEventListener;)V } public class com/facebook/react/uimanager/TouchTargetHelper { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/BridgeReactContext.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/BridgeReactContext.kt index 2adffc7da4a..0f37c2fd675 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/BridgeReactContext.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/BridgeReactContext.kt @@ -8,194 +8,13 @@ package com.facebook.react.bridge import android.content.Context -import com.facebook.common.logging.FLog -import com.facebook.react.bridge.queue.ReactQueueConfiguration -import com.facebook.react.common.ReactConstants import com.facebook.react.common.annotations.DeprecatedInNewArchitecture -import com.facebook.react.common.annotations.FrameworkAPI -import com.facebook.react.common.annotations.UnstableReactNativeAPI /** * This is the bridge-specific concrete subclass of ReactContext. ReactContext has many methods that - * delegate to the react instance. This subclass implements those methods, by delegating to the + * delegate to the react instance. This subclass will implement those methods, by delegating to the * CatalystInstance. If you need to create a ReactContext within an "bridge context", please create * BridgeReactContext. */ @DeprecatedInNewArchitecture -public class BridgeReactContext(base: Context) : ReactApplicationContext(base) { - @Volatile private var destroyed = false - private var catalystInstance: CatalystInstance? = null - - public fun initializeWithInstance(otherCatalystInstance: CatalystInstance?): Unit { - if (otherCatalystInstance == null) { - throw IllegalArgumentException("CatalystInstance cannot be null.") - } - if (catalystInstance != null) { - throw IllegalStateException("ReactContext has been already initialized") - } - if (destroyed) { - ReactSoftExceptionLogger.logSoftException( - TAG, IllegalStateException("Cannot initialize ReactContext after it has been destroyed.")) - } - - catalystInstance = otherCatalystInstance - - val queueConfig: ReactQueueConfiguration = otherCatalystInstance.reactQueueConfiguration - initializeMessageQueueThreads(queueConfig) - initializeInteropModules() - } - - public override fun getJSModule(jsInterface: Class?): T? { - val instance = - catalystInstance - ?: throw IllegalStateException( - if (destroyed) LATE_JS_ACCESS_EXCEPTION_MESSAGE - else EARLY_JS_ACCESS_EXCEPTION_MESSAGE) - - val interopModuleRegistry = mInteropModuleRegistry - if (interopModuleRegistry != null && - interopModuleRegistry.shouldReturnInteropModule(jsInterface)) { - return interopModuleRegistry.getInteropModule(jsInterface) - } - - return instance.getJSModule(jsInterface) - } - - public override fun hasNativeModule( - nativeModuleInterface: Class? - ): Boolean { - val instance = - catalystInstance - ?: throw IllegalStateException( - if (destroyed) LATE_NATIVE_MODULE_EXCEPTION_MESSAGE - else EARLY_NATIVE_MODULE_EXCEPTION_MESSAGE) - return instance.hasNativeModule(nativeModuleInterface) - } - - public override fun getNativeModules(): MutableCollection { - val instance = - catalystInstance - ?: throw IllegalStateException( - if (destroyed) LATE_NATIVE_MODULE_EXCEPTION_MESSAGE - else EARLY_NATIVE_MODULE_EXCEPTION_MESSAGE) - return instance.nativeModules - } - - public override fun getNativeModule(nativeModuleInterface: Class?): T? { - val instance = - catalystInstance - ?: throw IllegalStateException( - if (destroyed) LATE_NATIVE_MODULE_EXCEPTION_MESSAGE - else EARLY_NATIVE_MODULE_EXCEPTION_MESSAGE) - return instance.getNativeModule(nativeModuleInterface) - } - - @FrameworkAPI - @UnstableReactNativeAPI - public override fun getRuntimeExecutor(): RuntimeExecutor? { - val instance = - catalystInstance - ?: throw IllegalStateException( - if (destroyed) LATE_RUNTIME_EXECUTOR_ACCESS_EXCEPTION_MESSAGE - else EARLY_RUNTIME_EXECUTOR_ACCESS_EXCEPTION_MESSAGE) - - return instance.getRuntimeExecutor() - } - - public override fun getCatalystInstance(): CatalystInstance { - return catalystInstance!! - } - - @Deprecated( - "This API is unsupported in the New Architecture.", ReplaceWith("hasActiveReactInstance()")) - public override fun hasActiveCatalystInstance(): Boolean { - return hasActiveReactInstance() - } - - public override fun hasActiveReactInstance(): Boolean { - val instance = catalystInstance - return instance != null && !instance.isDestroyed - } - - public override fun hasCatalystInstance(): Boolean { - return catalystInstance != null - } - - public override fun destroy(): Unit { - UiThreadUtil.assertOnUiThread() - - destroyed = true - catalystInstance?.destroy() - } - - public override fun handleException(e: Exception?): Unit { - val jsExceptionHandler: JSExceptionHandler? = jsExceptionHandler - - if (hasActiveReactInstance() && jsExceptionHandler != null) { - jsExceptionHandler.handleException(e) - } else { - FLog.e( - ReactConstants.TAG, - "Unable to handle Exception - catalystInstanceVariableExists: " + - (catalystInstance != null) + - " - isCatalystInstanceAlive: " + - hasActiveReactInstance() + - " - hasExceptionHandler: " + - (jsExceptionHandler != null), - e) - throw IllegalStateException(e) - } - } - - public override fun isBridgeless(): Boolean { - return false - } - - public override fun getJavaScriptContextHolder(): JavaScriptContextHolder? { - return catalystInstance?.javaScriptContextHolder - } - - public override fun getFabricUIManager(): UIManager? { - val instance = - catalystInstance - ?: throw IllegalStateException( - if (destroyed) LATE_FABRIC_UI_MANAGER_ACCESS_EXCEPTION_MESSAGE - else EARLY_FABRIC_UI_MANAGER_ACCESS_EXCEPTION_MESSAGE) - - return instance.fabricUIManager ?: instance.getJSIModule(JSIModuleType.UIManager) as? UIManager - } - - public override fun getSourceURL(): String? { - return catalystInstance?.sourceURL - } - - public override fun registerSegment(segmentId: Int, path: String?, callback: Callback?): Unit { - catalystInstance!!.registerSegment(segmentId, path) - callback!!.invoke() - } - - private companion object { - private const val TAG = "BridgeReactContext" - - private const val EARLY_JS_ACCESS_EXCEPTION_MESSAGE = - ("Tried to access a JS module before the React instance was fully set up. Calls to " + - "ReactContext#getJSModule should only happen once initialize() has been called on your " + - "native module.") - private const val LATE_JS_ACCESS_EXCEPTION_MESSAGE = - "Tried to access a JS module after the React instance was destroyed." - private const val EARLY_NATIVE_MODULE_EXCEPTION_MESSAGE = - "Trying to call native module before CatalystInstance has been set!" - private const val LATE_NATIVE_MODULE_EXCEPTION_MESSAGE = - "Trying to call native module after CatalystInstance has been destroyed!" - - private const val EARLY_RUNTIME_EXECUTOR_ACCESS_EXCEPTION_MESSAGE = - "Tried to access a RuntimeExecutor before CatalystInstance has been set!" - private const val LATE_RUNTIME_EXECUTOR_ACCESS_EXCEPTION_MESSAGE = - "Tried to access a RuntimeExecutor after CatalystInstance has been destroyed!" - - private const val LATE_FABRIC_UI_MANAGER_ACCESS_EXCEPTION_MESSAGE = - "Tried to access a FabricUIManager after CatalystInstance has been destroyed!" - private const val EARLY_FABRIC_UI_MANAGER_ACCESS_EXCEPTION_MESSAGE = - "Tried to access a FabricUIManager after CatalystInstance before it has been set!" - } -} +public class BridgeReactContext(base: Context) : ReactApplicationContext(base) {} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java index 03e8726111c..9111da5ebd9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -25,6 +25,7 @@ import com.facebook.react.bridge.interop.InteropModuleRegistry; import com.facebook.react.bridge.queue.MessageQueueThread; import com.facebook.react.bridge.queue.ReactQueueConfiguration; import com.facebook.react.common.LifecycleState; +import com.facebook.react.common.ReactConstants; import com.facebook.react.common.annotations.DeprecatedInNewArchitecture; import com.facebook.react.common.annotations.FrameworkAPI; import com.facebook.react.common.annotations.UnstableReactNativeAPI; @@ -44,6 +45,16 @@ public abstract class ReactContext extends ContextWrapper { } private static final String TAG = "ReactContext"; + private static final String EARLY_JS_ACCESS_EXCEPTION_MESSAGE = + "Tried to access a JS module before the React instance was fully set up. Calls to " + + "ReactContext#getJSModule should only happen once initialize() has been called on your " + + "native module."; + private static final String LATE_JS_ACCESS_EXCEPTION_MESSAGE = + "Tried to access a JS module after the React instance was destroyed."; + private static final String EARLY_NATIVE_MODULE_EXCEPTION_MESSAGE = + "Trying to call native module before CatalystInstance has been set!"; + private static final String LATE_NATIVE_MODULE_EXCEPTION_MESSAGE = + "Trying to call native module after CatalystInstance has been destroyed!"; private final CopyOnWriteArraySet mLifecycleEventListeners = new CopyOnWriteArraySet<>(); @@ -54,8 +65,9 @@ public abstract class ReactContext extends ContextWrapper { private LifecycleState mLifecycleState = LifecycleState.BEFORE_CREATE; + private volatile boolean mDestroyed = false; + private @Nullable CatalystInstance mCatalystInstance; private @Nullable LayoutInflater mInflater; - private @Nullable ReactQueueConfiguration mQueueConfig; private @Nullable MessageQueueThread mUiMessageQueueThread; private @Nullable MessageQueueThread mNativeModulesMessageQueueThread; private @Nullable MessageQueueThread mJSMessageQueueThread; @@ -70,9 +82,25 @@ public abstract class ReactContext extends ContextWrapper { super(base); } - protected void initializeFromOther(ReactContext other) { - initializeMessageQueueThreads(other.mQueueConfig); - mInteropModuleRegistry = other.mInteropModuleRegistry; + /** Set and initialize CatalystInstance for this Context. This should be called exactly once. */ + public void initializeWithInstance(CatalystInstance catalystInstance) { + if (catalystInstance == null) { + throw new IllegalArgumentException("CatalystInstance cannot be null."); + } + if (mCatalystInstance != null) { + throw new IllegalStateException("ReactContext has been already initialized"); + } + if (mDestroyed) { + ReactSoftExceptionLogger.logSoftException( + TAG, + new IllegalStateException("Cannot initialize ReactContext after it has been destroyed.")); + } + + mCatalystInstance = catalystInstance; + + ReactQueueConfiguration queueConfig = catalystInstance.getReactQueueConfiguration(); + initializeMessageQueueThreads(queueConfig); + initializeInteropModules(); } /** Initialize message queue threads using a ReactQueueConfiguration. */ @@ -83,7 +111,6 @@ public abstract class ReactContext extends ContextWrapper { || mJSMessageQueueThread != null) { throw new IllegalStateException("Message queue threads already initialized"); } - mQueueConfig = queueConfig; mUiMessageQueueThread = queueConfig.getUIQueueThread(); mNativeModulesMessageQueueThread = queueConfig.getNativeModulesQueueThread(); mJSMessageQueueThread = queueConfig.getJSQueueThread(); @@ -105,6 +132,10 @@ public abstract class ReactContext extends ContextWrapper { mInteropModuleRegistry = new InteropModuleRegistry(); } + protected void initializeInteropModules(ReactContext reactContext) { + mInteropModuleRegistry = reactContext.mInteropModuleRegistry; + } + public void resetPerfStats() { if (mNativeModulesMessageQueueThread != null) { mNativeModulesMessageQueueThread.resetPerfStats(); @@ -118,6 +149,11 @@ public abstract class ReactContext extends ContextWrapper { mJSExceptionHandler = jSExceptionHandler; } + private void raiseCatalystInstanceMissingException() { + throw new IllegalStateException( + mDestroyed ? LATE_NATIVE_MODULE_EXCEPTION_MESSAGE : EARLY_NATIVE_MODULE_EXCEPTION_MESSAGE); + } + // We override the following method so that views inflated with the inflater obtained from this // context return the ReactContext in #getContext(). The default implementation uses the base // context instead, so it couldn't be cast to ReactContext. @@ -136,17 +172,44 @@ public abstract class ReactContext extends ContextWrapper { /** * @return handle to the specified JS module for the CatalystInstance associated with this Context */ - public abstract T getJSModule(Class jsInterface); + public T getJSModule(Class jsInterface) { + if (mCatalystInstance == null) { + if (mDestroyed) { + throw new IllegalStateException(LATE_JS_ACCESS_EXCEPTION_MESSAGE); + } + throw new IllegalStateException(EARLY_JS_ACCESS_EXCEPTION_MESSAGE); + } + if (mInteropModuleRegistry != null + && mInteropModuleRegistry.shouldReturnInteropModule(jsInterface)) { + return mInteropModuleRegistry.getInteropModule(jsInterface); + } + return mCatalystInstance.getJSModule(jsInterface); + } - public abstract boolean hasNativeModule(Class nativeModuleInterface); + public boolean hasNativeModule(Class nativeModuleInterface) { + if (mCatalystInstance == null) { + raiseCatalystInstanceMissingException(); + } + return mCatalystInstance.hasNativeModule(nativeModuleInterface); + } - public abstract Collection getNativeModules(); + public Collection getNativeModules() { + if (mCatalystInstance == null) { + raiseCatalystInstanceMissingException(); + } + return mCatalystInstance.getNativeModules(); + } /** * @return the instance of the specified module interface associated with this ReactContext. */ @Nullable - public abstract T getNativeModule(Class nativeModuleInterface); + public T getNativeModule(Class nativeModuleInterface) { + if (mCatalystInstance == null) { + raiseCatalystInstanceMissingException(); + } + return mCatalystInstance.getNativeModule(nativeModuleInterface); + } /** * @return the RuntimeExecutor, a thread-safe handler for accessing the runtime. @@ -155,7 +218,12 @@ public abstract class ReactContext extends ContextWrapper { @Nullable @FrameworkAPI @UnstableReactNativeAPI - public abstract RuntimeExecutor getRuntimeExecutor(); + public RuntimeExecutor getRuntimeExecutor() { + if (mCatalystInstance == null) { + raiseCatalystInstanceMissingException(); + } + return mCatalystInstance.getRuntimeExecutor(); + } /** * Calls RCTDeviceEventEmitter.emit to JavaScript, with given event name and an optional list of @@ -172,7 +240,9 @@ public abstract class ReactContext extends ContextWrapper { emitDeviceEvent(eventName, null); } - public abstract CatalystInstance getCatalystInstance(); + public CatalystInstance getCatalystInstance() { + return Assertions.assertNotNull(mCatalystInstance); + } /** * This API has been deprecated due to naming consideration, please use hasActiveReactInstance() @@ -181,14 +251,20 @@ public abstract class ReactContext extends ContextWrapper { * @return */ @Deprecated - public abstract boolean hasActiveCatalystInstance(); + public boolean hasActiveCatalystInstance() { + return hasActiveReactInstance(); + } /** * @return true if there is an non-null, alive react native instance */ - public abstract boolean hasActiveReactInstance(); + public boolean hasActiveReactInstance() { + return mCatalystInstance != null && !mCatalystInstance.isDestroyed(); + } - public abstract boolean hasCatalystInstance(); + public boolean hasCatalystInstance() { + return mCatalystInstance != null; + } public LifecycleState getLifecycleState() { return mLifecycleState; @@ -304,7 +380,14 @@ public abstract class ReactContext extends ContextWrapper { /** Destroy this instance, making it unusable. */ @ThreadConfined(UI) - public abstract void destroy(); + public void destroy() { + UiThreadUtil.assertOnUiThread(); + + mDestroyed = true; + if (mCatalystInstance != null) { + mCatalystInstance.destroy(); + } + } /** Should be called by the hosting Fragment in {@link Fragment#onActivityResult} */ public void onActivityResult( @@ -397,7 +480,27 @@ public abstract class ReactContext extends ContextWrapper { * Passes the given exception to the current {@link JSExceptionHandler} if one exists, rethrowing * otherwise. */ - public abstract void handleException(Exception e); + public void handleException(Exception e) { + boolean catalystInstanceVariableExists = mCatalystInstance != null; + boolean isCatalystInstanceAlive = + catalystInstanceVariableExists && !mCatalystInstance.isDestroyed(); + boolean hasExceptionHandler = mJSExceptionHandler != null; + + if (isCatalystInstanceAlive && hasExceptionHandler) { + mJSExceptionHandler.handleException(e); + } else { + FLog.e( + ReactConstants.TAG, + "Unable to handle Exception - catalystInstanceVariableExists: " + + catalystInstanceVariableExists + + " - isCatalystInstanceAlive: " + + isCatalystInstanceAlive + + " - hasExceptionHandler: " + + hasExceptionHandler, + e); + throw new IllegalStateException(e); + } + } public class ExceptionHandlerWrapper implements JSExceptionHandler { @Override @@ -451,7 +554,9 @@ public abstract class ReactContext extends ContextWrapper { * @deprecated DO NOT USE, this method will be removed in the near future. */ @Deprecated - public abstract boolean isBridgeless(); + public boolean isBridgeless() { + return false; + } /** * Get the C pointer (as a long) to the JavaScriptCore context associated with this instance. Use @@ -459,7 +564,12 @@ public abstract class ReactContext extends ContextWrapper { * JavaScriptContextHolder jsContext = reactContext.getJavaScriptContextHolder() * synchronized(jsContext) { nativeThingNeedingJsContext(jsContext.get()); } */ - public abstract @Nullable JavaScriptContextHolder getJavaScriptContextHolder(); + public @Nullable JavaScriptContextHolder getJavaScriptContextHolder() { + if (mCatalystInstance != null) { + return mCatalystInstance.getJavaScriptContextHolder(); + } + return null; + } @DeprecatedInNewArchitecture( message = @@ -470,7 +580,12 @@ public abstract class ReactContext extends ContextWrapper { * * @return The UIManager when CatalystInstance is active. */ - public abstract @Nullable UIManager getFabricUIManager(); + public @Nullable UIManager getFabricUIManager() { + UIManager uiManager = mCatalystInstance.getFabricUIManager(); + return uiManager != null + ? uiManager + : (UIManager) mCatalystInstance.getJSIModule(JSIModuleType.UIManager); + } /** * Get the sourceURL for the JS bundle from the CatalystInstance. This method is needed for @@ -478,13 +593,18 @@ public abstract class ReactContext extends ContextWrapper { * * @return The JS bundle URL set when the bundle was loaded */ - public abstract @Nullable String getSourceURL(); + public @Nullable String getSourceURL() { + return mCatalystInstance == null ? null : mCatalystInstance.getSourceURL(); + } /** * Register a JS segment after loading it from cache or server, make sure mCatalystInstance is * properly initialised and not null before calling. */ - public abstract void registerSegment(int segmentId, String path, Callback callback); + public void registerSegment(int segmentId, String path, Callback callback) { + Assertions.assertNotNull(mCatalystInstance).registerSegment(segmentId, path); + Assertions.assertNotNull(callback).invoke(); + } /** * Register a {@link JavaScriptModule} within the Interop Layer so that can be consumed whenever diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java index 74f772b4371..853cf74be64 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java @@ -90,25 +90,11 @@ class BridgelessReactContext extends ReactApplicationContext implements EventDis return new BridgelessCatalystInstance(mReactHost); } - @Deprecated - @Override - public boolean hasActiveCatalystInstance() { - return hasActiveReactInstance(); - } - @Override public boolean hasActiveReactInstance() { return mReactHost.isInstanceInitialized(); } - @Override - public boolean hasCatalystInstance() { - return false; - } - - @Override - public void destroy() {} - DevSupportManager getDevSupportManager() { return mReactHost.getDevSupportManager(); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java index 90496c1976f..50c22442af0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java @@ -7,20 +7,13 @@ package com.facebook.react.uimanager; +import android.app.Activity; import android.content.Context; import androidx.annotation.Nullable; -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.CatalystInstance; -import com.facebook.react.bridge.JavaScriptContextHolder; -import com.facebook.react.bridge.JavaScriptModule; -import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.RuntimeExecutor; import com.facebook.react.bridge.UIManager; -import com.facebook.react.common.annotations.FrameworkAPI; -import com.facebook.react.common.annotations.UnstableReactNativeAPI; -import java.util.Collection; /** * Wraps {@link ReactContext} with the base {@link Context} passed into the constructor. It provides @@ -53,67 +46,33 @@ public class ThemedReactContext extends ReactContext { @Nullable String moduleName, int surfaceId) { super(base); - if (reactApplicationContext.hasActiveReactInstance()) { - initializeFromOther(reactApplicationContext); + if (reactApplicationContext.hasCatalystInstance()) { + initializeWithInstance(reactApplicationContext.getCatalystInstance()); } + initializeInteropModules(reactApplicationContext); mReactApplicationContext = reactApplicationContext; mModuleName = moduleName; mSurfaceId = surfaceId; } @Override - public T getJSModule(Class jsInterface) { - return mReactApplicationContext.getJSModule(jsInterface); + public void addLifecycleEventListener(LifecycleEventListener listener) { + mReactApplicationContext.addLifecycleEventListener(listener); } @Override - public boolean hasNativeModule(Class nativeModuleInterface) { - return mReactApplicationContext.hasNativeModule(nativeModuleInterface); + public void removeLifecycleEventListener(LifecycleEventListener listener) { + mReactApplicationContext.removeLifecycleEventListener(listener); } @Override - public Collection getNativeModules() { - return mReactApplicationContext.getNativeModules(); - } - - @Nullable - @Override - public T getNativeModule(Class nativeModuleInterface) { - return mReactApplicationContext.getNativeModule(nativeModuleInterface); - } - - @Nullable - @Override - @FrameworkAPI - @UnstableReactNativeAPI - public RuntimeExecutor getRuntimeExecutor() { - return mReactApplicationContext.getRuntimeExecutor(); + public boolean hasCurrentActivity() { + return mReactApplicationContext.hasCurrentActivity(); } @Override - public CatalystInstance getCatalystInstance() { - return mReactApplicationContext.getCatalystInstance(); - } - - @Deprecated - @Override - public boolean hasActiveCatalystInstance() { - return mReactApplicationContext.hasActiveCatalystInstance(); - } - - @Override - public boolean hasActiveReactInstance() { - return mReactApplicationContext.hasActiveCatalystInstance(); - } - - @Override - public boolean hasCatalystInstance() { - return mReactApplicationContext.hasCatalystInstance(); - } - - @Override - public void destroy() { - mReactApplicationContext.destroy(); + public @Nullable Activity getCurrentActivity() { + return mReactApplicationContext.getCurrentActivity(); } /** @@ -144,36 +103,16 @@ public class ThemedReactContext extends ReactContext { return mReactApplicationContext; } - @Override - public void handleException(Exception e) { - mReactApplicationContext.handleException(e); - } - - @Deprecated @Override public boolean isBridgeless() { return mReactApplicationContext.isBridgeless(); } - @Nullable - @Override - public JavaScriptContextHolder getJavaScriptContextHolder() { - return mReactApplicationContext.getJavaScriptContextHolder(); - } - @Override public UIManager getFabricUIManager() { - return mReactApplicationContext.getFabricUIManager(); - } - - @Nullable - @Override - public String getSourceURL() { - return mReactApplicationContext.getSourceURL(); - } - - @Override - public void registerSegment(int segmentId, String path, Callback callback) { - mReactApplicationContext.registerSegment(segmentId, path, callback); + if (isBridgeless()) { + return mReactApplicationContext.getFabricUIManager(); + } + return super.getFabricUIManager(); } }