diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 575cb907e14185..bb791b858c5649 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -792,6 +792,10 @@ public abstract interface class com/facebook/react/bridge/JSExceptionHandler { public abstract fun handleException (Ljava/lang/Exception;)V } +public abstract interface class com/facebook/react/bridge/JSInstance { + public abstract fun invokeCallback (ILcom/facebook/react/bridge/NativeArrayInterface;)V +} + public class com/facebook/react/bridge/JSONArguments { public fun ()V public static fun fromJSONArray (Lorg/json/JSONArray;)Lcom/facebook/react/bridge/ReadableArray; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.kt similarity index 55% rename from packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java rename to packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.kt index e924caf946b125..3ef2970b2ce58b 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.kt @@ -5,17 +5,15 @@ * LICENSE file in the root directory of this source tree. */ -package com.facebook.react.bridge; - -import androidx.annotation.Nullable; -import com.facebook.proguard.annotations.DoNotStrip; -import com.facebook.react.bridge.queue.ReactQueueConfiguration; -import com.facebook.react.common.annotations.DeprecatedInNewArchitecture; -import com.facebook.react.common.annotations.VisibleForTesting; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModuleRegistry; -import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder; -import com.facebook.react.turbomodule.core.interfaces.NativeMethodCallInvokerHolder; -import java.util.Collection; +package com.facebook.react.bridge + +import com.facebook.proguard.annotations.DoNotStrip +import com.facebook.react.bridge.queue.ReactQueueConfiguration +import com.facebook.react.common.annotations.DeprecatedInNewArchitecture +import com.facebook.react.common.annotations.VisibleForTesting +import com.facebook.react.internal.turbomodule.core.interfaces.TurboModuleRegistry +import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder +import com.facebook.react.turbomodule.core.interfaces.NativeMethodCallInvokerHolder /** * A higher level API on top of the asynchronous JSC bridge. This provides an environment allowing @@ -23,61 +21,53 @@ * well. */ @DoNotStrip -public interface CatalystInstance - extends MemoryPressureListener, JSInstance, JSBundleLoaderDelegate { - void runJSBundle(); +public interface CatalystInstance : MemoryPressureListener, JSInstance, JSBundleLoaderDelegate { + public fun runJSBundle() // Returns the status of running the JS bundle; waits for an answer if runJSBundle is running - boolean hasRunJSBundle(); + public fun hasRunJSBundle(): Boolean /** - * Return the source URL of the JS Bundle that was run, or {@code null} if no JS bundle has been - * run yet. + * Return the source URL of the JS Bundle that was run, or `null` if no JS bundle has been run + * yet. */ - @Nullable - String getSourceURL(); + public val sourceURL: String? // This is called from java code, so it won't be stripped anyway, but proguard will rename it, // which this prevents. - @Override - @DoNotStrip - void invokeCallback(int callbackID, NativeArrayInterface arguments); + @DoNotStrip public override fun invokeCallback(callbackID: Int, arguments: NativeArrayInterface) - @DoNotStrip - void callFunction(String module, String method, NativeArray arguments); + @DoNotStrip public fun callFunction(module: String, method: String, arguments: NativeArray?) /** * Destroys this catalyst instance, waiting for any other threads in ReactQueueConfiguration * (besides the UI thread) to finish running. Must be called from the UI thread so that we can * fully shut down other threads. */ - void destroy(); + public fun destroy() - boolean isDestroyed(); + public val isDestroyed: Boolean /** Initialize all the native modules */ - @VisibleForTesting - void initialize(); + @VisibleForTesting public fun initialize() - ReactQueueConfiguration getReactQueueConfiguration(); + public val reactQueueConfiguration: ReactQueueConfiguration - T getJSModule(Class jsInterface); + public fun getJSModule(jsInterface: Class): T? - boolean hasNativeModule(Class nativeModuleInterface); + public fun hasNativeModule(nativeModuleInterface: Class): Boolean - @Nullable - T getNativeModule(Class nativeModuleInterface); + public fun getNativeModule(nativeModuleInterface: Class): T? - @Nullable - NativeModule getNativeModule(String moduleName); + public fun getNativeModule(moduleName: String): NativeModule? - Collection getNativeModules(); + public val nativeModules: Collection /** * This method permits a CatalystInstance to extend the known Native modules. This provided * registry contains only the new modules to load. */ - void extendNativeModules(NativeModuleRegistry modules); + public fun extendNativeModules(modules: NativeModuleRegistry) /** * Adds a idle listener for this Catalyst instance. The listener will receive notifications @@ -85,19 +75,18 @@ public interface CatalystInstance * defined as there being some non-zero number of calls to JS that haven't resolved via a * onBatchCompleted call. The listener should be purely passive and not affect application logic. */ - void addBridgeIdleDebugListener(NotThreadSafeBridgeIdleDebugListener listener); + public fun addBridgeIdleDebugListener(listener: NotThreadSafeBridgeIdleDebugListener) /** - * Removes a NotThreadSafeBridgeIdleDebugListener previously added with {@link - * #addBridgeIdleDebugListener} + * Removes a NotThreadSafeBridgeIdleDebugListener previously added with + * [ ][.addBridgeIdleDebugListener] */ - void removeBridgeIdleDebugListener(NotThreadSafeBridgeIdleDebugListener listener); + public fun removeBridgeIdleDebugListener(listener: NotThreadSafeBridgeIdleDebugListener) /** This method registers the file path of an additional JS segment by its ID. */ - void registerSegment(int segmentId, String path); + public fun registerSegment(segmentId: Int, path: String) - @VisibleForTesting - void setGlobalVariable(String propName, String jsonValue); + @VisibleForTesting public fun setGlobalVariable(propName: String, jsonValue: String) /** * Do not use this anymore. Use {@link #getRuntimeExecutor()} instead. Get the C pointer (as a @@ -107,41 +96,39 @@ public interface CatalystInstance * it: JavaScriptContextHolder jsContext = reactContext.getJavaScriptContextHolder() * synchronized(jsContext) { nativeThingNeedingJsContext(jsContext.get()); } */ - @Deprecated - JavaScriptContextHolder getJavaScriptContextHolder(); - - RuntimeExecutor getRuntimeExecutor(); + @get:Deprecated("Use getRuntimeExecutor() instead.") + public val javaScriptContextHolder: JavaScriptContextHolder - RuntimeScheduler getRuntimeScheduler(); + public val runtimeExecutor: RuntimeExecutor? + public val runtimeScheduler: RuntimeScheduler? /** * Returns a hybrid object that contains a pointer to a JS CallInvoker, which is used to schedule * work on the JS Thread. Required for TurboModuleManager initialization. */ - @Deprecated - CallInvokerHolder getJSCallInvokerHolder(); + @get:Deprecated("") public val jSCallInvokerHolder: CallInvokerHolder /** * Returns a hybrid object that contains a pointer to a NativeMethodCallInvoker, which is used to * schedule work on the NativeModules thread. Required for TurboModuleManager initialization. */ - NativeMethodCallInvokerHolder getNativeMethodCallInvokerHolder(); + public val nativeMethodCallInvokerHolder: NativeMethodCallInvokerHolder @DeprecatedInNewArchitecture( message = - "This method will be deprecated later as part of Stable APIs with bridge removal and not" - + " encouraged usage.") - void setTurboModuleRegistry(TurboModuleRegistry turboModuleRegistry); + "This method will be deprecated later as part of Stable APIs with bridge removal and not" + + " encouraged usage.") + public fun setTurboModuleRegistry(turboModuleRegistry: TurboModuleRegistry) @DeprecatedInNewArchitecture( message = - "This method will be deprecated later as part of Stable APIs with bridge removal and not" - + " encouraged usage.") - void setFabricUIManager(UIManager fabricUIManager); + "This method will be deprecated later as part of Stable APIs with bridge removal and not" + + " encouraged usage.") + public fun setFabricUIManager(fabricUIManager: UIManager) @DeprecatedInNewArchitecture( message = - "This method will be deprecated later as part of Stable APIs with bridge removal and not" - + " encouraged usage.") - UIManager getFabricUIManager(); + "This method will be deprecated later as part of Stable APIs with bridge removal and not" + + " encouraged usage.") + public fun getFabricUIManager(): UIManager? } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSInstance.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSInstance.kt index b5d5c2d3b1a24f..193adcd9c0e5cd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSInstance.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSInstance.kt @@ -11,7 +11,7 @@ package com.facebook.react.bridge * This interface includes the methods needed to use a running JS instance, without specifying any * of the bridge-specific initialization or lifecycle management. */ -internal interface JSInstance { +public interface JSInstance { public fun invokeCallback(callbackID: Int, arguments: NativeArrayInterface) // TODO if this interface survives refactoring, think about adding diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerProviderImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerProviderImpl.java index ed507ea33e7db4..cdb7249b0bab8a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerProviderImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerProviderImpl.java @@ -10,6 +10,8 @@ import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.bridge.CatalystInstance; import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.RuntimeExecutor; +import com.facebook.react.bridge.RuntimeScheduler; import com.facebook.react.bridge.UIManager; import com.facebook.react.bridge.UIManagerProvider; import com.facebook.react.fabric.events.EventBeatManager; @@ -49,13 +51,22 @@ public UIManager createUIManager(ReactApplicationContext reactApplicationContext CatalystInstance catalystInstance = reactApplicationContext.getCatalystInstance(); - binding.register( - catalystInstance.getRuntimeExecutor(), - catalystInstance.getRuntimeScheduler(), - fabricUIManager, - eventBeatManager, - mComponentFactory, - mConfig); + RuntimeExecutor runtimeExecutor = catalystInstance.getRuntimeExecutor(); + RuntimeScheduler runtimeScheduler = catalystInstance.getRuntimeScheduler(); + + if (runtimeExecutor != null && runtimeScheduler != null) { + binding.register( + runtimeExecutor, + runtimeScheduler, + fabricUIManager, + eventBeatManager, + mComponentFactory, + mConfig); + } else { + throw new IllegalStateException( + "Unable to register FabricUIManager with CatalystInstance, runtimeExecutor and" + + " runtimeScheduler must not be null"); + } Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt index 10bc63a9c98e2b..86cdcf513fd146 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt @@ -63,16 +63,12 @@ public class BridgelessCatalystInstance(private val reactHost: ReactHostImpl) : throw UnsupportedOperationException("Unimplemented method 'hasRunJSBundle'") } - override fun getSourceURL(): String? { - throw UnsupportedOperationException("Unimplemented method 'getSourceURL'") - } - @DoNotStrip override fun invokeCallback(callbackID: Int, arguments: NativeArrayInterface) { throw UnsupportedOperationException("Unimplemented method 'invokeCallback'") } - override fun callFunction(module: String, method: String, arguments: NativeArray) { + override fun callFunction(module: String, method: String, arguments: NativeArray?) { throw UnsupportedOperationException("Unimplemented method 'callFunction'") } @@ -80,20 +76,27 @@ public class BridgelessCatalystInstance(private val reactHost: ReactHostImpl) : throw UnsupportedOperationException("Unimplemented method 'destroy'") } - override fun isDestroyed(): Boolean { - throw UnsupportedOperationException("Unimplemented method 'isDestroyed'") - } + override public val isDestroyed: Boolean + get() = throw UnsupportedOperationException("Unimplemented method 'isDestroyed'") @VisibleForTesting override fun initialize() { throw UnsupportedOperationException("Unimplemented method 'initialize'") } - override fun getReactQueueConfiguration(): ReactQueueConfiguration = - reactHost.reactQueueConfiguration!! + override fun getJSModule(jsInterface: Class): T? = + reactHost.currentReactContext?.getJSModule(jsInterface) + + override public val javaScriptContextHolder: JavaScriptContextHolder + get() = reactHost.getJavaScriptContextHolder()!! + + override public val jSCallInvokerHolder: CallInvokerHolder + get() = reactHost.getJSCallInvokerHolder()!! - override fun getJSModule(jsInterface: Class): T = - reactHost.currentReactContext?.getJSModule(jsInterface)!! + override public val nativeMethodCallInvokerHolder: NativeMethodCallInvokerHolder + get() = + throw UnsupportedOperationException( + "Unimplemented method 'getNativeMethodCallInvokerHolder'") override fun hasNativeModule(nativeModuleInterface: Class): Boolean = reactHost.hasNativeModule(nativeModuleInterface) @@ -104,12 +107,25 @@ public class BridgelessCatalystInstance(private val reactHost: ReactHostImpl) : override fun getNativeModule(moduleName: String): NativeModule? = reactHost.getNativeModule(moduleName) - override fun getNativeModules(): Collection = reactHost.getNativeModules() + override public val nativeModules: Collection + get() = reactHost.getNativeModules() - override fun extendNativeModules(modules: NativeModuleRegistry) { + override public val reactQueueConfiguration: ReactQueueConfiguration + get() = reactHost.reactQueueConfiguration!! + + override public val runtimeExecutor: RuntimeExecutor? + get() = reactHost.getRuntimeExecutor() + + override public val runtimeScheduler: RuntimeScheduler? + get() = throw UnsupportedOperationException("Unimplemented method 'getRuntimeScheduler'") + + override public fun extendNativeModules(modules: NativeModuleRegistry) { throw UnsupportedOperationException("Unimplemented method 'extendNativeModules'") } + override public val sourceURL: String? + get() = throw UnsupportedOperationException("Unimplemented method 'getSourceURL'") + override fun addBridgeIdleDebugListener(listener: NotThreadSafeBridgeIdleDebugListener) { throw UnsupportedOperationException("Unimplemented method 'addBridgeIdleDebugListener'") } @@ -127,27 +143,6 @@ public class BridgelessCatalystInstance(private val reactHost: ReactHostImpl) : throw UnsupportedOperationException("Unimplemented method 'setGlobalVariable'") } - @Deprecated(message = "This API is unsupported in the New Architecture.") - override fun getJavaScriptContextHolder(): JavaScriptContextHolder? { - return reactHost.getJavaScriptContextHolder() - } - - override fun getRuntimeExecutor(): RuntimeExecutor? { - return reactHost.getRuntimeExecutor() - } - - override fun getRuntimeScheduler(): RuntimeScheduler { - throw UnsupportedOperationException("Unimplemented method 'getRuntimeScheduler'") - } - - override fun getJSCallInvokerHolder(): CallInvokerHolder? { - return reactHost.getJSCallInvokerHolder() - } - - override fun getNativeMethodCallInvokerHolder(): NativeMethodCallInvokerHolder { - throw UnsupportedOperationException("Unimplemented method 'getNativeMethodCallInvokerHolder'") - } - @DeprecatedInNewArchitecture( message = "This method will be deprecated later as part of Stable APIs with bridge removal and not encouraged usage.") diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/ReactTestHelper.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/ReactTestHelper.kt index 69d96486b6d59f..8de19b6fd58818 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/ReactTestHelper.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/ReactTestHelper.kt @@ -39,10 +39,10 @@ object ReactTestHelper { val reactQueueConfiguration: ReactQueueConfiguration = ReactQueueConfigurationImpl.create(spec) { e -> throw RuntimeException(e) } val reactInstance: CatalystInstance = mock(CatalystInstance::class.java) - whenever(reactInstance.getReactQueueConfiguration()).thenReturn(reactQueueConfiguration) + whenever(reactInstance.reactQueueConfiguration).thenReturn(reactQueueConfiguration) whenever(reactInstance.getNativeModule(UIManagerModule::class.java)) .thenReturn(mock(UIManagerModule::class.java)) - whenever(reactInstance.isDestroyed()).thenReturn(false) + whenever(reactInstance.isDestroyed).thenReturn(false) return reactInstance } }