Allow passing custom JSRuntimeFactory to DefaultReactHost (#49366)

Summary:
an effort of lean core for jsc: https://github.com/Kudo/discussions-and-proposals/blob/%40kudo/lean-core-jsc/proposals/0836-lean-core-jsc.md

## Changelog:

[ANDROID] [CHANGED] - Allow passing custom JSRuntimeFactory to DefaultReactHost

Pull Request resolved: https://github.com/facebook/react-native/pull/49366

Test Plan:
- ci passed
- test from https://github.com/react-native-community/javascriptcore/pull/4

Reviewed By: cipolleschi

Differential Revision: D69656837

Pulled By: cortinico

fbshipit-source-id: ba8bf744c920a70c10fe5f6743f8dd182c88c4d4
This commit is contained in:
Kudo Chien
2025-02-17 07:30:45 -08:00
committed by Facebook GitHub Bot
parent 63080727a7
commit cdc166709d
3 changed files with 152 additions and 19 deletions
@@ -1982,9 +1982,14 @@ public class com/facebook/react/defaults/DefaultReactActivityDelegate : com/face
public final class com/facebook/react/defaults/DefaultReactHost {
public static final field INSTANCE Lcom/facebook/react/defaults/DefaultReactHost;
public static final fun getDefaultReactHost (Landroid/content/Context;Lcom/facebook/react/ReactNativeHost;)Lcom/facebook/react/ReactHost;
public static final fun getDefaultReactHost (Landroid/content/Context;Lcom/facebook/react/ReactNativeHost;Lcom/facebook/react/runtime/JSRuntimeFactory;)Lcom/facebook/react/ReactHost;
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/runtime/JSRuntimeFactory;ZLjava/util/List;)Lcom/facebook/react/ReactHost;
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/runtime/JSRuntimeFactory;ZLjava/util/List;Lkotlin/jvm/functions/Function1;Lcom/facebook/react/runtime/BindingsInstaller;)Lcom/facebook/react/ReactHost;
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;)Lcom/facebook/react/ReactHost;
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;Lkotlin/jvm/functions/Function1;Lcom/facebook/react/runtime/BindingsInstaller;)Lcom/facebook/react/ReactHost;
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Lcom/facebook/react/ReactNativeHost;Lcom/facebook/react/runtime/JSRuntimeFactory;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/runtime/JSRuntimeFactory;ZLjava/util/List;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/runtime/JSRuntimeFactory;ZLjava/util/List;Lkotlin/jvm/functions/Function1;Lcom/facebook/react/runtime/BindingsInstaller;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;Lkotlin/jvm/functions/Function1;Lcom/facebook/react/runtime/BindingsInstaller;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
}
@@ -18,6 +18,7 @@ import com.facebook.react.common.build.ReactBuildConfig
import com.facebook.react.fabric.ComponentFactory
import com.facebook.react.runtime.BindingsInstaller
import com.facebook.react.runtime.JSCInstance
import com.facebook.react.runtime.JSRuntimeFactory
import com.facebook.react.runtime.ReactHostImpl
import com.facebook.react.runtime.cxxreactpackage.CxxReactPackage
import com.facebook.react.runtime.hermes.HermesInstance
@@ -45,7 +46,7 @@ public object DefaultReactHost {
* composed in a `asset://...` URL
* @param jsBundleFilePath the path to the JS bundle on the filesystem. Will be composed in a
* `file://...` URL
* @param isHermesEnabled whether to use Hermes as the JS engine, default to true.
* @param jsRuntimeFactory the JS engine to use for executing [ReactHost], default to Hermes.
* @param useDevSupport whether to enable dev support, default to ReactBuildConfig.DEBUG.
* @param cxxReactPackageProviders a list of cxxreactpackage providers (to register c++ turbo
* modules)
@@ -60,7 +61,7 @@ public object DefaultReactHost {
jsMainModulePath: String = "index",
jsBundleAssetPath: String = "index",
jsBundleFilePath: String? = null,
isHermesEnabled: Boolean = true,
jsRuntimeFactory: JSRuntimeFactory? = null,
useDevSupport: Boolean = ReactBuildConfig.DEBUG,
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage> = emptyList(),
): ReactHost =
@@ -70,7 +71,7 @@ public object DefaultReactHost {
jsMainModulePath,
jsBundleAssetPath,
jsBundleFilePath,
isHermesEnabled,
jsRuntimeFactory,
useDevSupport,
cxxReactPackageProviders,
{ throw it },
@@ -88,7 +89,7 @@ public object DefaultReactHost {
* composed in a `asset://...` URL
* @param jsBundleFilePath the path to the JS bundle on the filesystem. Will be composed in a
* `file://...` URL
* @param isHermesEnabled whether to use Hermes as the JS engine, default to true.
* @param jsRuntimeFactory the JS engine to use for executing [ReactHost], default to Hermes.
* @param useDevSupport whether to enable dev support, default to ReactBuildConfig.DEBUG.
* @param cxxReactPackageProviders a list of cxxreactpackage providers (to register c++ turbo
* modules)
@@ -106,7 +107,7 @@ public object DefaultReactHost {
jsMainModulePath: String = "index",
jsBundleAssetPath: String = "index",
jsBundleFilePath: String? = null,
isHermesEnabled: Boolean = true,
jsRuntimeFactory: JSRuntimeFactory? = null,
useDevSupport: Boolean = ReactBuildConfig.DEBUG,
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage> = emptyList(),
exceptionHandler: (Exception) -> Unit = { throw it },
@@ -124,7 +125,6 @@ public object DefaultReactHost {
} else {
JSBundleLoader.createAssetLoader(context, "assets://$jsBundleAssetPath", true)
}
val jsRuntimeFactory = if (isHermesEnabled) HermesInstance() else JSCInstance()
val defaultTmmDelegateBuilder = DefaultTurboModuleManagerDelegate.Builder()
cxxReactPackageProviders.forEach { defaultTmmDelegateBuilder.addCxxReactPackage(it) }
val defaultReactHostDelegate =
@@ -132,7 +132,7 @@ public object DefaultReactHost {
jsMainModulePath = jsMainModulePath,
jsBundleLoader = bundleLoader,
reactPackages = packageList,
jsRuntimeFactory = jsRuntimeFactory,
jsRuntimeFactory = jsRuntimeFactory ?: HermesInstance(),
bindingsInstaller = bindingsInstaller,
turboModuleManagerDelegateBuilder = defaultTmmDelegateBuilder,
exceptionHandler = exceptionHandler)
@@ -151,6 +151,124 @@ public object DefaultReactHost {
return reactHost as ReactHost
}
/**
* Util function to create a default [ReactHost] to be used in your application. This method is
* used by the New App template.
*
* @param context the Android [Context] to use for creating the [ReactHost]
* @param packageList the list of [ReactPackage]s to use for creating the [ReactHost]
* @param jsMainModulePath the path to your app's main module on Metro. Usually `index` or
* `index.<platform>`
* @param jsBundleAssetPath the path to the JS bundle relative to the assets directory. Will be
* composed in a `asset://...` URL
* @param jsBundleFilePath the path to the JS bundle on the filesystem. Will be composed in a
* `file://...` URL
* @param isHermesEnabled whether to use Hermes as the JS engine, default to true.
* @param useDevSupport whether to enable dev support, default to ReactBuildConfig.DEBUG.
* @param cxxReactPackageProviders a list of cxxreactpackage providers (to register c++ turbo
* modules)
* @param exceptionHandler Callback that can be used by React Native host applications to react to
* exceptions thrown by the internals of React Native.
* @param bindingsInstaller that can be used for installing bindings.
*/
@Deprecated(
message = "Use `getDefaultReactHost` with `jsRuntimeFactory` instead",
replaceWith =
ReplaceWith(
"""
fun getDefaultReactHost(
context: Context,
packageList: List<ReactPackage>,
jsMainModulePath: String,
jsBundleAssetPath: String,
jsBundleFilePath: String?,
jsRuntimeFactory: JSRuntimeFactory?,
useDevSupport: Boolean,
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage>,
exceptionHandler: (Exception) -> Unit,
bindingsInstaller: BindingsInstaller?,
): ReactHost
"""))
@JvmStatic
public fun getDefaultReactHost(
context: Context,
packageList: List<ReactPackage>,
jsMainModulePath: String = "index",
jsBundleAssetPath: String = "index",
jsBundleFilePath: String? = null,
isHermesEnabled: Boolean = true,
useDevSupport: Boolean = ReactBuildConfig.DEBUG,
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage> = emptyList(),
exceptionHandler: (Exception) -> Unit = { throw it },
bindingsInstaller: BindingsInstaller? = null,
): ReactHost =
getDefaultReactHost(
context,
packageList,
jsMainModulePath,
jsBundleAssetPath,
jsBundleFilePath,
if (isHermesEnabled) HermesInstance() else JSCInstance(),
useDevSupport,
cxxReactPackageProviders,
exceptionHandler,
bindingsInstaller)
/**
* Util function to create a default [ReactHost] to be used in your application. This method is
* used by the New App template.
*
* @param context the Android [Context] to use for creating the [ReactHost]
* @param packageList the list of [ReactPackage]s to use for creating the [ReactHost]
* @param jsMainModulePath the path to your app's main module on Metro. Usually `index` or
* `index.<platform>`
* @param jsBundleAssetPath the path to the JS bundle relative to the assets directory. Will be
* composed in a `asset://...` URL
* @param jsBundleFilePath the path to the JS bundle on the filesystem. Will be composed in a
* `file://...` URL
* @param isHermesEnabled whether to use Hermes as the JS engine, default to true.
* @param useDevSupport whether to enable dev support, default to ReactBuildConfig.DEBUG.
* @param cxxReactPackageProviders a list of cxxreactpackage providers (to register c++ turbo
* modules)
*/
@Deprecated(
message = "Use `getDefaultReactHost` with `jsRuntimeFactory` instead",
replaceWith =
ReplaceWith(
"""
fun getDefaultReactHost(
context: Context,
packageList: List<ReactPackage>,
jsMainModulePath: String,
jsBundleAssetPath: String,
jsBundleFilePath: String?,
jsRuntimeFactory: JSRuntimeFactory?,
useDevSupport: Boolean,
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage>,
): ReactHost
"""))
@JvmStatic
public fun getDefaultReactHost(
context: Context,
packageList: List<ReactPackage>,
jsMainModulePath: String = "index",
jsBundleAssetPath: String = "index",
jsBundleFilePath: String? = null,
isHermesEnabled: Boolean = true,
useDevSupport: Boolean = ReactBuildConfig.DEBUG,
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage> = emptyList(),
): ReactHost =
getDefaultReactHost(
context,
packageList,
jsMainModulePath,
jsBundleAssetPath,
jsBundleFilePath,
if (isHermesEnabled) HermesInstance() else JSCInstance(),
useDevSupport,
cxxReactPackageProviders,
)
/**
* Util function to create a default [ReactHost] to be used in your application. This method is
* used by the New App template.
@@ -169,11 +287,12 @@ public object DefaultReactHost {
public fun getDefaultReactHost(
context: Context,
reactNativeHost: ReactNativeHost,
jsRuntimeFactory: JSRuntimeFactory? = null
): ReactHost {
require(reactNativeHost is DefaultReactNativeHost) {
"You can call getDefaultReactHost only with instances of DefaultReactNativeHost"
}
return reactNativeHost.toReactHost(context)
return reactNativeHost.toReactHost(context, jsRuntimeFactory)
}
/**
@@ -18,6 +18,9 @@ import com.facebook.react.bridge.UIManagerProvider
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.fabric.ComponentFactory
import com.facebook.react.fabric.FabricUIManagerProviderImpl
import com.facebook.react.runtime.JSCInstance
import com.facebook.react.runtime.JSRuntimeFactory
import com.facebook.react.runtime.hermes.HermesInstance
import com.facebook.react.uimanager.ViewManagerRegistry
import com.facebook.react.uimanager.ViewManagerResolver
@@ -108,14 +111,20 @@ protected constructor(
* @param context the Android [Context] to use for creating the [ReactHost]
*/
@UnstableReactNativeAPI
internal fun toReactHost(context: Context): ReactHost =
DefaultReactHost.getDefaultReactHost(
context,
packages,
jsMainModuleName,
bundleAssetName ?: "index",
jsBundleFile,
isHermesEnabled ?: true,
useDeveloperSupport,
)
internal fun toReactHost(
context: Context,
jsRuntimeFactory: JSRuntimeFactory? = null
): ReactHost {
val concreteJSRuntimeFactory =
jsRuntimeFactory ?: if (isHermesEnabled == false) JSCInstance() else HermesInstance()
return DefaultReactHost.getDefaultReactHost(
context,
packages,
jsMainModuleName,
bundleAssetName ?: "index",
jsBundleFile,
concreteJSRuntimeFactory,
useDeveloperSupport,
)
}
}