Skip to content

Commit

Permalink
Kotlinify react.bridge.CatalystInstance interface (#44545)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #44545

# Changelog:
[Internal] -

As in the title.

Reviewed By: javache

Differential Revision: D57253633

fbshipit-source-id: d8631f5d25c00bdf4c94fcd0d56746c35e5b2fc3
  • Loading branch information
rshest authored and facebook-github-bot committed May 14, 2024
1 parent 13dff7c commit 734ac42
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 106 deletions.
4 changes: 4 additions & 0 deletions packages/react-native/ReactAndroid/api/ReactAndroid.api
Original file line number Diff line number Diff line change
Expand Up @@ -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 <init> ()V
public static fun fromJSONArray (Lorg/json/JSONArray;)Lcom/facebook/react/bridge/ReadableArray;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,99 +5,88 @@
* 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
* the invocation of JavaScript methods and lets a set of Java APIs be invocable from JavaScript as
* 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 extends JavaScriptModule> T getJSModule(Class<T> jsInterface);
public fun <T : JavaScriptModule> getJSModule(jsInterface: Class<T>): T?

<T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface);
public fun <T : NativeModule> hasNativeModule(nativeModuleInterface: Class<T>): Boolean

@Nullable
<T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface);
public fun <T : NativeModule> getNativeModule(nativeModuleInterface: Class<T>): T?

@Nullable
NativeModule getNativeModule(String moduleName);
public fun getNativeModule(moduleName: String): NativeModule?

Collection<NativeModule> getNativeModules();
public val nativeModules: Collection<NativeModule>

/**
* 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
* whenever the bridge transitions from idle to busy and vice-versa, where the busy state is
* 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
Expand All @@ -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?
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,37 +63,40 @@ 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'")
}

override fun destroy() {
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 <T : JavaScriptModule> getJSModule(jsInterface: Class<T>): T? =
reactHost.currentReactContext?.getJSModule(jsInterface)

override public val javaScriptContextHolder: JavaScriptContextHolder
get() = reactHost.getJavaScriptContextHolder()!!

override public val jSCallInvokerHolder: CallInvokerHolder
get() = reactHost.getJSCallInvokerHolder()!!

override fun <T : JavaScriptModule> getJSModule(jsInterface: Class<T>): T =
reactHost.currentReactContext?.getJSModule(jsInterface)!!
override public val nativeMethodCallInvokerHolder: NativeMethodCallInvokerHolder
get() =
throw UnsupportedOperationException(
"Unimplemented method 'getNativeMethodCallInvokerHolder'")

override fun <T : NativeModule> hasNativeModule(nativeModuleInterface: Class<T>): Boolean =
reactHost.hasNativeModule(nativeModuleInterface)
Expand All @@ -104,12 +107,25 @@ public class BridgelessCatalystInstance(private val reactHost: ReactHostImpl) :
override fun getNativeModule(moduleName: String): NativeModule? =
reactHost.getNativeModule(moduleName)

override fun getNativeModules(): Collection<NativeModule> = reactHost.getNativeModules()
override public val nativeModules: Collection<NativeModule>
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'")
}
Expand All @@ -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.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

0 comments on commit 734ac42

Please sign in to comment.